@budibase/server 1.0.49 → 1.0.50-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 (381) hide show
  1. package/__mocks__/arangojs.ts +1 -1
  2. package/__mocks__/aws-sdk.ts +4 -4
  3. package/__mocks__/mongodb.ts +4 -5
  4. package/__mocks__/mssql.ts +3 -3
  5. package/__mocks__/node-fetch.ts +2 -1
  6. package/__mocks__/pg.ts +3 -5
  7. package/builder/assets/index.c0cc369d.css +6 -0
  8. package/builder/assets/{index.2c37968e.js → index.ff2bad21.js} +252 -249
  9. package/builder/assets/{vendor.f9faf6ab.js → vendor.5ad9695a.js} +202 -106
  10. package/builder/index.html +3 -3
  11. package/coverage/clover.xml +3105 -2814
  12. package/coverage/coverage-final.json +106 -101
  13. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/application.js.html +257 -152
  16. package/coverage/lcov-report/api/controllers/auth.js.html +22 -13
  17. package/coverage/lcov-report/api/controllers/automation.js.html +39 -69
  18. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/cloud.js.html +8 -11
  20. package/coverage/lcov-report/api/controllers/component.js.html +13 -16
  21. package/coverage/lcov-report/api/controllers/datasource.js.html +81 -51
  22. package/coverage/lcov-report/api/controllers/dev.js.html +6 -6
  23. package/coverage/lcov-report/api/controllers/index.html +78 -78
  24. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/layout.js.html +9 -9
  26. package/coverage/lcov-report/api/controllers/metadata.js.html +6 -21
  27. package/coverage/lcov-report/api/controllers/migrations.js.html +119 -0
  28. package/coverage/lcov-report/api/controllers/permission.js.html +19 -19
  29. package/coverage/lcov-report/api/controllers/query/index.html +10 -10
  30. package/coverage/lcov-report/api/controllers/query/index.js.html +38 -35
  31. package/coverage/lcov-report/api/controllers/query/validation.js.html +6 -6
  32. package/coverage/lcov-report/api/controllers/role.js.html +16 -16
  33. package/coverage/lcov-report/api/controllers/routing.js.html +7 -10
  34. package/coverage/lcov-report/api/controllers/row/external.js.html +48 -141
  35. package/coverage/lcov-report/api/controllers/row/index.html +55 -40
  36. package/coverage/lcov-report/api/controllers/row/index.js.html +26 -26
  37. package/coverage/lcov-report/api/controllers/row/internal.js.html +118 -226
  38. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +52 -34
  39. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +548 -0
  40. package/coverage/lcov-report/api/controllers/row/utils.js.html +47 -62
  41. package/coverage/lcov-report/api/controllers/screen.js.html +15 -21
  42. package/coverage/lcov-report/api/controllers/script.js.html +4 -4
  43. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +599 -0
  44. package/coverage/lcov-report/api/controllers/table/external.js.html +25 -34
  45. package/coverage/lcov-report/api/controllers/table/index.html +58 -43
  46. package/coverage/lcov-report/api/controllers/table/index.js.html +58 -82
  47. package/coverage/lcov-report/api/controllers/table/internal.js.html +81 -66
  48. package/coverage/lcov-report/api/controllers/table/utils.js.html +218 -110
  49. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  50. package/coverage/lcov-report/api/controllers/user.js.html +79 -76
  51. package/coverage/lcov-report/api/controllers/view/exporters.js.html +4 -4
  52. package/coverage/lcov-report/api/controllers/view/index.html +16 -16
  53. package/coverage/lcov-report/api/controllers/view/index.js.html +27 -33
  54. package/coverage/lcov-report/api/controllers/view/utils.js.html +35 -20
  55. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +7 -7
  56. package/coverage/lcov-report/api/controllers/webhook.js.html +34 -28
  57. package/coverage/lcov-report/api/index.html +1 -1
  58. package/coverage/lcov-report/api/index.js.html +8 -8
  59. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/index.html +18 -18
  71. package/coverage/lcov-report/api/routes/index.js.html +3 -3
  72. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/{hosting.js.html → migrations.js.html} +17 -14
  76. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  81. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  82. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  83. package/coverage/lcov-report/api/routes/static.js.html +17 -2
  84. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  85. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  86. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  87. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  88. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  89. package/coverage/lcov-report/automations/actions.js.html +24 -24
  90. package/coverage/lcov-report/automations/automationUtils.js.html +7 -10
  91. package/coverage/lcov-report/automations/bullboard.js.html +16 -16
  92. package/coverage/lcov-report/automations/index.html +18 -18
  93. package/coverage/lcov-report/automations/index.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/bash.js.html +6 -6
  95. package/coverage/lcov-report/automations/steps/createRow.js.html +13 -22
  96. package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
  97. package/coverage/lcov-report/automations/steps/deleteRow.js.html +11 -20
  98. package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
  99. package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
  100. package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
  101. package/coverage/lcov-report/automations/steps/filter.js.html +7 -7
  102. package/coverage/lcov-report/automations/steps/index.html +13 -13
  103. package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
  104. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
  105. package/coverage/lcov-report/automations/steps/queryRows.js.html +10 -10
  106. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
  107. package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
  108. package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
  109. package/coverage/lcov-report/automations/steps/updateRow.js.html +7 -7
  110. package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
  111. package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
  112. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  113. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  114. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  115. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  116. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  117. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  118. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  119. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  120. package/coverage/lcov-report/automations/triggers.js.html +61 -55
  121. package/coverage/lcov-report/automations/utils.js.html +54 -42
  122. package/coverage/lcov-report/constants/index.html +5 -5
  123. package/coverage/lcov-report/constants/index.js.html +53 -26
  124. package/coverage/lcov-report/constants/layouts.js.html +5 -5
  125. package/coverage/lcov-report/constants/screens.js.html +4 -4
  126. package/coverage/lcov-report/db/client.js.html +18 -18
  127. package/coverage/lcov-report/db/inMemoryView.js.html +7 -7
  128. package/coverage/lcov-report/db/index.html +15 -15
  129. package/coverage/lcov-report/db/index.js.html +3 -3
  130. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +25 -37
  131. package/coverage/lcov-report/db/linkedRows/index.html +27 -27
  132. package/coverage/lcov-report/db/linkedRows/index.js.html +51 -96
  133. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +42 -42
  134. package/coverage/lcov-report/db/newid.js.html +4 -4
  135. package/coverage/lcov-report/db/utils.js.html +87 -87
  136. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  137. package/coverage/lcov-report/events/index.html +1 -1
  138. package/coverage/lcov-report/events/index.js.html +5 -5
  139. package/coverage/lcov-report/events/utils.js.html +3 -3
  140. package/coverage/lcov-report/index.html +135 -120
  141. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  142. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  143. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  144. package/coverage/lcov-report/middleware/authorized.js.html +173 -65
  145. package/coverage/lcov-report/middleware/builder.js.html +10 -10
  146. package/coverage/lcov-report/middleware/currentapp.js.html +95 -83
  147. package/coverage/lcov-report/middleware/index.html +38 -38
  148. package/coverage/lcov-report/middleware/joi-validator.js.html +3 -3
  149. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  150. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  151. package/coverage/lcov-report/middleware/usageQuota.js.html +281 -53
  152. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  153. package/coverage/lcov-report/threads/automation.js.html +30 -24
  154. package/coverage/lcov-report/threads/index.html +26 -26
  155. package/coverage/lcov-report/threads/index.js.html +10 -10
  156. package/coverage/lcov-report/threads/query.js.html +39 -24
  157. package/coverage/lcov-report/threads/utils.js.html +14 -14
  158. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  159. package/coverage/lcov-report/utilities/budibaseDir.js.html +7 -7
  160. package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
  161. package/coverage/lcov-report/utilities/csvParser.js.html +6 -6
  162. package/coverage/lcov-report/utilities/global.js.html +58 -49
  163. package/coverage/lcov-report/utilities/index.html +37 -37
  164. package/coverage/lcov-report/utilities/index.js.html +43 -73
  165. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +8 -8
  166. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  167. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  168. package/coverage/lcov-report/utilities/routing/index.js.html +7 -7
  169. package/coverage/lcov-report/utilities/rowProcessor/index.html +27 -27
  170. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +97 -103
  171. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +75 -27
  172. package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
  173. package/coverage/lcov-report/utilities/security.js.html +8 -8
  174. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  175. package/coverage/lcov-report/utilities/usageQuota/index.html +141 -0
  176. package/coverage/lcov-report/utilities/usageQuota/index.js.html +359 -0
  177. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +305 -0
  178. package/coverage/lcov-report/{api/controllers/hosting.js.html → utilities/usageQuota/usageQuoteReset.js.html} +36 -48
  179. package/coverage/lcov-report/utilities/users.js.html +9 -9
  180. package/coverage/lcov-report/utilities/workerRequests.js.html +43 -112
  181. package/coverage/lcov.info +5010 -4425
  182. package/dist/api/controllers/application.js +90 -60
  183. package/dist/api/controllers/auth.js +8 -5
  184. package/dist/api/controllers/automation.js +14 -19
  185. package/dist/api/controllers/cloud.js +2 -3
  186. package/dist/api/controllers/component.js +3 -4
  187. package/dist/api/controllers/datasource.js +20 -10
  188. package/dist/api/controllers/deploy/Deployment.js +3 -6
  189. package/dist/api/controllers/deploy/index.js +12 -13
  190. package/dist/api/controllers/dev.js +5 -5
  191. package/dist/api/controllers/layout.js +3 -3
  192. package/dist/api/controllers/metadata.js +4 -4
  193. package/dist/api/controllers/migrations.js +21 -0
  194. package/dist/api/controllers/permission.js +4 -4
  195. package/dist/api/controllers/query/import/index.js +4 -6
  196. package/dist/api/controllers/query/index.js +11 -10
  197. package/dist/api/controllers/role.js +5 -5
  198. package/dist/api/controllers/routing.js +5 -6
  199. package/dist/api/controllers/row/ExternalRequest.js +90 -67
  200. package/dist/api/controllers/row/external.js +14 -22
  201. package/dist/api/controllers/row/internal.js +55 -93
  202. package/dist/api/controllers/row/internalSearch.js +23 -17
  203. package/dist/api/controllers/row/staticFormula.js +147 -0
  204. package/dist/api/controllers/row/utils.js +13 -14
  205. package/dist/api/controllers/screen.js +5 -7
  206. package/dist/api/controllers/static/index.js +62 -16
  207. package/dist/api/controllers/table/bulkFormula.js +159 -0
  208. package/dist/api/controllers/table/external.js +7 -10
  209. package/dist/api/controllers/table/index.js +16 -13
  210. package/dist/api/controllers/table/internal.js +22 -16
  211. package/dist/api/controllers/table/utils.js +62 -35
  212. package/dist/api/controllers/user.js +43 -43
  213. package/dist/api/controllers/view/index.js +8 -10
  214. package/dist/api/controllers/view/utils.js +9 -4
  215. package/dist/api/controllers/webhook.js +10 -8
  216. package/dist/api/routes/index.js +2 -2
  217. package/dist/api/routes/migrations.js +9 -0
  218. package/dist/api/routes/static.js +2 -1
  219. package/dist/api/routes/tests/utilities/TestFunctions.js +37 -17
  220. package/dist/app.js +35 -5
  221. package/dist/automations/automationUtils.js +2 -3
  222. package/dist/automations/steps/createRow.js +3 -5
  223. package/dist/automations/steps/deleteRow.js +1 -4
  224. package/dist/automations/steps/updateRow.js +1 -1
  225. package/dist/automations/triggers.js +27 -25
  226. package/dist/automations/utils.js +10 -5
  227. package/dist/constants/index.js +7 -0
  228. package/dist/db/linkedRows/LinkController.js +3 -7
  229. package/dist/db/linkedRows/index.js +16 -27
  230. package/dist/db/linkedRows/linkUtils.js +6 -6
  231. package/dist/db/views/staticViews.js +9 -10
  232. package/dist/definitions/datasource.js +1 -0
  233. package/dist/environment.js +4 -1
  234. package/dist/integrations/base/sql.js +62 -21
  235. package/dist/integrations/googlesheets.js +340 -0
  236. package/dist/integrations/index.js +3 -0
  237. package/dist/integrations/utils.js +60 -9
  238. package/dist/middleware/authorized.js +57 -30
  239. package/dist/middleware/builder.js +2 -2
  240. package/dist/middleware/currentapp.js +41 -37
  241. package/dist/middleware/usageQuota.js +82 -15
  242. package/dist/migrations/functions/appUrls.js +46 -0
  243. package/dist/migrations/functions/quotas1.js +50 -0
  244. package/dist/migrations/functions/usageQuotas/index.js +20 -0
  245. package/dist/migrations/functions/usageQuotas/syncApps.js +29 -0
  246. package/dist/migrations/functions/usageQuotas/syncRows.js +33 -0
  247. package/dist/migrations/functions/userEmailViewCasing.js +24 -0
  248. package/dist/migrations/index.js +62 -0
  249. package/dist/package.json +8 -5
  250. package/dist/tests/utilities/TestConfiguration.js +80 -50
  251. package/dist/threads/automation.js +13 -11
  252. package/dist/threads/query.js +15 -11
  253. package/dist/tsconfig.tsbuildinfo +1 -1
  254. package/dist/utilities/fileSystem/index.js +4 -3
  255. package/dist/utilities/global.js +15 -12
  256. package/dist/utilities/index.js +7 -17
  257. package/dist/utilities/routing/index.js +5 -5
  258. package/dist/utilities/rowProcessor/index.js +23 -17
  259. package/dist/utilities/rowProcessor/utils.js +14 -4
  260. package/dist/utilities/{usageQuota.js → usageQuota/index.js} +45 -31
  261. package/dist/utilities/usageQuota/rows.js +78 -0
  262. package/dist/utilities/usageQuota/usageQuoteReset.js +16 -0
  263. package/dist/utilities/users.js +3 -3
  264. package/dist/utilities/workerRequests.js +4 -24
  265. package/nodemon.json +1 -1
  266. package/package.json +9 -6
  267. package/scripts/integrations/mssql/data/Dockerfile +1 -1
  268. package/scripts/integrations/mssql/data/setup.sql +17 -4
  269. package/scripts/integrations/postgres/init.sql +11 -6
  270. package/scripts/likeCypress.ts +1 -1
  271. package/src/api/controllers/application.js +85 -50
  272. package/src/api/controllers/auth.js +8 -5
  273. package/src/api/controllers/automation.js +13 -23
  274. package/src/api/controllers/cloud.js +2 -3
  275. package/src/api/controllers/component.js +3 -4
  276. package/src/api/controllers/datasource.js +21 -11
  277. package/src/api/controllers/deploy/Deployment.js +3 -7
  278. package/src/api/controllers/deploy/index.js +20 -13
  279. package/src/api/controllers/dev.js +5 -5
  280. package/src/api/controllers/layout.js +3 -3
  281. package/src/api/controllers/metadata.js +4 -9
  282. package/src/api/controllers/migrations.js +13 -0
  283. package/src/api/controllers/permission.js +4 -4
  284. package/src/api/controllers/query/import/index.ts +4 -6
  285. package/src/api/controllers/query/import/tests/index.spec.js +2 -1
  286. package/src/api/controllers/query/index.js +11 -10
  287. package/src/api/controllers/role.js +5 -5
  288. package/src/api/controllers/routing.js +5 -6
  289. package/src/api/controllers/row/ExternalRequest.ts +67 -43
  290. package/src/api/controllers/row/external.js +27 -58
  291. package/src/api/controllers/row/internal.js +54 -90
  292. package/src/api/controllers/row/internalSearch.js +23 -17
  293. package/src/api/controllers/row/staticFormula.js +156 -0
  294. package/src/api/controllers/row/utils.js +13 -18
  295. package/src/api/controllers/screen.js +5 -7
  296. package/src/api/controllers/static/index.js +66 -15
  297. package/src/api/controllers/table/bulkFormula.js +173 -0
  298. package/src/api/controllers/table/external.js +7 -10
  299. package/src/api/controllers/table/index.js +20 -28
  300. package/src/api/controllers/table/internal.js +24 -19
  301. package/src/api/controllers/table/utils.js +78 -42
  302. package/src/api/controllers/user.js +46 -45
  303. package/src/api/controllers/view/index.js +8 -10
  304. package/src/api/controllers/view/utils.js +9 -4
  305. package/src/api/controllers/webhook.js +10 -8
  306. package/src/api/routes/index.js +2 -2
  307. package/src/api/routes/migrations.js +14 -0
  308. package/src/api/routes/static.js +5 -0
  309. package/src/api/routes/tests/application.spec.js +2 -2
  310. package/src/api/routes/tests/auth.spec.js +1 -2
  311. package/src/api/routes/tests/automation.spec.js +1 -0
  312. package/src/api/routes/tests/misc.spec.js +0 -1
  313. package/src/api/routes/tests/routing.spec.js +21 -12
  314. package/src/api/routes/tests/row.spec.js +7 -4
  315. package/src/api/routes/tests/static.spec.js +98 -0
  316. package/src/api/routes/tests/utilities/TestFunctions.js +39 -17
  317. package/src/app.ts +18 -5
  318. package/src/automations/automationUtils.js +2 -3
  319. package/src/automations/steps/createRow.js +2 -5
  320. package/src/automations/steps/deleteRow.js +1 -4
  321. package/src/automations/steps/updateRow.js +1 -1
  322. package/src/automations/triggers.js +33 -31
  323. package/src/automations/utils.js +9 -5
  324. package/src/constants/index.js +9 -0
  325. package/src/db/linkedRows/LinkController.js +3 -7
  326. package/src/db/linkedRows/index.js +16 -31
  327. package/src/db/linkedRows/linkUtils.js +6 -6
  328. package/src/db/tests/linkController.spec.js +0 -1
  329. package/src/db/tests/linkTests.spec.js +5 -6
  330. package/src/db/views/staticViews.js +8 -10
  331. package/src/definitions/common.ts +3 -0
  332. package/src/definitions/datasource.ts +3 -0
  333. package/src/environment.js +4 -1
  334. package/src/integrations/base/sql.ts +75 -29
  335. package/src/integrations/googlesheets.ts +353 -0
  336. package/src/integrations/index.ts +3 -0
  337. package/src/integrations/tests/sql.spec.js +16 -0
  338. package/src/integrations/utils.ts +75 -12
  339. package/src/middleware/authorized.js +66 -30
  340. package/src/middleware/builder.js +2 -2
  341. package/src/middleware/currentapp.js +50 -46
  342. package/src/middleware/tests/authorized.spec.js +13 -6
  343. package/src/middleware/tests/currentapp.spec.js +6 -0
  344. package/src/middleware/tests/usageQuota.spec.js +18 -24
  345. package/src/middleware/usageQuota.js +93 -17
  346. package/src/migrations/functions/appUrls.ts +34 -0
  347. package/src/migrations/functions/quotas1.ts +20 -0
  348. package/src/migrations/functions/tests/appUrls.spec.js +29 -0
  349. package/src/migrations/functions/tests/quotas1.spec.js +27 -0
  350. package/src/migrations/functions/tests/userEmailViewCasing.spec.js +25 -0
  351. package/src/migrations/functions/usageQuotas/index.ts +8 -0
  352. package/src/migrations/functions/usageQuotas/syncApps.ts +18 -0
  353. package/src/migrations/functions/usageQuotas/syncRows.ts +22 -0
  354. package/src/migrations/functions/usageQuotas/tests/syncApps.spec.js +37 -0
  355. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.js +43 -0
  356. package/src/migrations/functions/userEmailViewCasing.ts +13 -0
  357. package/src/migrations/index.ts +56 -0
  358. package/src/module.d.ts +3 -0
  359. package/src/tests/utilities/TestConfiguration.js +82 -55
  360. package/src/threads/automation.js +17 -15
  361. package/src/threads/query.js +17 -12
  362. package/src/utilities/fileSystem/index.js +4 -3
  363. package/src/utilities/global.js +15 -12
  364. package/src/utilities/index.js +7 -17
  365. package/src/utilities/routing/index.js +5 -5
  366. package/src/utilities/rowProcessor/index.js +25 -27
  367. package/src/utilities/rowProcessor/utils.js +23 -7
  368. package/src/utilities/tests/usageQuota/usageQuota.spec.js +72 -0
  369. package/src/utilities/usageQuota/index.js +93 -0
  370. package/src/utilities/usageQuota/rows.js +75 -0
  371. package/src/utilities/usageQuota/usageQuoteReset.js +18 -0
  372. package/src/utilities/users.js +3 -3
  373. package/src/utilities/workerRequests.js +4 -27
  374. package/tsconfig.json +2 -1
  375. package/builder/assets/index.39e01193.css +0 -1
  376. package/dist/api/controllers/hosting.js +0 -30
  377. package/dist/api/routes/hosting.js +0 -11
  378. package/src/api/controllers/hosting.js +0 -22
  379. package/src/api/routes/hosting.js +0 -13
  380. package/src/api/routes/tests/hosting.spec.js +0 -36
  381. package/src/utilities/usageQuota.js +0 -73
@@ -19,13 +19,11 @@ var __rest = (this && this.__rest) || function (s, e) {
19
19
  }
20
20
  return t;
21
21
  };
22
- const CouchDB = require("../../../db");
23
22
  const linkRows = require("../../../db/linkedRows");
24
- const { getRowParams, generateRowID, DocumentTypes, InternalTables, } = require("../../../db/utils");
23
+ const { generateRowID, getRowParams, DocumentTypes, InternalTables, } = require("../../../db/utils");
25
24
  const userController = require("../user");
26
- const { inputProcessing, outputProcessing, processAutoColumn, cleanupAttachments, } = require("../../../utilities/rowProcessor");
25
+ const { inputProcessing, outputProcessing, cleanupAttachments, } = require("../../../utilities/rowProcessor");
27
26
  const { FieldTypes } = require("../../../constants");
28
- const { isEqual } = require("lodash");
29
27
  const { validate, findRow } = require("./utils");
30
28
  const { fullSearch, paginatedSearch } = require("./internalSearch");
31
29
  const { getGlobalUsersFromMetadata } = require("../../../utilities/global");
@@ -33,59 +31,13 @@ const inMemoryViews = require("../../../db/inMemoryView");
33
31
  const env = require("../../../environment");
34
32
  const { migrateToInMemoryView, migrateToDesignView, getFromDesignDoc, getFromMemoryDoc, } = require("../view/utils");
35
33
  const { cloneDeep } = require("lodash/fp");
34
+ const { getAppDB } = require("@budibase/backend-core/context");
35
+ const { finaliseRow, updateRelatedFormula } = require("./staticFormula");
36
36
  const CALCULATION_TYPES = {
37
37
  SUM: "sum",
38
38
  COUNT: "count",
39
39
  STATS: "stats",
40
40
  };
41
- function storeResponse(ctx, db, row, oldTable, table) {
42
- return __awaiter(this, void 0, void 0, function* () {
43
- row.type = "row";
44
- // don't worry about rev, tables handle rev/lastID updates
45
- // if another row has been written since processing this will
46
- // handle the auto ID clash
47
- if (!isEqual(oldTable, table)) {
48
- try {
49
- yield db.put(table);
50
- }
51
- catch (err) {
52
- if (err.status === 409) {
53
- const updatedTable = yield db.get(table._id);
54
- let response = processAutoColumn(null, updatedTable, row, {
55
- reprocessing: true,
56
- });
57
- yield db.put(response.table);
58
- row = response.row;
59
- }
60
- else {
61
- throw err;
62
- }
63
- }
64
- }
65
- const response = yield db.put(row);
66
- row._rev = response.rev;
67
- // process the row before return, to include relationships
68
- row = yield outputProcessing(ctx, table, row, { squash: false });
69
- return { row, table };
70
- });
71
- }
72
- // doesn't do the outputProcessing
73
- function getRawTableData(ctx, db, tableId) {
74
- return __awaiter(this, void 0, void 0, function* () {
75
- let rows;
76
- if (tableId === InternalTables.USER_METADATA) {
77
- yield userController.fetchMetadata(ctx);
78
- rows = ctx.body;
79
- }
80
- else {
81
- const response = yield db.allDocs(getRowParams(tableId, null, {
82
- include_docs: true,
83
- }));
84
- rows = response.rows.map(row => row.doc);
85
- }
86
- return rows;
87
- });
88
- }
89
41
  function getView(db, viewName) {
90
42
  return __awaiter(this, void 0, void 0, function* () {
91
43
  let mainGetter = env.SELF_HOSTED ? getFromDesignDoc : getFromMemoryDoc;
@@ -114,9 +66,24 @@ function getView(db, viewName) {
114
66
  return viewInfo;
115
67
  });
116
68
  }
69
+ function getRawTableData(ctx, db, tableId) {
70
+ return __awaiter(this, void 0, void 0, function* () {
71
+ let rows;
72
+ if (tableId === InternalTables.USER_METADATA) {
73
+ yield userController.fetchMetadata(ctx);
74
+ rows = ctx.body;
75
+ }
76
+ else {
77
+ const response = yield db.allDocs(getRowParams(tableId, null, {
78
+ include_docs: true,
79
+ }));
80
+ rows = response.rows.map(row => row.doc);
81
+ }
82
+ return rows;
83
+ });
84
+ }
117
85
  exports.patch = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
118
- const appId = ctx.appId;
119
- const db = new CouchDB(appId);
86
+ const db = getAppDB();
120
87
  const inputs = ctx.request.body;
121
88
  const tableId = inputs.tableId;
122
89
  const isUserTable = tableId === InternalTables.USER_METADATA;
@@ -155,26 +122,27 @@ exports.patch = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
155
122
  }
156
123
  // returned row is cleaned and prepared for writing to DB
157
124
  row = yield linkRows.updateLinks({
158
- appId,
159
125
  eventType: linkRows.EventType.ROW_UPDATE,
160
126
  row,
161
127
  tableId: row.tableId,
162
128
  table,
163
129
  });
164
130
  // check if any attachments removed
165
- yield cleanupAttachments(appId, table, { oldRow, row });
131
+ yield cleanupAttachments(table, { oldRow, row });
166
132
  if (isUserTable) {
167
133
  // the row has been updated, need to put it into the ctx
168
134
  ctx.request.body = row;
169
135
  yield userController.updateMetadata(ctx);
170
136
  return { row: ctx.body, table };
171
137
  }
172
- return storeResponse(ctx, db, row, dbTable, table);
138
+ return finaliseRow(table, row, {
139
+ oldTable: dbTable,
140
+ updateFormula: true,
141
+ });
173
142
  });
174
143
  exports.save = function (ctx) {
175
144
  return __awaiter(this, void 0, void 0, function* () {
176
- const appId = ctx.appId;
177
- const db = new CouchDB(appId);
145
+ const db = getAppDB();
178
146
  let inputs = ctx.request.body;
179
147
  inputs.tableId = ctx.params.tableId;
180
148
  if (!inputs._rev && !inputs._id) {
@@ -192,24 +160,25 @@ exports.save = function (ctx) {
192
160
  }
193
161
  // make sure link rows are up to date
194
162
  row = yield linkRows.updateLinks({
195
- appId,
196
163
  eventType: linkRows.EventType.ROW_SAVE,
197
164
  row,
198
165
  tableId: row.tableId,
199
166
  table,
200
167
  });
201
- return storeResponse(ctx, db, row, dbTable, table);
168
+ return finaliseRow(table, row, {
169
+ oldTable: dbTable,
170
+ updateFormula: true,
171
+ });
202
172
  });
203
173
  };
204
174
  exports.fetchView = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
205
- const appId = ctx.appId;
206
175
  const viewName = ctx.params.viewName;
207
176
  // if this is a table view being looked for just transfer to that
208
177
  if (viewName.startsWith(DocumentTypes.TABLE)) {
209
178
  ctx.params.tableId = viewName;
210
179
  return exports.fetch(ctx);
211
180
  }
212
- const db = new CouchDB(appId);
181
+ const db = getAppDB();
213
182
  const { calculation, group, field } = ctx.query;
214
183
  const viewInfo = yield getView(db, viewName);
215
184
  let response;
@@ -237,7 +206,7 @@ exports.fetchView = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
237
206
  schema: {},
238
207
  };
239
208
  }
240
- rows = yield outputProcessing(ctx, table, response.rows);
209
+ rows = yield outputProcessing(table, response.rows);
241
210
  }
242
211
  if (calculation === CALCULATION_TYPES.STATS) {
243
212
  response.rows = response.rows.map(row => (Object.assign(Object.assign({ group: row.key, field }, row.value), { avg: row.value.sum / row.value.count })));
@@ -254,25 +223,22 @@ exports.fetchView = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
254
223
  return rows;
255
224
  });
256
225
  exports.fetch = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
257
- const appId = ctx.appId;
258
- const db = new CouchDB(appId);
226
+ const db = getAppDB();
259
227
  const tableId = ctx.params.tableId;
260
228
  let table = yield db.get(tableId);
261
229
  let rows = yield getRawTableData(ctx, db, tableId);
262
- return outputProcessing(ctx, table, rows);
230
+ return outputProcessing(table, rows);
263
231
  });
264
232
  exports.find = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
265
- const appId = ctx.appId;
266
- const db = new CouchDB(appId);
233
+ const db = getAppDB();
267
234
  const table = yield db.get(ctx.params.tableId);
268
- let row = yield findRow(ctx, db, ctx.params.tableId, ctx.params.rowId);
269
- row = yield outputProcessing(ctx, table, row);
235
+ let row = yield findRow(ctx, ctx.params.tableId, ctx.params.rowId);
236
+ row = yield outputProcessing(table, row);
270
237
  return row;
271
238
  });
272
239
  exports.destroy = function (ctx) {
273
240
  return __awaiter(this, void 0, void 0, function* () {
274
- const appId = ctx.appId;
275
- const db = new CouchDB(appId);
241
+ const db = getAppDB();
276
242
  const { _id, _rev } = ctx.request.body;
277
243
  let row = yield db.get(_id);
278
244
  if (row.tableId !== ctx.params.tableId) {
@@ -280,16 +246,17 @@ exports.destroy = function (ctx) {
280
246
  }
281
247
  const table = yield db.get(row.tableId);
282
248
  // update the row to include full relationships before deleting them
283
- row = yield outputProcessing(ctx, table, row, { squash: false });
249
+ row = yield outputProcessing(table, row, { squash: false });
284
250
  // now remove the relationships
285
251
  yield linkRows.updateLinks({
286
- appId,
287
252
  eventType: linkRows.EventType.ROW_DELETE,
288
253
  row,
289
254
  tableId: row.tableId,
290
255
  });
291
256
  // remove any attachments that were on the row from object storage
292
- yield cleanupAttachments(appId, table, { row });
257
+ yield cleanupAttachments(table, { row });
258
+ // remove any static formula
259
+ yield updateRelatedFormula(table, row);
293
260
  let response;
294
261
  if (ctx.params.tableId === InternalTables.USER_METADATA) {
295
262
  ctx.params = {
@@ -305,17 +272,15 @@ exports.destroy = function (ctx) {
305
272
  });
306
273
  };
307
274
  exports.bulkDestroy = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
308
- const appId = ctx.appId;
309
- const db = new CouchDB(appId);
275
+ const db = getAppDB();
310
276
  const tableId = ctx.params.tableId;
311
277
  const table = yield db.get(tableId);
312
278
  let { rows } = ctx.request.body;
313
279
  // before carrying out any updates, make sure the rows are ready to be returned
314
280
  // they need to be the full rows (including previous relationships) for automations
315
- rows = yield outputProcessing(ctx, table, rows, { squash: false });
281
+ rows = yield outputProcessing(table, rows, { squash: false });
316
282
  // remove the relationships first
317
283
  let updates = rows.map(row => linkRows.updateLinks({
318
- appId,
319
284
  eventType: linkRows.EventType.ROW_DELETE,
320
285
  row,
321
286
  tableId: row.tableId,
@@ -332,7 +297,8 @@ exports.bulkDestroy = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
332
297
  yield db.bulkDocs(rows.map(row => (Object.assign(Object.assign({}, row), { _deleted: true }))));
333
298
  }
334
299
  // remove any attachments that were on the rows from object storage
335
- yield cleanupAttachments(appId, table, { rows });
300
+ yield cleanupAttachments(table, { rows });
301
+ yield updateRelatedFormula(table, rows);
336
302
  yield Promise.all(updates);
337
303
  return { response: { ok: true }, rows };
338
304
  });
@@ -341,50 +307,46 @@ exports.search = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
341
307
  if (env.isCypress()) {
342
308
  return { rows: yield exports.fetch(ctx) };
343
309
  }
344
- const appId = ctx.appId;
345
310
  const { tableId } = ctx.params;
346
- const db = new CouchDB(appId);
311
+ const db = getAppDB();
347
312
  const _a = ctx.request.body, { paginate, query } = _a, params = __rest(_a, ["paginate", "query"]);
348
313
  params.version = ctx.version;
349
314
  params.tableId = tableId;
350
315
  let response;
351
316
  if (paginate) {
352
- response = yield paginatedSearch(appId, query, params);
317
+ response = yield paginatedSearch(query, params);
353
318
  }
354
319
  else {
355
- response = yield fullSearch(appId, query, params);
320
+ response = yield fullSearch(query, params);
356
321
  }
357
322
  // Enrich search results with relationships
358
323
  if (response.rows && response.rows.length) {
359
324
  // enrich with global users if from users table
360
325
  if (tableId === InternalTables.USER_METADATA) {
361
- response.rows = yield getGlobalUsersFromMetadata(appId, response.rows);
326
+ response.rows = yield getGlobalUsersFromMetadata(response.rows);
362
327
  }
363
328
  const table = yield db.get(tableId);
364
- response.rows = yield outputProcessing(ctx, table, response.rows);
329
+ response.rows = yield outputProcessing(table, response.rows);
365
330
  }
366
331
  return response;
367
332
  });
368
333
  exports.validate = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
369
334
  return validate({
370
- appId: ctx.appId,
371
335
  tableId: ctx.params.tableId,
372
336
  row: ctx.request.body,
373
337
  });
374
338
  });
375
339
  exports.fetchEnrichedRow = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
376
- const appId = ctx.appId;
377
- const db = new CouchDB(appId);
340
+ const db = getAppDB();
378
341
  const tableId = ctx.params.tableId;
379
342
  const rowId = ctx.params.rowId;
380
343
  // need table to work out where links go in row
381
344
  let [table, row] = yield Promise.all([
382
345
  db.get(tableId),
383
- findRow(ctx, db, tableId, rowId),
346
+ findRow(ctx, tableId, rowId),
384
347
  ]);
385
348
  // get the link docs
386
349
  const linkVals = yield linkRows.getLinkDocuments({
387
- appId,
388
350
  tableId,
389
351
  rowId,
390
352
  });
@@ -408,7 +370,7 @@ exports.fetchEnrichedRow = (ctx) => __awaiter(void 0, void 0, void 0, function*
408
370
  let linkedRows = [];
409
371
  for (let [tableId, rows] of Object.entries(groups)) {
410
372
  // need to include the IDs in these rows for any links they may have
411
- linkedRows = linkedRows.concat(yield outputProcessing(ctx, tables[tableId], rows));
373
+ linkedRows = linkedRows.concat(yield outputProcessing(tables[tableId], rows));
412
374
  }
413
375
  // insert the link rows in the correct place throughout the main row
414
376
  for (let fieldName of Object.keys(table.schema)) {
@@ -11,13 +11,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  const { SearchIndexes } = require("../../../db/utils");
12
12
  const fetch = require("node-fetch");
13
13
  const { getCouchUrl } = require("@budibase/backend-core/db");
14
+ const { getAppId } = require("@budibase/backend-core/context");
14
15
  /**
15
16
  * Class to build lucene query URLs.
16
17
  * Optionally takes a base lucene query object.
17
18
  */
18
19
  class QueryBuilder {
19
- constructor(appId, base) {
20
- this.appId = appId;
20
+ constructor(base) {
21
21
  this.query = Object.assign({ string: {}, fuzzy: {}, range: {}, equal: {}, notEqual: {}, empty: {}, notEmpty: {} }, base);
22
22
  this.limit = 50;
23
23
  this.sortOrder = "ascending";
@@ -34,19 +34,27 @@ class QueryBuilder {
34
34
  return this;
35
35
  }
36
36
  setLimit(limit) {
37
- this.limit = limit;
37
+ if (limit != null) {
38
+ this.limit = limit;
39
+ }
38
40
  return this;
39
41
  }
40
42
  setSort(sort) {
41
- this.sort = sort;
43
+ if (sort != null) {
44
+ this.sort = sort;
45
+ }
42
46
  return this;
43
47
  }
44
48
  setSortOrder(sortOrder) {
45
- this.sortOrder = sortOrder;
49
+ if (sortOrder != null) {
50
+ this.sortOrder = sortOrder;
51
+ }
46
52
  return this;
47
53
  }
48
54
  setSortType(sortType) {
49
- this.sortType = sortType;
55
+ if (sortType != null) {
56
+ this.sortType = sortType;
57
+ }
50
58
  return this;
51
59
  }
52
60
  setBookmark(bookmark) {
@@ -213,7 +221,8 @@ class QueryBuilder {
213
221
  }
214
222
  run() {
215
223
  return __awaiter(this, void 0, void 0, function* () {
216
- const url = `${getCouchUrl()}/${this.appId}/_design/database/_search/${SearchIndexes.ROWS}`;
224
+ const appId = getAppId();
225
+ const url = `${getCouchUrl()}/${appId}/_design/database/_search/${SearchIndexes.ROWS}`;
217
226
  const body = this.buildSearchBody();
218
227
  return yield runQuery(url, body);
219
228
  });
@@ -246,7 +255,6 @@ const runQuery = (url, body) => __awaiter(void 0, void 0, void 0, function* () {
246
255
  * Gets round the fixed limit of 200 results from a query by fetching as many
247
256
  * pages as required and concatenating the results. This recursively operates
248
257
  * until enough results have been found.
249
- * @param appId {string} The app ID to search
250
258
  * @param query {object} The JSON query structure
251
259
  * @param params {object} The search params including:
252
260
  * tableId {string} The table ID to search
@@ -259,7 +267,7 @@ const runQuery = (url, body) => __awaiter(void 0, void 0, void 0, function* () {
259
267
  * rows {array|null} Current results in the recursive search
260
268
  * @returns {Promise<*[]|*>}
261
269
  */
262
- const recursiveSearch = (appId, query, params) => __awaiter(void 0, void 0, void 0, function* () {
270
+ const recursiveSearch = (query, params) => __awaiter(void 0, void 0, void 0, function* () {
263
271
  const bookmark = params.bookmark;
264
272
  const rows = params.rows || [];
265
273
  if (rows.length >= params.limit) {
@@ -269,7 +277,7 @@ const recursiveSearch = (appId, query, params) => __awaiter(void 0, void 0, void
269
277
  if (rows.length > params.limit - 200) {
270
278
  pageSize = params.limit - rows.length;
271
279
  }
272
- const page = yield new QueryBuilder(appId, query)
280
+ const page = yield new QueryBuilder(query)
273
281
  .setVersion(params.version)
274
282
  .setTable(params.tableId)
275
283
  .setBookmark(bookmark)
@@ -285,13 +293,12 @@ const recursiveSearch = (appId, query, params) => __awaiter(void 0, void 0, void
285
293
  return [...rows, ...page.rows];
286
294
  }
287
295
  const newParams = Object.assign(Object.assign({}, params), { bookmark: page.bookmark, rows: [...rows, ...page.rows] });
288
- return yield recursiveSearch(appId, query, newParams);
296
+ return yield recursiveSearch(query, newParams);
289
297
  });
290
298
  /**
291
299
  * Performs a paginated search. A bookmark will be returned to allow the next
292
300
  * page to be fetched. There is a max limit off 200 results per page in a
293
301
  * paginated search.
294
- * @param appId {string} The app ID to search
295
302
  * @param query {object} The JSON query structure
296
303
  * @param params {object} The search params including:
297
304
  * tableId {string} The table ID to search
@@ -303,13 +310,13 @@ const recursiveSearch = (appId, query, params) => __awaiter(void 0, void 0, void
303
310
  * bookmark {string} The bookmark to resume from
304
311
  * @returns {Promise<{hasNextPage: boolean, rows: *[]}>}
305
312
  */
306
- exports.paginatedSearch = (appId, query, params) => __awaiter(void 0, void 0, void 0, function* () {
313
+ exports.paginatedSearch = (query, params) => __awaiter(void 0, void 0, void 0, function* () {
307
314
  let limit = params.limit;
308
315
  if (limit == null || isNaN(limit) || limit < 0) {
309
316
  limit = 50;
310
317
  }
311
318
  limit = Math.min(limit, 200);
312
- const search = new QueryBuilder(appId, query)
319
+ const search = new QueryBuilder(query)
313
320
  .setVersion(params.version)
314
321
  .setTable(params.tableId)
315
322
  .setSort(params.sort)
@@ -332,7 +339,6 @@ exports.paginatedSearch = (appId, query, params) => __awaiter(void 0, void 0, vo
332
339
  * desired amount of results. There is a limit of 1000 results to avoid
333
340
  * heavy performance hits, and to avoid client components breaking from
334
341
  * handling too much data.
335
- * @param appId {string} The app ID to search
336
342
  * @param query {object} The JSON query structure
337
343
  * @param params {object} The search params including:
338
344
  * tableId {string} The table ID to search
@@ -343,12 +349,12 @@ exports.paginatedSearch = (appId, query, params) => __awaiter(void 0, void 0, vo
343
349
  * limit {number} The desired number of results
344
350
  * @returns {Promise<{rows: *}>}
345
351
  */
346
- exports.fullSearch = (appId, query, params) => __awaiter(void 0, void 0, void 0, function* () {
352
+ exports.fullSearch = (query, params) => __awaiter(void 0, void 0, void 0, function* () {
347
353
  let limit = params.limit;
348
354
  if (limit == null || isNaN(limit) || limit < 0) {
349
355
  limit = 1000;
350
356
  }
351
357
  params.limit = Math.min(limit, 1000);
352
- const rows = yield recursiveSearch(appId, query, params);
358
+ const rows = yield recursiveSearch(query, params);
353
359
  return { rows };
354
360
  });
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ const { getRowParams } = require("../../../db/utils");
12
+ const { outputProcessing, processAutoColumn, processFormulas, } = require("../../../utilities/rowProcessor");
13
+ const { FieldTypes, FormulaTypes } = require("../../../constants");
14
+ const { isEqual } = require("lodash");
15
+ const { cloneDeep } = require("lodash/fp");
16
+ const { getAppDB } = require("@budibase/backend-core/context");
17
+ /**
18
+ * This function runs through a list of enriched rows, looks at the rows which
19
+ * are related and then checks if they need the state of their formulas
20
+ * updated.
21
+ * NOTE: this will only for affect static formulas.
22
+ */
23
+ exports.updateRelatedFormula = (table, enrichedRows) => __awaiter(void 0, void 0, void 0, function* () {
24
+ const db = getAppDB();
25
+ // no formula to update, we're done
26
+ if (!table.relatedFormula) {
27
+ return;
28
+ }
29
+ let promises = [];
30
+ for (let enrichedRow of Array.isArray(enrichedRows)
31
+ ? enrichedRows
32
+ : [enrichedRows]) {
33
+ // the related rows by tableId
34
+ let relatedRows = {};
35
+ for (let [key, field] of Object.entries(enrichedRow)) {
36
+ const columnDefinition = table.schema[key];
37
+ if (columnDefinition && columnDefinition.type === FieldTypes.LINK) {
38
+ const relatedTableId = columnDefinition.tableId;
39
+ if (!relatedRows[relatedTableId]) {
40
+ relatedRows[relatedTableId] = [];
41
+ }
42
+ relatedRows[relatedTableId] = relatedRows[relatedTableId].concat(field);
43
+ }
44
+ }
45
+ for (let tableId of table.relatedFormula) {
46
+ let relatedTable;
47
+ try {
48
+ // no rows to update, skip
49
+ if (!relatedRows[tableId] || relatedRows[tableId].length === 0) {
50
+ continue;
51
+ }
52
+ relatedTable = yield db.get(tableId);
53
+ }
54
+ catch (err) {
55
+ // no error scenario, table doesn't seem to exist anymore, ignore
56
+ }
57
+ for (let column of Object.values(relatedTable.schema)) {
58
+ // needs updated in related rows
59
+ if (column.type === FieldTypes.FORMULA &&
60
+ column.formulaType === FormulaTypes.STATIC) {
61
+ // re-enrich rows for all the related, don't update the related formula for them
62
+ promises = promises.concat(relatedRows[tableId].map(related => exports.finaliseRow(relatedTable, related, {
63
+ updateFormula: false,
64
+ })));
65
+ }
66
+ }
67
+ }
68
+ }
69
+ yield Promise.all(promises);
70
+ });
71
+ exports.updateAllFormulasInTable = (table) => __awaiter(void 0, void 0, void 0, function* () {
72
+ const db = getAppDB();
73
+ // start by getting the raw rows (which will be written back to DB after update)
74
+ let rows = (yield db.allDocs(getRowParams(table._id, null, {
75
+ include_docs: true,
76
+ }))).rows.map(row => row.doc);
77
+ // now enrich the rows, note the clone so that we have the base state of the
78
+ // rows so that we don't write any of the enriched information back
79
+ let enrichedRows = yield outputProcessing(table, cloneDeep(rows), {
80
+ squash: false,
81
+ });
82
+ const updatedRows = [];
83
+ for (let row of rows) {
84
+ // find the enriched row, if found process the formulas
85
+ const enrichedRow = enrichedRows.find(enriched => enriched._id === row._id);
86
+ if (enrichedRow) {
87
+ const processed = processFormulas(table, cloneDeep(row), {
88
+ dynamic: false,
89
+ contextRows: enrichedRow,
90
+ });
91
+ // values have changed, need to add to bulk docs to update
92
+ if (!isEqual(processed, row)) {
93
+ updatedRows.push(processed);
94
+ }
95
+ }
96
+ }
97
+ yield db.bulkDocs(updatedRows);
98
+ });
99
+ /**
100
+ * This function runs at the end of the save/patch functions of the row controller, all this
101
+ * really does is enrich the row, handle any static formula processing, then return the enriched
102
+ * row. The reason we need to return the enriched row is that the automation row created trigger
103
+ * expects the row to be totally enriched/contain all relationships.
104
+ */
105
+ exports.finaliseRow = (table, row, { oldTable, updateFormula } = { updateFormula: true }) => __awaiter(void 0, void 0, void 0, function* () {
106
+ const db = getAppDB();
107
+ row.type = "row";
108
+ // process the row before return, to include relationships
109
+ let enrichedRow = yield outputProcessing(table, cloneDeep(row), {
110
+ squash: false,
111
+ });
112
+ // use enriched row to generate formulas for saving, specifically only use as context
113
+ row = processFormulas(table, row, {
114
+ dynamic: false,
115
+ contextRows: enrichedRow,
116
+ });
117
+ // don't worry about rev, tables handle rev/lastID updates
118
+ // if another row has been written since processing this will
119
+ // handle the auto ID clash
120
+ if (oldTable && !isEqual(oldTable, table)) {
121
+ try {
122
+ yield db.put(table);
123
+ }
124
+ catch (err) {
125
+ if (err.status === 409) {
126
+ const updatedTable = yield db.get(table._id);
127
+ let response = processAutoColumn(null, updatedTable, row, {
128
+ reprocessing: true,
129
+ });
130
+ yield db.put(response.table);
131
+ row = response.row;
132
+ }
133
+ else {
134
+ throw err;
135
+ }
136
+ }
137
+ }
138
+ const response = yield db.put(row);
139
+ // for response, calculate the formulas for the enriched row
140
+ enrichedRow._rev = response.rev;
141
+ enrichedRow = yield processFormulas(table, enrichedRow, { dynamic: false });
142
+ // this updates the related formulas in other rows based on the relations to this row
143
+ if (updateFormula) {
144
+ yield exports.updateRelatedFormula(table, enrichedRow);
145
+ }
146
+ return { row: enrichedRow, table };
147
+ });
@@ -10,12 +10,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  const validateJs = require("validate.js");
12
12
  const { cloneDeep } = require("lodash/fp");
13
- const CouchDB = require("../../../db");
14
13
  const { InternalTables } = require("../../../db/utils");
15
14
  const userController = require("../user");
16
15
  const { FieldTypes } = require("../../../constants");
17
16
  const { processStringSync } = require("@budibase/string-templates");
18
17
  const { makeExternalQuery } = require("../../../integrations/base/utils");
18
+ const { getAppDB } = require("@budibase/backend-core/context");
19
19
  validateJs.extend(validateJs.validators.datetime, {
20
20
  parse: function (value) {
21
21
  return new Date(value).getTime();
@@ -25,13 +25,14 @@ validateJs.extend(validateJs.validators.datetime, {
25
25
  return new Date(value).toISOString();
26
26
  },
27
27
  });
28
- exports.getDatasourceAndQuery = (appId, json) => __awaiter(void 0, void 0, void 0, function* () {
28
+ exports.getDatasourceAndQuery = (json) => __awaiter(void 0, void 0, void 0, function* () {
29
29
  const datasourceId = json.endpoint.datasourceId;
30
- const db = new CouchDB(appId);
30
+ const db = getAppDB();
31
31
  const datasource = yield db.get(datasourceId);
32
32
  return makeExternalQuery(datasource, json);
33
33
  });
34
- exports.findRow = (ctx, db, tableId, rowId) => __awaiter(void 0, void 0, void 0, function* () {
34
+ exports.findRow = (ctx, tableId, rowId) => __awaiter(void 0, void 0, void 0, function* () {
35
+ const db = getAppDB();
35
36
  let row;
36
37
  // TODO remove special user case in future
37
38
  if (tableId === InternalTables.USER_METADATA) {
@@ -49,9 +50,9 @@ exports.findRow = (ctx, db, tableId, rowId) => __awaiter(void 0, void 0, void 0,
49
50
  }
50
51
  return row;
51
52
  });
52
- exports.validate = ({ appId, tableId, row, table }) => __awaiter(void 0, void 0, void 0, function* () {
53
+ exports.validate = ({ tableId, row, table }) => __awaiter(void 0, void 0, void 0, function* () {
53
54
  if (!table) {
54
- const db = new CouchDB(appId);
55
+ const db = getAppDB();
55
56
  table = yield db.get(tableId);
56
57
  }
57
58
  const errors = {};
@@ -64,19 +65,17 @@ exports.validate = ({ appId, tableId, row, table }) => __awaiter(void 0, void 0,
64
65
  }
65
66
  let res;
66
67
  // Validate.js doesn't seem to handle array
67
- if (type === FieldTypes.ARRAY) {
68
- const hasValues = Array.isArray(row[fieldName]) && row[fieldName].length > 0;
69
- // Check values are valid if values are specified
70
- if (hasValues) {
68
+ if (type === FieldTypes.ARRAY && row[fieldName]) {
69
+ if (row[fieldName].length) {
71
70
  row[fieldName].map(val => {
72
71
  if (!constraints.inclusion.includes(val)) {
73
- errors[fieldName] = "Value not in list";
72
+ errors[fieldName] = "Field not in list";
74
73
  }
75
74
  });
76
75
  }
77
- // Check for required constraint
78
- if (constraints.presence === true && !hasValues) {
79
- errors[fieldName] = "Required field";
76
+ else if (constraints.presence && row[fieldName].length === 0) {
77
+ // non required MultiSelect creates an empty array, which should not throw errors
78
+ errors[fieldName] = [`${fieldName} is required`];
80
79
  }
81
80
  }
82
81
  else if (type === FieldTypes.JSON && typeof row[fieldName] === "string") {