@budibase/server 0.9.188 → 0.9.190-alpha.2
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.7d405e74.css +1 -0
- package/builder/assets/index.edea4fa5.js +1316 -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 +1507 -1081
- package/coverage/coverage-final.json +93 -89
- 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 +64 -13
- 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 +232 -28
- 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 +91 -91
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +3 -3
- 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 +53 -209
- package/coverage/lcov-report/api/controllers/role.js.html +9 -9
- package/coverage/lcov-report/api/controllers/routing.js.html +3 -3
- 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 +2 -2
- 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 +545 -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 +1 -1
- 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 +1 -1
- 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 +35 -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 +42 -12
- 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 +1 -1
- 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 +3 -3
- package/coverage/lcov-report/db/utils.js.html +57 -57
- 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 +11 -8
- package/coverage/lcov-report/middleware/builder.js.html +16 -7
- package/coverage/lcov-report/middleware/currentapp.js.html +6 -6
- 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 +1 -1
- 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 +26 -11
- package/coverage/lcov-report/utilities/index.html +48 -48
- package/coverage/lcov-report/utilities/index.js.html +47 -14
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +30 -9
- 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 +1 -1
- 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 +2495 -1737
- package/dist/api/controllers/application.js +15 -1
- 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 +30 -58
- package/dist/api/controllers/row/ExternalRequest.js +78 -34
- 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 +150 -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/table.js +7 -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 +5 -0
- 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 +353 -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 +347 -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 +12 -7
- 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 +13 -8
- package/scripts/dev/manage.js +1 -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 -1
- 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 +29 -81
- package/src/api/controllers/row/ExternalRequest.ts +91 -36
- 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 +155 -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/table.js +11 -0
- 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 +0 -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 +10 -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 +377 -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 +458 -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
|
@@ -7,8 +7,9 @@ const {
|
|
|
7
7
|
BudibaseInternalDB,
|
|
8
8
|
getTableParams,
|
|
9
9
|
} = require("../../db/utils")
|
|
10
|
+
const { BuildSchemaErrors, InvalidColumns } = require("../../constants")
|
|
10
11
|
const { integrations } = require("../../integrations")
|
|
11
|
-
const {
|
|
12
|
+
const { getDatasourceAndQuery } = require("./row/utils")
|
|
12
13
|
|
|
13
14
|
exports.fetch = async function (ctx) {
|
|
14
15
|
const database = new CouchDB(ctx.appId)
|
|
@@ -43,13 +44,17 @@ exports.buildSchemaFromDb = async function (ctx) {
|
|
|
43
44
|
const db = new CouchDB(ctx.appId)
|
|
44
45
|
const datasource = await db.get(ctx.params.datasourceId)
|
|
45
46
|
|
|
46
|
-
const tables = await buildSchemaHelper(datasource)
|
|
47
|
+
const { tables, error } = await buildSchemaHelper(datasource)
|
|
47
48
|
datasource.entities = tables
|
|
48
49
|
|
|
49
|
-
const
|
|
50
|
-
datasource._rev =
|
|
50
|
+
const dbResp = await db.put(datasource)
|
|
51
|
+
datasource._rev = dbResp.rev
|
|
51
52
|
|
|
52
|
-
|
|
53
|
+
const response = { datasource }
|
|
54
|
+
if (error) {
|
|
55
|
+
response.error = error
|
|
56
|
+
}
|
|
57
|
+
ctx.body = response
|
|
53
58
|
}
|
|
54
59
|
|
|
55
60
|
exports.update = async function (ctx) {
|
|
@@ -71,7 +76,7 @@ exports.update = async function (ctx) {
|
|
|
71
76
|
|
|
72
77
|
ctx.status = 200
|
|
73
78
|
ctx.message = "Datasource saved successfully."
|
|
74
|
-
ctx.body = datasource
|
|
79
|
+
ctx.body = { datasource }
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
exports.save = async function (ctx) {
|
|
@@ -85,13 +90,15 @@ exports.save = async function (ctx) {
|
|
|
85
90
|
...ctx.request.body.datasource,
|
|
86
91
|
}
|
|
87
92
|
|
|
93
|
+
let schemaError = null
|
|
88
94
|
if (fetchSchema) {
|
|
89
|
-
|
|
95
|
+
const { tables, error } = await buildSchemaHelper(datasource)
|
|
96
|
+
schemaError = error
|
|
90
97
|
datasource.entities = tables
|
|
91
98
|
}
|
|
92
99
|
|
|
93
|
-
const
|
|
94
|
-
datasource._rev =
|
|
100
|
+
const dbResp = await db.put(datasource)
|
|
101
|
+
datasource._rev = dbResp.rev
|
|
95
102
|
|
|
96
103
|
// Drain connection pools when configuration is changed
|
|
97
104
|
if (datasource.source) {
|
|
@@ -101,17 +108,27 @@ exports.save = async function (ctx) {
|
|
|
101
108
|
}
|
|
102
109
|
}
|
|
103
110
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
111
|
+
const response = { datasource }
|
|
112
|
+
if (schemaError) {
|
|
113
|
+
response.error = schemaError
|
|
114
|
+
}
|
|
115
|
+
ctx.body = response
|
|
107
116
|
}
|
|
108
117
|
|
|
109
118
|
exports.destroy = async function (ctx) {
|
|
110
119
|
const db = new CouchDB(ctx.appId)
|
|
111
120
|
|
|
112
121
|
// Delete all queries for the datasource
|
|
113
|
-
const
|
|
114
|
-
|
|
122
|
+
const queries = await db.allDocs(
|
|
123
|
+
getQueryParams(ctx.params.datasourceId, null)
|
|
124
|
+
)
|
|
125
|
+
await db.bulkDocs(
|
|
126
|
+
queries.rows.map(row => ({
|
|
127
|
+
_id: row.id,
|
|
128
|
+
_rev: row.value.rev,
|
|
129
|
+
_deleted: true,
|
|
130
|
+
}))
|
|
131
|
+
)
|
|
115
132
|
|
|
116
133
|
// delete the datasource
|
|
117
134
|
await db.remove(ctx.params.datasourceId, ctx.params.revId)
|
|
@@ -129,12 +146,29 @@ exports.find = async function (ctx) {
|
|
|
129
146
|
exports.query = async function (ctx) {
|
|
130
147
|
const queryJson = ctx.request.body
|
|
131
148
|
try {
|
|
132
|
-
ctx.body = await
|
|
149
|
+
ctx.body = await getDatasourceAndQuery(ctx.appId, queryJson)
|
|
133
150
|
} catch (err) {
|
|
134
151
|
ctx.throw(400, err)
|
|
135
152
|
}
|
|
136
153
|
}
|
|
137
154
|
|
|
155
|
+
function getErrorTables(errors, errorType) {
|
|
156
|
+
return Object.entries(errors)
|
|
157
|
+
.filter(entry => entry[1] === errorType)
|
|
158
|
+
.map(([name]) => name)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function updateError(error, newError, tables) {
|
|
162
|
+
if (!error) {
|
|
163
|
+
error = ""
|
|
164
|
+
}
|
|
165
|
+
if (error.length > 0) {
|
|
166
|
+
error += "\n"
|
|
167
|
+
}
|
|
168
|
+
error += `${newError} ${tables.join(", ")}`
|
|
169
|
+
return error
|
|
170
|
+
}
|
|
171
|
+
|
|
138
172
|
const buildSchemaHelper = async datasource => {
|
|
139
173
|
const Connector = integrations[datasource.source]
|
|
140
174
|
|
|
@@ -143,5 +177,39 @@ const buildSchemaHelper = async datasource => {
|
|
|
143
177
|
await connector.buildSchema(datasource._id, datasource.entities)
|
|
144
178
|
datasource.entities = connector.tables
|
|
145
179
|
|
|
146
|
-
|
|
180
|
+
// make sure they all have a display name selected
|
|
181
|
+
for (let entity of Object.values(datasource.entities)) {
|
|
182
|
+
if (entity.primaryDisplay) {
|
|
183
|
+
continue
|
|
184
|
+
}
|
|
185
|
+
const notAutoColumn = Object.values(entity.schema).find(
|
|
186
|
+
schema => !schema.autocolumn
|
|
187
|
+
)
|
|
188
|
+
if (notAutoColumn) {
|
|
189
|
+
entity.primaryDisplay = notAutoColumn.name
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const errors = connector.schemaErrors
|
|
194
|
+
let error = null
|
|
195
|
+
if (errors && Object.keys(errors).length > 0) {
|
|
196
|
+
const noKey = getErrorTables(errors, BuildSchemaErrors.NO_KEY)
|
|
197
|
+
const invalidCol = getErrorTables(errors, BuildSchemaErrors.INVALID_COLUMN)
|
|
198
|
+
if (noKey.length) {
|
|
199
|
+
error = updateError(
|
|
200
|
+
error,
|
|
201
|
+
"No primary key constraint found for the following:",
|
|
202
|
+
noKey
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
if (invalidCol.length) {
|
|
206
|
+
const invalidCols = Object.values(InvalidColumns).join(", ")
|
|
207
|
+
error = updateError(
|
|
208
|
+
error,
|
|
209
|
+
`Cannot use columns ${invalidCols} found in following:`,
|
|
210
|
+
invalidCol
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return { tables: connector.tables, error }
|
|
147
215
|
}
|
|
@@ -6,6 +6,7 @@ const {
|
|
|
6
6
|
disableAllCrons,
|
|
7
7
|
enableCronTrigger,
|
|
8
8
|
} = require("../../../automations/utils")
|
|
9
|
+
const { app: appCache } = require("@budibase/auth/cache")
|
|
9
10
|
|
|
10
11
|
// the max time we can wait for an invalidation to complete before considering it failed
|
|
11
12
|
const MAX_PENDING_TIME_MS = 30 * 60000
|
|
@@ -103,6 +104,7 @@ async function deployApp(deployment) {
|
|
|
103
104
|
appDoc.appId = productionAppId
|
|
104
105
|
appDoc.instance._id = productionAppId
|
|
105
106
|
await db.put(appDoc)
|
|
107
|
+
await appCache.invalidateAppMetadata(productionAppId)
|
|
106
108
|
console.log("New app doc written successfully.")
|
|
107
109
|
await initDeployedApp(productionAppId)
|
|
108
110
|
console.log("Deployed app initialised, setting deployment to successful")
|
|
@@ -6,6 +6,7 @@ const { request } = require("../../utilities/workerRequests")
|
|
|
6
6
|
const { clearLock } = require("../../utilities/redis")
|
|
7
7
|
const { Replication } = require("@budibase/auth").db
|
|
8
8
|
const { DocumentTypes } = require("../../db/utils")
|
|
9
|
+
const { app: appCache } = require("@budibase/auth/cache")
|
|
9
10
|
|
|
10
11
|
async function redirect(ctx, method, path = "global") {
|
|
11
12
|
const { devPath } = ctx.params
|
|
@@ -24,7 +25,8 @@ async function redirect(ctx, method, path = "global") {
|
|
|
24
25
|
)
|
|
25
26
|
)
|
|
26
27
|
if (response.status !== 200) {
|
|
27
|
-
|
|
28
|
+
const err = await response.text()
|
|
29
|
+
ctx.throw(400, err)
|
|
28
30
|
}
|
|
29
31
|
const cookie = response.headers.get("set-cookie")
|
|
30
32
|
if (cookie) {
|
|
@@ -106,6 +108,7 @@ exports.revert = async ctx => {
|
|
|
106
108
|
appDoc.appId = appId
|
|
107
109
|
appDoc.instance._id = appId
|
|
108
110
|
await db.put(appDoc)
|
|
111
|
+
await appCache.invalidateAppMetadata(appId)
|
|
109
112
|
ctx.body = {
|
|
110
113
|
message: "Reverted changes successfully.",
|
|
111
114
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
const { processString } = require("@budibase/string-templates")
|
|
2
2
|
const CouchDB = require("../../db")
|
|
3
3
|
const { generateQueryID, getQueryParams } = require("../../db/utils")
|
|
4
|
-
const { integrations } = require("../../integrations")
|
|
5
4
|
const { BaseQueryVerbs } = require("../../constants")
|
|
6
5
|
const env = require("../../environment")
|
|
7
|
-
const
|
|
6
|
+
const { Thread, ThreadType } = require("../../threads")
|
|
7
|
+
|
|
8
|
+
const Runner = new Thread(ThreadType.QUERY, { timeoutMs: 10000 })
|
|
8
9
|
|
|
9
10
|
// simple function to append "readable" to all read queries
|
|
10
11
|
function enrichQueries(input) {
|
|
@@ -18,47 +19,6 @@ function enrichQueries(input) {
|
|
|
18
19
|
return wasArray ? queries : queries[0]
|
|
19
20
|
}
|
|
20
21
|
|
|
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
22
|
exports.fetch = async function (ctx) {
|
|
63
23
|
const db = new CouchDB(ctx.appId)
|
|
64
24
|
|
|
@@ -98,7 +58,9 @@ async function enrichQueryFields(fields, parameters = {}) {
|
|
|
98
58
|
enrichedQuery[key] = await enrichQueryFields(fields[key], parameters)
|
|
99
59
|
} else if (typeof fields[key] === "string") {
|
|
100
60
|
// enrich string value as normal
|
|
101
|
-
enrichedQuery[key] = await processString(fields[key], parameters
|
|
61
|
+
enrichedQuery[key] = await processString(fields[key], parameters, {
|
|
62
|
+
noHelpers: true,
|
|
63
|
+
})
|
|
102
64
|
} else {
|
|
103
65
|
enrichedQuery[key] = fields[key]
|
|
104
66
|
}
|
|
@@ -141,30 +103,23 @@ exports.preview = async function (ctx) {
|
|
|
141
103
|
|
|
142
104
|
const datasource = await db.get(ctx.request.body.datasourceId)
|
|
143
105
|
|
|
144
|
-
const Integration = integrations[datasource.source]
|
|
145
|
-
|
|
146
|
-
if (!Integration) {
|
|
147
|
-
ctx.throw(400, "Integration type does not exist.")
|
|
148
|
-
}
|
|
149
|
-
|
|
150
106
|
const { fields, parameters, queryVerb, transformer } = ctx.request.body
|
|
151
107
|
const enrichedQuery = await enrichQueryFields(fields, parameters)
|
|
152
|
-
const integration = new Integration(datasource.config)
|
|
153
108
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
109
|
+
try {
|
|
110
|
+
const { rows, keys } = await Runner.run({
|
|
111
|
+
datasource,
|
|
112
|
+
queryVerb,
|
|
113
|
+
query: enrichedQuery,
|
|
114
|
+
transformer,
|
|
115
|
+
})
|
|
160
116
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
integration.end()
|
|
117
|
+
ctx.body = {
|
|
118
|
+
rows,
|
|
119
|
+
schemaFields: [...new Set(keys)],
|
|
120
|
+
}
|
|
121
|
+
} catch (err) {
|
|
122
|
+
ctx.throw(400, err)
|
|
168
123
|
}
|
|
169
124
|
}
|
|
170
125
|
|
|
@@ -174,29 +129,22 @@ exports.execute = async function (ctx) {
|
|
|
174
129
|
const query = await db.get(ctx.params.queryId)
|
|
175
130
|
const datasource = await db.get(query.datasourceId)
|
|
176
131
|
|
|
177
|
-
const Integration = integrations[datasource.source]
|
|
178
|
-
|
|
179
|
-
if (!Integration) {
|
|
180
|
-
ctx.throw(400, "Integration type does not exist.")
|
|
181
|
-
}
|
|
182
|
-
|
|
183
132
|
const enrichedQuery = await enrichQueryFields(
|
|
184
133
|
query.fields,
|
|
185
134
|
ctx.request.body.parameters
|
|
186
135
|
)
|
|
187
|
-
const integration = new Integration(datasource.config)
|
|
188
136
|
|
|
189
137
|
// call the relevant CRUD method on the integration class
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
138
|
+
try {
|
|
139
|
+
const { rows } = await Runner.run({
|
|
140
|
+
datasource,
|
|
141
|
+
queryVerb: query.queryVerb,
|
|
142
|
+
query: enrichedQuery,
|
|
143
|
+
transformer: query.transformer,
|
|
144
|
+
})
|
|
145
|
+
ctx.body = rows
|
|
146
|
+
} catch (err) {
|
|
147
|
+
ctx.throw(400, err)
|
|
200
148
|
}
|
|
201
149
|
}
|
|
202
150
|
|
|
@@ -33,10 +33,11 @@ interface RunConfig {
|
|
|
33
33
|
sort?: SortJson
|
|
34
34
|
paginate?: PaginationJson
|
|
35
35
|
row?: Row
|
|
36
|
+
rows?: Row[]
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
module External {
|
|
39
|
-
const {
|
|
40
|
+
const { getDatasourceAndQuery } = require("./utils")
|
|
40
41
|
const {
|
|
41
42
|
DataSourceOperation,
|
|
42
43
|
FieldTypes,
|
|
@@ -46,6 +47,7 @@ module External {
|
|
|
46
47
|
const { processObjectSync } = require("@budibase/string-templates")
|
|
47
48
|
const { cloneDeep } = require("lodash/fp")
|
|
48
49
|
const CouchDB = require("../../../db")
|
|
50
|
+
const { processFormulas } = require("../../../utilities/rowProcessor/utils")
|
|
49
51
|
|
|
50
52
|
function buildFilters(
|
|
51
53
|
id: string | undefined,
|
|
@@ -162,8 +164,8 @@ module External {
|
|
|
162
164
|
}
|
|
163
165
|
}
|
|
164
166
|
|
|
165
|
-
function basicProcessing(row: Row, table: Table) {
|
|
166
|
-
const thisRow:
|
|
167
|
+
function basicProcessing(row: Row, table: Table): Row {
|
|
168
|
+
const thisRow: Row = {}
|
|
167
169
|
// filter the row down to what is actually the row (not joined)
|
|
168
170
|
for (let fieldName of Object.keys(table.schema)) {
|
|
169
171
|
const value = row[`${table.name}.${fieldName}`] || row[fieldName]
|
|
@@ -178,9 +180,26 @@ module External {
|
|
|
178
180
|
return thisRow
|
|
179
181
|
}
|
|
180
182
|
|
|
181
|
-
function
|
|
183
|
+
function fixArrayTypes(row: Row, table: Table) {
|
|
184
|
+
for (let [fieldName, schema] of Object.entries(table.schema)) {
|
|
185
|
+
if (
|
|
186
|
+
schema.type === FieldTypes.ARRAY &&
|
|
187
|
+
typeof row[fieldName] === "string"
|
|
188
|
+
) {
|
|
189
|
+
try {
|
|
190
|
+
row[fieldName] = JSON.parse(row[fieldName])
|
|
191
|
+
} catch (err) {
|
|
192
|
+
// couldn't convert back to array, ignore
|
|
193
|
+
delete row[fieldName]
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return row
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function isOneSide(field: FieldSchema) {
|
|
182
201
|
return (
|
|
183
|
-
field.relationshipType && field.relationshipType.split("-")[0] === "
|
|
202
|
+
field.relationshipType && field.relationshipType.split("-")[0] === "one"
|
|
184
203
|
)
|
|
185
204
|
}
|
|
186
205
|
|
|
@@ -225,7 +244,12 @@ module External {
|
|
|
225
244
|
manyRelationships: ManyRelationship[] = []
|
|
226
245
|
for (let [key, field] of Object.entries(table.schema)) {
|
|
227
246
|
// if set already, or not set just skip it
|
|
228
|
-
if (
|
|
247
|
+
if (
|
|
248
|
+
row[key] == null ||
|
|
249
|
+
newRow[key] ||
|
|
250
|
+
field.autocolumn ||
|
|
251
|
+
field.type === FieldTypes.FORMULA
|
|
252
|
+
) {
|
|
229
253
|
continue
|
|
230
254
|
}
|
|
231
255
|
// if its an empty string then it means return the column to null (if possible)
|
|
@@ -250,25 +274,37 @@ module External {
|
|
|
250
274
|
const linkTable = this.tables[linkTableName]
|
|
251
275
|
// @ts-ignore
|
|
252
276
|
const linkTablePrimary = linkTable.primary[0]
|
|
253
|
-
|
|
277
|
+
// one to many
|
|
278
|
+
if (isOneSide(field)) {
|
|
254
279
|
newRow[field.foreignKey || linkTablePrimary] = breakRowIdField(
|
|
255
280
|
row[key][0]
|
|
256
281
|
)[0]
|
|
257
|
-
}
|
|
282
|
+
}
|
|
283
|
+
// many to many
|
|
284
|
+
else if (field.through) {
|
|
258
285
|
// 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
|
|
286
|
+
const otherKey: string = field.throughFrom || linkTablePrimary
|
|
287
|
+
const thisKey: string = field.throughTo || tablePrimary
|
|
267
288
|
row[key].map((relationship: any) => {
|
|
268
|
-
// we don't really support composite keys for relationships, this is why [0] is used
|
|
269
289
|
manyRelationships.push({
|
|
270
290
|
tableId: field.through || field.tableId,
|
|
271
|
-
isUpdate,
|
|
291
|
+
isUpdate: false,
|
|
292
|
+
key: otherKey,
|
|
293
|
+
[otherKey]: breakRowIdField(relationship)[0],
|
|
294
|
+
// leave the ID for enrichment later
|
|
295
|
+
[thisKey]: `{{ literal ${tablePrimary} }}`,
|
|
296
|
+
})
|
|
297
|
+
})
|
|
298
|
+
}
|
|
299
|
+
// many to one
|
|
300
|
+
else {
|
|
301
|
+
const thisKey: string = "id"
|
|
302
|
+
// @ts-ignore
|
|
303
|
+
const otherKey: string = field.fieldName
|
|
304
|
+
row[key].map((relationship: any) => {
|
|
305
|
+
manyRelationships.push({
|
|
306
|
+
tableId: field.tableId,
|
|
307
|
+
isUpdate: true,
|
|
272
308
|
key: otherKey,
|
|
273
309
|
[thisKey]: breakRowIdField(relationship)[0],
|
|
274
310
|
// leave the ID for enrichment later
|
|
@@ -336,7 +372,7 @@ module External {
|
|
|
336
372
|
table: Table,
|
|
337
373
|
relationships: RelationshipsJson[]
|
|
338
374
|
) {
|
|
339
|
-
if (rows[0].read === true) {
|
|
375
|
+
if (!rows || rows.length === 0 || rows[0].read === true) {
|
|
340
376
|
return []
|
|
341
377
|
}
|
|
342
378
|
let finalRows: { [key: string]: Row } = {}
|
|
@@ -352,7 +388,10 @@ module External {
|
|
|
352
388
|
)
|
|
353
389
|
continue
|
|
354
390
|
}
|
|
355
|
-
const thisRow = basicProcessing(row, table)
|
|
391
|
+
const thisRow = fixArrayTypes(basicProcessing(row, table), table)
|
|
392
|
+
if (thisRow._id == null) {
|
|
393
|
+
throw "Unable to generate row ID for SQL rows"
|
|
394
|
+
}
|
|
356
395
|
finalRows[thisRow._id] = thisRow
|
|
357
396
|
// do this at end once its been added to the final rows
|
|
358
397
|
finalRows = this.updateRelationshipColumns(
|
|
@@ -361,7 +400,7 @@ module External {
|
|
|
361
400
|
relationships
|
|
362
401
|
)
|
|
363
402
|
}
|
|
364
|
-
return Object.values(finalRows)
|
|
403
|
+
return processFormulas(table, Object.values(finalRows))
|
|
365
404
|
}
|
|
366
405
|
|
|
367
406
|
/**
|
|
@@ -398,8 +437,8 @@ module External {
|
|
|
398
437
|
)
|
|
399
438
|
definition.through = throughTableName
|
|
400
439
|
// don't support composite keys for relationships
|
|
401
|
-
definition.from = field.
|
|
402
|
-
definition.to = field.
|
|
440
|
+
definition.from = field.throughTo || table.primary[0]
|
|
441
|
+
definition.to = field.throughFrom || linkTable.primary[0]
|
|
403
442
|
definition.fromPrimary = table.primary[0]
|
|
404
443
|
definition.toPrimary = linkTable.primary[0]
|
|
405
444
|
}
|
|
@@ -421,24 +460,36 @@ module External {
|
|
|
421
460
|
// make a new request to get the row with all its relationships
|
|
422
461
|
// we need this to work out if any relationships need removed
|
|
423
462
|
for (let field of Object.values(table.schema)) {
|
|
424
|
-
if (
|
|
463
|
+
if (
|
|
464
|
+
field.type !== FieldTypes.LINK ||
|
|
465
|
+
!field.fieldName ||
|
|
466
|
+
isOneSide(field)
|
|
467
|
+
) {
|
|
425
468
|
continue
|
|
426
469
|
}
|
|
427
470
|
const isMany = field.relationshipType === RelationshipTypes.MANY_TO_MANY
|
|
428
471
|
const tableId = isMany ? field.through : field.tableId
|
|
429
|
-
const
|
|
472
|
+
const { tableName: relatedTableName } = breakExternalTableId(tableId)
|
|
473
|
+
// @ts-ignore
|
|
474
|
+
const linkPrimaryKey = this.tables[relatedTableName].primary[0]
|
|
475
|
+
const manyKey = field.throughTo || primaryKey
|
|
476
|
+
const lookupField = isMany ? primaryKey : field.foreignKey
|
|
430
477
|
const fieldName = isMany ? manyKey : field.fieldName
|
|
431
|
-
|
|
478
|
+
if (!lookupField || !row[lookupField]) {
|
|
479
|
+
continue
|
|
480
|
+
}
|
|
481
|
+
const response = await getDatasourceAndQuery(this.appId, {
|
|
432
482
|
endpoint: getEndpoint(tableId, DataSourceOperation.READ),
|
|
433
483
|
filters: {
|
|
434
484
|
equal: {
|
|
435
|
-
[fieldName]: row[
|
|
485
|
+
[fieldName]: row[lookupField],
|
|
436
486
|
},
|
|
437
487
|
},
|
|
438
488
|
})
|
|
439
489
|
// this is the response from knex if no rows found
|
|
440
490
|
const rows = !response[0].read ? response : []
|
|
441
|
-
|
|
491
|
+
const storeTo = isMany ? field.throughFrom || linkPrimaryKey : manyKey
|
|
492
|
+
related[storeTo] = { rows, isMany, tableId }
|
|
442
493
|
}
|
|
443
494
|
return related
|
|
444
495
|
}
|
|
@@ -479,7 +530,7 @@ module External {
|
|
|
479
530
|
: DataSourceOperation.CREATE
|
|
480
531
|
if (!found) {
|
|
481
532
|
promises.push(
|
|
482
|
-
|
|
533
|
+
getDatasourceAndQuery(appId, {
|
|
483
534
|
endpoint: getEndpoint(tableId, operation),
|
|
484
535
|
// if we're doing many relationships then we're writing, only one response
|
|
485
536
|
body,
|
|
@@ -509,7 +560,7 @@ module External {
|
|
|
509
560
|
: DataSourceOperation.UPDATE
|
|
510
561
|
const body = isMany ? null : { [colName]: null }
|
|
511
562
|
promises.push(
|
|
512
|
-
|
|
563
|
+
getDatasourceAndQuery(this.appId, {
|
|
513
564
|
endpoint: getEndpoint(tableId, op),
|
|
514
565
|
body,
|
|
515
566
|
filters,
|
|
@@ -532,16 +583,17 @@ module External {
|
|
|
532
583
|
table: Table,
|
|
533
584
|
includeRelations: IncludeRelationships = IncludeRelationships.INCLUDE
|
|
534
585
|
) {
|
|
535
|
-
function
|
|
586
|
+
function extractRealFields(table: Table, existing: string[] = []) {
|
|
536
587
|
return Object.entries(table.schema)
|
|
537
588
|
.filter(
|
|
538
589
|
column =>
|
|
539
590
|
column[1].type !== FieldTypes.LINK &&
|
|
591
|
+
column[1].type !== FieldTypes.FORMULA &&
|
|
540
592
|
!existing.find((field: string) => field === column[0])
|
|
541
593
|
)
|
|
542
594
|
.map(column => `${table.name}.${column[0]}`)
|
|
543
595
|
}
|
|
544
|
-
let fields =
|
|
596
|
+
let fields = extractRealFields(table)
|
|
545
597
|
for (let field of Object.values(table.schema)) {
|
|
546
598
|
if (field.type !== FieldTypes.LINK || !includeRelations) {
|
|
547
599
|
continue
|
|
@@ -549,7 +601,7 @@ module External {
|
|
|
549
601
|
const { tableName: linkTableName } = breakExternalTableId(field.tableId)
|
|
550
602
|
const linkTable = this.tables[linkTableName]
|
|
551
603
|
if (linkTable) {
|
|
552
|
-
const linkedFields =
|
|
604
|
+
const linkedFields = extractRealFields(linkTable, fields)
|
|
553
605
|
fields = fields.concat(linkedFields)
|
|
554
606
|
}
|
|
555
607
|
}
|
|
@@ -573,7 +625,10 @@ module External {
|
|
|
573
625
|
throw `Unable to process query, table "${tableName}" not defined.`
|
|
574
626
|
}
|
|
575
627
|
// look for specific components of config which may not be considered acceptable
|
|
576
|
-
let { id, row, filters, sort, paginate } = cleanupConfig(
|
|
628
|
+
let { id, row, filters, sort, paginate, rows } = cleanupConfig(
|
|
629
|
+
config,
|
|
630
|
+
table
|
|
631
|
+
)
|
|
577
632
|
filters = buildFilters(id, filters || {}, table)
|
|
578
633
|
const relationships = this.buildRelationships(table)
|
|
579
634
|
// clean up row on ingress using schema
|
|
@@ -599,7 +654,7 @@ module External {
|
|
|
599
654
|
sort,
|
|
600
655
|
paginate,
|
|
601
656
|
relationships,
|
|
602
|
-
body: row,
|
|
657
|
+
body: row || rows,
|
|
603
658
|
// pass an id filter into extra, purely for mysql/returning
|
|
604
659
|
extra: {
|
|
605
660
|
idFilter: buildFilters(id || generateIdForRow(row, table), {}, table),
|
|
@@ -609,7 +664,7 @@ module External {
|
|
|
609
664
|
},
|
|
610
665
|
}
|
|
611
666
|
// can't really use response right now
|
|
612
|
-
const response = await
|
|
667
|
+
const response = await getDatasourceAndQuery(appId, json)
|
|
613
668
|
// handle many to many relationships now if we know the ID (could be auto increment)
|
|
614
669
|
if (
|
|
615
670
|
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
|
|