@budibase/server 2.0.23 → 2.0.24-alpha.0
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.b61c225e.js → index.868c6c14.js} +260 -260
- package/builder/assets/{index.dfa4073c.css → index.aef99fa8.css} +2 -2
- package/builder/index.html +2 -2
- package/coverage/clover.xml +344 -341
- package/coverage/coverage-final.json +24 -24
- package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
- 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/datasource.js.html +1 -1
- package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
- package/coverage/lcov-report/api/controllers/index.html +1 -1
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
- 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 +1 -1
- package/coverage/lcov-report/api/controllers/query/index.html +1 -1
- package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
- package/coverage/lcov-report/api/controllers/role.js.html +1 -1
- package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/index.html +1 -1
- package/coverage/lcov-report/api/controllers/row/internal.js.html +12 -12
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +15 -15
- package/coverage/lcov-report/api/controllers/row/utils.js.html +13 -13
- package/coverage/lcov-report/api/controllers/script.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
- package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +5 -5
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/routes/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/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/screen.js.html +1 -1
- package/coverage/lcov-report/api/routes/script.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 +1 -1
- package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
- package/coverage/lcov-report/automations/bullboard.js.html +1 -1
- package/coverage/lcov-report/automations/index.html +1 -1
- package/coverage/lcov-report/automations/index.js.html +5 -5
- package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
- package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
- package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +1 -1
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
- package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
- 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 +3 -3
- package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/triggers.js.html +22 -22
- package/coverage/lcov-report/constants/index.html +1 -1
- package/coverage/lcov-report/constants/index.js.html +1 -1
- 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/inMemoryView.js.html +1 -1
- package/coverage/lcov-report/db/index.html +1 -1
- package/coverage/lcov-report/db/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +11 -11
- package/coverage/lcov-report/db/linkedRows/index.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.js.html +11 -11
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +3 -3
- package/coverage/lcov-report/db/newid.js.html +2 -2
- package/coverage/lcov-report/db/utils.js.html +10 -16
- 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 +2 -2
- package/coverage/lcov-report/events/utils.js.html +9 -9
- package/coverage/lcov-report/index.html +15 -15
- 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/builder.js.html +11 -11
- package/coverage/lcov-report/middleware/currentapp.js.html +34 -34
- package/coverage/lcov-report/middleware/index.html +1 -1
- 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 +7 -7
- package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
- package/coverage/lcov-report/middleware/utils.js.html +2 -2
- 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 +1 -1
- package/coverage/lcov-report/utilities/global.js.html +16 -16
- package/coverage/lcov-report/utilities/index.html +1 -1
- package/coverage/lcov-report/utilities/index.js.html +1 -1
- package/coverage/lcov-report/utilities/plugins.js.html +1 -1
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +13 -13
- 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 +38 -38
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +10 -10
- package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
- package/coverage/lcov-report/utilities/security.js.html +1 -1
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/index.html +14 -14
- package/coverage/lcov-report/utilities/usageQuota/rows.js.html +23 -11
- package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +1 -1
- package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
- package/coverage/lcov.info +619 -614
- package/dist/api/controllers/application.js +2 -2
- package/dist/api/controllers/query/index.js +6 -2
- package/dist/api/controllers/row/index.js +30 -10
- package/dist/api/controllers/table/internal.js +3 -1
- package/dist/api/controllers/table/utils.js +3 -1
- package/dist/automations/steps/updateRow.js +2 -2
- package/dist/automations/utils.js +5 -3
- package/dist/db/utils.js +1 -1
- package/dist/migrations/functions/{quotas1.js → syncQuotas.js} +3 -7
- package/dist/migrations/functions/usageQuotas/syncApps.js +0 -1
- package/dist/migrations/functions/{pluginCount.js → usageQuotas/syncPlugins.js} +1 -3
- package/dist/migrations/functions/usageQuotas/syncRows.js +9 -5
- package/dist/migrations/index.js +3 -9
- package/dist/package.json +7 -7
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utilities/usageQuota/rows.js +6 -4
- package/package.json +8 -8
- package/src/api/controllers/application.ts +2 -2
- package/src/api/controllers/query/index.ts +7 -2
- package/src/api/controllers/row/index.ts +36 -13
- package/src/api/controllers/table/internal.ts +3 -1
- package/src/api/controllers/table/utils.ts +3 -1
- package/src/api/routes/tests/row.spec.js +22 -27
- package/src/automations/steps/updateRow.js +2 -2
- package/src/automations/tests/automation.spec.js +1 -6
- package/src/automations/utils.ts +6 -4
- package/src/db/utils.js +0 -2
- package/src/migrations/functions/backfill/global.ts +1 -1
- package/src/migrations/functions/{quotas1.ts → syncQuotas.ts} +3 -8
- package/src/migrations/functions/tests/{quotas1.spec.js → syncQuotas.spec.js} +5 -2
- package/src/migrations/functions/usageQuotas/syncApps.ts +0 -1
- package/src/migrations/functions/usageQuotas/syncPlugins.ts +10 -0
- package/src/migrations/functions/usageQuotas/syncRows.ts +15 -6
- package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +9 -1
- package/src/migrations/index.ts +3 -15
- package/src/migrations/tests/index.spec.ts +0 -1
- package/src/utilities/usageQuota/rows.js +7 -3
- package/src/migrations/functions/pluginCount.ts +0 -12
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
const { getRowParams, USER_METDATA_PREFIX } = require("../../db/utils");
|
|
12
|
-
const { isDevAppID, getDevelopmentAppID, doWithDB, } = require("@budibase/backend-core/db");
|
|
12
|
+
const { isDevAppID, getDevelopmentAppID, getProdAppID, doWithDB, } = require("@budibase/backend-core/db");
|
|
13
13
|
const ROW_EXCLUSIONS = [USER_METDATA_PREFIX];
|
|
14
14
|
const getAppPairs = appIds => {
|
|
15
15
|
// collect the app ids into dev / prod pairs
|
|
@@ -53,7 +53,7 @@ const getAppRows = (appId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
53
53
|
* Rows duplicates may exist across apps due to data import so they are not filtered out.
|
|
54
54
|
*/
|
|
55
55
|
exports.getUniqueRows = (appIds) => __awaiter(void 0, void 0, void 0, function* () {
|
|
56
|
-
let uniqueRows = [];
|
|
56
|
+
let uniqueRows = [], rowsByApp = {};
|
|
57
57
|
const pairs = getAppPairs(appIds);
|
|
58
58
|
for (let pair of Object.values(pairs)) {
|
|
59
59
|
let appRows = [];
|
|
@@ -73,7 +73,9 @@ exports.getUniqueRows = (appIds) => __awaiter(void 0, void 0, void 0, function*
|
|
|
73
73
|
// this can't be done on all rows because app import results in
|
|
74
74
|
// duplicate row ids across apps
|
|
75
75
|
// the array pre-concat is important to avoid stack overflow
|
|
76
|
-
|
|
76
|
+
const prodId = getProdAppID(pair.devId || pair.prodId);
|
|
77
|
+
rowsByApp[prodId] = [...new Set(appRows)];
|
|
78
|
+
uniqueRows = uniqueRows.concat(rowsByApp[prodId]);
|
|
77
79
|
}
|
|
78
|
-
return uniqueRows;
|
|
80
|
+
return { rows: uniqueRows, appRows: rowsByApp };
|
|
79
81
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/server",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.24-alpha.0",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -77,11 +77,11 @@
|
|
|
77
77
|
"license": "GPL-3.0",
|
|
78
78
|
"dependencies": {
|
|
79
79
|
"@apidevtools/swagger-parser": "10.0.3",
|
|
80
|
-
"@budibase/backend-core": "
|
|
81
|
-
"@budibase/client": "
|
|
82
|
-
"@budibase/pro": "2.0.
|
|
83
|
-
"@budibase/string-templates": "
|
|
84
|
-
"@budibase/types": "
|
|
80
|
+
"@budibase/backend-core": "2.0.24-alpha.0",
|
|
81
|
+
"@budibase/client": "2.0.24-alpha.0",
|
|
82
|
+
"@budibase/pro": "2.0.23",
|
|
83
|
+
"@budibase/string-templates": "2.0.24-alpha.0",
|
|
84
|
+
"@budibase/types": "2.0.24-alpha.0",
|
|
85
85
|
"@bull-board/api": "3.7.0",
|
|
86
86
|
"@bull-board/koa": "3.9.4",
|
|
87
87
|
"@elastic/elasticsearch": "7.10.0",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"to-json-schema": "0.2.5",
|
|
147
147
|
"uuid": "3.3.2",
|
|
148
148
|
"validate.js": "0.13.1",
|
|
149
|
-
"vm2": "3.9.
|
|
149
|
+
"vm2": "3.9.11",
|
|
150
150
|
"worker-farm": "1.7.0",
|
|
151
151
|
"xml2js": "0.4.23",
|
|
152
152
|
"yargs": "13.2.4",
|
|
@@ -199,5 +199,5 @@
|
|
|
199
199
|
"optionalDependencies": {
|
|
200
200
|
"oracledb": "5.3.0"
|
|
201
201
|
},
|
|
202
|
-
"gitHead": "
|
|
202
|
+
"gitHead": "0d274e3477fc01e01ec51c31140a0372f918408b"
|
|
203
203
|
}
|
|
@@ -360,7 +360,7 @@ const appPostCreate = async (ctx: any, app: App) => {
|
|
|
360
360
|
await creationEvents(ctx.request, app)
|
|
361
361
|
// app import & template creation
|
|
362
362
|
if (ctx.request.body.useTemplate === "true") {
|
|
363
|
-
const rows = await getUniqueRows([app.appId])
|
|
363
|
+
const { rows } = await getUniqueRows([app.appId])
|
|
364
364
|
const rowCount = rows ? rows.length : 0
|
|
365
365
|
if (rowCount) {
|
|
366
366
|
try {
|
|
@@ -494,7 +494,7 @@ const destroyApp = async (ctx: any) => {
|
|
|
494
494
|
}
|
|
495
495
|
|
|
496
496
|
const preDestroyApp = async (ctx: any) => {
|
|
497
|
-
const rows = await getUniqueRows([ctx.params.appId])
|
|
497
|
+
const { rows } = await getUniqueRows([ctx.params.appId])
|
|
498
498
|
ctx.rowCount = rows.length
|
|
499
499
|
}
|
|
500
500
|
|
|
@@ -153,7 +153,10 @@ export async function preview(ctx: any) {
|
|
|
153
153
|
auth: { ...authConfigCtx },
|
|
154
154
|
},
|
|
155
155
|
})
|
|
156
|
-
|
|
156
|
+
|
|
157
|
+
const { rows, keys, info, extra } = await quotas.addQuery(runFn, {
|
|
158
|
+
datasourceId: datasource._id,
|
|
159
|
+
})
|
|
157
160
|
const schemaFields: any = {}
|
|
158
161
|
if (rows?.length > 0) {
|
|
159
162
|
for (let key of [...new Set(keys)] as string[]) {
|
|
@@ -234,7 +237,9 @@ async function execute(
|
|
|
234
237
|
},
|
|
235
238
|
})
|
|
236
239
|
|
|
237
|
-
const { rows, pagination, extra } = await quotas.addQuery(runFn
|
|
240
|
+
const { rows, pagination, extra } = await quotas.addQuery(runFn, {
|
|
241
|
+
datasourceId: datasource._id,
|
|
242
|
+
})
|
|
238
243
|
// remove the raw from execution incase transformer being used to hide data
|
|
239
244
|
if (extra?.raw) {
|
|
240
245
|
delete extra.raw
|
|
@@ -31,8 +31,11 @@ export async function patch(ctx: any): Promise<any> {
|
|
|
31
31
|
return save(ctx)
|
|
32
32
|
}
|
|
33
33
|
try {
|
|
34
|
-
const { row, table } = await quotas.addQuery(
|
|
35
|
-
pickApi(tableId).patch(ctx)
|
|
34
|
+
const { row, table } = await quotas.addQuery(
|
|
35
|
+
() => pickApi(tableId).patch(ctx),
|
|
36
|
+
{
|
|
37
|
+
datasourceId: tableId,
|
|
38
|
+
}
|
|
36
39
|
)
|
|
37
40
|
ctx.status = 200
|
|
38
41
|
ctx.eventEmitter &&
|
|
@@ -54,7 +57,9 @@ export const save = async (ctx: any) => {
|
|
|
54
57
|
}
|
|
55
58
|
try {
|
|
56
59
|
const { row, table } = await quotas.addRow(() =>
|
|
57
|
-
quotas.addQuery(() => pickApi(tableId).save(ctx)
|
|
60
|
+
quotas.addQuery(() => pickApi(tableId).save(ctx), {
|
|
61
|
+
datasourceId: tableId,
|
|
62
|
+
})
|
|
58
63
|
)
|
|
59
64
|
ctx.status = 200
|
|
60
65
|
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:save`, appId, row, table)
|
|
@@ -68,7 +73,9 @@ export const save = async (ctx: any) => {
|
|
|
68
73
|
export async function fetchView(ctx: any) {
|
|
69
74
|
const tableId = getTableId(ctx)
|
|
70
75
|
try {
|
|
71
|
-
ctx.body = await quotas.addQuery(() => pickApi(tableId).fetchView(ctx)
|
|
76
|
+
ctx.body = await quotas.addQuery(() => pickApi(tableId).fetchView(ctx), {
|
|
77
|
+
datasourceId: tableId,
|
|
78
|
+
})
|
|
72
79
|
} catch (err) {
|
|
73
80
|
ctx.throw(400, err)
|
|
74
81
|
}
|
|
@@ -77,7 +84,9 @@ export async function fetchView(ctx: any) {
|
|
|
77
84
|
export async function fetch(ctx: any) {
|
|
78
85
|
const tableId = getTableId(ctx)
|
|
79
86
|
try {
|
|
80
|
-
ctx.body = await quotas.addQuery(() => pickApi(tableId).fetch(ctx)
|
|
87
|
+
ctx.body = await quotas.addQuery(() => pickApi(tableId).fetch(ctx), {
|
|
88
|
+
datasourceId: tableId,
|
|
89
|
+
})
|
|
81
90
|
} catch (err) {
|
|
82
91
|
ctx.throw(400, err)
|
|
83
92
|
}
|
|
@@ -86,7 +95,9 @@ export async function fetch(ctx: any) {
|
|
|
86
95
|
export async function find(ctx: any) {
|
|
87
96
|
const tableId = getTableId(ctx)
|
|
88
97
|
try {
|
|
89
|
-
ctx.body = await quotas.addQuery(() => pickApi(tableId).find(ctx)
|
|
98
|
+
ctx.body = await quotas.addQuery(() => pickApi(tableId).find(ctx), {
|
|
99
|
+
datasourceId: tableId,
|
|
100
|
+
})
|
|
90
101
|
} catch (err) {
|
|
91
102
|
ctx.throw(400, err)
|
|
92
103
|
}
|
|
@@ -98,8 +109,11 @@ export async function destroy(ctx: any) {
|
|
|
98
109
|
const tableId = getTableId(ctx)
|
|
99
110
|
let response, row
|
|
100
111
|
if (inputs.rows) {
|
|
101
|
-
let { rows } = await quotas.addQuery(
|
|
102
|
-
pickApi(tableId).bulkDestroy(ctx)
|
|
112
|
+
let { rows } = await quotas.addQuery(
|
|
113
|
+
() => pickApi(tableId).bulkDestroy(ctx),
|
|
114
|
+
{
|
|
115
|
+
datasourceId: tableId,
|
|
116
|
+
}
|
|
103
117
|
)
|
|
104
118
|
await quotas.removeRows(rows.length)
|
|
105
119
|
response = rows
|
|
@@ -107,7 +121,9 @@ export async function destroy(ctx: any) {
|
|
|
107
121
|
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row)
|
|
108
122
|
}
|
|
109
123
|
} else {
|
|
110
|
-
let resp = await quotas.addQuery(() => pickApi(tableId).destroy(ctx)
|
|
124
|
+
let resp = await quotas.addQuery(() => pickApi(tableId).destroy(ctx), {
|
|
125
|
+
datasourceId: tableId,
|
|
126
|
+
})
|
|
111
127
|
await quotas.removeRow()
|
|
112
128
|
response = resp.response
|
|
113
129
|
row = resp.row
|
|
@@ -123,7 +139,9 @@ export async function search(ctx: any) {
|
|
|
123
139
|
const tableId = getTableId(ctx)
|
|
124
140
|
try {
|
|
125
141
|
ctx.status = 200
|
|
126
|
-
ctx.body = await quotas.addQuery(() => pickApi(tableId).search(ctx)
|
|
142
|
+
ctx.body = await quotas.addQuery(() => pickApi(tableId).search(ctx), {
|
|
143
|
+
datasourceId: tableId,
|
|
144
|
+
})
|
|
127
145
|
} catch (err) {
|
|
128
146
|
ctx.throw(400, err)
|
|
129
147
|
}
|
|
@@ -141,8 +159,11 @@ export async function validate(ctx: any) {
|
|
|
141
159
|
export async function fetchEnrichedRow(ctx: any) {
|
|
142
160
|
const tableId = getTableId(ctx)
|
|
143
161
|
try {
|
|
144
|
-
ctx.body = await quotas.addQuery(
|
|
145
|
-
pickApi(tableId).fetchEnrichedRow(ctx)
|
|
162
|
+
ctx.body = await quotas.addQuery(
|
|
163
|
+
() => pickApi(tableId).fetchEnrichedRow(ctx),
|
|
164
|
+
{
|
|
165
|
+
datasourceId: tableId,
|
|
166
|
+
}
|
|
146
167
|
)
|
|
147
168
|
} catch (err) {
|
|
148
169
|
ctx.throw(400, err)
|
|
@@ -152,7 +173,9 @@ export async function fetchEnrichedRow(ctx: any) {
|
|
|
152
173
|
export const exportRows = async (ctx: any) => {
|
|
153
174
|
const tableId = getTableId(ctx)
|
|
154
175
|
try {
|
|
155
|
-
ctx.body = await quotas.addQuery(() => pickApi(tableId).exportRows(ctx)
|
|
176
|
+
ctx.body = await quotas.addQuery(() => pickApi(tableId).exportRows(ctx), {
|
|
177
|
+
datasourceId: tableId,
|
|
178
|
+
})
|
|
156
179
|
} catch (err) {
|
|
157
180
|
ctx.throw(400, err)
|
|
158
181
|
}
|
|
@@ -153,7 +153,9 @@ export async function destroy(ctx: any) {
|
|
|
153
153
|
await db.bulkDocs(
|
|
154
154
|
rows.rows.map((row: any) => ({ ...row.doc, _deleted: true }))
|
|
155
155
|
)
|
|
156
|
-
await quotas.removeRows(rows.rows.length
|
|
156
|
+
await quotas.removeRows(rows.rows.length, {
|
|
157
|
+
tableId: ctx.params.tableId,
|
|
158
|
+
})
|
|
157
159
|
|
|
158
160
|
// update linked rows
|
|
159
161
|
await updateLinks({
|
|
@@ -148,7 +148,9 @@ export async function handleDataImport(user: any, table: any, dataImport: any) {
|
|
|
148
148
|
finalData.push(row)
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
await quotas.addRows(finalData.length, () => db.bulkDocs(finalData)
|
|
151
|
+
await quotas.addRows(finalData.length, () => db.bulkDocs(finalData), {
|
|
152
|
+
tableId: table._id,
|
|
153
|
+
})
|
|
152
154
|
await events.rows.imported(table, "csv", finalData.length)
|
|
153
155
|
return table
|
|
154
156
|
}
|
|
@@ -34,18 +34,13 @@ describe("/rows", () => {
|
|
|
34
34
|
.expect(status)
|
|
35
35
|
|
|
36
36
|
const getRowUsage = async () => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
)
|
|
37
|
+
const { total } = await config.doInContext(null, () => quotas.getCurrentUsageValues(QuotaUsageType.STATIC, StaticQuotaName.ROWS))
|
|
38
|
+
return total
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
const getQueryUsage = async () => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
QuotaUsageType.MONTHLY,
|
|
46
|
-
MonthlyQuotaName.QUERIES
|
|
47
|
-
)
|
|
48
|
-
)
|
|
42
|
+
const { total } = await config.doInContext(null, () => quotas.getCurrentUsageValues(QuotaUsageType.MONTHLY, MonthlyQuotaName.QUERIES))
|
|
43
|
+
return total
|
|
49
44
|
}
|
|
50
45
|
|
|
51
46
|
const assertRowUsage = async expected => {
|
|
@@ -60,26 +55,26 @@ describe("/rows", () => {
|
|
|
60
55
|
|
|
61
56
|
describe("save, load, update", () => {
|
|
62
57
|
it("returns a success message when the row is created", async () => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
58
|
+
const rowUsage = await getRowUsage()
|
|
59
|
+
const queryUsage = await getQueryUsage()
|
|
60
|
+
|
|
61
|
+
const res = await request
|
|
62
|
+
.post(`/api/${row.tableId}/rows`)
|
|
63
|
+
.send(row)
|
|
64
|
+
.set(config.defaultHeaders())
|
|
65
|
+
.expect('Content-Type', /json/)
|
|
66
|
+
.expect(200)
|
|
67
|
+
expect(res.res.statusMessage).toEqual(`${table.name} saved successfully`)
|
|
68
|
+
expect(res.body.name).toEqual("Test Contact")
|
|
69
|
+
expect(res.body._rev).toBeDefined()
|
|
70
|
+
await assertRowUsage(rowUsage + 1)
|
|
71
|
+
await assertQueryUsage(queryUsage + 1)
|
|
77
72
|
})
|
|
78
73
|
|
|
79
74
|
it("updates a row successfully", async () => {
|
|
80
75
|
const existing = await config.createRow()
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
const rowUsage = await getRowUsage()
|
|
77
|
+
const queryUsage = await getQueryUsage()
|
|
83
78
|
|
|
84
79
|
const res = await request
|
|
85
80
|
.post(`/api/${table._id}/rows`)
|
|
@@ -97,8 +92,8 @@ describe("/rows", () => {
|
|
|
97
92
|
`${table.name} updated successfully.`
|
|
98
93
|
)
|
|
99
94
|
expect(res.body.name).toEqual("Updated Name")
|
|
100
|
-
|
|
101
|
-
|
|
95
|
+
await assertRowUsage(rowUsage)
|
|
96
|
+
await assertQueryUsage(queryUsage + 1)
|
|
102
97
|
})
|
|
103
98
|
|
|
104
99
|
it("should load a row", async () => {
|
|
@@ -66,9 +66,9 @@ exports.run = async function ({ inputs, appId, emitter }) {
|
|
|
66
66
|
}
|
|
67
67
|
const tableId = inputs.row.tableId
|
|
68
68
|
|
|
69
|
-
// clear any
|
|
69
|
+
// clear any undefined, null or empty string properties so that they aren't updated
|
|
70
70
|
for (let propKey of Object.keys(inputs.row)) {
|
|
71
|
-
if (
|
|
71
|
+
if (inputs.row[propKey] == null || inputs.row[propKey] === "") {
|
|
72
72
|
delete inputs.row[propKey]
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -29,16 +29,11 @@ describe("Run through some parts of the automations system", () => {
|
|
|
29
29
|
afterAll(setup.afterAll)
|
|
30
30
|
|
|
31
31
|
it("should be able to init in builder", async () => {
|
|
32
|
-
await triggers.externalTrigger(basicAutomation(), { a: 1 })
|
|
32
|
+
await triggers.externalTrigger(basicAutomation(), { a: 1, appId: "app_123" })
|
|
33
33
|
await wait(100)
|
|
34
34
|
expect(thread.execute).toHaveBeenCalled()
|
|
35
35
|
})
|
|
36
36
|
|
|
37
|
-
it("should be able to init in prod", async () => {
|
|
38
|
-
await triggers.externalTrigger(basicAutomation(), { a: 1 })
|
|
39
|
-
await wait(100)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
37
|
it("should check coercion", async () => {
|
|
43
38
|
const table = await config.createTable()
|
|
44
39
|
const automation = basicAutomation()
|
package/src/automations/utils.ts
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
getAppId,
|
|
14
14
|
getProdAppDB,
|
|
15
15
|
} from "@budibase/backend-core/context"
|
|
16
|
-
import {
|
|
16
|
+
import { context } from "@budibase/backend-core"
|
|
17
17
|
import { quotas } from "@budibase/pro"
|
|
18
18
|
import { Automation } from "@budibase/types"
|
|
19
19
|
|
|
@@ -28,12 +28,14 @@ const jobMessage = (job: any, message: string) => {
|
|
|
28
28
|
|
|
29
29
|
export async function processEvent(job: any) {
|
|
30
30
|
try {
|
|
31
|
+
const automationId = job.data.automation._id
|
|
31
32
|
console.log(jobMessage(job, "running"))
|
|
32
33
|
// need to actually await these so that an error can be captured properly
|
|
33
|
-
|
|
34
|
-
return await tenancy.doInTenant(tenantId, async () => {
|
|
34
|
+
return await context.doInContext(job.data.event.appId, async () => {
|
|
35
35
|
const runFn = () => Runner.run(job)
|
|
36
|
-
return quotas.addAutomation(runFn
|
|
36
|
+
return quotas.addAutomation(runFn, {
|
|
37
|
+
automationId,
|
|
38
|
+
})
|
|
37
39
|
})
|
|
38
40
|
} catch (err) {
|
|
39
41
|
const errJson = JSON.stringify(err)
|
package/src/db/utils.js
CHANGED
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
import { runQuotaMigration } from "./usageQuotas"
|
|
2
2
|
import * as syncApps from "./usageQuotas/syncApps"
|
|
3
3
|
import * as syncRows from "./usageQuotas/syncRows"
|
|
4
|
+
import * as syncPlugins from "./usageQuotas/syncPlugins"
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
-
* January 2022
|
|
8
|
-
*
|
|
9
|
-
* Description:
|
|
10
|
-
* Synchronise the app and row quotas to the state of the db after it was
|
|
11
|
-
* discovered that the quota resets were still in place and the row quotas
|
|
12
|
-
* weren't being decremented correctly.
|
|
7
|
+
* Synchronise quotas to the state of the db.
|
|
13
8
|
*/
|
|
14
|
-
|
|
15
9
|
export const run = async () => {
|
|
16
10
|
await runQuotaMigration(async () => {
|
|
17
11
|
await syncApps.run()
|
|
18
12
|
await syncRows.run()
|
|
13
|
+
await syncPlugins.run()
|
|
19
14
|
})
|
|
20
15
|
}
|
|
@@ -2,11 +2,13 @@ const TestConfig = require("../../../tests/utilities/TestConfiguration")
|
|
|
2
2
|
|
|
3
3
|
const syncApps = jest.fn()
|
|
4
4
|
const syncRows = jest.fn()
|
|
5
|
+
const syncPlugins = jest.fn()
|
|
5
6
|
|
|
6
7
|
jest.mock("../usageQuotas/syncApps", () => ({ run: syncApps }) )
|
|
7
8
|
jest.mock("../usageQuotas/syncRows", () => ({ run: syncRows }) )
|
|
9
|
+
jest.mock("../usageQuotas/syncPlugins", () => ({ run: syncPlugins }) )
|
|
8
10
|
|
|
9
|
-
const migration = require("../
|
|
11
|
+
const migration = require("../syncQuotas")
|
|
10
12
|
|
|
11
13
|
describe("run", () => {
|
|
12
14
|
let config = new TestConfig(false)
|
|
@@ -17,9 +19,10 @@ describe("run", () => {
|
|
|
17
19
|
|
|
18
20
|
afterAll(config.end)
|
|
19
21
|
|
|
20
|
-
it("
|
|
22
|
+
it("run", async () => {
|
|
21
23
|
await migration.run()
|
|
22
24
|
expect(syncApps).toHaveBeenCalledTimes(1)
|
|
23
25
|
expect(syncRows).toHaveBeenCalledTimes(1)
|
|
26
|
+
expect(syncPlugins).toHaveBeenCalledTimes(1)
|
|
24
27
|
})
|
|
25
28
|
})
|
|
@@ -2,19 +2,28 @@ import { getTenantId } from "@budibase/backend-core/tenancy"
|
|
|
2
2
|
import { getAllApps } from "@budibase/backend-core/db"
|
|
3
3
|
import { getUniqueRows } from "../../../utilities/usageQuota/rows"
|
|
4
4
|
import { quotas } from "@budibase/pro"
|
|
5
|
-
import {
|
|
5
|
+
import { StaticQuotaName, QuotaUsageType } from "@budibase/types"
|
|
6
6
|
|
|
7
7
|
export const run = async () => {
|
|
8
8
|
// get all rows in all apps
|
|
9
|
-
// @ts-ignore
|
|
10
9
|
const allApps = await getAllApps({ all: true })
|
|
11
|
-
// @ts-ignore
|
|
12
10
|
const appIds = allApps ? allApps.map((app: { appId: any }) => app.appId) : []
|
|
13
|
-
const
|
|
14
|
-
|
|
11
|
+
const { appRows } = await getUniqueRows(appIds)
|
|
12
|
+
|
|
13
|
+
// get the counts per app
|
|
14
|
+
const counts: { [key: string]: number } = {}
|
|
15
|
+
let rowCount = 0
|
|
16
|
+
Object.entries(appRows).forEach(([appId, rows]) => {
|
|
17
|
+
counts[appId] = rows.length
|
|
18
|
+
rowCount += rows.length
|
|
19
|
+
})
|
|
15
20
|
|
|
16
21
|
// sync row count
|
|
17
22
|
const tenantId = getTenantId()
|
|
18
23
|
console.log(`[Tenant: ${tenantId}] Syncing row count: ${rowCount}`)
|
|
19
|
-
await quotas.
|
|
24
|
+
await quotas.setUsagePerApp(
|
|
25
|
+
counts,
|
|
26
|
+
StaticQuotaName.ROWS,
|
|
27
|
+
QuotaUsageType.STATIC
|
|
28
|
+
)
|
|
20
29
|
}
|
|
@@ -2,6 +2,7 @@ import TestConfig from "../../../../tests/utilities/TestConfiguration"
|
|
|
2
2
|
import * as syncRows from "../syncRows"
|
|
3
3
|
import { quotas } from "@budibase/pro"
|
|
4
4
|
import { QuotaUsageType, StaticQuotaName } from "@budibase/types"
|
|
5
|
+
const { getProdAppID } = require("@budibase/backend-core/db")
|
|
5
6
|
|
|
6
7
|
describe("syncRows", () => {
|
|
7
8
|
let config = new TestConfig(false)
|
|
@@ -22,10 +23,11 @@ describe("syncRows", () => {
|
|
|
22
23
|
expect(usageDoc.usageQuota.rows).toEqual(300)
|
|
23
24
|
|
|
24
25
|
// app 1
|
|
26
|
+
const app1 = config.app
|
|
25
27
|
await config.createTable()
|
|
26
28
|
await config.createRow()
|
|
27
29
|
// app 2
|
|
28
|
-
await config.createApp("second-app")
|
|
30
|
+
const app2 = await config.createApp("second-app")
|
|
29
31
|
await config.createTable()
|
|
30
32
|
await config.createRow()
|
|
31
33
|
await config.createRow()
|
|
@@ -36,6 +38,12 @@ describe("syncRows", () => {
|
|
|
36
38
|
// assert the migration worked
|
|
37
39
|
usageDoc = await quotas.getQuotaUsage()
|
|
38
40
|
expect(usageDoc.usageQuota.rows).toEqual(3)
|
|
41
|
+
expect(usageDoc.apps?.[getProdAppID(app1.appId)].usageQuota.rows).toEqual(
|
|
42
|
+
1
|
|
43
|
+
)
|
|
44
|
+
expect(usageDoc.apps?.[getProdAppID(app2.appId)].usageQuota.rows).toEqual(
|
|
45
|
+
2
|
|
46
|
+
)
|
|
39
47
|
})
|
|
40
48
|
})
|
|
41
49
|
})
|
package/src/migrations/index.ts
CHANGED
|
@@ -4,11 +4,9 @@ import env from "../environment"
|
|
|
4
4
|
|
|
5
5
|
// migration functions
|
|
6
6
|
import * as userEmailViewCasing from "./functions/userEmailViewCasing"
|
|
7
|
-
import * as
|
|
7
|
+
import * as syncQuotas from "./functions/syncQuotas"
|
|
8
8
|
import * as appUrls from "./functions/appUrls"
|
|
9
9
|
import * as backfill from "./functions/backfill"
|
|
10
|
-
import * as pluginCount from "./functions/pluginCount"
|
|
11
|
-
|
|
12
10
|
/**
|
|
13
11
|
* Populate the migration function and additional configuration from
|
|
14
12
|
* the static migration definitions.
|
|
@@ -26,10 +24,10 @@ export const buildMigrations = () => {
|
|
|
26
24
|
})
|
|
27
25
|
break
|
|
28
26
|
}
|
|
29
|
-
case MigrationName.
|
|
27
|
+
case MigrationName.SYNC_QUOTAS: {
|
|
30
28
|
serverMigrations.push({
|
|
31
29
|
...definition,
|
|
32
|
-
fn:
|
|
30
|
+
fn: syncQuotas.run,
|
|
33
31
|
})
|
|
34
32
|
break
|
|
35
33
|
}
|
|
@@ -69,16 +67,6 @@ export const buildMigrations = () => {
|
|
|
69
67
|
})
|
|
70
68
|
break
|
|
71
69
|
}
|
|
72
|
-
case MigrationName.PLUGIN_COUNT: {
|
|
73
|
-
if (env.SELF_HOSTED) {
|
|
74
|
-
serverMigrations.push({
|
|
75
|
-
...definition,
|
|
76
|
-
fn: pluginCount.run,
|
|
77
|
-
silent: !!env.SELF_HOSTED,
|
|
78
|
-
preventRetry: false,
|
|
79
|
-
})
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
70
|
}
|
|
83
71
|
}
|
|
84
72
|
|
|
@@ -2,6 +2,7 @@ const { getRowParams, USER_METDATA_PREFIX } = require("../../db/utils")
|
|
|
2
2
|
const {
|
|
3
3
|
isDevAppID,
|
|
4
4
|
getDevelopmentAppID,
|
|
5
|
+
getProdAppID,
|
|
5
6
|
doWithDB,
|
|
6
7
|
} = require("@budibase/backend-core/db")
|
|
7
8
|
|
|
@@ -52,7 +53,8 @@ const getAppRows = async appId => {
|
|
|
52
53
|
* Rows duplicates may exist across apps due to data import so they are not filtered out.
|
|
53
54
|
*/
|
|
54
55
|
exports.getUniqueRows = async appIds => {
|
|
55
|
-
let uniqueRows = []
|
|
56
|
+
let uniqueRows = [],
|
|
57
|
+
rowsByApp = {}
|
|
56
58
|
const pairs = getAppPairs(appIds)
|
|
57
59
|
|
|
58
60
|
for (let pair of Object.values(pairs)) {
|
|
@@ -73,8 +75,10 @@ exports.getUniqueRows = async appIds => {
|
|
|
73
75
|
// this can't be done on all rows because app import results in
|
|
74
76
|
// duplicate row ids across apps
|
|
75
77
|
// the array pre-concat is important to avoid stack overflow
|
|
76
|
-
|
|
78
|
+
const prodId = getProdAppID(pair.devId || pair.prodId)
|
|
79
|
+
rowsByApp[prodId] = [...new Set(appRows)]
|
|
80
|
+
uniqueRows = uniqueRows.concat(rowsByApp[prodId])
|
|
77
81
|
}
|
|
78
82
|
|
|
79
|
-
return uniqueRows
|
|
83
|
+
return { rows: uniqueRows, appRows: rowsByApp }
|
|
80
84
|
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { tenancy, logging } from "@budibase/backend-core"
|
|
2
|
-
import { plugins } from "@budibase/pro"
|
|
3
|
-
|
|
4
|
-
export const run = async () => {
|
|
5
|
-
try {
|
|
6
|
-
await tenancy.doInTenant(tenancy.DEFAULT_TENANT_ID, async () => {
|
|
7
|
-
await plugins.checkPluginQuotas()
|
|
8
|
-
})
|
|
9
|
-
} catch (err) {
|
|
10
|
-
logging.logAlert("Failed to update plugin quotas", err)
|
|
11
|
-
}
|
|
12
|
-
}
|