@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
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
const CouchDB = require("../../../db")
|
|
2
|
+
const linkRows = require("../../../db/linkedRows")
|
|
3
|
+
const { getRowParams, generateTableID } = require("../../../db/utils")
|
|
4
|
+
const { FieldTypes } = require("../../../constants")
|
|
5
|
+
const {
|
|
6
|
+
TableSaveFunctions,
|
|
7
|
+
hasTypeChanged,
|
|
8
|
+
getTable,
|
|
9
|
+
handleDataImport,
|
|
10
|
+
} = require("./utils")
|
|
11
|
+
|
|
12
|
+
exports.save = async function (ctx) {
|
|
13
|
+
const appId = ctx.appId
|
|
14
|
+
const db = new CouchDB(appId)
|
|
15
|
+
const { dataImport, ...rest } = ctx.request.body
|
|
16
|
+
let tableToSave = {
|
|
17
|
+
type: "table",
|
|
18
|
+
_id: generateTableID(),
|
|
19
|
+
views: {},
|
|
20
|
+
...rest,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// if the table obj had an _id then it will have been retrieved
|
|
24
|
+
let oldTable
|
|
25
|
+
if (ctx.request.body && ctx.request.body._id) {
|
|
26
|
+
oldTable = await db.get(ctx.request.body._id)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (hasTypeChanged(tableToSave, oldTable)) {
|
|
30
|
+
ctx.throw(400, "A column type has changed.")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// saving a table is a complex operation, involving many different steps, this
|
|
34
|
+
// has been broken out into a utility to make it more obvious/easier to manipulate
|
|
35
|
+
const tableSaveFunctions = new TableSaveFunctions({
|
|
36
|
+
db,
|
|
37
|
+
ctx,
|
|
38
|
+
oldTable,
|
|
39
|
+
dataImport,
|
|
40
|
+
})
|
|
41
|
+
tableToSave = await tableSaveFunctions.before(tableToSave)
|
|
42
|
+
|
|
43
|
+
// make sure that types don't change of a column, have to remove
|
|
44
|
+
// the column if you want to change the type
|
|
45
|
+
if (oldTable && oldTable.schema) {
|
|
46
|
+
for (let propKey of Object.keys(tableToSave.schema)) {
|
|
47
|
+
let column = tableToSave.schema[propKey]
|
|
48
|
+
let oldColumn = oldTable.schema[propKey]
|
|
49
|
+
if (oldColumn && oldColumn.type === "internal") {
|
|
50
|
+
oldColumn.type = "auto"
|
|
51
|
+
}
|
|
52
|
+
if (oldColumn && oldColumn.type !== column.type) {
|
|
53
|
+
ctx.throw(400, "Cannot change the type of a column")
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Don't rename if the name is the same
|
|
59
|
+
let { _rename } = tableToSave
|
|
60
|
+
/* istanbul ignore next */
|
|
61
|
+
if (_rename && _rename.old === _rename.updated) {
|
|
62
|
+
_rename = null
|
|
63
|
+
delete tableToSave._rename
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// rename row fields when table column is renamed
|
|
67
|
+
/* istanbul ignore next */
|
|
68
|
+
if (_rename && tableToSave.schema[_rename.updated].type === FieldTypes.LINK) {
|
|
69
|
+
ctx.throw(400, "Cannot rename a linked column.")
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
tableToSave = await tableSaveFunctions.mid(tableToSave)
|
|
73
|
+
|
|
74
|
+
// update schema of non-statistics views when new columns are added
|
|
75
|
+
for (let view in tableToSave.views) {
|
|
76
|
+
const tableView = tableToSave.views[view]
|
|
77
|
+
if (!tableView) continue
|
|
78
|
+
|
|
79
|
+
if (tableView.schema.group || tableView.schema.field) continue
|
|
80
|
+
tableView.schema = tableToSave.schema
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// update linked rows
|
|
84
|
+
try {
|
|
85
|
+
const linkResp = await linkRows.updateLinks({
|
|
86
|
+
appId,
|
|
87
|
+
eventType: oldTable
|
|
88
|
+
? linkRows.EventType.TABLE_UPDATED
|
|
89
|
+
: linkRows.EventType.TABLE_SAVE,
|
|
90
|
+
table: tableToSave,
|
|
91
|
+
oldTable: oldTable,
|
|
92
|
+
})
|
|
93
|
+
if (linkResp != null && linkResp._rev) {
|
|
94
|
+
tableToSave._rev = linkResp._rev
|
|
95
|
+
}
|
|
96
|
+
} catch (err) {
|
|
97
|
+
ctx.throw(400, err)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// don't perform any updates until relationships have been
|
|
101
|
+
// checked by the updateLinks function
|
|
102
|
+
const updatedRows = tableSaveFunctions.getUpdatedRows()
|
|
103
|
+
if (updatedRows && updatedRows.length !== 0) {
|
|
104
|
+
await db.bulkDocs(updatedRows)
|
|
105
|
+
}
|
|
106
|
+
const result = await db.put(tableToSave)
|
|
107
|
+
tableToSave._rev = result.rev
|
|
108
|
+
|
|
109
|
+
tableToSave = await tableSaveFunctions.after(tableToSave)
|
|
110
|
+
|
|
111
|
+
return tableToSave
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
exports.destroy = async function (ctx) {
|
|
115
|
+
const appId = ctx.appId
|
|
116
|
+
const db = new CouchDB(appId)
|
|
117
|
+
const tableToDelete = await db.get(ctx.params.tableId)
|
|
118
|
+
|
|
119
|
+
// Delete all rows for that table
|
|
120
|
+
const rows = await db.allDocs(
|
|
121
|
+
getRowParams(ctx.params.tableId, null, {
|
|
122
|
+
include_docs: true,
|
|
123
|
+
})
|
|
124
|
+
)
|
|
125
|
+
await db.bulkDocs(rows.rows.map(row => ({ ...row.doc, _deleted: true })))
|
|
126
|
+
|
|
127
|
+
// update linked rows
|
|
128
|
+
await linkRows.updateLinks({
|
|
129
|
+
appId,
|
|
130
|
+
eventType: linkRows.EventType.TABLE_DELETE,
|
|
131
|
+
table: tableToDelete,
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
// don't remove the table itself until very end
|
|
135
|
+
await db.remove(tableToDelete)
|
|
136
|
+
|
|
137
|
+
// remove table search index
|
|
138
|
+
const currentIndexes = await db.getIndexes()
|
|
139
|
+
const existingIndex = currentIndexes.indexes.find(
|
|
140
|
+
existing => existing.name === `search:${ctx.params.tableId}`
|
|
141
|
+
)
|
|
142
|
+
if (existingIndex) {
|
|
143
|
+
await db.deleteIndex(existingIndex)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return tableToDelete
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
exports.bulkImport = async function (ctx) {
|
|
150
|
+
const appId = ctx.appId
|
|
151
|
+
const table = await getTable(appId, ctx.params.tableId)
|
|
152
|
+
const { dataImport } = ctx.request.body
|
|
153
|
+
await handleDataImport(appId, ctx.user, table, dataImport)
|
|
154
|
+
return table
|
|
155
|
+
}
|
|
@@ -8,7 +8,7 @@ const {
|
|
|
8
8
|
const { isEqual } = require("lodash/fp")
|
|
9
9
|
const { AutoFieldSubTypes, FieldTypes } = require("../../../constants")
|
|
10
10
|
const { inputProcessing } = require("../../../utilities/rowProcessor")
|
|
11
|
-
const { USERS_TABLE_SCHEMA } = require("../../../constants")
|
|
11
|
+
const { USERS_TABLE_SCHEMA, SwitchableTypes } = require("../../../constants")
|
|
12
12
|
const {
|
|
13
13
|
isExternalTable,
|
|
14
14
|
breakExternalTableId,
|
|
@@ -72,43 +72,47 @@ exports.makeSureTableUpToDate = (table, tableToSave) => {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
exports.handleDataImport = async (appId, user, table, dataImport) => {
|
|
75
|
+
if (!dataImport || !dataImport.csvString) {
|
|
76
|
+
return table
|
|
77
|
+
}
|
|
75
78
|
const db = new CouchDB(appId)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// check whether the options need to be updated for inclusion as part of the data import
|
|
93
|
-
if (
|
|
94
|
-
schema.type === FieldTypes.OPTIONS &&
|
|
95
|
-
(!schema.constraints.inclusion ||
|
|
96
|
-
schema.constraints.inclusion.indexOf(row[fieldName]) === -1)
|
|
97
|
-
) {
|
|
98
|
-
schema.constraints.inclusion = [
|
|
99
|
-
...schema.constraints.inclusion,
|
|
100
|
-
row[fieldName],
|
|
101
|
-
]
|
|
102
|
-
}
|
|
103
|
-
}
|
|
79
|
+
// Populate the table with rows imported from CSV in a bulk update
|
|
80
|
+
const data = await csvParser.transform({
|
|
81
|
+
...dataImport,
|
|
82
|
+
existingTable: table,
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
let finalData = []
|
|
86
|
+
for (let i = 0; i < data.length; i++) {
|
|
87
|
+
let row = data[i]
|
|
88
|
+
row._id = generateRowID(table._id)
|
|
89
|
+
row.tableId = table._id
|
|
90
|
+
const processed = inputProcessing(user, table, row, {
|
|
91
|
+
noAutoRelationships: true,
|
|
92
|
+
})
|
|
93
|
+
table = processed.table
|
|
94
|
+
row = processed.row
|
|
104
95
|
|
|
105
|
-
|
|
96
|
+
for (let [fieldName, schema] of Object.entries(table.schema)) {
|
|
97
|
+
// check whether the options need to be updated for inclusion as part of the data import
|
|
98
|
+
if (
|
|
99
|
+
schema.type === FieldTypes.OPTIONS &&
|
|
100
|
+
(!schema.constraints.inclusion ||
|
|
101
|
+
schema.constraints.inclusion.indexOf(row[fieldName]) === -1)
|
|
102
|
+
) {
|
|
103
|
+
schema.constraints.inclusion = [
|
|
104
|
+
...schema.constraints.inclusion,
|
|
105
|
+
row[fieldName],
|
|
106
|
+
]
|
|
107
|
+
}
|
|
106
108
|
}
|
|
107
109
|
|
|
108
|
-
|
|
109
|
-
let response = await db.put(table)
|
|
110
|
-
table._rev = response._rev
|
|
110
|
+
finalData.push(row)
|
|
111
111
|
}
|
|
112
|
+
|
|
113
|
+
await db.bulkDocs(finalData)
|
|
114
|
+
let response = await db.put(table)
|
|
115
|
+
table._rev = response._rev
|
|
112
116
|
return table
|
|
113
117
|
}
|
|
114
118
|
|
|
@@ -315,4 +319,41 @@ exports.checkForViewUpdates = async (db, table, rename, deletedColumns) => {
|
|
|
315
319
|
}
|
|
316
320
|
}
|
|
317
321
|
|
|
322
|
+
exports.generateForeignKey = (column, relatedTable) => {
|
|
323
|
+
return `fk_${relatedTable.name}_${column.fieldName}`
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
exports.generateJunctionTableName = (column, table, relatedTable) => {
|
|
327
|
+
return `jt_${table.name}_${relatedTable.name}_${column.name}_${column.fieldName}`
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
exports.foreignKeyStructure = (keyName, meta = null) => {
|
|
331
|
+
const structure = {
|
|
332
|
+
type: FieldTypes.NUMBER,
|
|
333
|
+
constraints: {},
|
|
334
|
+
name: keyName,
|
|
335
|
+
}
|
|
336
|
+
if (meta) {
|
|
337
|
+
structure.meta = meta
|
|
338
|
+
}
|
|
339
|
+
return structure
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
exports.hasTypeChanged = (table, oldTable) => {
|
|
343
|
+
if (!oldTable) {
|
|
344
|
+
return false
|
|
345
|
+
}
|
|
346
|
+
for (let [key, field] of Object.entries(oldTable.schema)) {
|
|
347
|
+
const oldType = field.type
|
|
348
|
+
if (!table.schema[key]) {
|
|
349
|
+
continue
|
|
350
|
+
}
|
|
351
|
+
const newType = table.schema[key].type
|
|
352
|
+
if (oldType !== newType && SwitchableTypes.indexOf(oldType) === -1) {
|
|
353
|
+
return true
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return false
|
|
357
|
+
}
|
|
358
|
+
|
|
318
359
|
exports.TableSaveFunctions = TableSaveFunctions
|
|
@@ -4,27 +4,144 @@ const {
|
|
|
4
4
|
getUserMetadataParams,
|
|
5
5
|
} = require("../../db/utils")
|
|
6
6
|
const { InternalTables } = require("../../db/utils")
|
|
7
|
-
const { getGlobalUsers } = require("../../utilities/global")
|
|
7
|
+
const { getGlobalUsers, getRawGlobalUser } = require("../../utilities/global")
|
|
8
8
|
const { getFullUser } = require("../../utilities/users")
|
|
9
|
+
const { isEqual } = require("lodash")
|
|
10
|
+
const { BUILTIN_ROLE_IDS } = require("@budibase/auth/roles")
|
|
11
|
+
const { getDevelopmentAppID, getDeployedAppIDs } = require("@budibase/auth/db")
|
|
12
|
+
const { doesDatabaseExist } = require("../../utilities")
|
|
13
|
+
const { UserStatus } = require("@budibase/auth/constants")
|
|
9
14
|
|
|
10
|
-
function
|
|
11
|
-
|
|
15
|
+
async function rawMetadata(db) {
|
|
16
|
+
return (
|
|
17
|
+
await db.allDocs(
|
|
18
|
+
getUserMetadataParams(null, {
|
|
19
|
+
include_docs: true,
|
|
20
|
+
})
|
|
21
|
+
)
|
|
22
|
+
).rows.map(row => row.doc)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function combineMetadataAndUser(user, metadata) {
|
|
26
|
+
// skip users with no access
|
|
27
|
+
if (user.roleId === BUILTIN_ROLE_IDS.PUBLIC) {
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
delete user._rev
|
|
31
|
+
const metadataId = generateUserMetadataID(user._id)
|
|
32
|
+
const newDoc = {
|
|
33
|
+
...user,
|
|
34
|
+
_id: metadataId,
|
|
35
|
+
tableId: InternalTables.USER_METADATA,
|
|
36
|
+
}
|
|
37
|
+
const found = Array.isArray(metadata)
|
|
38
|
+
? metadata.find(doc => doc._id === metadataId)
|
|
39
|
+
: metadata
|
|
40
|
+
// copy rev over for the purposes of equality check
|
|
41
|
+
if (found) {
|
|
42
|
+
newDoc._rev = found._rev
|
|
43
|
+
}
|
|
44
|
+
if (found == null || !isEqual(newDoc, found)) {
|
|
45
|
+
return {
|
|
46
|
+
...found,
|
|
47
|
+
...newDoc,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
exports.syncGlobalUsers = async appId => {
|
|
54
|
+
// sync user metadata
|
|
55
|
+
const db = new CouchDB(appId)
|
|
56
|
+
const [users, metadata] = await Promise.all([
|
|
57
|
+
getGlobalUsers(appId),
|
|
58
|
+
rawMetadata(db),
|
|
59
|
+
])
|
|
60
|
+
const toWrite = []
|
|
61
|
+
for (let user of users) {
|
|
62
|
+
const combined = await combineMetadataAndUser(user, metadata)
|
|
63
|
+
if (combined) {
|
|
64
|
+
toWrite.push(combined)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
await db.bulkDocs(toWrite)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
exports.syncUser = async function (ctx) {
|
|
71
|
+
let deleting = false,
|
|
72
|
+
user
|
|
73
|
+
const userId = ctx.params.id
|
|
74
|
+
try {
|
|
75
|
+
user = await getRawGlobalUser(userId)
|
|
76
|
+
} catch (err) {
|
|
77
|
+
if (err && err.status === 404) {
|
|
78
|
+
user = {}
|
|
79
|
+
deleting = true
|
|
80
|
+
} else {
|
|
81
|
+
throw err
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const roles = user.roles
|
|
85
|
+
// remove props which aren't useful to metadata
|
|
12
86
|
delete user.password
|
|
87
|
+
delete user.forceResetPassword
|
|
13
88
|
delete user.roles
|
|
14
|
-
|
|
15
|
-
|
|
89
|
+
// run through all production appIDs in the users roles
|
|
90
|
+
let prodAppIds
|
|
91
|
+
// if they are a builder then get all production app IDs
|
|
92
|
+
if ((user.builder && user.builder.global) || deleting) {
|
|
93
|
+
prodAppIds = await getDeployedAppIDs(CouchDB)
|
|
94
|
+
} else {
|
|
95
|
+
prodAppIds = Object.entries(roles)
|
|
96
|
+
.filter(entry => entry[1] !== BUILTIN_ROLE_IDS.PUBLIC)
|
|
97
|
+
.map(([appId]) => appId)
|
|
98
|
+
}
|
|
99
|
+
for (let prodAppId of prodAppIds) {
|
|
100
|
+
const roleId = roles[prodAppId]
|
|
101
|
+
const devAppId = getDevelopmentAppID(prodAppId)
|
|
102
|
+
for (let appId of [prodAppId, devAppId]) {
|
|
103
|
+
if (!(await doesDatabaseExist(appId))) {
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
const db = new CouchDB(appId)
|
|
107
|
+
const metadataId = generateUserMetadataID(userId)
|
|
108
|
+
let metadata
|
|
109
|
+
try {
|
|
110
|
+
metadata = await db.get(metadataId)
|
|
111
|
+
} catch (err) {
|
|
112
|
+
if (deleting) {
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
metadata = {
|
|
116
|
+
tableId: InternalTables.USER_METADATA,
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// assign the roleId for the metadata doc
|
|
120
|
+
if (roleId) {
|
|
121
|
+
metadata.roleId = roleId
|
|
122
|
+
}
|
|
123
|
+
let combined = !deleting
|
|
124
|
+
? combineMetadataAndUser(user, metadata)
|
|
125
|
+
: {
|
|
126
|
+
...metadata,
|
|
127
|
+
status: UserStatus.INACTIVE,
|
|
128
|
+
metadata: BUILTIN_ROLE_IDS.PUBLIC,
|
|
129
|
+
}
|
|
130
|
+
// if its null then there was no updates required
|
|
131
|
+
if (combined) {
|
|
132
|
+
await db.put(combined)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
ctx.body = {
|
|
137
|
+
message: "User synced.",
|
|
138
|
+
}
|
|
16
139
|
}
|
|
17
140
|
|
|
18
141
|
exports.fetchMetadata = async function (ctx) {
|
|
19
142
|
const database = new CouchDB(ctx.appId)
|
|
20
143
|
const global = await getGlobalUsers(ctx.appId)
|
|
21
|
-
const metadata = (
|
|
22
|
-
await database.allDocs(
|
|
23
|
-
getUserMetadataParams(null, {
|
|
24
|
-
include_docs: true,
|
|
25
|
-
})
|
|
26
|
-
)
|
|
27
|
-
).rows.map(row => row.doc)
|
|
144
|
+
const metadata = await rawMetadata(database)
|
|
28
145
|
const users = []
|
|
29
146
|
for (let user of global) {
|
|
30
147
|
// find the metadata that matches up to the global ID
|
|
@@ -52,7 +169,9 @@ exports.updateSelfMetadata = async function (ctx) {
|
|
|
52
169
|
exports.updateMetadata = async function (ctx) {
|
|
53
170
|
const appId = ctx.appId
|
|
54
171
|
const db = new CouchDB(appId)
|
|
55
|
-
const user =
|
|
172
|
+
const user = ctx.request.body
|
|
173
|
+
// this isn't applicable to the user
|
|
174
|
+
delete user.roles
|
|
56
175
|
const metadata = {
|
|
57
176
|
tableId: InternalTables.USER_METADATA,
|
|
58
177
|
...user,
|
|
@@ -4,6 +4,7 @@ const { apiFileReturn } = require("../../../utilities/fileSystem")
|
|
|
4
4
|
const exporters = require("./exporters")
|
|
5
5
|
const { saveView, getView, getViews, deleteView } = require("./utils")
|
|
6
6
|
const { fetchView } = require("../row")
|
|
7
|
+
const { getTable } = require("../table/utils")
|
|
7
8
|
|
|
8
9
|
exports.fetch = async ctx => {
|
|
9
10
|
const db = new CouchDB(ctx.appId)
|
|
@@ -56,7 +57,7 @@ exports.exportView = async ctx => {
|
|
|
56
57
|
const view = await getView(db, viewName)
|
|
57
58
|
|
|
58
59
|
const format = ctx.query.format
|
|
59
|
-
if (!format) {
|
|
60
|
+
if (!format || !Object.values(exporters.ExportFormats).includes(format)) {
|
|
60
61
|
ctx.throw(400, "Format must be specified, either csv or json")
|
|
61
62
|
}
|
|
62
63
|
|
|
@@ -80,10 +81,22 @@ exports.exportView = async ctx => {
|
|
|
80
81
|
let schema = view && view.meta && view.meta.schema
|
|
81
82
|
if (!schema) {
|
|
82
83
|
const tableId = ctx.params.tableId || view.meta.tableId
|
|
83
|
-
const table = await
|
|
84
|
+
const table = await getTable(ctx.appId, tableId)
|
|
84
85
|
schema = table.schema
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
// make sure no "undefined" entries appear in the CSV
|
|
89
|
+
if (format === exporters.ExportFormats.CSV) {
|
|
90
|
+
const schemaKeys = Object.keys(schema)
|
|
91
|
+
for (let key of schemaKeys) {
|
|
92
|
+
for (let row of ctx.body) {
|
|
93
|
+
if (row[key] == null) {
|
|
94
|
+
row[key] = ""
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
87
100
|
// Export part
|
|
88
101
|
let headers = Object.keys(schema)
|
|
89
102
|
const exporter = exporters[format]
|
package/src/api/routes/query.js
CHANGED
package/src/api/routes/table.js
CHANGED
|
@@ -53,5 +53,16 @@ router
|
|
|
53
53
|
authorized(BUILDER),
|
|
54
54
|
tableController.destroy
|
|
55
55
|
)
|
|
56
|
+
// this is currently builder only, but in the future
|
|
57
|
+
// it could be carried out by an end user in app,
|
|
58
|
+
// however some thought will need to be had about
|
|
59
|
+
// implications for automations (triggers)
|
|
60
|
+
// new trigger type, bulk rows created
|
|
61
|
+
.post(
|
|
62
|
+
"/api/tables/:tableId/import",
|
|
63
|
+
paramResource("tableId"),
|
|
64
|
+
authorized(BUILDER),
|
|
65
|
+
tableController.bulkImport
|
|
66
|
+
)
|
|
56
67
|
|
|
57
68
|
module.exports = router
|
|
@@ -26,8 +26,8 @@ describe("/datasources", () => {
|
|
|
26
26
|
.expect('Content-Type', /json/)
|
|
27
27
|
.expect(200)
|
|
28
28
|
|
|
29
|
-
expect(res.
|
|
30
|
-
expect(res.body.
|
|
29
|
+
expect(res.body.datasource.name).toEqual("Test")
|
|
30
|
+
expect(res.body.errors).toBeUndefined()
|
|
31
31
|
})
|
|
32
32
|
})
|
|
33
33
|
|
|
@@ -75,7 +75,11 @@ describe("run misc tests", () => {
|
|
|
75
75
|
},
|
|
76
76
|
})
|
|
77
77
|
const dataImport = {
|
|
78
|
-
csvString: "a,b,c,d\n1,2,3,4"
|
|
78
|
+
csvString: "a,b,c,d\n1,2,3,4",
|
|
79
|
+
schema: {},
|
|
80
|
+
}
|
|
81
|
+
for (let col of ["a", "b", "c", "d"]) {
|
|
82
|
+
dataImport.schema[col] = { type: "string" }
|
|
79
83
|
}
|
|
80
84
|
await tableUtils.handleDataImport(
|
|
81
85
|
config.getAppId(),
|
package/src/api/routes/user.js
CHANGED
|
@@ -34,5 +34,10 @@ router
|
|
|
34
34
|
authorized(PermissionTypes.USER, PermissionLevels.WRITE),
|
|
35
35
|
controller.destroyMetadata
|
|
36
36
|
)
|
|
37
|
+
.post(
|
|
38
|
+
"/api/users/metadata/sync/:id",
|
|
39
|
+
authorized(PermissionTypes.USER, PermissionLevels.WRITE),
|
|
40
|
+
controller.syncUser
|
|
41
|
+
)
|
|
37
42
|
|
|
38
43
|
module.exports = router
|
package/src/app.ts
CHANGED
|
@@ -41,16 +41,8 @@ app.use(
|
|
|
41
41
|
)
|
|
42
42
|
|
|
43
43
|
if (!env.isTest()) {
|
|
44
|
-
const
|
|
45
|
-
app.use(
|
|
46
|
-
if (ctx.path.startsWith(bullboard.pathPrefix)) {
|
|
47
|
-
ctx.status = 200
|
|
48
|
-
ctx.respond = false
|
|
49
|
-
bullApp(ctx.req, ctx.res)
|
|
50
|
-
} else {
|
|
51
|
-
await next()
|
|
52
|
-
}
|
|
53
|
-
})
|
|
44
|
+
const plugin = bullboard.init()
|
|
45
|
+
app.use(plugin)
|
|
54
46
|
}
|
|
55
47
|
|
|
56
48
|
app.context.eventEmitter = eventEmitter
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const { createBullBoard } = require("bull-board")
|
|
2
|
-
const { BullAdapter } = require("bull-board/bullAdapter")
|
|
3
|
-
const
|
|
1
|
+
const { createBullBoard } = require("@bull-board/api")
|
|
2
|
+
const { BullAdapter } = require("@bull-board/api/bullAdapter")
|
|
3
|
+
const { KoaAdapter } = require("@bull-board/koa")
|
|
4
4
|
const env = require("../environment")
|
|
5
5
|
const Queue = env.isTest()
|
|
6
6
|
? require("../utilities/queue/inMemoryQueue")
|
|
@@ -9,23 +9,40 @@ const { JobQueues } = require("../constants")
|
|
|
9
9
|
const { utils } = require("@budibase/auth/redis")
|
|
10
10
|
const { opts, redisProtocolUrl } = utils.getRedisOptions()
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
|
|
12
|
+
const CLEANUP_PERIOD_MS = 60 * 1000
|
|
13
|
+
const queueConfig = redisProtocolUrl || { redis: opts }
|
|
14
|
+
let cleanupInternal = null
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
let automationQueue = new Queue(JobQueues.AUTOMATIONS, queueConfig)
|
|
17
|
+
|
|
18
|
+
async function cleanup() {
|
|
19
|
+
await automationQueue.clean(CLEANUP_PERIOD_MS, "completed")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const PATH_PREFIX = "/bulladmin"
|
|
16
23
|
|
|
17
24
|
exports.init = () => {
|
|
18
|
-
|
|
25
|
+
// cleanup the events every 5 minutes
|
|
26
|
+
if (!cleanupInternal) {
|
|
27
|
+
cleanupInternal = setInterval(cleanup, CLEANUP_PERIOD_MS)
|
|
28
|
+
// fire off an initial cleanup
|
|
29
|
+
cleanup().catch(err => {
|
|
30
|
+
console.error(`Unable to cleanup automation queue initially - ${err}`)
|
|
31
|
+
})
|
|
32
|
+
}
|
|
19
33
|
// Set up queues for bull board admin
|
|
20
34
|
const queues = [automationQueue]
|
|
21
35
|
const adapters = []
|
|
36
|
+
const serverAdapter = new KoaAdapter()
|
|
22
37
|
for (let queue of queues) {
|
|
23
38
|
adapters.push(new BullAdapter(queue))
|
|
24
39
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
40
|
+
createBullBoard({
|
|
41
|
+
queues: adapters,
|
|
42
|
+
serverAdapter,
|
|
43
|
+
})
|
|
44
|
+
serverAdapter.setBasePath(PATH_PREFIX)
|
|
45
|
+
return serverAdapter.registerPlugin()
|
|
29
46
|
}
|
|
30
47
|
|
|
31
48
|
exports.queue = automationQueue
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
jest.mock("../../utilities/usageQuota")
|
|
2
|
-
jest.mock("
|
|
2
|
+
jest.mock("../../threads/automation")
|
|
3
3
|
jest.mock("../../utilities/redis", () => ({
|
|
4
4
|
init: jest.fn(),
|
|
5
5
|
checkTestFlag: () => {
|
|
@@ -11,8 +11,7 @@ jest.spyOn(global.console, "error")
|
|
|
11
11
|
|
|
12
12
|
require("../../environment")
|
|
13
13
|
const automation = require("../index")
|
|
14
|
-
const
|
|
15
|
-
const thread = require("../thread")
|
|
14
|
+
const thread = require("../../threads/automation")
|
|
16
15
|
const triggers = require("../triggers")
|
|
17
16
|
const { basicAutomation } = require("../../tests/utilities/structures")
|
|
18
17
|
const { wait } = require("../../utilities")
|
|
@@ -62,7 +61,7 @@ describe("Run through some parts of the automations system", () => {
|
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
}
|
|
65
|
-
}))
|
|
64
|
+
}), expect.any(Function))
|
|
66
65
|
})
|
|
67
66
|
|
|
68
67
|
it("should be able to clean inputs with the utilities", () => {
|