@budibase/server 1.0.49-alpha.0 → 1.0.49-alpha.4
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.dd9e386f.css → index.83c0944f.css} +1 -1
- package/builder/assets/{index.8184eed9.js → index.f763d886.js} +206 -205
- package/builder/assets/{vendor.3bd2f661.js → vendor.d526bfe8.js} +1 -1
- package/builder/index.html +3 -3
- package/coverage/clover.xml +1743 -1610
- package/coverage/coverage-final.json +90 -89
- 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 +106 -106
- 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 +1 -1
- package/coverage/lcov-report/api/controllers/index.html +27 -12
- 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/{migrations/usageQuotas/syncApps.js.html → api/controllers/migrations.js.html} +30 -45
- 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 +6 -6
- 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 +16 -16
- package/coverage/lcov-report/api/controllers/row/index.html +40 -25
- package/coverage/lcov-report/api/controllers/row/index.js.html +13 -13
- package/coverage/lcov-report/api/controllers/row/internal.js.html +83 -146
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +41 -17
- package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +551 -0
- package/coverage/lcov-report/api/controllers/row/utils.js.html +13 -13
- 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 +629 -0
- package/coverage/lcov-report/api/controllers/table/external.js.html +12 -12
- package/coverage/lcov-report/api/controllers/table/index.html +45 -30
- package/coverage/lcov-report/api/controllers/table/index.js.html +23 -65
- package/coverage/lcov-report/api/controllers/table/internal.js.html +33 -15
- package/coverage/lcov-report/api/controllers/table/utils.js.html +161 -41
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +20 -20
- 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 +11 -11
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +7 -7
- package/coverage/lcov-report/api/controllers/webhook.js.html +15 -15
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +3 -3
- 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 +22 -7
- package/coverage/lcov-report/api/routes/index.js.html +10 -4
- 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/{migrations/usageQuotas/index.js.html → api/routes/migrations.js.html} +25 -55
- 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/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 +1 -1
- package/coverage/lcov-report/automations/index.js.html +1 -1
- package/coverage/lcov-report/automations/steps/bash.js.html +6 -6
- 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 +32 -32
- package/coverage/lcov-report/constants/index.html +5 -5
- package/coverage/lcov-report/constants/index.js.html +42 -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/client.js.html +18 -18
- package/coverage/lcov-report/db/inMemoryView.js.html +7 -7
- package/coverage/lcov-report/db/index.html +1 -1
- package/coverage/lcov-report/db/index.js.html +3 -3
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +7 -7
- package/coverage/lcov-report/db/linkedRows/index.html +10 -10
- package/coverage/lcov-report/db/linkedRows/index.js.html +26 -29
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +13 -13
- package/coverage/lcov-report/db/newid.js.html +4 -4
- package/coverage/lcov-report/db/utils.js.html +71 -71
- 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 +61 -76
- 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 +1 -1
- package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
- package/coverage/lcov-report/middleware/index.html +11 -11
- package/coverage/lcov-report/middleware/joi-validator.js.html +3 -3
- 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 +6 -12
- 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 +1 -1
- package/coverage/lcov-report/threads/index.js.html +10 -10
- package/coverage/lcov-report/threads/query.js.html +1 -1
- package/coverage/lcov-report/threads/utils.js.html +14 -14
- 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 +14 -14
- package/coverage/lcov-report/utilities/index.html +1 -1
- package/coverage/lcov-report/utilities/index.js.html +24 -24
- 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 +27 -27
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +80 -44
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +75 -27
- 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 +1 -1
- package/coverage/lcov-report/utilities/usageQuota/index.js.html +10 -10
- package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
- 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 +12 -12
- package/coverage/lcov.info +2545 -2257
- package/dist/api/controllers/application.js +18 -20
- package/dist/api/controllers/migrations.js +21 -0
- package/dist/api/controllers/row/internal.js +30 -53
- package/dist/api/controllers/row/internalSearch.js +12 -4
- package/dist/api/controllers/row/staticFormula.js +147 -0
- package/dist/api/controllers/table/bulkFormula.js +160 -0
- package/dist/api/controllers/table/index.js +3 -6
- package/dist/api/controllers/table/internal.js +7 -0
- package/dist/api/controllers/table/utils.js +32 -10
- package/dist/api/routes/index.js +2 -0
- package/dist/api/routes/migrations.js +9 -0
- package/dist/app.js +35 -5
- package/dist/constants/index.js +4 -0
- package/dist/db/linkedRows/index.js +4 -5
- package/dist/environment.js +1 -0
- package/dist/middleware/usageQuota.js +0 -2
- package/dist/migrations/functions/appUrls.js +46 -0
- package/dist/migrations/functions/quotas1.js +50 -0
- package/dist/migrations/{usageQuotas → functions/usageQuotas}/index.js +6 -10
- package/dist/migrations/{usageQuotas → functions/usageQuotas}/syncApps.js +11 -5
- package/dist/migrations/{usageQuotas → functions/usageQuotas}/syncRows.js +14 -8
- package/dist/migrations/functions/userEmailViewCasing.js +24 -0
- package/dist/migrations/index.js +62 -0
- package/dist/package.json +4 -4
- package/dist/tests/utilities/TestConfiguration.js +3 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/rowProcessor/index.js +18 -11
- package/dist/utilities/rowProcessor/utils.js +14 -4
- package/package.json +5 -5
- package/src/api/controllers/application.js +3 -3
- package/src/api/controllers/migrations.js +13 -0
- package/src/api/controllers/row/internal.js +29 -50
- package/src/api/controllers/row/internalSearch.js +12 -4
- package/src/api/controllers/row/staticFormula.js +157 -0
- package/src/api/controllers/table/bulkFormula.js +183 -0
- package/src/api/controllers/table/index.js +3 -17
- package/src/api/controllers/table/internal.js +7 -1
- package/src/api/controllers/table/utils.js +48 -8
- package/src/api/routes/index.js +2 -0
- package/src/api/routes/migrations.js +14 -0
- package/src/app.ts +18 -5
- package/src/constants/index.js +5 -0
- package/src/db/linkedRows/index.js +4 -5
- package/src/definitions/common.ts +3 -0
- package/src/environment.js +1 -0
- package/src/middleware/usageQuota.js +0 -2
- package/src/migrations/functions/appUrls.ts +34 -0
- package/src/migrations/functions/quotas1.ts +20 -0
- package/src/migrations/functions/tests/appUrls.spec.js +29 -0
- package/src/migrations/{tests/usageQuotas/index.spec.js → functions/tests/quotas1.spec.js} +5 -5
- package/src/migrations/functions/tests/userEmailViewCasing.spec.js +25 -0
- package/src/migrations/functions/usageQuotas/index.ts +8 -0
- package/src/migrations/{usageQuotas/syncApps.js → functions/usageQuotas/syncApps.ts} +3 -3
- package/src/migrations/{usageQuotas/syncRows.js → functions/usageQuotas/syncRows.ts} +5 -5
- package/src/migrations/{tests/usageQuotas → functions/usageQuotas/tests}/syncApps.spec.js +4 -4
- package/src/migrations/{tests/usageQuotas → functions/usageQuotas/tests}/syncRows.spec.js +4 -4
- package/src/migrations/functions/userEmailViewCasing.ts +13 -0
- package/src/migrations/index.ts +56 -0
- package/src/tests/utilities/TestConfiguration.js +4 -0
- package/src/utilities/rowProcessor/index.js +24 -12
- package/src/utilities/rowProcessor/utils.js +23 -7
- package/coverage/lcov-report/migrations/usageQuotas/index.html +0 -141
- package/coverage/lcov-report/migrations/usageQuotas/syncRows.js.html +0 -143
- package/src/migrations/usageQuotas/index.js +0 -24
|
@@ -175,6 +175,7 @@ function processAutoColumn(user, table, row, opts = { reprocessing: false, noAut
|
|
|
175
175
|
return { table, row };
|
|
176
176
|
}
|
|
177
177
|
exports.processAutoColumn = processAutoColumn;
|
|
178
|
+
exports.processFormulas = processFormulas;
|
|
178
179
|
/**
|
|
179
180
|
* This will coerce a value to the correct types based on the type transform map
|
|
180
181
|
* @param {object} row The value to coerce
|
|
@@ -218,11 +219,11 @@ exports.inputProcessing = (user = {}, table, row, opts = { noAutoRelationships:
|
|
|
218
219
|
}
|
|
219
220
|
continue;
|
|
220
221
|
}
|
|
221
|
-
//
|
|
222
|
-
// type coercion cannot completely remove the field, so have to do it here
|
|
222
|
+
// remove any formula values, they are to be generated
|
|
223
223
|
if (field.type === FieldTypes.FORMULA) {
|
|
224
224
|
delete clonedRow[key];
|
|
225
225
|
}
|
|
226
|
+
// otherwise coerce what is there to correct types
|
|
226
227
|
else {
|
|
227
228
|
clonedRow[key] = exports.coerce(value, field.type);
|
|
228
229
|
}
|
|
@@ -237,24 +238,23 @@ exports.inputProcessing = (user = {}, table, row, opts = { noAutoRelationships:
|
|
|
237
238
|
/**
|
|
238
239
|
* This function enriches the input rows with anything they are supposed to contain, for example
|
|
239
240
|
* link records or attachment links.
|
|
240
|
-
* @param {
|
|
241
|
+
* @param {string} appId the app in which the request is looking for enriched rows.
|
|
241
242
|
* @param {object} table the table from which these rows came from originally, this is used to determine
|
|
242
243
|
* the schema of the rows and then enrich.
|
|
243
244
|
* @param {object[]|object} rows the rows which are to be enriched.
|
|
244
245
|
* @param {object} opts used to set some options for the output, such as disabling relationship squashing.
|
|
245
246
|
* @returns {object[]|object} the enriched rows will be returned.
|
|
246
247
|
*/
|
|
247
|
-
exports.outputProcessing = (
|
|
248
|
-
const appId = ctx.appId;
|
|
248
|
+
exports.outputProcessing = ({ appId }, table, rows, opts = { squash: true }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
249
249
|
let wasArray = true;
|
|
250
250
|
if (!(rows instanceof Array)) {
|
|
251
251
|
rows = [rows];
|
|
252
252
|
wasArray = false;
|
|
253
253
|
}
|
|
254
254
|
// attach any linked row information
|
|
255
|
-
let enriched = yield linkRows.attachFullLinkedDocs(
|
|
255
|
+
let enriched = yield linkRows.attachFullLinkedDocs(appId, table, rows);
|
|
256
256
|
// process formulas
|
|
257
|
-
enriched = processFormulas(table, enriched);
|
|
257
|
+
enriched = processFormulas(table, enriched, { dynamic: true });
|
|
258
258
|
// update the attachments URL depending on hosting
|
|
259
259
|
for (let [property, column] of Object.entries(table.schema)) {
|
|
260
260
|
if (column.type === FieldTypes.ATTACHMENT) {
|
|
@@ -280,9 +280,11 @@ exports.outputProcessing = (ctx, table, rows, opts = { squash: true }) => __awai
|
|
|
280
280
|
* @param {any} row optional - the row being removed.
|
|
281
281
|
* @param {any} rows optional - if multiple rows being deleted can do this in bulk.
|
|
282
282
|
* @param {any} oldRow optional - if updating a row this will determine the difference.
|
|
283
|
+
* @param {any} oldTable optional - if updating a table, can supply the old table to look for
|
|
284
|
+
* deleted attachment columns.
|
|
283
285
|
* @return {Promise<void>} When all attachments have been removed this will return.
|
|
284
286
|
*/
|
|
285
|
-
exports.cleanupAttachments = (appId, table, { row, rows, oldRow }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
287
|
+
exports.cleanupAttachments = (appId, table, { row, rows, oldRow, oldTable }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
286
288
|
if (!isProdAppID(appId)) {
|
|
287
289
|
const prodAppId = getDeployedAppID(appId);
|
|
288
290
|
// if prod exists, then don't allow deleting
|
|
@@ -297,12 +299,17 @@ exports.cleanupAttachments = (appId, table, { row, rows, oldRow }) => __awaiter(
|
|
|
297
299
|
files = files.concat(row[key].map(attachment => attachment.key));
|
|
298
300
|
}
|
|
299
301
|
}
|
|
300
|
-
|
|
302
|
+
const schemaToUse = oldTable ? oldTable.schema : table.schema;
|
|
303
|
+
for (let [key, schema] of Object.entries(schemaToUse)) {
|
|
301
304
|
if (schema.type !== FieldTypes.ATTACHMENT) {
|
|
302
305
|
continue;
|
|
303
306
|
}
|
|
304
|
-
//
|
|
305
|
-
if (
|
|
307
|
+
// old table had this column, new table doesn't - delete it
|
|
308
|
+
if (oldTable && !table.schema[key]) {
|
|
309
|
+
rows.forEach(row => addFiles(row, key));
|
|
310
|
+
}
|
|
311
|
+
else if (oldRow && row) {
|
|
312
|
+
// if updating, need to manage the differences
|
|
306
313
|
files = files.concat(getRemovedAttachmentKeys(oldRow, row, key));
|
|
307
314
|
}
|
|
308
315
|
else if (row) {
|
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const { FieldTypes } = require("../../constants");
|
|
2
|
+
const { FieldTypes, FormulaTypes } = require("../../constants");
|
|
3
3
|
const { processStringSync } = require("@budibase/string-templates");
|
|
4
4
|
/**
|
|
5
5
|
* Looks through the rows provided and finds formulas - which it then processes.
|
|
6
6
|
*/
|
|
7
|
-
exports.processFormulas = (table, rows) => {
|
|
7
|
+
exports.processFormulas = (table, rows, { dynamic, contextRows } = { dynamic: true }) => {
|
|
8
8
|
const single = !Array.isArray(rows);
|
|
9
9
|
if (single) {
|
|
10
10
|
rows = [rows];
|
|
11
|
+
contextRows = contextRows ? [contextRows] : contextRows;
|
|
11
12
|
}
|
|
12
13
|
for (let [column, schema] of Object.entries(table.schema)) {
|
|
13
|
-
|
|
14
|
+
const isStatic = schema.formulaType === FormulaTypes.STATIC;
|
|
15
|
+
if (schema.type !== FieldTypes.FORMULA ||
|
|
16
|
+
(dynamic && isStatic) ||
|
|
17
|
+
(!dynamic && !isStatic)) {
|
|
14
18
|
continue;
|
|
15
19
|
}
|
|
16
20
|
// iterate through rows and process formula
|
|
17
|
-
|
|
21
|
+
for (let i = 0; i < rows.length; i++) {
|
|
22
|
+
if (schema.formula) {
|
|
23
|
+
let row = rows[i];
|
|
24
|
+
let context = contextRows ? contextRows[i] : row;
|
|
25
|
+
rows[i] = Object.assign(Object.assign({}, row), { [column]: processStringSync(schema.formula, context) });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
18
28
|
}
|
|
19
29
|
return single ? rows[0] : rows;
|
|
20
30
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/server",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "1.0.49-alpha.
|
|
4
|
+
"version": "1.0.49-alpha.4",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
"license": "GPL-3.0",
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@apidevtools/swagger-parser": "^10.0.3",
|
|
73
|
-
"@budibase/backend-core": "^1.0.49-alpha.
|
|
74
|
-
"@budibase/client": "^1.0.49-alpha.
|
|
75
|
-
"@budibase/string-templates": "^1.0.49-alpha.
|
|
73
|
+
"@budibase/backend-core": "^1.0.49-alpha.4",
|
|
74
|
+
"@budibase/client": "^1.0.49-alpha.4",
|
|
75
|
+
"@budibase/string-templates": "^1.0.49-alpha.4",
|
|
76
76
|
"@bull-board/api": "^3.7.0",
|
|
77
77
|
"@bull-board/koa": "^3.7.0",
|
|
78
78
|
"@elastic/elasticsearch": "7.10.0",
|
|
@@ -168,5 +168,5 @@
|
|
|
168
168
|
"optionalDependencies": {
|
|
169
169
|
"oracledb": "^5.3.0"
|
|
170
170
|
},
|
|
171
|
-
"gitHead": "
|
|
171
|
+
"gitHead": "c991f284e3be5257091f234bdde5abaf1d53d2be"
|
|
172
172
|
}
|
|
@@ -75,7 +75,7 @@ function getUserRoleId(ctx) {
|
|
|
75
75
|
: ctx.user.role._id
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
exports.getAppUrl = ctx => {
|
|
79
79
|
// construct the url
|
|
80
80
|
let url
|
|
81
81
|
if (ctx.request.body.url) {
|
|
@@ -219,7 +219,7 @@ exports.create = async ctx => {
|
|
|
219
219
|
const apps = await getAllApps(CouchDB, { dev: true })
|
|
220
220
|
const name = ctx.request.body.name
|
|
221
221
|
checkAppName(ctx, apps, name)
|
|
222
|
-
const url =
|
|
222
|
+
const url = exports.getAppUrl(ctx)
|
|
223
223
|
checkAppUrl(ctx, apps, url)
|
|
224
224
|
|
|
225
225
|
const { useTemplate, templateKey, templateString } = ctx.request.body
|
|
@@ -286,7 +286,7 @@ exports.update = async ctx => {
|
|
|
286
286
|
if (name) {
|
|
287
287
|
checkAppName(ctx, apps, name, ctx.params.appId)
|
|
288
288
|
}
|
|
289
|
-
const url = await getAppUrl(ctx)
|
|
289
|
+
const url = await exports.getAppUrl(ctx)
|
|
290
290
|
if (url) {
|
|
291
291
|
checkAppUrl(ctx, apps, url, ctx.params.appId)
|
|
292
292
|
ctx.request.body.url = url
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const { migrate, MIGRATIONS } = require("../../migrations")
|
|
2
|
+
|
|
3
|
+
exports.migrate = async ctx => {
|
|
4
|
+
const options = ctx.request.body
|
|
5
|
+
// don't await as can take a while, just return
|
|
6
|
+
migrate(options)
|
|
7
|
+
ctx.status = 200
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
exports.fetchDefinitions = async ctx => {
|
|
11
|
+
ctx.body = MIGRATIONS
|
|
12
|
+
ctx.status = 200
|
|
13
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const CouchDB = require("../../../db")
|
|
2
2
|
const linkRows = require("../../../db/linkedRows")
|
|
3
3
|
const {
|
|
4
|
-
getRowParams,
|
|
5
4
|
generateRowID,
|
|
5
|
+
getRowParams,
|
|
6
6
|
DocumentTypes,
|
|
7
7
|
InternalTables,
|
|
8
8
|
} = require("../../../db/utils")
|
|
@@ -10,11 +10,9 @@ const userController = require("../user")
|
|
|
10
10
|
const {
|
|
11
11
|
inputProcessing,
|
|
12
12
|
outputProcessing,
|
|
13
|
-
processAutoColumn,
|
|
14
13
|
cleanupAttachments,
|
|
15
14
|
} = require("../../../utilities/rowProcessor")
|
|
16
15
|
const { FieldTypes } = require("../../../constants")
|
|
17
|
-
const { isEqual } = require("lodash")
|
|
18
16
|
const { validate, findRow } = require("./utils")
|
|
19
17
|
const { fullSearch, paginatedSearch } = require("./internalSearch")
|
|
20
18
|
const { getGlobalUsersFromMetadata } = require("../../../utilities/global")
|
|
@@ -27,6 +25,7 @@ const {
|
|
|
27
25
|
getFromMemoryDoc,
|
|
28
26
|
} = require("../view/utils")
|
|
29
27
|
const { cloneDeep } = require("lodash/fp")
|
|
28
|
+
const { finaliseRow, updateRelatedFormula } = require("./staticFormula")
|
|
30
29
|
|
|
31
30
|
const CALCULATION_TYPES = {
|
|
32
31
|
SUM: "sum",
|
|
@@ -34,51 +33,6 @@ const CALCULATION_TYPES = {
|
|
|
34
33
|
STATS: "stats",
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
async function storeResponse(ctx, db, row, oldTable, table) {
|
|
38
|
-
row.type = "row"
|
|
39
|
-
// don't worry about rev, tables handle rev/lastID updates
|
|
40
|
-
// if another row has been written since processing this will
|
|
41
|
-
// handle the auto ID clash
|
|
42
|
-
if (!isEqual(oldTable, table)) {
|
|
43
|
-
try {
|
|
44
|
-
await db.put(table)
|
|
45
|
-
} catch (err) {
|
|
46
|
-
if (err.status === 409) {
|
|
47
|
-
const updatedTable = await db.get(table._id)
|
|
48
|
-
let response = processAutoColumn(null, updatedTable, row, {
|
|
49
|
-
reprocessing: true,
|
|
50
|
-
})
|
|
51
|
-
await db.put(response.table)
|
|
52
|
-
row = response.row
|
|
53
|
-
} else {
|
|
54
|
-
throw err
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
const response = await db.put(row)
|
|
59
|
-
row._rev = response.rev
|
|
60
|
-
// process the row before return, to include relationships
|
|
61
|
-
row = await outputProcessing(ctx, table, row, { squash: false })
|
|
62
|
-
return { row, table }
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// doesn't do the outputProcessing
|
|
66
|
-
async function getRawTableData(ctx, db, tableId) {
|
|
67
|
-
let rows
|
|
68
|
-
if (tableId === InternalTables.USER_METADATA) {
|
|
69
|
-
await userController.fetchMetadata(ctx)
|
|
70
|
-
rows = ctx.body
|
|
71
|
-
} else {
|
|
72
|
-
const response = await db.allDocs(
|
|
73
|
-
getRowParams(tableId, null, {
|
|
74
|
-
include_docs: true,
|
|
75
|
-
})
|
|
76
|
-
)
|
|
77
|
-
rows = response.rows.map(row => row.doc)
|
|
78
|
-
}
|
|
79
|
-
return rows
|
|
80
|
-
}
|
|
81
|
-
|
|
82
36
|
async function getView(db, viewName) {
|
|
83
37
|
let mainGetter = env.SELF_HOSTED ? getFromDesignDoc : getFromMemoryDoc
|
|
84
38
|
let secondaryGetter = env.SELF_HOSTED ? getFromMemoryDoc : getFromDesignDoc
|
|
@@ -105,6 +59,22 @@ async function getView(db, viewName) {
|
|
|
105
59
|
return viewInfo
|
|
106
60
|
}
|
|
107
61
|
|
|
62
|
+
async function getRawTableData(ctx, db, tableId) {
|
|
63
|
+
let rows
|
|
64
|
+
if (tableId === InternalTables.USER_METADATA) {
|
|
65
|
+
await userController.fetchMetadata(ctx)
|
|
66
|
+
rows = ctx.body
|
|
67
|
+
} else {
|
|
68
|
+
const response = await db.allDocs(
|
|
69
|
+
getRowParams(tableId, null, {
|
|
70
|
+
include_docs: true,
|
|
71
|
+
})
|
|
72
|
+
)
|
|
73
|
+
rows = response.rows.map(row => row.doc)
|
|
74
|
+
}
|
|
75
|
+
return rows
|
|
76
|
+
}
|
|
77
|
+
|
|
108
78
|
exports.patch = async ctx => {
|
|
109
79
|
const appId = ctx.appId
|
|
110
80
|
const db = new CouchDB(appId)
|
|
@@ -162,7 +132,10 @@ exports.patch = async ctx => {
|
|
|
162
132
|
return { row: ctx.body, table }
|
|
163
133
|
}
|
|
164
134
|
|
|
165
|
-
return
|
|
135
|
+
return finaliseRow(ctx.appId, table, row, {
|
|
136
|
+
oldTable: dbTable,
|
|
137
|
+
updateFormula: true,
|
|
138
|
+
})
|
|
166
139
|
}
|
|
167
140
|
|
|
168
141
|
exports.save = async function (ctx) {
|
|
@@ -196,7 +169,10 @@ exports.save = async function (ctx) {
|
|
|
196
169
|
table,
|
|
197
170
|
})
|
|
198
171
|
|
|
199
|
-
return
|
|
172
|
+
return finaliseRow(ctx.appId, table, row, {
|
|
173
|
+
oldTable: dbTable,
|
|
174
|
+
updateFormula: true,
|
|
175
|
+
})
|
|
200
176
|
}
|
|
201
177
|
|
|
202
178
|
exports.fetchView = async ctx => {
|
|
@@ -302,6 +278,8 @@ exports.destroy = async function (ctx) {
|
|
|
302
278
|
})
|
|
303
279
|
// remove any attachments that were on the row from object storage
|
|
304
280
|
await cleanupAttachments(appId, table, { row })
|
|
281
|
+
// remove any static formula
|
|
282
|
+
await updateRelatedFormula(appId, table, row)
|
|
305
283
|
|
|
306
284
|
let response
|
|
307
285
|
if (ctx.params.tableId === InternalTables.USER_METADATA) {
|
|
@@ -350,6 +328,7 @@ exports.bulkDestroy = async ctx => {
|
|
|
350
328
|
}
|
|
351
329
|
// remove any attachments that were on the rows from object storage
|
|
352
330
|
await cleanupAttachments(appId, table, { rows })
|
|
331
|
+
await updateRelatedFormula(appId, table, rows)
|
|
353
332
|
await Promise.all(updates)
|
|
354
333
|
return { response: { ok: true }, rows }
|
|
355
334
|
}
|
|
@@ -37,22 +37,30 @@ class QueryBuilder {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
setLimit(limit) {
|
|
40
|
-
|
|
40
|
+
if (limit != null) {
|
|
41
|
+
this.limit = limit
|
|
42
|
+
}
|
|
41
43
|
return this
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
setSort(sort) {
|
|
45
|
-
|
|
47
|
+
if (sort != null) {
|
|
48
|
+
this.sort = sort
|
|
49
|
+
}
|
|
46
50
|
return this
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
setSortOrder(sortOrder) {
|
|
50
|
-
|
|
54
|
+
if (sortOrder != null) {
|
|
55
|
+
this.sortOrder = sortOrder
|
|
56
|
+
}
|
|
51
57
|
return this
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
setSortType(sortType) {
|
|
55
|
-
|
|
61
|
+
if (sortType != null) {
|
|
62
|
+
this.sortType = sortType
|
|
63
|
+
}
|
|
56
64
|
return this
|
|
57
65
|
}
|
|
58
66
|
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
const CouchDB = require("../../../db")
|
|
2
|
+
const { getRowParams } = require("../../../db/utils")
|
|
3
|
+
const {
|
|
4
|
+
outputProcessing,
|
|
5
|
+
processAutoColumn,
|
|
6
|
+
processFormulas,
|
|
7
|
+
} = require("../../../utilities/rowProcessor")
|
|
8
|
+
const { FieldTypes, FormulaTypes } = require("../../../constants")
|
|
9
|
+
const { isEqual } = require("lodash")
|
|
10
|
+
const { cloneDeep } = require("lodash/fp")
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* This function runs through a list of enriched rows, looks at the rows which
|
|
14
|
+
* are related and then checks if they need the state of their formulas
|
|
15
|
+
* updated.
|
|
16
|
+
* NOTE: this will only for affect static formulas.
|
|
17
|
+
*/
|
|
18
|
+
exports.updateRelatedFormula = async (appId, table, enrichedRows) => {
|
|
19
|
+
const db = new CouchDB(appId)
|
|
20
|
+
// no formula to update, we're done
|
|
21
|
+
if (!table.relatedFormula) {
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
let promises = []
|
|
25
|
+
for (let enrichedRow of Array.isArray(enrichedRows)
|
|
26
|
+
? enrichedRows
|
|
27
|
+
: [enrichedRows]) {
|
|
28
|
+
// the related rows by tableId
|
|
29
|
+
let relatedRows = {}
|
|
30
|
+
for (let [key, field] of Object.entries(enrichedRow)) {
|
|
31
|
+
const columnDefinition = table.schema[key]
|
|
32
|
+
if (columnDefinition && columnDefinition.type === FieldTypes.LINK) {
|
|
33
|
+
const relatedTableId = columnDefinition.tableId
|
|
34
|
+
if (!relatedRows[relatedTableId]) {
|
|
35
|
+
relatedRows[relatedTableId] = []
|
|
36
|
+
}
|
|
37
|
+
relatedRows[relatedTableId] = relatedRows[relatedTableId].concat(field)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
for (let tableId of table.relatedFormula) {
|
|
41
|
+
let relatedTable
|
|
42
|
+
try {
|
|
43
|
+
// no rows to update, skip
|
|
44
|
+
if (!relatedRows[tableId] || relatedRows[tableId].length === 0) {
|
|
45
|
+
continue
|
|
46
|
+
}
|
|
47
|
+
relatedTable = await db.get(tableId)
|
|
48
|
+
} catch (err) {
|
|
49
|
+
// no error scenario, table doesn't seem to exist anymore, ignore
|
|
50
|
+
}
|
|
51
|
+
for (let column of Object.values(relatedTable.schema)) {
|
|
52
|
+
// needs updated in related rows
|
|
53
|
+
if (
|
|
54
|
+
column.type === FieldTypes.FORMULA &&
|
|
55
|
+
column.formulaType === FormulaTypes.STATIC
|
|
56
|
+
) {
|
|
57
|
+
// re-enrich rows for all the related, don't update the related formula for them
|
|
58
|
+
promises = promises.concat(
|
|
59
|
+
relatedRows[tableId].map(related =>
|
|
60
|
+
exports.finaliseRow(appId, relatedTable, related, {
|
|
61
|
+
updateFormula: false,
|
|
62
|
+
})
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
await Promise.all(promises)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
exports.updateAllFormulasInTable = async (appId, table) => {
|
|
73
|
+
const db = new CouchDB(appId)
|
|
74
|
+
// start by getting the raw rows (which will be written back to DB after update)
|
|
75
|
+
let rows = (
|
|
76
|
+
await db.allDocs(
|
|
77
|
+
getRowParams(table._id, null, {
|
|
78
|
+
include_docs: true,
|
|
79
|
+
})
|
|
80
|
+
)
|
|
81
|
+
).rows.map(row => row.doc)
|
|
82
|
+
// now enrich the rows, note the clone so that we have the base state of the
|
|
83
|
+
// rows so that we don't write any of the enriched information back
|
|
84
|
+
let enrichedRows = await outputProcessing({ appId }, table, cloneDeep(rows), {
|
|
85
|
+
squash: false,
|
|
86
|
+
})
|
|
87
|
+
const updatedRows = []
|
|
88
|
+
for (let row of rows) {
|
|
89
|
+
// find the enriched row, if found process the formulas
|
|
90
|
+
const enrichedRow = enrichedRows.find(enriched => enriched._id === row._id)
|
|
91
|
+
if (enrichedRow) {
|
|
92
|
+
const processed = processFormulas(table, cloneDeep(row), {
|
|
93
|
+
dynamic: false,
|
|
94
|
+
contextRows: enrichedRow,
|
|
95
|
+
})
|
|
96
|
+
// values have changed, need to add to bulk docs to update
|
|
97
|
+
if (!isEqual(processed, row)) {
|
|
98
|
+
updatedRows.push(processed)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
await db.bulkDocs(updatedRows)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* This function runs at the end of the save/patch functions of the row controller, all this
|
|
107
|
+
* really does is enrich the row, handle any static formula processing, then return the enriched
|
|
108
|
+
* row. The reason we need to return the enriched row is that the automation row created trigger
|
|
109
|
+
* expects the row to be totally enriched/contain all relationships.
|
|
110
|
+
*/
|
|
111
|
+
exports.finaliseRow = async (
|
|
112
|
+
appId,
|
|
113
|
+
table,
|
|
114
|
+
row,
|
|
115
|
+
{ oldTable, updateFormula } = { updateFormula: true }
|
|
116
|
+
) => {
|
|
117
|
+
const db = new CouchDB(appId)
|
|
118
|
+
row.type = "row"
|
|
119
|
+
// process the row before return, to include relationships
|
|
120
|
+
let enrichedRow = await outputProcessing({ appId }, table, cloneDeep(row), {
|
|
121
|
+
squash: false,
|
|
122
|
+
})
|
|
123
|
+
// use enriched row to generate formulas for saving, specifically only use as context
|
|
124
|
+
row = processFormulas(table, row, {
|
|
125
|
+
dynamic: false,
|
|
126
|
+
contextRows: enrichedRow,
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
// don't worry about rev, tables handle rev/lastID updates
|
|
130
|
+
// if another row has been written since processing this will
|
|
131
|
+
// handle the auto ID clash
|
|
132
|
+
if (oldTable && !isEqual(oldTable, table)) {
|
|
133
|
+
try {
|
|
134
|
+
await db.put(table)
|
|
135
|
+
} catch (err) {
|
|
136
|
+
if (err.status === 409) {
|
|
137
|
+
const updatedTable = await db.get(table._id)
|
|
138
|
+
let response = processAutoColumn(null, updatedTable, row, {
|
|
139
|
+
reprocessing: true,
|
|
140
|
+
})
|
|
141
|
+
await db.put(response.table)
|
|
142
|
+
row = response.row
|
|
143
|
+
} else {
|
|
144
|
+
throw err
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const response = await db.put(row)
|
|
149
|
+
// for response, calculate the formulas for the enriched row
|
|
150
|
+
enrichedRow._rev = response.rev
|
|
151
|
+
enrichedRow = await processFormulas(table, enrichedRow, { dynamic: false })
|
|
152
|
+
// this updates the related formulas in other rows based on the relations to this row
|
|
153
|
+
if (updateFormula) {
|
|
154
|
+
await exports.updateRelatedFormula(appId, table, enrichedRow)
|
|
155
|
+
}
|
|
156
|
+
return { row: enrichedRow, table }
|
|
157
|
+
}
|