@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.
Files changed (190) hide show
  1. package/builder/assets/{index.b61c225e.js → index.868c6c14.js} +260 -260
  2. package/builder/assets/{index.dfa4073c.css → index.aef99fa8.css} +2 -2
  3. package/builder/index.html +2 -2
  4. package/coverage/clover.xml +344 -341
  5. package/coverage/coverage-final.json +24 -24
  6. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  7. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/index.html +1 -1
  13. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  19. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  24. package/coverage/lcov-report/api/controllers/row/internal.js.html +12 -12
  25. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +15 -15
  27. package/coverage/lcov-report/api/controllers/row/utils.js.html +13 -13
  28. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  32. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  37. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  41. package/coverage/lcov-report/api/index.html +1 -1
  42. package/coverage/lcov-report/api/index.js.html +5 -5
  43. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  44. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  45. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  46. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  47. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  48. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  49. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/index.html +1 -1
  53. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  67. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  70. package/coverage/lcov-report/automations/actions.js.html +1 -1
  71. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  72. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  73. package/coverage/lcov-report/automations/index.html +1 -1
  74. package/coverage/lcov-report/automations/index.js.html +5 -5
  75. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  76. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  77. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  78. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  79. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  80. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  81. package/coverage/lcov-report/automations/steps/index.html +1 -1
  82. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/updateRow.js.html +3 -3
  90. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  92. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  93. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  94. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  95. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  96. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  97. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  98. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  100. package/coverage/lcov-report/automations/triggers.js.html +22 -22
  101. package/coverage/lcov-report/constants/index.html +1 -1
  102. package/coverage/lcov-report/constants/index.js.html +1 -1
  103. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  104. package/coverage/lcov-report/constants/screens.js.html +1 -1
  105. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  106. package/coverage/lcov-report/db/index.html +1 -1
  107. package/coverage/lcov-report/db/index.js.html +1 -1
  108. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +11 -11
  109. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  110. package/coverage/lcov-report/db/linkedRows/index.js.html +11 -11
  111. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +3 -3
  112. package/coverage/lcov-report/db/newid.js.html +2 -2
  113. package/coverage/lcov-report/db/utils.js.html +10 -16
  114. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  115. package/coverage/lcov-report/events/index.html +1 -1
  116. package/coverage/lcov-report/events/index.js.html +2 -2
  117. package/coverage/lcov-report/events/utils.js.html +9 -9
  118. package/coverage/lcov-report/index.html +15 -15
  119. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  120. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  121. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  122. package/coverage/lcov-report/middleware/builder.js.html +11 -11
  123. package/coverage/lcov-report/middleware/currentapp.js.html +34 -34
  124. package/coverage/lcov-report/middleware/index.html +1 -1
  125. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  126. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  127. package/coverage/lcov-report/middleware/resourceId.js.html +7 -7
  128. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  129. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  130. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  131. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  132. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  133. package/coverage/lcov-report/utilities/global.js.html +16 -16
  134. package/coverage/lcov-report/utilities/index.html +1 -1
  135. package/coverage/lcov-report/utilities/index.js.html +1 -1
  136. package/coverage/lcov-report/utilities/plugins.js.html +1 -1
  137. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +13 -13
  138. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  139. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  140. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  141. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  142. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +38 -38
  143. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +10 -10
  144. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  145. package/coverage/lcov-report/utilities/security.js.html +1 -1
  146. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  147. package/coverage/lcov-report/utilities/usageQuota/index.html +14 -14
  148. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +23 -11
  149. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  150. package/coverage/lcov-report/utilities/users.js.html +1 -1
  151. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  152. package/coverage/lcov.info +619 -614
  153. package/dist/api/controllers/application.js +2 -2
  154. package/dist/api/controllers/query/index.js +6 -2
  155. package/dist/api/controllers/row/index.js +30 -10
  156. package/dist/api/controllers/table/internal.js +3 -1
  157. package/dist/api/controllers/table/utils.js +3 -1
  158. package/dist/automations/steps/updateRow.js +2 -2
  159. package/dist/automations/utils.js +5 -3
  160. package/dist/db/utils.js +1 -1
  161. package/dist/migrations/functions/{quotas1.js → syncQuotas.js} +3 -7
  162. package/dist/migrations/functions/usageQuotas/syncApps.js +0 -1
  163. package/dist/migrations/functions/{pluginCount.js → usageQuotas/syncPlugins.js} +1 -3
  164. package/dist/migrations/functions/usageQuotas/syncRows.js +9 -5
  165. package/dist/migrations/index.js +3 -9
  166. package/dist/package.json +7 -7
  167. package/dist/tsconfig.build.tsbuildinfo +1 -1
  168. package/dist/utilities/usageQuota/rows.js +6 -4
  169. package/package.json +8 -8
  170. package/src/api/controllers/application.ts +2 -2
  171. package/src/api/controllers/query/index.ts +7 -2
  172. package/src/api/controllers/row/index.ts +36 -13
  173. package/src/api/controllers/table/internal.ts +3 -1
  174. package/src/api/controllers/table/utils.ts +3 -1
  175. package/src/api/routes/tests/row.spec.js +22 -27
  176. package/src/automations/steps/updateRow.js +2 -2
  177. package/src/automations/tests/automation.spec.js +1 -6
  178. package/src/automations/utils.ts +6 -4
  179. package/src/db/utils.js +0 -2
  180. package/src/migrations/functions/backfill/global.ts +1 -1
  181. package/src/migrations/functions/{quotas1.ts → syncQuotas.ts} +3 -8
  182. package/src/migrations/functions/tests/{quotas1.spec.js → syncQuotas.spec.js} +5 -2
  183. package/src/migrations/functions/usageQuotas/syncApps.ts +0 -1
  184. package/src/migrations/functions/usageQuotas/syncPlugins.ts +10 -0
  185. package/src/migrations/functions/usageQuotas/syncRows.ts +15 -6
  186. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +9 -1
  187. package/src/migrations/index.ts +3 -15
  188. package/src/migrations/tests/index.spec.ts +0 -1
  189. package/src/utilities/usageQuota/rows.js +7 -3
  190. 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
- uniqueRows = uniqueRows.concat([...new Set(appRows)]);
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.23",
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": "^2.0.23",
81
- "@budibase/client": "^2.0.23",
82
- "@budibase/pro": "2.0.22",
83
- "@budibase/string-templates": "^2.0.23",
84
- "@budibase/types": "^2.0.23",
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.6",
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": "d185ab9bfc042deb6fdfba199667a70567548b77"
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
- const { rows, keys, info, extra } = await quotas.addQuery(runFn)
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
- return config.doInContext(null, () =>
38
- quotas.getCurrentUsageValue(QuotaUsageType.STATIC, StaticQuotaName.ROWS)
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
- return config.doInContext(null, () =>
44
- quotas.getCurrentUsageValue(
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
- // const rowUsage = await getRowUsage()
64
- // const queryUsage = await getQueryUsage()
65
- //
66
- // const res = await request
67
- // .post(`/api/${row.tableId}/rows`)
68
- // .send(row)
69
- // .set(config.defaultHeaders())
70
- // .expect('Content-Type', /json/)
71
- // .expect(200)
72
- // expect(res.res.statusMessage).toEqual(`${table.name} saved successfully`)
73
- // expect(res.body.name).toEqual("Test Contact")
74
- // expect(res.body._rev).toBeDefined()
75
- // await assertRowUsage(rowUsage + 1)
76
- // await assertQueryUsage(queryUsage + 1)
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
- // const rowUsage = await getRowUsage()
82
- // const queryUsage = await getQueryUsage()
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
- // await assertRowUsage(rowUsage)
101
- // await assertQueryUsage(queryUsage + 1)
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 falsy properties so that they aren't updated
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 (!inputs.row[propKey] || inputs.row[propKey] === "") {
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()
@@ -13,7 +13,7 @@ import {
13
13
  getAppId,
14
14
  getProdAppDB,
15
15
  } from "@budibase/backend-core/context"
16
- import { tenancy } from "@budibase/backend-core"
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
- const tenantId = tenancy.getTenantIDFromAppID(job.data.event.appId)
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
@@ -34,8 +34,6 @@ const DocumentType = {
34
34
  INSTANCE: "inst",
35
35
  LAYOUT: "layout",
36
36
  SCREEN: "screen",
37
- DATASOURCE: "datasource",
38
- DATASOURCE_PLUS: "datasource_plus",
39
37
  QUERY: "query",
40
38
  DEPLOYMENTS: "deployments",
41
39
  METADATA: "metadata",
@@ -8,7 +8,7 @@ import {
8
8
  accounts,
9
9
  db as dbUtils,
10
10
  } from "@budibase/backend-core"
11
- import { QuotaUsage } from "@budibase/pro"
11
+ import { QuotaUsage } from "@budibase/types"
12
12
  import {
13
13
  CloudAccount,
14
14
  App,
@@ -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
- * 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.
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("../quotas1")
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("runs ", async () => {
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
  })
@@ -5,7 +5,6 @@ import { QuotaUsageType, StaticQuotaName } from "@budibase/types"
5
5
 
6
6
  export const run = async () => {
7
7
  // get app count
8
- // @ts-ignore
9
8
  const devApps = await getAllApps({ dev: true })
10
9
  const appCount = devApps ? devApps.length : 0
11
10
 
@@ -0,0 +1,10 @@
1
+ import { logging } from "@budibase/backend-core"
2
+ import { plugins } from "@budibase/pro"
3
+
4
+ export const run = async () => {
5
+ try {
6
+ await plugins.checkPluginQuotas()
7
+ } catch (err) {
8
+ logging.logAlert("Failed to update plugin quotas", err)
9
+ }
10
+ }
@@ -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 { QuotaUsageType, StaticQuotaName } from "@budibase/types"
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 rows = await getUniqueRows(appIds)
14
- const rowCount = rows ? rows.length : 0
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.setUsage(rowCount, StaticQuotaName.ROWS, QuotaUsageType.STATIC)
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
  })
@@ -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 quota1 from "./functions/quotas1"
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.QUOTAS_1: {
27
+ case MigrationName.SYNC_QUOTAS: {
30
28
  serverMigrations.push({
31
29
  ...definition,
32
- fn: quota1.run,
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
 
@@ -4,7 +4,6 @@ import {
4
4
  tenancy,
5
5
  DocumentType,
6
6
  context,
7
- db,
8
7
  } from "@budibase/backend-core"
9
8
  import TestConfig from "../../tests/utilities/TestConfiguration"
10
9
  import structures from "../../tests/utilities/structures"
@@ -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
- uniqueRows = uniqueRows.concat([...new Set(appRows)])
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
- }