@budibase/server 0.9.188 → 0.9.190-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +7 -1
- package/__mocks__/mssql.ts +1 -1
- package/__mocks__/oracledb.ts +31 -0
- package/__mocks__/pg.ts +3 -0
- package/builder/assets/bb-space-man.5be51a45.svg +290 -0
- package/builder/assets/index.2bd3b345.js +1316 -0
- package/builder/assets/index.4fb3f887.css +1 -0
- package/builder/assets/oracle.66592424.png +0 -0
- package/builder/assets/vendor.470042a4.js +152 -0
- package/builder/assets/vendor.5e1fe644.css +1 -0
- package/builder/index.html +4 -4
- package/coverage/clover.xml +1608 -1191
- package/coverage/coverage-final.json +97 -93
- package/coverage/lcov-report/api/controllers/analytics.js.html +2 -2
- package/coverage/lcov-report/api/controllers/apikeys.js.html +2 -2
- package/coverage/lcov-report/api/controllers/application.js.html +113 -80
- package/coverage/lcov-report/api/controllers/auth.js.html +19 -10
- package/coverage/lcov-report/api/controllers/automation.js.html +3 -3
- package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
- package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
- package/coverage/lcov-report/api/controllers/component.js.html +4 -4
- package/coverage/lcov-report/api/controllers/datasource.js.html +245 -41
- package/coverage/lcov-report/api/controllers/dev.js.html +16 -7
- package/coverage/lcov-report/api/controllers/hosting.js.html +10 -10
- package/coverage/lcov-report/api/controllers/index.html +98 -98
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +9 -9
- package/coverage/lcov-report/api/controllers/metadata.js.html +3 -3
- package/coverage/lcov-report/api/controllers/permission.js.html +3 -3
- package/coverage/lcov-report/api/controllers/query.js.html +79 -229
- package/coverage/lcov-report/api/controllers/role.js.html +9 -9
- package/coverage/lcov-report/api/controllers/routing.js.html +29 -29
- package/coverage/lcov-report/api/controllers/row/external.js.html +17 -8
- package/coverage/lcov-report/api/controllers/row/index.html +26 -26
- package/coverage/lcov-report/api/controllers/row/index.js.html +2 -2
- package/coverage/lcov-report/api/controllers/row/internal.js.html +9 -9
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +2 -2
- package/coverage/lcov-report/api/controllers/row/utils.js.html +21 -30
- package/coverage/lcov-report/api/controllers/screen.js.html +3 -3
- package/coverage/lcov-report/api/controllers/script.js.html +3 -3
- package/coverage/lcov-report/api/controllers/table/external.js.html +1001 -0
- package/coverage/lcov-report/api/controllers/table/index.html +56 -26
- package/coverage/lcov-report/api/controllers/table/index.js.html +80 -350
- package/coverage/lcov-report/api/controllers/table/internal.js.html +533 -0
- package/coverage/lcov-report/api/controllers/table/utils.js.html +175 -52
- package/coverage/lcov-report/api/controllers/templates.js.html +4 -4
- package/coverage/lcov-report/api/controllers/user.js.html +390 -33
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +19 -4
- package/coverage/lcov-report/api/controllers/view/index.html +22 -22
- package/coverage/lcov-report/api/controllers/view/index.js.html +52 -13
- package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +3 -3
- package/coverage/lcov-report/api/controllers/webhook.js.html +4 -4
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +5 -5
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/routes/application.js.html +1 -1
- package/coverage/lcov-report/api/routes/auth.js.html +1 -1
- package/coverage/lcov-report/api/routes/automation.js.html +1 -1
- package/coverage/lcov-report/api/routes/backup.js.html +1 -1
- package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
- package/coverage/lcov-report/api/routes/component.js.html +1 -1
- package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
- package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
- package/coverage/lcov-report/api/routes/dev.js.html +2 -2
- package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
- package/coverage/lcov-report/api/routes/index.html +4 -4
- package/coverage/lcov-report/api/routes/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/integration.js.html +1 -1
- package/coverage/lcov-report/api/routes/layout.js.html +1 -1
- package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
- package/coverage/lcov-report/api/routes/permission.js.html +1 -1
- package/coverage/lcov-report/api/routes/query.js.html +5 -2
- package/coverage/lcov-report/api/routes/role.js.html +1 -1
- package/coverage/lcov-report/api/routes/routing.js.html +1 -1
- package/coverage/lcov-report/api/routes/row.js.html +536 -2
- package/coverage/lcov-report/api/routes/screen.js.html +1 -1
- package/coverage/lcov-report/api/routes/script.js.html +1 -1
- package/coverage/lcov-report/api/routes/static.js.html +2 -2
- package/coverage/lcov-report/api/routes/table.js.html +464 -2
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +17 -2
- package/coverage/lcov-report/api/routes/view.js.html +1 -1
- package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/actions.js.html +2 -2
- package/coverage/lcov-report/automations/automationUtils.js.html +4 -4
- package/coverage/lcov-report/automations/bullboard.js.html +71 -20
- package/coverage/lcov-report/automations/index.html +35 -50
- package/coverage/lcov-report/automations/index.js.html +2 -2
- package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
- package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
- package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/discord.js.html +3 -3
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeScript.js.html +3 -3
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +14 -14
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +3 -3
- package/coverage/lcov-report/automations/steps/queryRows.js.html +3 -3
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
- package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
- package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
- package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/utils.js.html +7 -7
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
- package/coverage/lcov-report/automations/triggers.js.html +22 -10
- package/coverage/lcov-report/automations/utils.js.html +46 -16
- package/coverage/lcov-report/constants/index.html +5 -5
- package/coverage/lcov-report/constants/index.js.html +87 -21
- package/coverage/lcov-report/constants/layouts.js.html +1 -1
- package/coverage/lcov-report/constants/screens.js.html +2 -2
- package/coverage/lcov-report/db/client.js.html +2 -2
- package/coverage/lcov-report/db/inMemoryView.js.html +2 -2
- package/coverage/lcov-report/db/index.html +2 -2
- package/coverage/lcov-report/db/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +6 -6
- package/coverage/lcov-report/db/linkedRows/index.html +10 -10
- package/coverage/lcov-report/db/linkedRows/index.js.html +5 -5
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +6 -6
- package/coverage/lcov-report/db/newid.js.html +4 -4
- package/coverage/lcov-report/db/utils.js.html +75 -75
- package/coverage/lcov-report/events/AutomationEmitter.js.html +6 -6
- package/coverage/lcov-report/events/index.html +6 -6
- package/coverage/lcov-report/events/index.js.html +1 -1
- package/coverage/lcov-report/events/utils.js.html +5 -5
- package/coverage/lcov-report/index.html +106 -91
- package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
- package/coverage/lcov-report/integrations/tests/index.html +1 -1
- package/coverage/lcov-report/middleware/appInfo.js.html +2 -2
- package/coverage/lcov-report/middleware/authorized.js.html +19 -16
- package/coverage/lcov-report/middleware/builder.js.html +22 -13
- package/coverage/lcov-report/middleware/currentapp.js.html +33 -33
- package/coverage/lcov-report/middleware/index.html +23 -23
- package/coverage/lcov-report/middleware/joi-validator.js.html +2 -2
- package/coverage/lcov-report/middleware/resourceId.js.html +18 -18
- package/coverage/lcov-report/middleware/selfhost.js.html +2 -2
- package/coverage/lcov-report/middleware/usageQuota.js.html +4 -4
- package/coverage/lcov-report/middleware/utils.js.html +2 -2
- package/coverage/lcov-report/{automations/thread.js.html → threads/automation.js.html} +90 -33
- package/coverage/lcov-report/threads/index.html +141 -0
- package/coverage/lcov-report/threads/index.js.html +278 -0
- package/coverage/lcov-report/threads/query.js.html +278 -0
- package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
- package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
- package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
- package/coverage/lcov-report/utilities/csvParser.js.html +144 -15
- package/coverage/lcov-report/utilities/global.js.html +38 -23
- package/coverage/lcov-report/utilities/index.html +48 -48
- package/coverage/lcov-report/utilities/index.js.html +49 -16
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +31 -10
- package/coverage/lcov-report/utilities/queue/index.html +14 -14
- package/coverage/lcov-report/utilities/routing/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.js.html +2 -2
- package/coverage/lcov-report/utilities/rowProcessor/index.html +4 -4
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +2 -2
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +3 -3
- package/coverage/lcov-report/utilities/scriptRunner.js.html +16 -7
- package/coverage/lcov-report/utilities/security.js.html +3 -3
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +1 -1
- package/coverage/lcov-report/utilities/workerRequests.js.html +5 -5
- package/coverage/lcov.info +2687 -1942
- package/dist/api/controllers/application.js +16 -6
- package/dist/api/controllers/auth.js +3 -3
- package/dist/api/controllers/datasource.js +67 -16
- package/dist/api/controllers/deploy/index.js +2 -0
- package/dist/api/controllers/dev.js +4 -1
- package/dist/api/controllers/query.js +32 -62
- package/dist/api/controllers/row/ExternalRequest.js +83 -36
- package/dist/api/controllers/row/external.js +3 -1
- package/dist/api/controllers/row/utils.js +6 -12
- package/dist/api/controllers/table/external.js +249 -0
- package/dist/api/controllers/table/index.js +49 -123
- package/dist/api/controllers/table/internal.js +146 -0
- package/dist/api/controllers/table/utils.js +62 -28
- package/dist/api/controllers/user.js +123 -11
- package/dist/api/controllers/view/exporters.js +4 -0
- package/dist/api/controllers/view/index.js +14 -2
- package/dist/api/routes/query.js +1 -1
- package/dist/api/routes/row.js +178 -0
- package/dist/api/routes/table.js +150 -1
- package/dist/api/routes/user.js +2 -1
- package/dist/app.js +2 -11
- package/dist/automations/bullboard.js +37 -10
- package/dist/automations/triggers.js +7 -3
- package/dist/automations/utils.js +11 -2
- package/dist/constants/index.js +19 -0
- package/dist/definitions/datasource.js +17 -1
- package/dist/environment.js +13 -0
- package/dist/integrations/base/IntegrationBase.js +2 -0
- package/dist/integrations/base/datasourcePlus.js +2 -0
- package/dist/integrations/base/sql.js +350 -177
- package/dist/integrations/base/sqlTable.js +143 -0
- package/dist/integrations/base/utils.js +30 -0
- package/dist/integrations/index.js +6 -0
- package/dist/integrations/microsoftSqlServer.js +117 -9
- package/dist/integrations/mysql.js +16 -85
- package/dist/integrations/oracle.js +367 -0
- package/dist/integrations/postgres.js +35 -28
- package/dist/integrations/utils.js +71 -9
- package/dist/middleware/authorized.js +2 -1
- package/dist/middleware/builder.js +4 -1
- package/dist/package.json +18 -9
- package/dist/tests/utilities/TestConfiguration.js +2 -1
- package/dist/{automations/thread.js → threads/automation.js} +26 -8
- package/dist/threads/index.js +64 -0
- package/dist/threads/query.js +64 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/csvParser.js +46 -5
- package/dist/utilities/global.js +6 -2
- package/dist/utilities/index.js +11 -0
- package/dist/utilities/queue/inMemoryQueue.js +8 -0
- package/dist/utilities/scriptRunner.js +4 -1
- package/package.json +19 -10
- package/scripts/dev/manage.js +1 -0
- package/scripts/docs/README.md +31 -0
- package/scripts/docs/generate.js +74 -0
- package/scripts/docs/toSwagger.js +320 -0
- package/scripts/integrations/mssql/data/Dockerfile +9 -0
- package/scripts/integrations/mssql/data/entrypoint.sh +24 -0
- package/scripts/integrations/mssql/data/setup.sql +54 -0
- package/scripts/integrations/mssql/docker-compose.yaml +12 -0
- package/scripts/integrations/mssql/reset.sh +3 -0
- package/scripts/integrations/oracle/docker-compose.yml +19 -0
- package/scripts/integrations/oracle/instantclient/linux/x86-64/basiclite-21.4.zip +0 -0
- package/scripts/integrations/oracle/instantclient/linux/x86-64/install.sh +23 -0
- package/scripts/integrations/oracle/oracle.md +90 -0
- package/scripts/integrations/postgres/docker-compose.yml +3 -3
- package/scripts/likeCypress.ts +33 -0
- package/src/api/controllers/application.js +18 -7
- package/src/api/controllers/auth.js +3 -0
- package/src/api/controllers/datasource.js +84 -16
- package/src/api/controllers/deploy/index.js +2 -0
- package/src/api/controllers/dev.js +4 -1
- package/src/api/controllers/query.js +35 -85
- package/src/api/controllers/row/ExternalRequest.ts +99 -38
- package/src/api/controllers/row/external.js +4 -1
- package/src/api/controllers/row/utils.js +8 -11
- package/src/api/controllers/table/external.js +307 -0
- package/src/api/controllers/table/index.js +47 -137
- package/src/api/controllers/table/internal.js +151 -0
- package/src/api/controllers/table/utils.js +74 -33
- package/src/api/controllers/user.js +132 -13
- package/src/api/controllers/view/exporters.js +5 -0
- package/src/api/controllers/view/index.js +15 -2
- package/src/api/routes/query.js +1 -0
- package/src/api/routes/row.js +178 -0
- package/src/api/routes/table.js +154 -0
- package/src/api/routes/tests/application.spec.js +0 -2
- package/src/api/routes/tests/datasource.spec.js +2 -2
- package/src/api/routes/tests/misc.spec.js +5 -1
- package/src/api/routes/tests/query.spec.js +38 -9
- package/src/api/routes/tests/screen.spec.js +1 -1
- package/src/api/routes/user.js +5 -0
- package/src/app.ts +2 -10
- package/src/automations/bullboard.js +28 -11
- package/src/automations/tests/automation.spec.js +3 -4
- package/src/automations/triggers.js +7 -3
- package/src/automations/utils.js +12 -2
- package/src/constants/index.js +22 -0
- package/src/definitions/common.ts +7 -1
- package/src/definitions/datasource.ts +21 -3
- package/src/environment.js +15 -0
- package/src/integrations/airtable.ts +2 -1
- package/src/integrations/arangodb.ts +2 -1
- package/src/integrations/base/IntegrationBase.ts +6 -0
- package/src/integrations/base/datasourcePlus.ts +9 -0
- package/src/integrations/base/sql.ts +375 -218
- package/src/integrations/base/sqlTable.ts +180 -0
- package/src/integrations/base/utils.ts +22 -0
- package/src/integrations/couchdb.ts +2 -1
- package/src/integrations/dynamodb.ts +2 -1
- package/src/integrations/elasticsearch.ts +2 -1
- package/src/integrations/index.ts +7 -0
- package/src/integrations/microsoftSqlServer.ts +145 -13
- package/src/integrations/mongodb.ts +2 -1
- package/src/integrations/mysql.ts +23 -95
- package/src/integrations/oracle.ts +464 -0
- package/src/integrations/postgres.ts +45 -35
- package/src/integrations/rest.ts +2 -1
- package/src/integrations/s3.ts +2 -1
- package/src/integrations/tests/microsoftSqlServer.spec.js +22 -15
- package/src/integrations/tests/oracle.spec.js +94 -0
- package/src/integrations/tests/postgres.spec.js +4 -0
- package/src/integrations/utils.ts +78 -8
- package/src/middleware/authorized.js +2 -1
- package/src/middleware/builder.js +4 -1
- package/src/tests/utilities/TestConfiguration.js +2 -1
- package/src/{automations/thread.js → threads/automation.js} +27 -8
- package/src/threads/index.js +66 -0
- package/src/threads/query.js +66 -0
- package/src/utilities/csvParser.js +48 -5
- package/src/utilities/global.js +7 -2
- package/src/utilities/index.js +11 -0
- package/src/utilities/queue/inMemoryQueue.js +7 -0
- package/src/utilities/scriptRunner.js +4 -1
- package/src/utilities/tests/__snapshots__/csvParser.spec.js.snap +0 -6
- package/src/utilities/tests/csvParser.spec.js +3 -0
- package/tsconfig.json +1 -1
- package/builder/assets/index.550fdba7.js +0 -201
- package/builder/assets/index.7469e1e4.css +0 -29
- package/builder/assets/vendor.278a305c.js +0 -9
- package/builder/assets/vendor.d75d5eb7.css +0 -1
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
const { processString } = require("@budibase/string-templates")
|
|
2
2
|
const CouchDB = require("../../db")
|
|
3
|
-
const {
|
|
4
|
-
|
|
3
|
+
const {
|
|
4
|
+
generateQueryID,
|
|
5
|
+
getQueryParams,
|
|
6
|
+
isProdAppID,
|
|
7
|
+
} = require("../../db/utils")
|
|
5
8
|
const { BaseQueryVerbs } = require("../../constants")
|
|
6
|
-
const
|
|
7
|
-
|
|
9
|
+
const { Thread, ThreadType } = require("../../threads")
|
|
10
|
+
|
|
11
|
+
const Runner = new Thread(ThreadType.QUERY, { timeoutMs: 10000 })
|
|
8
12
|
|
|
9
13
|
// simple function to append "readable" to all read queries
|
|
10
14
|
function enrichQueries(input) {
|
|
@@ -18,47 +22,6 @@ function enrichQueries(input) {
|
|
|
18
22
|
return wasArray ? queries : queries[0]
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
function formatResponse(resp) {
|
|
22
|
-
if (typeof resp === "string") {
|
|
23
|
-
try {
|
|
24
|
-
resp = JSON.parse(resp)
|
|
25
|
-
} catch (err) {
|
|
26
|
-
resp = { response: resp }
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return resp
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async function runAndTransform(
|
|
33
|
-
integration,
|
|
34
|
-
queryVerb,
|
|
35
|
-
enrichedQuery,
|
|
36
|
-
transformer
|
|
37
|
-
) {
|
|
38
|
-
let rows = formatResponse(await integration[queryVerb](enrichedQuery))
|
|
39
|
-
|
|
40
|
-
// transform as required
|
|
41
|
-
if (transformer) {
|
|
42
|
-
const runner = new ScriptRunner(transformer, { data: rows })
|
|
43
|
-
rows = runner.execute()
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// needs to an array for next step
|
|
47
|
-
if (!Array.isArray(rows)) {
|
|
48
|
-
rows = [rows]
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// map into JSON if just raw primitive here
|
|
52
|
-
if (rows.find(row => typeof row !== "object")) {
|
|
53
|
-
rows = rows.map(value => ({ value }))
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// get all the potential fields in the schema
|
|
57
|
-
let keys = rows.flatMap(Object.keys)
|
|
58
|
-
|
|
59
|
-
return { rows, keys }
|
|
60
|
-
}
|
|
61
|
-
|
|
62
25
|
exports.fetch = async function (ctx) {
|
|
63
26
|
const db = new CouchDB(ctx.appId)
|
|
64
27
|
|
|
@@ -98,7 +61,9 @@ async function enrichQueryFields(fields, parameters = {}) {
|
|
|
98
61
|
enrichedQuery[key] = await enrichQueryFields(fields[key], parameters)
|
|
99
62
|
} else if (typeof fields[key] === "string") {
|
|
100
63
|
// enrich string value as normal
|
|
101
|
-
enrichedQuery[key] = await processString(fields[key], parameters
|
|
64
|
+
enrichedQuery[key] = await processString(fields[key], parameters, {
|
|
65
|
+
noHelpers: true,
|
|
66
|
+
})
|
|
102
67
|
} else {
|
|
103
68
|
enrichedQuery[key] = fields[key]
|
|
104
69
|
}
|
|
@@ -128,10 +93,9 @@ exports.find = async function (ctx) {
|
|
|
128
93
|
const db = new CouchDB(ctx.appId)
|
|
129
94
|
const query = enrichQueries(await db.get(ctx.params.queryId))
|
|
130
95
|
// remove properties that could be dangerous in real app
|
|
131
|
-
if (
|
|
96
|
+
if (isProdAppID(ctx.appId)) {
|
|
132
97
|
delete query.fields
|
|
133
98
|
delete query.parameters
|
|
134
|
-
delete query.schema
|
|
135
99
|
}
|
|
136
100
|
ctx.body = query
|
|
137
101
|
}
|
|
@@ -141,30 +105,23 @@ exports.preview = async function (ctx) {
|
|
|
141
105
|
|
|
142
106
|
const datasource = await db.get(ctx.request.body.datasourceId)
|
|
143
107
|
|
|
144
|
-
const Integration = integrations[datasource.source]
|
|
145
|
-
|
|
146
|
-
if (!Integration) {
|
|
147
|
-
ctx.throw(400, "Integration type does not exist.")
|
|
148
|
-
}
|
|
149
|
-
|
|
150
108
|
const { fields, parameters, queryVerb, transformer } = ctx.request.body
|
|
151
109
|
const enrichedQuery = await enrichQueryFields(fields, parameters)
|
|
152
|
-
const integration = new Integration(datasource.config)
|
|
153
110
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
111
|
+
try {
|
|
112
|
+
const { rows, keys } = await Runner.run({
|
|
113
|
+
datasource,
|
|
114
|
+
queryVerb,
|
|
115
|
+
query: enrichedQuery,
|
|
116
|
+
transformer,
|
|
117
|
+
})
|
|
160
118
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
integration.end()
|
|
119
|
+
ctx.body = {
|
|
120
|
+
rows,
|
|
121
|
+
schemaFields: [...new Set(keys)],
|
|
122
|
+
}
|
|
123
|
+
} catch (err) {
|
|
124
|
+
ctx.throw(400, err)
|
|
168
125
|
}
|
|
169
126
|
}
|
|
170
127
|
|
|
@@ -174,29 +131,22 @@ exports.execute = async function (ctx) {
|
|
|
174
131
|
const query = await db.get(ctx.params.queryId)
|
|
175
132
|
const datasource = await db.get(query.datasourceId)
|
|
176
133
|
|
|
177
|
-
const Integration = integrations[datasource.source]
|
|
178
|
-
|
|
179
|
-
if (!Integration) {
|
|
180
|
-
ctx.throw(400, "Integration type does not exist.")
|
|
181
|
-
}
|
|
182
|
-
|
|
183
134
|
const enrichedQuery = await enrichQueryFields(
|
|
184
135
|
query.fields,
|
|
185
136
|
ctx.request.body.parameters
|
|
186
137
|
)
|
|
187
|
-
const integration = new Integration(datasource.config)
|
|
188
138
|
|
|
189
139
|
// call the relevant CRUD method on the integration class
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
140
|
+
try {
|
|
141
|
+
const { rows } = await Runner.run({
|
|
142
|
+
datasource,
|
|
143
|
+
queryVerb: query.queryVerb,
|
|
144
|
+
query: enrichedQuery,
|
|
145
|
+
transformer: query.transformer,
|
|
146
|
+
})
|
|
147
|
+
ctx.body = rows
|
|
148
|
+
} catch (err) {
|
|
149
|
+
ctx.throw(400, err)
|
|
200
150
|
}
|
|
201
151
|
}
|
|
202
152
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
FilterTypes,
|
|
2
3
|
IncludeRelationships,
|
|
3
4
|
Operation,
|
|
4
5
|
PaginationJson,
|
|
@@ -33,10 +34,11 @@ interface RunConfig {
|
|
|
33
34
|
sort?: SortJson
|
|
34
35
|
paginate?: PaginationJson
|
|
35
36
|
row?: Row
|
|
37
|
+
rows?: Row[]
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
module External {
|
|
39
|
-
const {
|
|
41
|
+
const { getDatasourceAndQuery } = require("./utils")
|
|
40
42
|
const {
|
|
41
43
|
DataSourceOperation,
|
|
42
44
|
FieldTypes,
|
|
@@ -46,6 +48,7 @@ module External {
|
|
|
46
48
|
const { processObjectSync } = require("@budibase/string-templates")
|
|
47
49
|
const { cloneDeep } = require("lodash/fp")
|
|
48
50
|
const CouchDB = require("../../../db")
|
|
51
|
+
const { processFormulas } = require("../../../utilities/rowProcessor/utils")
|
|
49
52
|
|
|
50
53
|
function buildFilters(
|
|
51
54
|
id: string | undefined,
|
|
@@ -116,8 +119,13 @@ module External {
|
|
|
116
119
|
}
|
|
117
120
|
// check the row and filters to make sure they aren't a key of some sort
|
|
118
121
|
if (config.filters) {
|
|
119
|
-
for (let filter of Object.
|
|
120
|
-
|
|
122
|
+
for (let [key, filter] of Object.entries(config.filters)) {
|
|
123
|
+
// oneOf is an array, don't iterate it
|
|
124
|
+
if (
|
|
125
|
+
typeof filter !== "object" ||
|
|
126
|
+
Object.keys(filter).length === 0 ||
|
|
127
|
+
key === FilterTypes.ONE_OF
|
|
128
|
+
) {
|
|
121
129
|
continue
|
|
122
130
|
}
|
|
123
131
|
iterateObject(filter)
|
|
@@ -162,8 +170,8 @@ module External {
|
|
|
162
170
|
}
|
|
163
171
|
}
|
|
164
172
|
|
|
165
|
-
function basicProcessing(row: Row, table: Table) {
|
|
166
|
-
const thisRow:
|
|
173
|
+
function basicProcessing(row: Row, table: Table): Row {
|
|
174
|
+
const thisRow: Row = {}
|
|
167
175
|
// filter the row down to what is actually the row (not joined)
|
|
168
176
|
for (let fieldName of Object.keys(table.schema)) {
|
|
169
177
|
const value = row[`${table.name}.${fieldName}`] || row[fieldName]
|
|
@@ -178,9 +186,26 @@ module External {
|
|
|
178
186
|
return thisRow
|
|
179
187
|
}
|
|
180
188
|
|
|
181
|
-
function
|
|
189
|
+
function fixArrayTypes(row: Row, table: Table) {
|
|
190
|
+
for (let [fieldName, schema] of Object.entries(table.schema)) {
|
|
191
|
+
if (
|
|
192
|
+
schema.type === FieldTypes.ARRAY &&
|
|
193
|
+
typeof row[fieldName] === "string"
|
|
194
|
+
) {
|
|
195
|
+
try {
|
|
196
|
+
row[fieldName] = JSON.parse(row[fieldName])
|
|
197
|
+
} catch (err) {
|
|
198
|
+
// couldn't convert back to array, ignore
|
|
199
|
+
delete row[fieldName]
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return row
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function isOneSide(field: FieldSchema) {
|
|
182
207
|
return (
|
|
183
|
-
field.relationshipType && field.relationshipType.split("-")[0] === "
|
|
208
|
+
field.relationshipType && field.relationshipType.split("-")[0] === "one"
|
|
184
209
|
)
|
|
185
210
|
}
|
|
186
211
|
|
|
@@ -225,7 +250,12 @@ module External {
|
|
|
225
250
|
manyRelationships: ManyRelationship[] = []
|
|
226
251
|
for (let [key, field] of Object.entries(table.schema)) {
|
|
227
252
|
// if set already, or not set just skip it
|
|
228
|
-
if (
|
|
253
|
+
if (
|
|
254
|
+
row[key] == null ||
|
|
255
|
+
newRow[key] ||
|
|
256
|
+
field.autocolumn ||
|
|
257
|
+
field.type === FieldTypes.FORMULA
|
|
258
|
+
) {
|
|
229
259
|
continue
|
|
230
260
|
}
|
|
231
261
|
// if its an empty string then it means return the column to null (if possible)
|
|
@@ -250,25 +280,37 @@ module External {
|
|
|
250
280
|
const linkTable = this.tables[linkTableName]
|
|
251
281
|
// @ts-ignore
|
|
252
282
|
const linkTablePrimary = linkTable.primary[0]
|
|
253
|
-
|
|
283
|
+
// one to many
|
|
284
|
+
if (isOneSide(field)) {
|
|
254
285
|
newRow[field.foreignKey || linkTablePrimary] = breakRowIdField(
|
|
255
286
|
row[key][0]
|
|
256
287
|
)[0]
|
|
257
|
-
}
|
|
288
|
+
}
|
|
289
|
+
// many to many
|
|
290
|
+
else if (field.through) {
|
|
258
291
|
// we're not inserting a doc, will be a bunch of update calls
|
|
259
|
-
const
|
|
260
|
-
const thisKey: string =
|
|
261
|
-
? "id"
|
|
262
|
-
: field.throughTo || linkTablePrimary
|
|
263
|
-
// @ts-ignore
|
|
264
|
-
const otherKey: string = isUpdate
|
|
265
|
-
? field.fieldName
|
|
266
|
-
: field.throughFrom || tablePrimary
|
|
292
|
+
const otherKey: string = field.throughFrom || linkTablePrimary
|
|
293
|
+
const thisKey: string = field.throughTo || tablePrimary
|
|
267
294
|
row[key].map((relationship: any) => {
|
|
268
|
-
// we don't really support composite keys for relationships, this is why [0] is used
|
|
269
295
|
manyRelationships.push({
|
|
270
296
|
tableId: field.through || field.tableId,
|
|
271
|
-
isUpdate,
|
|
297
|
+
isUpdate: false,
|
|
298
|
+
key: otherKey,
|
|
299
|
+
[otherKey]: breakRowIdField(relationship)[0],
|
|
300
|
+
// leave the ID for enrichment later
|
|
301
|
+
[thisKey]: `{{ literal ${tablePrimary} }}`,
|
|
302
|
+
})
|
|
303
|
+
})
|
|
304
|
+
}
|
|
305
|
+
// many to one
|
|
306
|
+
else {
|
|
307
|
+
const thisKey: string = "id"
|
|
308
|
+
// @ts-ignore
|
|
309
|
+
const otherKey: string = field.fieldName
|
|
310
|
+
row[key].map((relationship: any) => {
|
|
311
|
+
manyRelationships.push({
|
|
312
|
+
tableId: field.tableId,
|
|
313
|
+
isUpdate: true,
|
|
272
314
|
key: otherKey,
|
|
273
315
|
[thisKey]: breakRowIdField(relationship)[0],
|
|
274
316
|
// leave the ID for enrichment later
|
|
@@ -336,7 +378,7 @@ module External {
|
|
|
336
378
|
table: Table,
|
|
337
379
|
relationships: RelationshipsJson[]
|
|
338
380
|
) {
|
|
339
|
-
if (rows[0].read === true) {
|
|
381
|
+
if (!rows || rows.length === 0 || rows[0].read === true) {
|
|
340
382
|
return []
|
|
341
383
|
}
|
|
342
384
|
let finalRows: { [key: string]: Row } = {}
|
|
@@ -352,7 +394,10 @@ module External {
|
|
|
352
394
|
)
|
|
353
395
|
continue
|
|
354
396
|
}
|
|
355
|
-
const thisRow = basicProcessing(row, table)
|
|
397
|
+
const thisRow = fixArrayTypes(basicProcessing(row, table), table)
|
|
398
|
+
if (thisRow._id == null) {
|
|
399
|
+
throw "Unable to generate row ID for SQL rows"
|
|
400
|
+
}
|
|
356
401
|
finalRows[thisRow._id] = thisRow
|
|
357
402
|
// do this at end once its been added to the final rows
|
|
358
403
|
finalRows = this.updateRelationshipColumns(
|
|
@@ -361,7 +406,7 @@ module External {
|
|
|
361
406
|
relationships
|
|
362
407
|
)
|
|
363
408
|
}
|
|
364
|
-
return Object.values(finalRows)
|
|
409
|
+
return processFormulas(table, Object.values(finalRows))
|
|
365
410
|
}
|
|
366
411
|
|
|
367
412
|
/**
|
|
@@ -398,8 +443,8 @@ module External {
|
|
|
398
443
|
)
|
|
399
444
|
definition.through = throughTableName
|
|
400
445
|
// don't support composite keys for relationships
|
|
401
|
-
definition.from = field.
|
|
402
|
-
definition.to = field.
|
|
446
|
+
definition.from = field.throughTo || table.primary[0]
|
|
447
|
+
definition.to = field.throughFrom || linkTable.primary[0]
|
|
403
448
|
definition.fromPrimary = table.primary[0]
|
|
404
449
|
definition.toPrimary = linkTable.primary[0]
|
|
405
450
|
}
|
|
@@ -421,24 +466,36 @@ module External {
|
|
|
421
466
|
// make a new request to get the row with all its relationships
|
|
422
467
|
// we need this to work out if any relationships need removed
|
|
423
468
|
for (let field of Object.values(table.schema)) {
|
|
424
|
-
if (
|
|
469
|
+
if (
|
|
470
|
+
field.type !== FieldTypes.LINK ||
|
|
471
|
+
!field.fieldName ||
|
|
472
|
+
isOneSide(field)
|
|
473
|
+
) {
|
|
425
474
|
continue
|
|
426
475
|
}
|
|
427
476
|
const isMany = field.relationshipType === RelationshipTypes.MANY_TO_MANY
|
|
428
477
|
const tableId = isMany ? field.through : field.tableId
|
|
429
|
-
const
|
|
478
|
+
const { tableName: relatedTableName } = breakExternalTableId(tableId)
|
|
479
|
+
// @ts-ignore
|
|
480
|
+
const linkPrimaryKey = this.tables[relatedTableName].primary[0]
|
|
481
|
+
const manyKey = field.throughTo || primaryKey
|
|
482
|
+
const lookupField = isMany ? primaryKey : field.foreignKey
|
|
430
483
|
const fieldName = isMany ? manyKey : field.fieldName
|
|
431
|
-
|
|
484
|
+
if (!lookupField || !row[lookupField]) {
|
|
485
|
+
continue
|
|
486
|
+
}
|
|
487
|
+
const response = await getDatasourceAndQuery(this.appId, {
|
|
432
488
|
endpoint: getEndpoint(tableId, DataSourceOperation.READ),
|
|
433
489
|
filters: {
|
|
434
490
|
equal: {
|
|
435
|
-
[fieldName]: row[
|
|
491
|
+
[fieldName]: row[lookupField],
|
|
436
492
|
},
|
|
437
493
|
},
|
|
438
494
|
})
|
|
439
495
|
// this is the response from knex if no rows found
|
|
440
496
|
const rows = !response[0].read ? response : []
|
|
441
|
-
|
|
497
|
+
const storeTo = isMany ? field.throughFrom || linkPrimaryKey : manyKey
|
|
498
|
+
related[storeTo] = { rows, isMany, tableId }
|
|
442
499
|
}
|
|
443
500
|
return related
|
|
444
501
|
}
|
|
@@ -479,7 +536,7 @@ module External {
|
|
|
479
536
|
: DataSourceOperation.CREATE
|
|
480
537
|
if (!found) {
|
|
481
538
|
promises.push(
|
|
482
|
-
|
|
539
|
+
getDatasourceAndQuery(appId, {
|
|
483
540
|
endpoint: getEndpoint(tableId, operation),
|
|
484
541
|
// if we're doing many relationships then we're writing, only one response
|
|
485
542
|
body,
|
|
@@ -509,7 +566,7 @@ module External {
|
|
|
509
566
|
: DataSourceOperation.UPDATE
|
|
510
567
|
const body = isMany ? null : { [colName]: null }
|
|
511
568
|
promises.push(
|
|
512
|
-
|
|
569
|
+
getDatasourceAndQuery(this.appId, {
|
|
513
570
|
endpoint: getEndpoint(tableId, op),
|
|
514
571
|
body,
|
|
515
572
|
filters,
|
|
@@ -532,16 +589,17 @@ module External {
|
|
|
532
589
|
table: Table,
|
|
533
590
|
includeRelations: IncludeRelationships = IncludeRelationships.INCLUDE
|
|
534
591
|
) {
|
|
535
|
-
function
|
|
592
|
+
function extractRealFields(table: Table, existing: string[] = []) {
|
|
536
593
|
return Object.entries(table.schema)
|
|
537
594
|
.filter(
|
|
538
595
|
column =>
|
|
539
596
|
column[1].type !== FieldTypes.LINK &&
|
|
597
|
+
column[1].type !== FieldTypes.FORMULA &&
|
|
540
598
|
!existing.find((field: string) => field === column[0])
|
|
541
599
|
)
|
|
542
600
|
.map(column => `${table.name}.${column[0]}`)
|
|
543
601
|
}
|
|
544
|
-
let fields =
|
|
602
|
+
let fields = extractRealFields(table)
|
|
545
603
|
for (let field of Object.values(table.schema)) {
|
|
546
604
|
if (field.type !== FieldTypes.LINK || !includeRelations) {
|
|
547
605
|
continue
|
|
@@ -549,7 +607,7 @@ module External {
|
|
|
549
607
|
const { tableName: linkTableName } = breakExternalTableId(field.tableId)
|
|
550
608
|
const linkTable = this.tables[linkTableName]
|
|
551
609
|
if (linkTable) {
|
|
552
|
-
const linkedFields =
|
|
610
|
+
const linkedFields = extractRealFields(linkTable, fields)
|
|
553
611
|
fields = fields.concat(linkedFields)
|
|
554
612
|
}
|
|
555
613
|
}
|
|
@@ -573,7 +631,10 @@ module External {
|
|
|
573
631
|
throw `Unable to process query, table "${tableName}" not defined.`
|
|
574
632
|
}
|
|
575
633
|
// look for specific components of config which may not be considered acceptable
|
|
576
|
-
let { id, row, filters, sort, paginate } = cleanupConfig(
|
|
634
|
+
let { id, row, filters, sort, paginate, rows } = cleanupConfig(
|
|
635
|
+
config,
|
|
636
|
+
table
|
|
637
|
+
)
|
|
577
638
|
filters = buildFilters(id, filters || {}, table)
|
|
578
639
|
const relationships = this.buildRelationships(table)
|
|
579
640
|
// clean up row on ingress using schema
|
|
@@ -599,7 +660,7 @@ module External {
|
|
|
599
660
|
sort,
|
|
600
661
|
paginate,
|
|
601
662
|
relationships,
|
|
602
|
-
body: row,
|
|
663
|
+
body: row || rows,
|
|
603
664
|
// pass an id filter into extra, purely for mysql/returning
|
|
604
665
|
extra: {
|
|
605
666
|
idFilter: buildFilters(id || generateIdForRow(row, table), {}, table),
|
|
@@ -609,7 +670,7 @@ module External {
|
|
|
609
670
|
},
|
|
610
671
|
}
|
|
611
672
|
// can't really use response right now
|
|
612
|
-
const response = await
|
|
673
|
+
const response = await getDatasourceAndQuery(appId, json)
|
|
613
674
|
// handle many to many relationships now if we know the ID (could be auto increment)
|
|
614
675
|
if (
|
|
615
676
|
operation !== DataSourceOperation.READ &&
|
|
@@ -30,6 +30,8 @@ async function handleRequest(appId, operation, tableId, opts = {}) {
|
|
|
30
30
|
)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
exports.handleRequest = handleRequest
|
|
34
|
+
|
|
33
35
|
exports.patch = async ctx => {
|
|
34
36
|
const appId = ctx.appId
|
|
35
37
|
const inputs = ctx.request.body
|
|
@@ -55,7 +57,8 @@ exports.save = async ctx => {
|
|
|
55
57
|
exports.fetchView = async ctx => {
|
|
56
58
|
// there are no views in external data sources, shouldn't ever be called
|
|
57
59
|
// for now just fetch
|
|
58
|
-
|
|
60
|
+
const split = ctx.params.viewName.split("all_")
|
|
61
|
+
ctx.params.tableId = split[1] ? split[1] : split[0]
|
|
59
62
|
return exports.fetch(ctx)
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -4,8 +4,8 @@ const CouchDB = require("../../../db")
|
|
|
4
4
|
const { InternalTables } = require("../../../db/utils")
|
|
5
5
|
const userController = require("../user")
|
|
6
6
|
const { FieldTypes } = require("../../../constants")
|
|
7
|
-
const { integrations } = require("../../../integrations")
|
|
8
7
|
const { processStringSync } = require("@budibase/string-templates")
|
|
8
|
+
const { makeExternalQuery } = require("../../../integrations/base/utils")
|
|
9
9
|
|
|
10
10
|
validateJs.extend(validateJs.validators.datetime, {
|
|
11
11
|
parse: function (value) {
|
|
@@ -17,18 +17,11 @@ validateJs.extend(validateJs.validators.datetime, {
|
|
|
17
17
|
},
|
|
18
18
|
})
|
|
19
19
|
|
|
20
|
-
exports.
|
|
20
|
+
exports.getDatasourceAndQuery = async (appId, json) => {
|
|
21
21
|
const datasourceId = json.endpoint.datasourceId
|
|
22
22
|
const db = new CouchDB(appId)
|
|
23
23
|
const datasource = await db.get(datasourceId)
|
|
24
|
-
|
|
25
|
-
// query is the opinionated function
|
|
26
|
-
if (Integration.prototype.query) {
|
|
27
|
-
const integration = new Integration(datasource.config)
|
|
28
|
-
return integration.query(json)
|
|
29
|
-
} else {
|
|
30
|
-
throw "Datasource does not support query."
|
|
31
|
-
}
|
|
24
|
+
return makeExternalQuery(datasource, json)
|
|
32
25
|
}
|
|
33
26
|
|
|
34
27
|
exports.findRow = async (ctx, db, tableId, rowId) => {
|
|
@@ -68,7 +61,11 @@ exports.validate = async ({ appId, tableId, row, table }) => {
|
|
|
68
61
|
let res
|
|
69
62
|
|
|
70
63
|
// Validate.js doesn't seem to handle array
|
|
71
|
-
if (
|
|
64
|
+
if (
|
|
65
|
+
table.schema[fieldName].type === FieldTypes.ARRAY &&
|
|
66
|
+
row[fieldName] &&
|
|
67
|
+
row[fieldName].length
|
|
68
|
+
) {
|
|
72
69
|
row[fieldName].map(val => {
|
|
73
70
|
if (!constraints.inclusion.includes(val)) {
|
|
74
71
|
errors[fieldName] = "Field not in list"
|