@budibase/server 1.0.113 → 1.0.116
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/builder/assets/{index.e3e5909b.js → index.28d8c64f.js} +4 -4
- package/builder/index.html +1 -1
- package/coverage/clover.xml +1212 -1269
- package/coverage/coverage-final.json +86 -87
- package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
- package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/controllers/application.js.html +126 -120
- package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
- package/coverage/lcov-report/api/controllers/automation.js.html +21 -21
- 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 +1 -1
- package/coverage/lcov-report/api/controllers/datasource.js.html +16 -16
- package/coverage/lcov-report/api/controllers/dev.js.html +23 -14
- package/coverage/lcov-report/api/controllers/index.html +17 -17
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +6 -6
- package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
- package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
- package/coverage/lcov-report/api/controllers/permission.js.html +15 -15
- package/coverage/lcov-report/api/controllers/query/index.html +1 -1
- package/coverage/lcov-report/api/controllers/query/index.js.html +19 -19
- package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
- package/coverage/lcov-report/api/controllers/role.js.html +9 -9
- package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/external.js.html +19 -19
- package/coverage/lcov-report/api/controllers/row/index.html +10 -10
- package/coverage/lcov-report/api/controllers/row/index.js.html +14 -14
- package/coverage/lcov-report/api/controllers/row/internal.js.html +37 -34
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +9 -9
- package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +10 -10
- package/coverage/lcov-report/api/controllers/row/utils.js.html +12 -12
- package/coverage/lcov-report/api/controllers/screen.js.html +7 -7
- package/coverage/lcov-report/api/controllers/script.js.html +4 -4
- package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +9 -9
- package/coverage/lcov-report/api/controllers/table/external.js.html +12 -12
- package/coverage/lcov-report/api/controllers/table/index.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.js.html +14 -14
- package/coverage/lcov-report/api/controllers/table/internal.js.html +13 -13
- package/coverage/lcov-report/api/controllers/table/utils.js.html +30 -30
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +19 -19
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +4 -4
- package/coverage/lcov-report/api/controllers/view/index.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.js.html +14 -14
- package/coverage/lcov-report/api/controllers/view/utils.js.html +12 -12
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +7 -7
- package/coverage/lcov-report/api/controllers/webhook.js.html +17 -17
- 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 +1 -1
- package/coverage/lcov-report/api/routes/index.html +1 -1
- 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/migrations.js.html +1 -1
- package/coverage/lcov-report/api/routes/permission.js.html +1 -1
- package/coverage/lcov-report/api/routes/query.js.html +1 -1
- 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 +1 -1
- package/coverage/lcov-report/api/routes/table.js.html +1 -1
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +1 -1
- package/coverage/lcov-report/api/routes/utils/index.html +1 -1
- package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
- 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 +24 -24
- package/coverage/lcov-report/automations/automationUtils.js.html +5 -5
- package/coverage/lcov-report/automations/bullboard.js.html +16 -16
- package/coverage/lcov-report/automations/index.html +5 -5
- package/coverage/lcov-report/automations/index.js.html +1 -1
- package/coverage/lcov-report/automations/steps/bash.js.html +7 -7
- package/coverage/lcov-report/automations/steps/createRow.js.html +7 -7
- package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
- package/coverage/lcov-report/automations/steps/deleteRow.js.html +7 -7
- package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
- package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
- package/coverage/lcov-report/automations/steps/filter.js.html +7 -7
- package/coverage/lcov-report/automations/steps/index.html +1 -1
- package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
- package/coverage/lcov-report/automations/steps/queryRows.js.html +10 -10
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
- package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
- package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
- package/coverage/lcov-report/automations/steps/updateRow.js.html +6 -6
- package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
- package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
- 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 +18 -18
- package/coverage/lcov-report/automations/utils.js.html +43 -40
- package/coverage/lcov-report/constants/index.html +1 -1
- package/coverage/lcov-report/constants/index.js.html +27 -27
- package/coverage/lcov-report/constants/layouts.js.html +5 -5
- package/coverage/lcov-report/constants/screens.js.html +4 -4
- package/coverage/lcov-report/db/inMemoryView.js.html +52 -49
- package/coverage/lcov-report/db/index.html +21 -36
- package/coverage/lcov-report/db/index.js.html +49 -10
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +7 -7
- package/coverage/lcov-report/db/linkedRows/index.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.js.html +18 -18
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +13 -13
- package/coverage/lcov-report/db/newid.js.html +2 -2
- package/coverage/lcov-report/db/utils.js.html +13 -13
- package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
- package/coverage/lcov-report/events/index.html +1 -1
- package/coverage/lcov-report/events/index.js.html +5 -5
- package/coverage/lcov-report/events/utils.js.html +3 -3
- package/coverage/lcov-report/index.html +52 -52
- 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 +1 -1
- package/coverage/lcov-report/middleware/authorized.js.html +1 -1
- package/coverage/lcov-report/middleware/builder.js.html +15 -12
- package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
- package/coverage/lcov-report/middleware/index.html +4 -4
- package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
- package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
- package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
- package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
- package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
- package/coverage/lcov-report/middleware/utils.js.html +1 -1
- package/coverage/lcov-report/threads/automation.js.html +1 -1
- package/coverage/lcov-report/threads/index.html +34 -34
- package/coverage/lcov-report/threads/index.js.html +35 -17
- package/coverage/lcov-report/threads/query.js.html +20 -356
- package/coverage/lcov-report/threads/utils.js.html +19 -22
- package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
- package/coverage/lcov-report/utilities/budibaseDir.js.html +7 -7
- package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
- package/coverage/lcov-report/utilities/csvParser.js.html +6 -6
- package/coverage/lcov-report/utilities/global.js.html +15 -15
- package/coverage/lcov-report/utilities/index.html +1 -1
- package/coverage/lcov-report/utilities/index.js.html +26 -26
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +8 -8
- package/coverage/lcov-report/utilities/queue/index.html +1 -1
- 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 +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +18 -18
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +4 -4
- package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
- package/coverage/lcov-report/utilities/security.js.html +8 -8
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/index.html +13 -13
- package/coverage/lcov-report/utilities/usageQuota/index.js.html +8 -8
- package/coverage/lcov-report/utilities/usageQuota/rows.js.html +38 -26
- package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +5 -5
- package/coverage/lcov-report/utilities/workerRequests.js.html +28 -28
- package/coverage/lcov.info +1570 -1660
- package/dist/api/controllers/application.js +4 -1
- package/dist/api/controllers/deploy/index.js +5 -1
- package/dist/api/controllers/dev.js +9 -5
- package/dist/api/controllers/row/internal.js +2 -1
- package/dist/api/controllers/webhook.js +2 -2
- package/dist/api/routes/tests/utilities/TestFunctions.js +1 -4
- package/dist/app.js +5 -2
- package/dist/automations/utils.js +6 -5
- package/dist/db/inMemoryView.js +33 -31
- package/dist/db/index.js +13 -2
- package/dist/integrations/couchdb.js +19 -25
- package/dist/integrations/queries/sql.js +108 -0
- package/dist/middleware/builder.js +10 -9
- package/dist/migrations/index.js +1 -5
- package/dist/package.json +5 -5
- package/dist/tests/utilities/TestConfiguration.js +66 -59
- package/dist/threads/index.js +6 -1
- package/dist/threads/query.js +4 -103
- package/dist/threads/utils.js +2 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/fileSystem/index.js +27 -26
- package/dist/utilities/usageQuota/rows.js +16 -16
- package/package.json +6 -6
- package/scripts/exportAppTemplate.js +10 -8
- package/scripts/integrations/mysql/init.sql +1 -0
- package/src/api/controllers/application.js +3 -1
- package/src/api/controllers/deploy/index.js +4 -4
- package/src/api/controllers/dev.js +9 -6
- package/src/api/controllers/query/import/tests/index.spec.js +7 -11
- package/src/api/controllers/row/internal.js +2 -1
- package/src/api/controllers/webhook.js +2 -2
- package/src/api/routes/tests/row.spec.js +15 -11
- package/src/api/routes/tests/table.spec.js +3 -2
- package/src/api/routes/tests/utilities/TestFunctions.js +1 -5
- package/src/app.ts +2 -2
- package/src/automations/tests/deleteRow.spec.js +1 -1
- package/src/automations/utils.js +6 -5
- package/src/db/inMemoryView.js +37 -36
- package/src/db/index.js +15 -2
- package/src/db/tests/linkTests.spec.js +8 -7
- package/src/integrations/couchdb.ts +28 -24
- package/src/integrations/queries/sql.ts +125 -0
- package/src/integrations/tests/airtable.spec.js +3 -1
- package/src/integrations/tests/couchdb.spec.js +4 -1
- package/src/middleware/builder.js +10 -9
- package/src/middleware/tests/authorized.spec.js +0 -1
- package/src/middleware/tests/usageQuota.spec.js +6 -20
- package/src/migrations/functions/tests/appUrls.spec.js +8 -11
- package/src/migrations/functions/tests/userEmailViewCasing.spec.js +13 -10
- package/src/migrations/functions/usageQuotas/tests/syncApps.spec.js +25 -21
- package/src/migrations/functions/usageQuotas/tests/syncRows.spec.js +26 -24
- package/src/migrations/index.ts +1 -2
- package/src/module.d.ts +8 -0
- package/src/tests/utilities/TestConfiguration.js +62 -55
- package/src/threads/index.js +7 -1
- package/src/threads/query.js +7 -119
- package/src/threads/utils.js +2 -3
- package/src/utilities/fileSystem/index.js +30 -30
- package/src/utilities/usageQuota/rows.js +22 -18
- package/coverage/lcov-report/db/client.js.html +0 -173
- package/dist/db/client.js +0 -25
- package/scripts/replicateApp.js +0 -50
- package/src/db/client.js +0 -31
|
@@ -53,51 +53,55 @@ module CouchDBModule {
|
|
|
53
53
|
|
|
54
54
|
class CouchDBIntegration implements IntegrationBase {
|
|
55
55
|
private config: CouchDBConfig
|
|
56
|
-
private client: any
|
|
56
|
+
private readonly client: any
|
|
57
57
|
|
|
58
58
|
constructor(config: CouchDBConfig) {
|
|
59
59
|
this.config = config
|
|
60
60
|
this.client = new PouchDB(`${config.url}/${config.database}`)
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
async
|
|
63
|
+
async query(
|
|
64
|
+
command: string,
|
|
65
|
+
errorMsg: string,
|
|
66
|
+
query: { json?: object; id?: string }
|
|
67
|
+
) {
|
|
64
68
|
try {
|
|
65
|
-
|
|
69
|
+
const response = await this.client[command](query.id || query.json)
|
|
70
|
+
await this.client.close()
|
|
71
|
+
return response
|
|
66
72
|
} catch (err) {
|
|
67
|
-
console.error(
|
|
73
|
+
console.error(errorMsg, err)
|
|
68
74
|
throw err
|
|
69
75
|
}
|
|
70
76
|
}
|
|
71
77
|
|
|
78
|
+
async create(query: { json: object }) {
|
|
79
|
+
return this.query("post", "Error writing to couchDB", query)
|
|
80
|
+
}
|
|
81
|
+
|
|
72
82
|
async read(query: { json: object }) {
|
|
73
|
-
|
|
74
|
-
|
|
83
|
+
const result = await this.query("allDocs", "Error querying couchDB", {
|
|
84
|
+
json: {
|
|
75
85
|
include_docs: true,
|
|
76
86
|
...query.json,
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
console.error("Error querying couchDB", err)
|
|
81
|
-
throw err
|
|
82
|
-
}
|
|
87
|
+
},
|
|
88
|
+
})
|
|
89
|
+
return result.rows.map((row: { doc: object }) => row.doc)
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
async update(query: { json: object }) {
|
|
86
|
-
|
|
87
|
-
return this.client.put(query.json)
|
|
88
|
-
} catch (err) {
|
|
89
|
-
console.error("Error updating couchDB document", err)
|
|
90
|
-
throw err
|
|
91
|
-
}
|
|
93
|
+
return this.query("put", "Error updating couchDB document", query)
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
async delete(query: { id: string }) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
const doc = await this.query(
|
|
98
|
+
"get",
|
|
99
|
+
"Cannot find doc to be deleted",
|
|
100
|
+
query
|
|
101
|
+
)
|
|
102
|
+
return this.query("remove", "Error deleting couchDB document", {
|
|
103
|
+
json: doc,
|
|
104
|
+
})
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
107
|
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { findHBSBlocks, processStringSync } from "@budibase/string-templates"
|
|
2
|
+
import { Integration } from "../../definitions/datasource"
|
|
3
|
+
import { DatasourcePlus } from "../base/datasourcePlus"
|
|
4
|
+
|
|
5
|
+
const CONST_CHAR_REGEX = new RegExp("'[^']*'", "g")
|
|
6
|
+
|
|
7
|
+
export function enrichQueryFields(
|
|
8
|
+
fields: { [key: string]: any },
|
|
9
|
+
parameters = {}
|
|
10
|
+
) {
|
|
11
|
+
const enrichedQuery: { [key: string]: any } = Array.isArray(fields) ? [] : {}
|
|
12
|
+
|
|
13
|
+
// enrich the fields with dynamic parameters
|
|
14
|
+
for (let key of Object.keys(fields)) {
|
|
15
|
+
if (fields[key] == null) {
|
|
16
|
+
continue
|
|
17
|
+
}
|
|
18
|
+
if (typeof fields[key] === "object") {
|
|
19
|
+
// enrich nested fields object
|
|
20
|
+
enrichedQuery[key] = enrichQueryFields(fields[key], parameters)
|
|
21
|
+
} else if (typeof fields[key] === "string") {
|
|
22
|
+
// enrich string value as normal
|
|
23
|
+
enrichedQuery[key] = processStringSync(fields[key], parameters, {
|
|
24
|
+
noEscaping: true,
|
|
25
|
+
noHelpers: true,
|
|
26
|
+
escapeNewlines: true,
|
|
27
|
+
})
|
|
28
|
+
} else {
|
|
29
|
+
enrichedQuery[key] = fields[key]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (
|
|
33
|
+
enrichedQuery.json ||
|
|
34
|
+
enrichedQuery.customData ||
|
|
35
|
+
enrichedQuery.requestBody
|
|
36
|
+
) {
|
|
37
|
+
try {
|
|
38
|
+
enrichedQuery.json = JSON.parse(
|
|
39
|
+
enrichedQuery.json ||
|
|
40
|
+
enrichedQuery.customData ||
|
|
41
|
+
enrichedQuery.requestBody
|
|
42
|
+
)
|
|
43
|
+
} catch (err) {
|
|
44
|
+
// no json found, ignore
|
|
45
|
+
}
|
|
46
|
+
delete enrichedQuery.customData
|
|
47
|
+
}
|
|
48
|
+
return enrichedQuery
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function interpolateSQL(
|
|
52
|
+
fields: { [key: string]: any },
|
|
53
|
+
parameters: { [key: string]: any },
|
|
54
|
+
integration: DatasourcePlus
|
|
55
|
+
) {
|
|
56
|
+
let sql = fields.sql
|
|
57
|
+
if (!sql || typeof sql !== "string") {
|
|
58
|
+
return fields
|
|
59
|
+
}
|
|
60
|
+
const bindings = findHBSBlocks(sql)
|
|
61
|
+
let variables = [],
|
|
62
|
+
arrays = []
|
|
63
|
+
for (let binding of bindings) {
|
|
64
|
+
// look for array/list operations in the SQL statement, which will need handled later
|
|
65
|
+
const listRegexMatch = sql.match(
|
|
66
|
+
new RegExp(`(in|IN|In|iN)( )+[(]?${binding}[)]?`)
|
|
67
|
+
)
|
|
68
|
+
// check if the variable was used as part of a string concat e.g. 'Hello {{binding}}'
|
|
69
|
+
// start by finding all the instances of const character strings
|
|
70
|
+
const charConstMatch = sql.match(CONST_CHAR_REGEX) || []
|
|
71
|
+
// now look within them to see if a binding is used
|
|
72
|
+
const charConstBindingMatch = charConstMatch.find((string: any) =>
|
|
73
|
+
string.match(new RegExp(`'[^']*${binding}[^']*'`))
|
|
74
|
+
)
|
|
75
|
+
if (charConstBindingMatch) {
|
|
76
|
+
let [part1, part2] = charConstBindingMatch.split(binding)
|
|
77
|
+
part1 = `'${part1.substring(1)}'`
|
|
78
|
+
part2 = `'${part2.substring(0, part2.length - 1)}'`
|
|
79
|
+
sql = sql.replace(
|
|
80
|
+
charConstBindingMatch,
|
|
81
|
+
integration.getStringConcat([
|
|
82
|
+
part1,
|
|
83
|
+
integration.getBindingIdentifier(),
|
|
84
|
+
part2,
|
|
85
|
+
])
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
// generate SQL parameterised array
|
|
89
|
+
else if (listRegexMatch) {
|
|
90
|
+
arrays.push(binding)
|
|
91
|
+
// determine the length of the array
|
|
92
|
+
const value = enrichQueryFields([binding], parameters)[0]
|
|
93
|
+
.split(",")
|
|
94
|
+
.map((val: string) => val.trim())
|
|
95
|
+
// build a string like ($1, $2, $3)
|
|
96
|
+
let replacement = `${Array.apply(null, Array(value.length))
|
|
97
|
+
.map(() => integration.getBindingIdentifier())
|
|
98
|
+
.join(",")}`
|
|
99
|
+
// check if parentheses are needed
|
|
100
|
+
if (!listRegexMatch[0].includes(`(${binding})`)) {
|
|
101
|
+
replacement = `(${replacement})`
|
|
102
|
+
}
|
|
103
|
+
sql = sql.replace(binding, replacement)
|
|
104
|
+
} else {
|
|
105
|
+
sql = sql.replace(binding, integration.getBindingIdentifier())
|
|
106
|
+
}
|
|
107
|
+
variables.push(binding)
|
|
108
|
+
}
|
|
109
|
+
// replicate the knex structure
|
|
110
|
+
fields.sql = sql
|
|
111
|
+
fields.bindings = enrichQueryFields(variables, parameters)
|
|
112
|
+
// check for arrays in the data
|
|
113
|
+
let updated: string[] = []
|
|
114
|
+
for (let i = 0; i < variables.length; i++) {
|
|
115
|
+
if (arrays.includes(variables[i])) {
|
|
116
|
+
updated = updated.concat(
|
|
117
|
+
fields.bindings[i].split(",").map((val: string) => val.trim())
|
|
118
|
+
)
|
|
119
|
+
} else {
|
|
120
|
+
updated.push(fields.bindings[i])
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
fields.bindings = updated
|
|
124
|
+
return fields
|
|
125
|
+
}
|
|
@@ -7,7 +7,9 @@ class TestConfiguration {
|
|
|
7
7
|
this.integration = new AirtableIntegration.integration(config)
|
|
8
8
|
this.client = {
|
|
9
9
|
create: jest.fn(),
|
|
10
|
-
select: jest.fn()
|
|
10
|
+
select: jest.fn(() => ({
|
|
11
|
+
firstPage: jest.fn(() => []),
|
|
12
|
+
})),
|
|
11
13
|
update: jest.fn(),
|
|
12
14
|
destroy: jest.fn(),
|
|
13
15
|
}
|
|
@@ -2,8 +2,10 @@ jest.mock("pouchdb", () => function CouchDBMock() {
|
|
|
2
2
|
this.post = jest.fn()
|
|
3
3
|
this.allDocs = jest.fn(() => ({ rows: [] }))
|
|
4
4
|
this.put = jest.fn()
|
|
5
|
+
this.get = jest.fn()
|
|
5
6
|
this.remove = jest.fn()
|
|
6
7
|
this.plugin = jest.fn()
|
|
8
|
+
this.close = jest.fn()
|
|
7
9
|
})
|
|
8
10
|
|
|
9
11
|
const CouchDBIntegration = require("../couchdb")
|
|
@@ -62,6 +64,7 @@ describe("CouchDB Integration", () => {
|
|
|
62
64
|
it("calls the delete method with the correct params", async () => {
|
|
63
65
|
const id = "1234"
|
|
64
66
|
const response = await config.integration.delete({ id })
|
|
65
|
-
expect(config.integration.client.
|
|
67
|
+
expect(config.integration.client.get).toHaveBeenCalledWith(id)
|
|
68
|
+
expect(config.integration.client.remove).toHaveBeenCalled()
|
|
66
69
|
})
|
|
67
70
|
})
|
|
@@ -5,7 +5,7 @@ const {
|
|
|
5
5
|
checkDebounce,
|
|
6
6
|
setDebounce,
|
|
7
7
|
} = require("../utilities/redis")
|
|
8
|
-
const {
|
|
8
|
+
const { doWithDB } = require("@budibase/backend-core/db")
|
|
9
9
|
const { DocumentTypes } = require("../db/utils")
|
|
10
10
|
const { PermissionTypes } = require("@budibase/backend-core/permissions")
|
|
11
11
|
const { app: appCache } = require("@budibase/backend-core/cache")
|
|
@@ -48,14 +48,15 @@ async function updateAppUpdatedAt(ctx) {
|
|
|
48
48
|
if (ctx.method === "GET" || (await checkDebounce(appId))) {
|
|
49
49
|
return
|
|
50
50
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
await doWithDB(appId, async db => {
|
|
52
|
+
const metadata = await db.get(DocumentTypes.APP_METADATA)
|
|
53
|
+
metadata.updatedAt = new Date().toISOString()
|
|
54
|
+
const response = await db.put(metadata)
|
|
55
|
+
metadata._rev = response.rev
|
|
56
|
+
await appCache.invalidateAppMetadata(appId, metadata)
|
|
57
|
+
// set a new debounce record with a short TTL
|
|
58
|
+
await setDebounce(appId, DEBOUNCE_TIME_SEC)
|
|
59
|
+
})
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
module.exports = async (ctx, permType) => {
|
|
@@ -10,7 +10,6 @@ jest.mock("../../environment", () => ({
|
|
|
10
10
|
const authorizedMiddleware = require("../authorized")
|
|
11
11
|
const env = require("../../environment")
|
|
12
12
|
const { PermissionTypes, PermissionLevels } = require("@budibase/backend-core/permissions")
|
|
13
|
-
require("@budibase/backend-core").init(require("../../db"))
|
|
14
13
|
const { doInAppContext } = require("@budibase/backend-core/context")
|
|
15
14
|
|
|
16
15
|
const APP_ID = ""
|
|
@@ -6,7 +6,10 @@ jest.mock("@budibase/backend-core/tenancy", () => ({
|
|
|
6
6
|
|
|
7
7
|
const usageQuotaMiddleware = require("../usageQuota")
|
|
8
8
|
const usageQuota = require("../../utilities/usageQuota")
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
jest.mock("@budibase/backend-core/db")
|
|
11
|
+
const { dangerousGetDB } = require("@budibase/backend-core/db")
|
|
12
|
+
|
|
10
13
|
const env = require("../../environment")
|
|
11
14
|
|
|
12
15
|
class TestConfiguration {
|
|
@@ -80,7 +83,7 @@ describe("usageQuota middleware", () => {
|
|
|
80
83
|
_rev: "test",
|
|
81
84
|
})
|
|
82
85
|
|
|
83
|
-
|
|
86
|
+
dangerousGetDB.mockImplementationOnce(() => ({
|
|
84
87
|
get: async () => true
|
|
85
88
|
}))
|
|
86
89
|
|
|
@@ -96,7 +99,7 @@ describe("usageQuota middleware", () => {
|
|
|
96
99
|
})
|
|
97
100
|
config.setProd(true)
|
|
98
101
|
|
|
99
|
-
|
|
102
|
+
dangerousGetDB.mockImplementationOnce(() => ({
|
|
100
103
|
get: async () => {
|
|
101
104
|
throw new Error()
|
|
102
105
|
}
|
|
@@ -114,21 +117,4 @@ describe("usageQuota middleware", () => {
|
|
|
114
117
|
expect(usageQuota.update).toHaveBeenCalledWith("rows", 1)
|
|
115
118
|
expect(config.next).toHaveBeenCalled()
|
|
116
119
|
})
|
|
117
|
-
|
|
118
|
-
// it("calculates the correct file size from a file upload call and adds it to quota", async () => {
|
|
119
|
-
// config.setUrl("/upload")
|
|
120
|
-
// config.setProd(true)
|
|
121
|
-
// config.setFiles([
|
|
122
|
-
// {
|
|
123
|
-
// size: 100
|
|
124
|
-
// },
|
|
125
|
-
// {
|
|
126
|
-
// size: 10000
|
|
127
|
-
// },
|
|
128
|
-
// ])
|
|
129
|
-
// await config.executeMiddleware()
|
|
130
|
-
|
|
131
|
-
// expect(usageQuota.update).toHaveBeenCalledWith("storage", 10100)
|
|
132
|
-
// expect(config.next).toHaveBeenCalled()
|
|
133
|
-
// })
|
|
134
120
|
})
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
const { DocumentTypes } = require("@budibase/backend-core/db")
|
|
2
|
-
const env = require("../../../environment")
|
|
1
|
+
const { DocumentTypes, doWithDB } = require("@budibase/backend-core/db")
|
|
3
2
|
const TestConfig = require("../../../tests/utilities/TestConfiguration")
|
|
4
3
|
|
|
5
4
|
const migration = require("../appUrls")
|
|
6
5
|
|
|
7
6
|
describe("run", () => {
|
|
8
7
|
let config = new TestConfig(false)
|
|
9
|
-
const CouchDB = config.getCouch()
|
|
10
8
|
|
|
11
9
|
beforeEach(async () => {
|
|
12
10
|
await config.init()
|
|
@@ -16,14 +14,13 @@ describe("run", () => {
|
|
|
16
14
|
|
|
17
15
|
it("runs successfully", async () => {
|
|
18
16
|
const app = await config.createApp("testApp")
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
metadata = await appDb.get(DocumentTypes.APP_METADATA)
|
|
17
|
+
const metadata = await doWithDB(app.appId, async db => {
|
|
18
|
+
const metadataDoc = await db.get(DocumentTypes.APP_METADATA)
|
|
19
|
+
delete metadataDoc.url
|
|
20
|
+
await db.put(metadataDoc)
|
|
21
|
+
await migration.run(db)
|
|
22
|
+
return await db.get(DocumentTypes.APP_METADATA)
|
|
23
|
+
})
|
|
27
24
|
expect(metadata.url).toEqual("/testapp")
|
|
28
25
|
})
|
|
29
26
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const TestConfig = require("../../../tests/utilities/TestConfiguration")
|
|
2
|
-
const {
|
|
2
|
+
const { TENANT_ID } = require("../../../tests/utilities/structures")
|
|
3
|
+
const { getGlobalDB, doInTenant } = require("@budibase/backend-core/tenancy")
|
|
3
4
|
|
|
4
5
|
// mock email view creation
|
|
5
6
|
const coreDb = require("@budibase/backend-core/db")
|
|
@@ -9,17 +10,19 @@ coreDb.createUserEmailView = createUserEmailView
|
|
|
9
10
|
const migration = require("../userEmailViewCasing")
|
|
10
11
|
|
|
11
12
|
describe("run", () => {
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
doInTenant(TENANT_ID, () => {
|
|
14
|
+
let config = new TestConfig(false)
|
|
15
|
+
const globalDb = getGlobalDB()
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
beforeEach(async () => {
|
|
18
|
+
await config.init()
|
|
19
|
+
})
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
afterAll(config.end)
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
it("runs successfully", async () => {
|
|
24
|
+
await migration.run(globalDb)
|
|
25
|
+
expect(createUserEmailView).toHaveBeenCalledTimes(1)
|
|
26
|
+
})
|
|
24
27
|
})
|
|
25
28
|
})
|
|
@@ -1,37 +1,41 @@
|
|
|
1
|
-
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
1
|
+
const { doInTenant, getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
2
2
|
const TestConfig = require("../../../../tests/utilities/TestConfiguration")
|
|
3
|
+
const { TENANT_ID } = require("../../../../tests/utilities/structures")
|
|
3
4
|
const { getUsageQuotaDoc, update, Properties } = require("../../../../utilities/usageQuota")
|
|
4
5
|
const syncApps = require("../syncApps")
|
|
5
6
|
const env = require("../../../../environment")
|
|
6
7
|
|
|
7
8
|
describe("syncApps", () => {
|
|
9
|
+
|
|
8
10
|
let config = new TestConfig(false)
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
await config.init()
|
|
14
|
+
env._set("USE_QUOTAS", 1)
|
|
15
|
+
})
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
afterAll(config.end)
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
it("runs successfully", async () => {
|
|
20
|
+
await doInTenant(TENANT_ID, async () => {
|
|
21
|
+
const db = getGlobalDB()
|
|
22
|
+
// create the usage quota doc and mock usages
|
|
23
|
+
await getUsageQuotaDoc(db)
|
|
24
|
+
await update(Properties.APPS, 3)
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
let usageDoc = await getUsageQuotaDoc(db)
|
|
27
|
+
expect(usageDoc.usageQuota.apps).toEqual(3)
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
// create an extra app to test the migration
|
|
30
|
+
await config.createApp("quota-test")
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
// migrate
|
|
33
|
+
await syncApps.run()
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
// assert the migration worked
|
|
36
|
+
usageDoc = await getUsageQuotaDoc(db)
|
|
37
|
+
expect(usageDoc.usageQuota.apps).toEqual(2)
|
|
38
|
+
})
|
|
39
|
+
})
|
|
36
40
|
})
|
|
37
41
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
1
|
+
const { doInTenant, getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
2
2
|
const TestConfig = require("../../../../tests/utilities/TestConfiguration")
|
|
3
|
+
const { TENANT_ID } = require("../../../../tests/utilities/structures")
|
|
3
4
|
const { getUsageQuotaDoc, update, Properties } = require("../../../../utilities/usageQuota")
|
|
4
5
|
const syncRows = require("../syncRows")
|
|
5
6
|
const env = require("../../../../environment")
|
|
@@ -15,29 +16,30 @@ describe("syncRows", () => {
|
|
|
15
16
|
afterAll(config.end)
|
|
16
17
|
|
|
17
18
|
it("runs successfully", async () => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
19
|
+
await doInTenant(TENANT_ID, async () => {
|
|
20
|
+
const db = getGlobalDB()
|
|
21
|
+
await getUsageQuotaDoc(db)
|
|
22
|
+
await update(Properties.ROW, 300)
|
|
23
|
+
|
|
24
|
+
let usageDoc = await getUsageQuotaDoc(db)
|
|
25
|
+
expect(usageDoc.usageQuota.rows).toEqual(300)
|
|
26
|
+
|
|
27
|
+
// app 1
|
|
28
|
+
await config.createTable()
|
|
29
|
+
await config.createRow()
|
|
30
|
+
// app 2
|
|
31
|
+
await config.createApp("second-app")
|
|
32
|
+
await config.createTable()
|
|
33
|
+
await config.createRow()
|
|
34
|
+
await config.createRow()
|
|
35
|
+
|
|
36
|
+
// migrate
|
|
37
|
+
await syncRows.run()
|
|
38
|
+
|
|
39
|
+
// assert the migration worked
|
|
40
|
+
usageDoc = await getUsageQuotaDoc(db)
|
|
41
|
+
expect(usageDoc.usageQuota.rows).toEqual(3)
|
|
42
|
+
})
|
|
41
43
|
})
|
|
42
44
|
})
|
|
43
45
|
|
package/src/migrations/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import CouchDB from "../db"
|
|
2
1
|
const {
|
|
3
2
|
MIGRATION_TYPES,
|
|
4
3
|
runMigrations,
|
|
@@ -52,5 +51,5 @@ export const MIGRATIONS: Migration[] = [
|
|
|
52
51
|
]
|
|
53
52
|
|
|
54
53
|
export const migrate = async (options?: MigrationOptions) => {
|
|
55
|
-
await runMigrations(
|
|
54
|
+
await runMigrations(MIGRATIONS, options)
|
|
56
55
|
}
|
package/src/module.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
1
|
declare module "@budibase/backend-core"
|
|
2
2
|
declare module "@budibase/backend-core/tenancy"
|
|
3
3
|
declare module "@budibase/backend-core/db"
|
|
4
|
+
declare module "@budibase/backend-core/context"
|
|
5
|
+
declare module "@budibase/backend-core/cache"
|
|
6
|
+
declare module "@budibase/backend-core/permissions"
|
|
7
|
+
declare module "@budibase/backend-core/roles"
|
|
8
|
+
declare module "@budibase/backend-core/constants"
|
|
9
|
+
declare module "@budibase/backend-core/auth"
|
|
10
|
+
declare module "@budibase/backend-core/sessions"
|
|
11
|
+
declare module "@budibase/backend-core/encryption"
|