@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
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
const CouchDB = require("../../../db")
|
|
2
|
+
const { FieldTypes, FormulaTypes } = require("../../../constants")
|
|
3
|
+
const { getAllInternalTables, clearColumns } = require("./utils")
|
|
4
|
+
const { doesContainStrings } = require("@budibase/string-templates")
|
|
5
|
+
const { cloneDeep } = require("lodash/fp")
|
|
6
|
+
const { isEqual, uniq } = require("lodash")
|
|
7
|
+
const { updateAllFormulasInTable } = require("../row/staticFormula")
|
|
8
|
+
|
|
9
|
+
function isStaticFormula(column) {
|
|
10
|
+
return (
|
|
11
|
+
column.type === FieldTypes.FORMULA &&
|
|
12
|
+
column.formulaType === FormulaTypes.STATIC
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* This retrieves the formula columns from a table schema that use a specified column name
|
|
18
|
+
* in the formula.
|
|
19
|
+
*/
|
|
20
|
+
function getFormulaThatUseColumn(table, columnNames) {
|
|
21
|
+
let formula = []
|
|
22
|
+
columnNames = Array.isArray(columnNames) ? columnNames : [columnNames]
|
|
23
|
+
for (let column of Object.values(table.schema)) {
|
|
24
|
+
// not a static formula, or doesn't contain a relationship
|
|
25
|
+
if (!isStaticFormula(column)) {
|
|
26
|
+
continue
|
|
27
|
+
}
|
|
28
|
+
if (!doesContainStrings(column.formula, columnNames)) {
|
|
29
|
+
continue
|
|
30
|
+
}
|
|
31
|
+
formula.push(column.name)
|
|
32
|
+
}
|
|
33
|
+
return formula
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* This functions checks for when a related table, column or related column is deleted, if any
|
|
38
|
+
* tables need to have the formula column removed.
|
|
39
|
+
*/
|
|
40
|
+
async function checkIfFormulaNeedsCleared(
|
|
41
|
+
appId,
|
|
42
|
+
table,
|
|
43
|
+
{ oldTable, deletion }
|
|
44
|
+
) {
|
|
45
|
+
const db = new CouchDB(appId)
|
|
46
|
+
// start by retrieving all tables, remove the current table from the list
|
|
47
|
+
const tables = (await getAllInternalTables(appId)).filter(
|
|
48
|
+
tbl => tbl._id !== table._id
|
|
49
|
+
)
|
|
50
|
+
const schemaToUse = oldTable ? oldTable.schema : table.schema
|
|
51
|
+
let removedColumns = Object.values(schemaToUse).filter(
|
|
52
|
+
column => deletion || !table.schema[column.name]
|
|
53
|
+
)
|
|
54
|
+
// remove any formula columns that used related columns
|
|
55
|
+
for (let removed of removedColumns) {
|
|
56
|
+
let tableToUse = table
|
|
57
|
+
// if relationship, get the related table
|
|
58
|
+
if (removed.type === FieldTypes.LINK) {
|
|
59
|
+
tableToUse = tables.find(table => table._id === removed.tableId)
|
|
60
|
+
}
|
|
61
|
+
const columnsToDelete = getFormulaThatUseColumn(tableToUse, removed.name)
|
|
62
|
+
if (columnsToDelete.length > 0) {
|
|
63
|
+
await clearColumns(db, table, columnsToDelete)
|
|
64
|
+
}
|
|
65
|
+
// need a special case, where a column has been removed from this table, but was used
|
|
66
|
+
// in a different, related tables formula
|
|
67
|
+
if (!table.relatedFormula) {
|
|
68
|
+
continue
|
|
69
|
+
}
|
|
70
|
+
for (let relatedTableId of table.relatedFormula) {
|
|
71
|
+
const relatedColumns = Object.values(table.schema).filter(
|
|
72
|
+
column => column.tableId === relatedTableId
|
|
73
|
+
)
|
|
74
|
+
const relatedTable = tables.find(table => table._id === relatedTableId)
|
|
75
|
+
// look to see if the column was used in a relationship formula,
|
|
76
|
+
// relationships won't be used for this
|
|
77
|
+
if (relatedTable && relatedColumns && removed.type !== FieldTypes.LINK) {
|
|
78
|
+
let relatedFormulaToRemove = []
|
|
79
|
+
for (let column of relatedColumns) {
|
|
80
|
+
relatedFormulaToRemove = relatedFormulaToRemove.concat(
|
|
81
|
+
getFormulaThatUseColumn(relatedTable, [
|
|
82
|
+
column.fieldName,
|
|
83
|
+
removed.name,
|
|
84
|
+
])
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
if (relatedFormulaToRemove.length > 0) {
|
|
88
|
+
await clearColumns(db, relatedTable, uniq(relatedFormulaToRemove))
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* This function adds a note to related tables that they are
|
|
97
|
+
* used in a static formula - so that the link controller
|
|
98
|
+
* can manage hydrating related rows formula fields. This is
|
|
99
|
+
* specifically only for static formula.
|
|
100
|
+
*/
|
|
101
|
+
async function updateRelatedFormulaLinksOnTables(
|
|
102
|
+
appId,
|
|
103
|
+
table,
|
|
104
|
+
{ deletion } = { deletion: false }
|
|
105
|
+
) {
|
|
106
|
+
const db = new CouchDB(appId)
|
|
107
|
+
// start by retrieving all tables, remove the current table from the list
|
|
108
|
+
const tables = (await getAllInternalTables(appId)).filter(
|
|
109
|
+
tbl => tbl._id !== table._id
|
|
110
|
+
)
|
|
111
|
+
// clone the tables, so we can compare at end
|
|
112
|
+
const initialTables = cloneDeep(tables)
|
|
113
|
+
// first find the related column names
|
|
114
|
+
const relatedColumns = Object.values(table.schema).filter(
|
|
115
|
+
col => col.type === FieldTypes.LINK
|
|
116
|
+
)
|
|
117
|
+
// we start by removing the formula field from all tables
|
|
118
|
+
for (let otherTable of tables) {
|
|
119
|
+
if (!otherTable.relatedFormula) {
|
|
120
|
+
continue
|
|
121
|
+
}
|
|
122
|
+
const index = otherTable.relatedFormula.indexOf(table._id)
|
|
123
|
+
if (index !== -1) {
|
|
124
|
+
otherTable.relatedFormula.splice(index, 1)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// if deleting, just remove the table IDs, don't try add
|
|
128
|
+
if (!deletion) {
|
|
129
|
+
for (let relatedCol of relatedColumns) {
|
|
130
|
+
let columns = getFormulaThatUseColumn(table, relatedCol.name)
|
|
131
|
+
if (!columns || columns.length === 0) {
|
|
132
|
+
continue
|
|
133
|
+
}
|
|
134
|
+
const relatedTable = tables.find(
|
|
135
|
+
related => related._id === relatedCol.tableId
|
|
136
|
+
)
|
|
137
|
+
// check if the table is already in the list of related formula, if it isn't, then add it
|
|
138
|
+
if (
|
|
139
|
+
relatedTable &&
|
|
140
|
+
(!relatedTable.relatedFormula ||
|
|
141
|
+
!relatedTable.relatedFormula.includes(table._id))
|
|
142
|
+
) {
|
|
143
|
+
relatedTable.relatedFormula = relatedTable.relatedFormula
|
|
144
|
+
? [...relatedTable.relatedFormula, table._id]
|
|
145
|
+
: [table._id]
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// now we just need to compare all the tables and see if any need saved
|
|
150
|
+
for (let initial of initialTables) {
|
|
151
|
+
const found = tables.find(tbl => initial._id === tbl._id)
|
|
152
|
+
if (found && !isEqual(initial, found)) {
|
|
153
|
+
await db.put(found)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function checkIfFormulaUpdated(appId, table, { oldTable }) {
|
|
159
|
+
// look to see if any formula values have changed
|
|
160
|
+
const shouldUpdate = Object.values(table.schema).find(
|
|
161
|
+
column =>
|
|
162
|
+
isStaticFormula(column) &&
|
|
163
|
+
(!oldTable ||
|
|
164
|
+
!oldTable.schema[column.name] ||
|
|
165
|
+
!isEqual(oldTable.schema[column.name], column))
|
|
166
|
+
)
|
|
167
|
+
// if a static formula column has updated, then need to run the update
|
|
168
|
+
if (shouldUpdate != null) {
|
|
169
|
+
await updateAllFormulasInTable(appId, table)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
exports.runStaticFormulaChecks = async (
|
|
174
|
+
appId,
|
|
175
|
+
table,
|
|
176
|
+
{ oldTable, deletion }
|
|
177
|
+
) => {
|
|
178
|
+
await updateRelatedFormulaLinksOnTables(appId, table, { deletion })
|
|
179
|
+
await checkIfFormulaNeedsCleared(appId, table, { oldTable, deletion })
|
|
180
|
+
if (!deletion) {
|
|
181
|
+
await checkIfFormulaUpdated(appId, table, { oldTable })
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -3,12 +3,8 @@ const internal = require("./internal")
|
|
|
3
3
|
const external = require("./external")
|
|
4
4
|
const csvParser = require("../../../utilities/csvParser")
|
|
5
5
|
const { isExternalTable, isSQL } = require("../../../integrations/utils")
|
|
6
|
-
const {
|
|
7
|
-
|
|
8
|
-
getDatasourceParams,
|
|
9
|
-
BudibaseInternalDB,
|
|
10
|
-
} = require("../../../db/utils")
|
|
11
|
-
const { getTable } = require("./utils")
|
|
6
|
+
const { getDatasourceParams } = require("../../../db/utils")
|
|
7
|
+
const { getTable, getAllInternalTables } = require("./utils")
|
|
12
8
|
|
|
13
9
|
function pickApi({ tableId, table }) {
|
|
14
10
|
if (table && !tableId) {
|
|
@@ -26,17 +22,7 @@ function pickApi({ tableId, table }) {
|
|
|
26
22
|
exports.fetch = async function (ctx) {
|
|
27
23
|
const db = new CouchDB(ctx.appId)
|
|
28
24
|
|
|
29
|
-
const
|
|
30
|
-
getTableParams(null, {
|
|
31
|
-
include_docs: true,
|
|
32
|
-
})
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
const internal = internalTables.rows.map(tableDoc => ({
|
|
36
|
-
...tableDoc.doc,
|
|
37
|
-
type: "internal",
|
|
38
|
-
sourceId: BudibaseInternalDB._id,
|
|
39
|
-
}))
|
|
25
|
+
const internal = await getAllInternalTables(ctx.appId)
|
|
40
26
|
|
|
41
27
|
const externalTables = await db.allDocs(
|
|
42
28
|
getDatasourceParams("plus", {
|
|
@@ -9,6 +9,8 @@ const {
|
|
|
9
9
|
handleDataImport,
|
|
10
10
|
} = require("./utils")
|
|
11
11
|
const usageQuota = require("../../../utilities/usageQuota")
|
|
12
|
+
const { cleanupAttachments } = require("../../../utilities/rowProcessor")
|
|
13
|
+
const { runStaticFormulaChecks } = require("./bulkFormula")
|
|
12
14
|
|
|
13
15
|
exports.save = async function (ctx) {
|
|
14
16
|
const appId = ctx.appId
|
|
@@ -104,7 +106,8 @@ exports.save = async function (ctx) {
|
|
|
104
106
|
tableToSave._rev = result.rev
|
|
105
107
|
|
|
106
108
|
tableToSave = await tableSaveFunctions.after(tableToSave)
|
|
107
|
-
|
|
109
|
+
// has to run after, make sure it has _id
|
|
110
|
+
await runStaticFormulaChecks(appId, tableToSave, { oldTable })
|
|
108
111
|
return tableToSave
|
|
109
112
|
}
|
|
110
113
|
|
|
@@ -141,6 +144,9 @@ exports.destroy = async function (ctx) {
|
|
|
141
144
|
await db.deleteIndex(existingIndex)
|
|
142
145
|
}
|
|
143
146
|
|
|
147
|
+
// has to run after, make sure it has _id
|
|
148
|
+
await runStaticFormulaChecks(appId, tableToDelete, { deletion: true })
|
|
149
|
+
await cleanupAttachments(appId, tableToDelete, { rows })
|
|
144
150
|
return tableToDelete
|
|
145
151
|
}
|
|
146
152
|
|
|
@@ -4,10 +4,15 @@ const {
|
|
|
4
4
|
getRowParams,
|
|
5
5
|
generateRowID,
|
|
6
6
|
InternalTables,
|
|
7
|
+
getTableParams,
|
|
8
|
+
BudibaseInternalDB,
|
|
7
9
|
} = require("../../../db/utils")
|
|
8
|
-
const { isEqual } = require("lodash
|
|
10
|
+
const { isEqual } = require("lodash")
|
|
9
11
|
const { AutoFieldSubTypes, FieldTypes } = require("../../../constants")
|
|
10
|
-
const {
|
|
12
|
+
const {
|
|
13
|
+
inputProcessing,
|
|
14
|
+
cleanupAttachments,
|
|
15
|
+
} = require("../../../utilities/rowProcessor")
|
|
11
16
|
const {
|
|
12
17
|
USERS_TABLE_SCHEMA,
|
|
13
18
|
SwitchableTypes,
|
|
@@ -21,8 +26,24 @@ const {
|
|
|
21
26
|
const { getViews, saveView } = require("../view/utils")
|
|
22
27
|
const viewTemplate = require("../view/viewBuilder")
|
|
23
28
|
const usageQuota = require("../../../utilities/usageQuota")
|
|
29
|
+
const { cloneDeep } = require("lodash/fp")
|
|
30
|
+
|
|
31
|
+
exports.clearColumns = async (appId, table, columnNames) => {
|
|
32
|
+
const db = new CouchDB(appId)
|
|
33
|
+
const rows = await db.allDocs(
|
|
34
|
+
getRowParams(table._id, null, {
|
|
35
|
+
include_docs: true,
|
|
36
|
+
})
|
|
37
|
+
)
|
|
38
|
+
return db.bulkDocs(
|
|
39
|
+
rows.rows.map(({ doc }) => {
|
|
40
|
+
columnNames.forEach(colName => delete doc[colName])
|
|
41
|
+
return doc
|
|
42
|
+
})
|
|
43
|
+
)
|
|
44
|
+
}
|
|
24
45
|
|
|
25
|
-
exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => {
|
|
46
|
+
exports.checkForColumnUpdates = async (appId, db, oldTable, updatedTable) => {
|
|
26
47
|
let updatedRows = []
|
|
27
48
|
const rename = updatedTable._rename
|
|
28
49
|
let deletedColumns = []
|
|
@@ -39,16 +60,20 @@ exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => {
|
|
|
39
60
|
include_docs: true,
|
|
40
61
|
})
|
|
41
62
|
)
|
|
42
|
-
|
|
63
|
+
const rawRows = rows.rows.map(({ doc }) => doc)
|
|
64
|
+
updatedRows = rawRows.map(row => {
|
|
65
|
+
row = cloneDeep(row)
|
|
43
66
|
if (rename) {
|
|
44
|
-
|
|
45
|
-
delete
|
|
67
|
+
row[rename.updated] = row[rename.old]
|
|
68
|
+
delete row[rename.old]
|
|
46
69
|
} else if (deletedColumns.length !== 0) {
|
|
47
|
-
deletedColumns.forEach(colName => delete
|
|
70
|
+
deletedColumns.forEach(colName => delete row[colName])
|
|
48
71
|
}
|
|
49
|
-
return
|
|
72
|
+
return row
|
|
50
73
|
})
|
|
51
74
|
|
|
75
|
+
// cleanup any attachments from object storage for deleted attachment columns
|
|
76
|
+
await cleanupAttachments(appId, updatedTable, { oldTable, rows: rawRows })
|
|
52
77
|
// Update views
|
|
53
78
|
await exports.checkForViewUpdates(db, updatedTable, rename, deletedColumns)
|
|
54
79
|
delete updatedTable._rename
|
|
@@ -209,6 +234,7 @@ class TableSaveFunctions {
|
|
|
209
234
|
// when confirmed valid
|
|
210
235
|
async mid(table) {
|
|
211
236
|
let response = await exports.checkForColumnUpdates(
|
|
237
|
+
this.appId,
|
|
212
238
|
this.db,
|
|
213
239
|
this.oldTable,
|
|
214
240
|
table
|
|
@@ -234,6 +260,20 @@ class TableSaveFunctions {
|
|
|
234
260
|
}
|
|
235
261
|
}
|
|
236
262
|
|
|
263
|
+
exports.getAllInternalTables = async appId => {
|
|
264
|
+
const db = new CouchDB(appId)
|
|
265
|
+
const internalTables = await db.allDocs(
|
|
266
|
+
getTableParams(null, {
|
|
267
|
+
include_docs: true,
|
|
268
|
+
})
|
|
269
|
+
)
|
|
270
|
+
return internalTables.rows.map(tableDoc => ({
|
|
271
|
+
...tableDoc.doc,
|
|
272
|
+
type: "internal",
|
|
273
|
+
sourceId: BudibaseInternalDB._id,
|
|
274
|
+
}))
|
|
275
|
+
}
|
|
276
|
+
|
|
237
277
|
exports.getAllExternalTables = async (appId, datasourceId) => {
|
|
238
278
|
const db = new CouchDB(appId)
|
|
239
279
|
const datasource = await db.get(datasourceId)
|
package/src/api/routes/index.js
CHANGED
|
@@ -24,6 +24,7 @@ const backupRoutes = require("./backup")
|
|
|
24
24
|
const metadataRoutes = require("./metadata")
|
|
25
25
|
const devRoutes = require("./dev")
|
|
26
26
|
const cloudRoutes = require("./cloud")
|
|
27
|
+
const migrationRoutes = require("./migrations")
|
|
27
28
|
|
|
28
29
|
exports.mainRoutes = [
|
|
29
30
|
authRoutes,
|
|
@@ -53,6 +54,7 @@ exports.mainRoutes = [
|
|
|
53
54
|
// this could be breaking as koa may recognise other routes as this
|
|
54
55
|
tableRoutes,
|
|
55
56
|
rowRoutes,
|
|
57
|
+
migrationRoutes,
|
|
56
58
|
]
|
|
57
59
|
|
|
58
60
|
exports.staticRoutes = staticRoutes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const Router = require("@koa/router")
|
|
2
|
+
const migrationsController = require("../controllers/migrations")
|
|
3
|
+
const router = Router()
|
|
4
|
+
const { internalApi } = require("@budibase/backend-core/auth")
|
|
5
|
+
|
|
6
|
+
router
|
|
7
|
+
.post("/api/migrations/run", internalApi, migrationsController.migrate)
|
|
8
|
+
.get(
|
|
9
|
+
"/api/migrations/definitions",
|
|
10
|
+
internalApi,
|
|
11
|
+
migrationsController.fetchDefinitions
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
module.exports = router
|
package/src/app.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// need to load environment first
|
|
2
2
|
import { ExtendableContext } from "koa"
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import * as env from "./environment"
|
|
5
5
|
const CouchDB = require("./db")
|
|
6
6
|
require("@budibase/backend-core").init(CouchDB)
|
|
7
7
|
const Koa = require("koa")
|
|
@@ -16,6 +16,7 @@ const Sentry = require("@sentry/node")
|
|
|
16
16
|
const fileSystem = require("./utilities/fileSystem")
|
|
17
17
|
const bullboard = require("./automations/bullboard")
|
|
18
18
|
const redis = require("./utilities/redis")
|
|
19
|
+
import * as migrations from "./migrations"
|
|
19
20
|
|
|
20
21
|
const app = new Koa()
|
|
21
22
|
|
|
@@ -84,13 +85,25 @@ module.exports = server.listen(env.PORT || 0, async () => {
|
|
|
84
85
|
await automations.init()
|
|
85
86
|
})
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
console.error(err)
|
|
88
|
+
const shutdown = () => {
|
|
89
89
|
server.close()
|
|
90
90
|
server.destroy()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
process.on("uncaughtException", err => {
|
|
94
|
+
console.error(err)
|
|
95
|
+
shutdown()
|
|
91
96
|
})
|
|
92
97
|
|
|
93
98
|
process.on("SIGTERM", () => {
|
|
94
|
-
|
|
95
|
-
server.destroy()
|
|
99
|
+
shutdown()
|
|
96
100
|
})
|
|
101
|
+
|
|
102
|
+
// run migrations on startup if not done via http
|
|
103
|
+
// not recommended in a clustered environment
|
|
104
|
+
if (!env.HTTP_MIGRATIONS) {
|
|
105
|
+
migrations.migrate().catch(err => {
|
|
106
|
+
console.error("Error performing migrations. Exiting.\n", err)
|
|
107
|
+
shutdown()
|
|
108
|
+
})
|
|
109
|
+
}
|
package/src/constants/index.js
CHANGED
|
@@ -72,7 +72,7 @@ async function getLinksForRows(appId, rows) {
|
|
|
72
72
|
)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
async function getFullLinkedDocs(
|
|
75
|
+
async function getFullLinkedDocs(appId, links) {
|
|
76
76
|
// create DBs
|
|
77
77
|
const db = new CouchDB(appId)
|
|
78
78
|
const linkedRowIds = links.map(link => link.id)
|
|
@@ -146,13 +146,12 @@ exports.updateLinks = async function (args) {
|
|
|
146
146
|
/**
|
|
147
147
|
* Given a table and a list of rows this will retrieve all of the attached docs and enrich them into the row.
|
|
148
148
|
* This is required for formula fields, this may only be utilised internally (for now).
|
|
149
|
-
* @param {
|
|
149
|
+
* @param {string} appId The ID of the app which this request is in the context of.
|
|
150
150
|
* @param {object} table The table from which the rows originated.
|
|
151
151
|
* @param {array<object>} rows The rows which are to be enriched.
|
|
152
152
|
* @return {Promise<*>} returns the rows with all of the enriched relationships on it.
|
|
153
153
|
*/
|
|
154
|
-
exports.attachFullLinkedDocs = async (
|
|
155
|
-
const appId = ctx.appId
|
|
154
|
+
exports.attachFullLinkedDocs = async (appId, table, rows) => {
|
|
156
155
|
const linkedTableIds = getLinkedTableIDs(table)
|
|
157
156
|
if (linkedTableIds.length === 0) {
|
|
158
157
|
return rows
|
|
@@ -166,7 +165,7 @@ exports.attachFullLinkedDocs = async (ctx, table, rows) => {
|
|
|
166
165
|
// clear any existing links that could be dupe'd
|
|
167
166
|
rows = clearRelationshipFields(table, rows)
|
|
168
167
|
// now get the docs and combine into the rows
|
|
169
|
-
let linked = await getFullLinkedDocs(
|
|
168
|
+
let linked = await getFullLinkedDocs(appId, links)
|
|
170
169
|
const linkedTables = []
|
|
171
170
|
for (let row of rows) {
|
|
172
171
|
for (let link of links.filter(link => link.thisId === row._id)) {
|
|
@@ -17,6 +17,8 @@ export interface FieldSchema {
|
|
|
17
17
|
autocolumn?: boolean
|
|
18
18
|
throughFrom?: string
|
|
19
19
|
throughTo?: string
|
|
20
|
+
formula?: string
|
|
21
|
+
formulaType?: string
|
|
20
22
|
main?: boolean
|
|
21
23
|
meta?: {
|
|
22
24
|
toTable: string
|
|
@@ -46,6 +48,7 @@ export interface Table extends Base {
|
|
|
46
48
|
schema: TableSchema
|
|
47
49
|
primaryDisplay?: string
|
|
48
50
|
sourceId?: string
|
|
51
|
+
relatedFormula?: string[]
|
|
49
52
|
constrained?: string[]
|
|
50
53
|
}
|
|
51
54
|
|
package/src/environment.js
CHANGED
|
@@ -43,6 +43,7 @@ module.exports = {
|
|
|
43
43
|
REDIS_PASSWORD: process.env.REDIS_PASSWORD,
|
|
44
44
|
INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
|
|
45
45
|
MULTI_TENANCY: process.env.MULTI_TENANCY,
|
|
46
|
+
HTTP_MIGRATIONS: process.env.HTTP_MIGRATIONS,
|
|
46
47
|
// environment
|
|
47
48
|
NODE_ENV: process.env.NODE_ENV,
|
|
48
49
|
JEST_WORKER_ID: process.env.JEST_WORKER_ID,
|
|
@@ -5,7 +5,6 @@ const {
|
|
|
5
5
|
isExternalTable,
|
|
6
6
|
isRowId: isExternalRowId,
|
|
7
7
|
} = require("../integrations/utils")
|
|
8
|
-
const migration = require("../migrations/usageQuotas")
|
|
9
8
|
|
|
10
9
|
// currently only counting new writes and deletes
|
|
11
10
|
const METHOD_MAP = {
|
|
@@ -74,7 +73,6 @@ module.exports = async (ctx, next) => {
|
|
|
74
73
|
usage = files.map(file => file.size).reduce((total, size) => total + size)
|
|
75
74
|
}
|
|
76
75
|
try {
|
|
77
|
-
await migration.run()
|
|
78
76
|
await performRequest(ctx, next, property, usage)
|
|
79
77
|
} catch (err) {
|
|
80
78
|
ctx.throw(400, err)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const { DocumentTypes } = require("@budibase/backend-core/db")
|
|
2
|
+
import { getAppUrl } from "../../api/controllers/application"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Date:
|
|
6
|
+
* January 2022
|
|
7
|
+
*
|
|
8
|
+
* Description:
|
|
9
|
+
* Add the url to the app metadata if it doesn't exist
|
|
10
|
+
*/
|
|
11
|
+
export const run = async (appDb: any) => {
|
|
12
|
+
let metadata
|
|
13
|
+
try {
|
|
14
|
+
metadata = await appDb.get(DocumentTypes.APP_METADATA)
|
|
15
|
+
} catch (e) {
|
|
16
|
+
// sometimes the metadata document doesn't exist
|
|
17
|
+
// exit early instead of failing the migration
|
|
18
|
+
console.error("Error retrieving app metadata. Skipping", e)
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!metadata.url) {
|
|
23
|
+
const context = {
|
|
24
|
+
request: {
|
|
25
|
+
body: {
|
|
26
|
+
name: metadata.name,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
metadata.url = getAppUrl(context)
|
|
31
|
+
console.log(`Adding url to app: ${metadata.url}`)
|
|
32
|
+
await appDb.put(metadata)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { runQuotaMigration } from "./usageQuotas"
|
|
2
|
+
import * as syncApps from "./usageQuotas/syncApps"
|
|
3
|
+
import * as syncRows from "./usageQuotas/syncRows"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Date:
|
|
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.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export const run = async () => {
|
|
16
|
+
await runQuotaMigration(async () => {
|
|
17
|
+
await syncApps.run()
|
|
18
|
+
await syncRows.run()
|
|
19
|
+
})
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const { DocumentTypes } = require("@budibase/backend-core/db")
|
|
2
|
+
const env = require("../../../environment")
|
|
3
|
+
const TestConfig = require("../../../tests/utilities/TestConfiguration")
|
|
4
|
+
|
|
5
|
+
const migration = require("../appUrls")
|
|
6
|
+
|
|
7
|
+
describe("run", () => {
|
|
8
|
+
let config = new TestConfig(false)
|
|
9
|
+
const CouchDB = config.getCouch()
|
|
10
|
+
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
await config.init()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
afterAll(config.end)
|
|
16
|
+
|
|
17
|
+
it("runs successfully", async () => {
|
|
18
|
+
const app = await config.createApp("testApp")
|
|
19
|
+
const appDb = new CouchDB(app.appId)
|
|
20
|
+
let metadata = await appDb.get(DocumentTypes.APP_METADATA)
|
|
21
|
+
delete metadata.url
|
|
22
|
+
await appDb.put(metadata)
|
|
23
|
+
|
|
24
|
+
await migration.run(appDb)
|
|
25
|
+
|
|
26
|
+
metadata = await appDb.get(DocumentTypes.APP_METADATA)
|
|
27
|
+
expect(metadata.url).toEqual("/testapp")
|
|
28
|
+
})
|
|
29
|
+
})
|
|
@@ -4,10 +4,10 @@ const TestConfig = require("../../../tests/utilities/TestConfiguration")
|
|
|
4
4
|
const syncApps = jest.fn()
|
|
5
5
|
const syncRows = jest.fn()
|
|
6
6
|
|
|
7
|
-
jest.mock("
|
|
8
|
-
jest.mock("
|
|
7
|
+
jest.mock("../usageQuotas/syncApps", () => ({ run: syncApps }) )
|
|
8
|
+
jest.mock("../usageQuotas/syncRows", () => ({ run: syncRows }) )
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const migration = require("../quotas1")
|
|
11
11
|
|
|
12
12
|
describe("run", () => {
|
|
13
13
|
let config = new TestConfig(false)
|
|
@@ -19,8 +19,8 @@ describe("run", () => {
|
|
|
19
19
|
|
|
20
20
|
afterAll(config.end)
|
|
21
21
|
|
|
22
|
-
it("runs
|
|
23
|
-
await
|
|
22
|
+
it("runs ", async () => {
|
|
23
|
+
await migration.run()
|
|
24
24
|
expect(syncApps).toHaveBeenCalledTimes(1)
|
|
25
25
|
expect(syncRows).toHaveBeenCalledTimes(1)
|
|
26
26
|
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const TestConfig = require("../../../tests/utilities/TestConfiguration")
|
|
2
|
+
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
3
|
+
|
|
4
|
+
// mock email view creation
|
|
5
|
+
const coreDb = require("@budibase/backend-core/db")
|
|
6
|
+
const createUserEmailView = jest.fn()
|
|
7
|
+
coreDb.createUserEmailView = createUserEmailView
|
|
8
|
+
|
|
9
|
+
const migration = require("../userEmailViewCasing")
|
|
10
|
+
|
|
11
|
+
describe("run", () => {
|
|
12
|
+
let config = new TestConfig(false)
|
|
13
|
+
const globalDb = getGlobalDB()
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
await config.init()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
afterAll(config.end)
|
|
20
|
+
|
|
21
|
+
it("runs successfully", async () => {
|
|
22
|
+
await migration.run(globalDb)
|
|
23
|
+
expect(createUserEmailView).toHaveBeenCalledTimes(1)
|
|
24
|
+
})
|
|
25
|
+
})
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
|
2
2
|
const { getAllApps } = require("@budibase/backend-core/db")
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import CouchDB from "../../../db"
|
|
4
|
+
import { getUsageQuotaDoc } from "../../../utilities/usageQuota"
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
export const run = async () => {
|
|
7
7
|
const db = getGlobalDB()
|
|
8
8
|
// get app count
|
|
9
9
|
const devApps = await getAllApps(CouchDB, { dev: true })
|