Adding schema validation and API endpoint to data sources for query.
This commit is contained in:
parent
9f50d2d329
commit
091b537e2d
|
@ -64,7 +64,17 @@ exports.find = async function (ctx) {
|
||||||
|
|
||||||
// dynamic query functionality
|
// dynamic query functionality
|
||||||
exports.query = async function (ctx) {
|
exports.query = async function (ctx) {
|
||||||
|
const queryJson = ctx.request.body
|
||||||
|
const datasourceId = queryJson.endpoint.datasourceId
|
||||||
|
const database = new CouchDB(ctx.appId)
|
||||||
|
const datasource = await database.get(datasourceId)
|
||||||
|
const source = integrations[datasource.source]
|
||||||
|
// query is the opinionated function
|
||||||
|
if (source.query) {
|
||||||
|
ctx.body = await source.query(queryJson)
|
||||||
|
} else {
|
||||||
|
ctx.throw(400, "Datasource does not support query.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: merge endpoint with main datasource endpoint
|
// TODO: merge endpoint with main datasource endpoint
|
||||||
|
|
|
@ -8,7 +8,7 @@ const {
|
||||||
PermissionTypes,
|
PermissionTypes,
|
||||||
} = require("@budibase/auth/permissions")
|
} = require("@budibase/auth/permissions")
|
||||||
const Joi = require("joi")
|
const Joi = require("joi")
|
||||||
const { FieldTypes } = require("../../constants")
|
const { FieldTypes, DataSourceOperation, SortDirection } = require("../../constants")
|
||||||
|
|
||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
|
@ -31,6 +31,35 @@ function generatePlusDatasourceSchema() {
|
||||||
}).unknown(true))
|
}).unknown(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateQueryDatasourceSchema() {
|
||||||
|
// prettier-ignore
|
||||||
|
return joiValidator.body(Joi.object({
|
||||||
|
endpoint: Joi.object({
|
||||||
|
datasourceId: Joi.string().required(),
|
||||||
|
operation: Joi.string().required().valid(...Object.values(DataSourceOperation)),
|
||||||
|
entityId: Joi.string().required(),
|
||||||
|
}).required(),
|
||||||
|
resource: Joi.object({
|
||||||
|
fields: Joi.array().items(Joi.string()).optional(),
|
||||||
|
}).optional(),
|
||||||
|
body: Joi.object().optional(),
|
||||||
|
sort: Joi.object().optional(),
|
||||||
|
filters: Joi.object({
|
||||||
|
string: Joi.object().optional(),
|
||||||
|
range: Joi.object().optional(),
|
||||||
|
equal: Joi.object().optional(),
|
||||||
|
notEqual: Joi.object().optional(),
|
||||||
|
empty: Joi.object().optional(),
|
||||||
|
notEmpty: Joi.object().optional(),
|
||||||
|
}).optional(),
|
||||||
|
paginate: Joi.object({
|
||||||
|
page: Joi.string().alphanum().optional(),
|
||||||
|
limit: Joi.number().optional(),
|
||||||
|
}).optional(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
router
|
router
|
||||||
.get("/api/datasources", authorized(BUILDER), datasourceController.fetch)
|
.get("/api/datasources", authorized(BUILDER), datasourceController.fetch)
|
||||||
.get(
|
.get(
|
||||||
|
@ -40,9 +69,16 @@ router
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/api/datasources/plus",
|
"/api/datasources/plus",
|
||||||
|
authorized(PermissionTypes.TABLE, PermissionLevels.READ),
|
||||||
generatePlusDatasourceSchema(),
|
generatePlusDatasourceSchema(),
|
||||||
datasourceController.plus
|
datasourceController.plus
|
||||||
)
|
)
|
||||||
|
.post(
|
||||||
|
"/api/datasources/query",
|
||||||
|
authorized(PermissionTypes.TABLE, PermissionLevels.READ),
|
||||||
|
generateQueryDatasourceSchema(),
|
||||||
|
datasourceController.query
|
||||||
|
)
|
||||||
.post("/api/datasources", authorized(BUILDER), datasourceController.save)
|
.post("/api/datasources", authorized(BUILDER), datasourceController.save)
|
||||||
.delete(
|
.delete(
|
||||||
"/api/datasources/:datasourceId/:revId",
|
"/api/datasources/:datasourceId/:revId",
|
||||||
|
|
|
@ -31,6 +31,19 @@ exports.AuthTypes = {
|
||||||
EXTERNAL: "external",
|
EXTERNAL: "external",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.DataSourceOperation = {
|
||||||
|
CREATE: "CREATE",
|
||||||
|
READ: "READ",
|
||||||
|
UPDATE: "UPDATE",
|
||||||
|
DELETE: "DELETE",
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.SortDirection = {
|
||||||
|
ASCENDING: "ASCENDING",
|
||||||
|
DESCENDING: "DESCENDING",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
exports.USERS_TABLE_SCHEMA = {
|
exports.USERS_TABLE_SCHEMA = {
|
||||||
_id: "ta_users",
|
_id: "ta_users",
|
||||||
type: "table",
|
type: "table",
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
const { Operation, SortDirection } = require("./constants")
|
const {
|
||||||
|
DataSourceOperation,
|
||||||
|
SortDirection,
|
||||||
|
} = require("../../constants")
|
||||||
|
|
||||||
const BASE_LIMIT = 5000
|
const BASE_LIMIT = 5000
|
||||||
|
|
||||||
|
@ -113,20 +116,20 @@ class SqlQueryBuilder {
|
||||||
const knex = require("knex")({ client: this._client })
|
const knex = require("knex")({ client: this._client })
|
||||||
let query
|
let query
|
||||||
switch (this._operation(json)) {
|
switch (this._operation(json)) {
|
||||||
case Operation.CREATE:
|
case DataSourceOperation.CREATE:
|
||||||
query = buildCreate(knex, json)
|
query = buildCreate(knex, json)
|
||||||
break
|
break
|
||||||
case Operation.READ:
|
case DataSourceOperation.READ:
|
||||||
query = buildRead(knex, json, this._limit)
|
query = buildRead(knex, json, this._limit)
|
||||||
break
|
break
|
||||||
case Operation.UPDATE:
|
case DataSourceOperation.UPDATE:
|
||||||
query = buildUpdate(knex, json)
|
query = buildUpdate(knex, json)
|
||||||
break
|
break
|
||||||
case Operation.DELETE:
|
case DataSourceOperation.DELETE:
|
||||||
query = buildDelete(knex, json)
|
query = buildDelete(knex, json)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
throw `Operation ${operation} type is not supported by SQL query builder`
|
throw `Operation type is not supported by SQL query builder`
|
||||||
}
|
}
|
||||||
return query.toSQL().toNative()
|
return query.toSQL().toNative()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue