@budibase/server 2.0.38 → 2.0.40-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 (295) hide show
  1. package/__mocks__/mongodb.ts +1 -1
  2. package/__mocks__/node-fetch.ts +12 -2
  3. package/builder/assets/backups-default.8c011f1b.png +0 -0
  4. package/builder/assets/{index.e0ddd30b.css → index.442de33f.css} +2 -2
  5. package/builder/assets/{index.598a950c.js → index.d7b4247d.js} +342 -334
  6. package/builder/index.html +2 -2
  7. package/coverage/clover.xml +1125 -1250
  8. package/coverage/coverage-final.json +73 -77
  9. package/coverage/lcov-report/api/controllers/apikeys.js.html +6 -6
  10. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/cloud.js.html +79 -67
  12. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/dev.js.html +21 -21
  14. package/coverage/lcov-report/api/controllers/index.html +17 -47
  15. package/coverage/lcov-report/api/controllers/integration.js.html +4 -4
  16. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/metadata.js.html +9 -9
  18. package/coverage/lcov-report/api/controllers/migrations.js.html +4 -4
  19. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  21. package/coverage/lcov-report/api/controllers/query/validation.js.html +4 -4
  22. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/routing.js.html +9 -9
  24. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/internal.js.html +13 -13
  27. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +15 -15
  29. package/coverage/lcov-report/api/controllers/row/utils.js.html +13 -13
  30. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +12 -9
  32. package/coverage/lcov-report/api/controllers/table/external.js.html +10 -10
  33. package/coverage/lcov-report/api/controllers/table/index.html +16 -16
  34. package/coverage/lcov-report/api/controllers/table/index.js.html +5 -5
  35. package/coverage/lcov-report/api/controllers/templates.js.html +6 -6
  36. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  39. package/coverage/lcov-report/api/controllers/view/index.js.html +3 -3
  40. package/coverage/lcov-report/api/controllers/view/utils.js.html +13 -13
  41. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +8 -8
  42. package/coverage/lcov-report/api/index.html +1 -1
  43. package/coverage/lcov-report/api/index.js.html +30 -30
  44. package/coverage/lcov-report/api/routes/analytics.js.html +7 -7
  45. package/coverage/lcov-report/api/routes/apikeys.js.html +8 -8
  46. package/coverage/lcov-report/api/routes/automation.js.html +11 -11
  47. package/coverage/lcov-report/api/routes/cloud.js.html +8 -8
  48. package/coverage/lcov-report/api/routes/component.js.html +8 -8
  49. package/coverage/lcov-report/api/routes/datasource.js.html +9 -9
  50. package/coverage/lcov-report/api/routes/deploy.js.html +8 -8
  51. package/coverage/lcov-report/api/routes/dev.js.html +13 -13
  52. package/coverage/lcov-report/api/routes/index.html +5 -35
  53. package/coverage/lcov-report/api/routes/integration.js.html +8 -8
  54. package/coverage/lcov-report/api/routes/layout.js.html +8 -8
  55. package/coverage/lcov-report/api/routes/metadata.js.html +9 -9
  56. package/coverage/lcov-report/api/routes/migrations.js.html +7 -7
  57. package/coverage/lcov-report/api/routes/permission.js.html +9 -9
  58. package/coverage/lcov-report/api/routes/query.js.html +10 -10
  59. package/coverage/lcov-report/api/routes/role.js.html +9 -9
  60. package/coverage/lcov-report/api/routes/routing.js.html +8 -8
  61. package/coverage/lcov-report/api/routes/screen.js.html +9 -9
  62. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/table.js.html +10 -10
  64. package/coverage/lcov-report/api/routes/templates.js.html +8 -8
  65. package/coverage/lcov-report/api/routes/user.js.html +8 -8
  66. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  67. package/coverage/lcov-report/api/routes/utils/validators.js.html +45 -45
  68. package/coverage/lcov-report/api/routes/view.js.html +10 -10
  69. package/coverage/lcov-report/automations/actions.js.html +1 -1
  70. package/coverage/lcov-report/automations/automationUtils.js.html +6 -6
  71. package/coverage/lcov-report/automations/bullboard.js.html +24 -84
  72. package/coverage/lcov-report/automations/index.html +21 -21
  73. package/coverage/lcov-report/automations/index.js.html +9 -9
  74. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  75. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  76. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  77. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  78. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  79. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  80. package/coverage/lcov-report/automations/steps/index.html +15 -15
  81. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/updateRow.js.html +3 -3
  89. package/coverage/lcov-report/automations/steps/utils.js.html +10 -10
  90. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  91. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  92. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  93. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  94. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  95. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  96. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  97. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  98. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  99. package/coverage/lcov-report/automations/triggers.js.html +49 -49
  100. package/coverage/lcov-report/constants/index.html +5 -5
  101. package/coverage/lcov-report/constants/index.js.html +10 -28
  102. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  103. package/coverage/lcov-report/constants/screens.js.html +1 -1
  104. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  105. package/coverage/lcov-report/db/index.html +19 -19
  106. package/coverage/lcov-report/db/index.js.html +1 -1
  107. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +17 -17
  108. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  109. package/coverage/lcov-report/db/linkedRows/index.js.html +28 -28
  110. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +15 -15
  111. package/coverage/lcov-report/db/newid.js.html +2 -2
  112. package/coverage/lcov-report/db/utils.js.html +37 -316
  113. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  114. package/coverage/lcov-report/events/index.html +1 -1
  115. package/coverage/lcov-report/events/index.js.html +3 -3
  116. package/coverage/lcov-report/events/utils.js.html +9 -9
  117. package/coverage/lcov-report/index.html +88 -88
  118. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  119. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  120. package/coverage/lcov-report/middleware/appInfo.js.html +5 -5
  121. package/coverage/lcov-report/middleware/builder.js.html +19 -19
  122. package/coverage/lcov-report/middleware/currentapp.js.html +49 -49
  123. package/coverage/lcov-report/middleware/index.html +1 -1
  124. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  125. package/coverage/lcov-report/middleware/publicApi.js.html +5 -5
  126. package/coverage/lcov-report/middleware/resourceId.js.html +28 -28
  127. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  128. package/coverage/lcov-report/middleware/utils.js.html +4 -4
  129. package/coverage/lcov-report/utilities/budibaseDir.js.html +3 -3
  130. package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
  131. package/coverage/lcov-report/utilities/csvParser.js.html +15 -12
  132. package/coverage/lcov-report/utilities/global.js.html +31 -31
  133. package/coverage/lcov-report/utilities/index.html +28 -28
  134. package/coverage/lcov-report/utilities/index.js.html +8 -8
  135. package/coverage/lcov-report/utilities/plugins.js.html +1 -1
  136. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +52 -52
  137. package/coverage/lcov-report/utilities/queue/index.html +21 -21
  138. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  139. package/coverage/lcov-report/utilities/routing/index.js.html +6 -6
  140. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  141. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +72 -57
  142. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +15 -15
  143. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  144. package/coverage/lcov-report/utilities/security.js.html +2 -2
  145. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  146. package/coverage/lcov-report/utilities/usageQuota/index.html +14 -14
  147. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +23 -11
  148. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  149. package/coverage/lcov-report/utilities/users.js.html +1 -1
  150. package/coverage/lcov-report/utilities/workerRequests.js.html +46 -46
  151. package/coverage/lcov.info +1691 -1899
  152. package/dist/api/controllers/application.js +4 -7
  153. package/dist/api/controllers/backup.js +19 -13
  154. package/dist/api/controllers/cloud.js +38 -35
  155. package/dist/api/controllers/deploy/index.js +11 -2
  156. package/dist/api/controllers/dev.js +1 -1
  157. package/dist/api/controllers/query/index.js +7 -2
  158. package/dist/api/controllers/row/index.js +40 -66
  159. package/dist/api/controllers/row/internal.js +1 -1
  160. package/dist/api/controllers/static/index.js +3 -2
  161. package/dist/api/controllers/static/templates/BudibaseApp.svelte +11 -0
  162. package/dist/api/controllers/static/templates/preview.hbs +10 -0
  163. package/dist/api/controllers/table/bulkFormula.js +4 -3
  164. package/dist/api/controllers/table/external.js +5 -4
  165. package/dist/api/controllers/table/index.js +4 -4
  166. package/dist/api/controllers/table/internal.js +10 -3
  167. package/dist/api/controllers/table/utils.js +7 -49
  168. package/dist/api/controllers/view/index.js +2 -2
  169. package/dist/api/controllers/webhook.js +88 -89
  170. package/dist/api/routes/backup.js +34 -7
  171. package/dist/api/routes/index.js +9 -4
  172. package/dist/api/routes/utils/validators.js +2 -2
  173. package/dist/api/routes/webhook.js +39 -11
  174. package/dist/app.js +2 -68
  175. package/dist/automations/automationUtils.js +2 -2
  176. package/dist/automations/bullboard.js +12 -35
  177. package/dist/automations/index.js +4 -4
  178. package/dist/automations/steps/updateRow.js +2 -2
  179. package/dist/automations/triggers.js +6 -6
  180. package/dist/automations/utils.js +23 -49
  181. package/dist/constants/index.js +4 -8
  182. package/dist/db/utils.js +10 -75
  183. package/dist/index.js +1 -0
  184. package/dist/integrations/arangodb.js +2 -0
  185. package/dist/integrations/base/sqlTable.js +1 -0
  186. package/dist/integrations/mongodb.js +300 -11
  187. package/dist/integrations/rest.js +38 -5
  188. package/dist/migrations/functions/backfill/app/tables.js +5 -8
  189. package/dist/migrations/functions/{quotas1.js → syncQuotas.js} +3 -7
  190. package/dist/migrations/functions/usageQuotas/syncApps.js +0 -1
  191. package/dist/migrations/functions/{pluginCount.js → usageQuotas/syncPlugins.js} +1 -3
  192. package/dist/migrations/functions/usageQuotas/syncRows.js +9 -5
  193. package/dist/migrations/index.js +10 -38
  194. package/dist/package.json +14 -14
  195. package/dist/sdk/app/automations/index.js +29 -0
  196. package/dist/sdk/app/automations/webhook.js +54 -0
  197. package/dist/sdk/app/backups/constants.js +5 -0
  198. package/dist/sdk/app/backups/exports.js +172 -0
  199. package/dist/sdk/app/backups/imports.js +190 -0
  200. package/dist/sdk/app/backups/index.js +29 -0
  201. package/dist/sdk/app/backups/statistics.js +73 -0
  202. package/dist/sdk/app/tables/index.js +61 -0
  203. package/dist/sdk/index.js +17 -0
  204. package/dist/startup.js +152 -0
  205. package/dist/tests/utilities/TestConfiguration.js +12 -2
  206. package/dist/threads/automation.js +12 -17
  207. package/dist/tsconfig.build.tsbuildinfo +1 -1
  208. package/dist/utilities/csvParser.js +1 -0
  209. package/dist/utilities/fileSystem/index.js +3 -95
  210. package/dist/utilities/fileSystem/utilities.js +2 -1
  211. package/dist/utilities/rowProcessor/index.js +5 -0
  212. package/dist/utilities/usageQuota/rows.js +6 -4
  213. package/package.json +15 -15
  214. package/specs/openapi.json +3 -0
  215. package/specs/openapi.yaml +3 -0
  216. package/src/api/controllers/application.ts +5 -12
  217. package/src/api/controllers/{backup.js → backup.ts} +7 -7
  218. package/src/api/controllers/cloud.js +44 -40
  219. package/src/api/controllers/deploy/index.ts +20 -8
  220. package/src/api/controllers/dev.js +1 -1
  221. package/src/api/controllers/query/index.ts +8 -2
  222. package/src/api/controllers/row/index.ts +50 -65
  223. package/src/api/controllers/row/internal.js +1 -1
  224. package/src/api/controllers/static/index.ts +4 -2
  225. package/src/api/controllers/static/templates/BudibaseApp.svelte +11 -0
  226. package/src/api/controllers/static/templates/preview.hbs +10 -0
  227. package/src/api/controllers/table/bulkFormula.js +4 -3
  228. package/src/api/controllers/table/external.js +4 -4
  229. package/src/api/controllers/table/index.js +4 -4
  230. package/src/api/controllers/table/internal.ts +8 -9
  231. package/src/api/controllers/table/utils.ts +4 -53
  232. package/src/api/controllers/view/index.js +2 -2
  233. package/src/api/controllers/{webhook.js → webhook.ts} +33 -48
  234. package/src/api/routes/backup.ts +10 -0
  235. package/src/api/routes/index.ts +11 -5
  236. package/src/api/routes/tests/backup.spec.js +1 -1
  237. package/src/api/routes/tests/{deployment.spec.js → deployment.spec.ts} +4 -4
  238. package/src/api/routes/tests/row.spec.js +22 -27
  239. package/src/api/routes/utils/validators.js +2 -2
  240. package/src/api/routes/{webhook.js → webhook.ts} +7 -6
  241. package/src/app.ts +3 -91
  242. package/src/automations/automationUtils.js +2 -2
  243. package/src/automations/bullboard.js +14 -34
  244. package/src/automations/index.js +4 -4
  245. package/src/automations/steps/updateRow.js +2 -2
  246. package/src/automations/tests/automation.spec.js +1 -6
  247. package/src/automations/triggers.js +6 -6
  248. package/src/automations/utils.ts +30 -32
  249. package/src/constants/index.js +4 -10
  250. package/src/db/utils.js +17 -110
  251. package/src/definitions/automations.ts +1 -18
  252. package/src/definitions/datasource.ts +1 -0
  253. package/src/index.ts +1 -0
  254. package/src/integrations/arangodb.ts +2 -0
  255. package/src/integrations/base/sqlTable.ts +1 -0
  256. package/src/integrations/mongodb.ts +290 -27
  257. package/src/integrations/rest.ts +17 -5
  258. package/src/integrations/tests/mongo.spec.ts +19 -19
  259. package/src/integrations/tests/rest.spec.ts +38 -22
  260. package/src/migrations/functions/backfill/app/tables.ts +7 -13
  261. package/src/migrations/functions/backfill/global.ts +1 -1
  262. package/src/migrations/functions/{quotas1.ts → syncQuotas.ts} +3 -8
  263. package/src/migrations/functions/tests/{quotas1.spec.js → syncQuotas.spec.js} +6 -5
  264. package/src/migrations/functions/tests/userEmailViewCasing.spec.js +6 -4
  265. package/src/migrations/functions/usageQuotas/syncApps.ts +0 -1
  266. package/src/migrations/functions/usageQuotas/syncPlugins.ts +10 -0
  267. package/src/migrations/functions/usageQuotas/syncRows.ts +15 -6
  268. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +9 -1
  269. package/src/migrations/index.ts +21 -45
  270. package/src/migrations/tests/index.spec.ts +0 -1
  271. package/src/sdk/app/automations/index.ts +5 -0
  272. package/src/sdk/app/automations/webhook.ts +43 -0
  273. package/src/sdk/app/backups/constants.ts +2 -0
  274. package/src/sdk/app/backups/exports.ts +171 -0
  275. package/src/sdk/app/backups/imports.ts +206 -0
  276. package/src/sdk/app/backups/index.ts +9 -0
  277. package/src/sdk/app/backups/statistics.ts +78 -0
  278. package/src/sdk/app/tables/index.ts +61 -0
  279. package/src/sdk/index.ts +15 -0
  280. package/src/startup.ts +138 -0
  281. package/src/tests/utilities/TestConfiguration.js +12 -2
  282. package/src/threads/automation.ts +20 -27
  283. package/src/utilities/csvParser.js +1 -0
  284. package/src/utilities/fileSystem/index.js +2 -119
  285. package/src/utilities/fileSystem/utilities.js +2 -0
  286. package/src/utilities/rowProcessor/index.js +5 -0
  287. package/src/utilities/usageQuota/rows.js +7 -3
  288. package/coverage/lcov-report/api/controllers/backup.js.html +0 -142
  289. package/coverage/lcov-report/api/controllers/webhook.js.html +0 -424
  290. package/coverage/lcov-report/api/routes/backup.js.html +0 -115
  291. package/coverage/lcov-report/api/routes/webhook.js.html +0 -163
  292. package/dist/automations/listeners.js +0 -102
  293. package/src/api/routes/backup.js +0 -10
  294. package/src/automations/listeners.ts +0 -78
  295. package/src/migrations/functions/pluginCount.ts +0 -12
@@ -25,11 +25,17 @@ import devRoutes from "./dev"
25
25
  import cloudRoutes from "./cloud"
26
26
  import migrationRoutes from "./migrations"
27
27
  import pluginRoutes from "./plugin"
28
+ import Router from "@koa/router"
29
+ import { api } from "@budibase/pro"
28
30
 
29
31
  export { default as staticRoutes } from "./static"
30
32
  export { default as publicRoutes } from "./public"
31
33
 
32
- export const mainRoutes = [
34
+ const appBackupRoutes = api.appBackups
35
+ const scheduleRoutes = api.schedules
36
+ export const mainRoutes: Router[] = [
37
+ appBackupRoutes,
38
+ backupRoutes,
33
39
  authRoutes,
34
40
  deployRoutes,
35
41
  layoutRoutes,
@@ -49,14 +55,14 @@ export const mainRoutes = [
49
55
  permissionRoutes,
50
56
  datasourceRoutes,
51
57
  queryRoutes,
52
- backupRoutes,
53
58
  metadataRoutes,
54
59
  devRoutes,
55
60
  cloudRoutes,
56
- // these need to be handled last as they still use /api/:tableId
57
- // this could be breaking as koa may recognise other routes as this
58
- tableRoutes,
59
61
  rowRoutes,
60
62
  migrationRoutes,
61
63
  pluginRoutes,
64
+ scheduleRoutes,
65
+ // these need to be handled last as they still use /api/:tableId
66
+ // this could be breaking as koa may recognise other routes as this
67
+ tableRoutes,
62
68
  ]
@@ -21,7 +21,7 @@ describe("/backups", () => {
21
21
  .set(config.defaultHeaders())
22
22
  .expect(200)
23
23
  expect(res.text).toBeDefined()
24
- expect(res.text.includes(`"db_name":"${config.getAppId()}"`)).toEqual(true)
24
+ expect(res.headers["content-type"]).toEqual("application/gzip")
25
25
  expect(events.app.exported.mock.calls.length).toBe(1)
26
26
  })
27
27
 
@@ -1,5 +1,5 @@
1
- const setup = require("./utilities")
2
- const { events } = require("@budibase/backend-core")
1
+ import setup from "./utilities"
2
+ import { events } from "@budibase/backend-core"
3
3
 
4
4
  describe("/deployments", () => {
5
5
  let request = setup.getRequest()
@@ -19,7 +19,7 @@ describe("/deployments", () => {
19
19
  .set(config.defaultHeaders())
20
20
  .expect("Content-Type", /json/)
21
21
  .expect(200)
22
- expect(events.app.published.mock.calls.length).toBe(1)
22
+ expect((events.app.published as jest.Mock).mock.calls.length).toBe(1)
23
23
  })
24
24
  })
25
- })
25
+ })
@@ -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 () => {
@@ -1,10 +1,10 @@
1
1
  const { joiValidator } = require("@budibase/backend-core/auth")
2
2
  const { DataSourceOperation } = require("../../../constants")
3
- const { WebhookType } = require("../../../constants")
4
3
  const {
5
4
  BUILTIN_PERMISSION_IDS,
6
5
  PermissionLevels,
7
6
  } = require("@budibase/backend-core/permissions")
7
+ const { WebhookActionType } = require("@budibase/types")
8
8
  const Joi = require("joi")
9
9
 
10
10
  const OPTIONAL_STRING = Joi.string().optional().allow(null).allow("")
@@ -126,7 +126,7 @@ exports.webhookValidator = () => {
126
126
  name: Joi.string().required(),
127
127
  bodySchema: Joi.object().optional(),
128
128
  action: Joi.object({
129
- type: Joi.string().required().valid(WebhookType.AUTOMATION),
129
+ type: Joi.string().required().valid(WebhookActionType.AUTOMATION),
130
130
  target: Joi.string().required(),
131
131
  }).required(),
132
132
  }).unknown(true))
@@ -1,9 +1,10 @@
1
- const Router = require("@koa/router")
2
- const controller = require("../controllers/webhook")
3
- const authorized = require("../../middleware/authorized")
4
- const { BUILDER } = require("@budibase/backend-core/permissions")
5
- const { webhookValidator } = require("./utils/validators")
1
+ import Router from "@koa/router"
2
+ import * as controller from "../controllers/webhook"
3
+ import authorized from "../../middleware/authorized"
4
+ import { permissions } from "@budibase/backend-core"
5
+ import { webhookValidator } from "./utils/validators"
6
6
 
7
+ const BUILDER = permissions.BUILDER
7
8
  const router = new Router()
8
9
 
9
10
  router
@@ -23,4 +24,4 @@ router
23
24
  // this shouldn't have authorisation, right now its always public
24
25
  .post("/api/webhooks/trigger/:instance/:id", controller.trigger)
25
26
 
26
- module.exports = router
27
+ export default router
package/src/app.ts CHANGED
@@ -15,28 +15,16 @@ db.init()
15
15
  const Koa = require("koa")
16
16
  const destroyable = require("server-destroy")
17
17
  const koaBody = require("koa-body")
18
- const pino = require("koa-pino-logger")
19
18
  const http = require("http")
20
19
  const api = require("./api")
21
- const eventEmitter = require("./events")
22
20
  const automations = require("./automations/index")
23
21
  const Sentry = require("@sentry/node")
24
- const fileSystem = require("./utilities/fileSystem")
25
- const bullboard = require("./automations/bullboard")
26
22
  const { logAlert } = require("@budibase/backend-core/logging")
27
- const { pinoSettings } = require("@budibase/backend-core")
28
23
  const { Thread } = require("./threads")
29
- const fs = require("fs")
30
24
  import redis from "./utilities/redis"
31
- import * as migrations from "./migrations"
32
- import { events, installation, tenancy } from "@budibase/backend-core"
33
- import {
34
- createAdminUser,
35
- generateApiKey,
36
- getChecklist,
37
- } from "./utilities/workerRequests"
38
- import { watch } from "./watch"
25
+ import { events } from "@budibase/backend-core"
39
26
  import { initialise as initialiseWebsockets } from "./websocket"
27
+ import { startup } from "./startup"
40
28
 
41
29
  const app = new Koa()
42
30
 
@@ -52,19 +40,6 @@ app.use(
52
40
  })
53
41
  )
54
42
 
55
- app.use(pino(pinoSettings()))
56
-
57
- if (!env.isTest()) {
58
- const plugin = bullboard.init()
59
- app.use(plugin)
60
- }
61
-
62
- app.context.eventEmitter = eventEmitter
63
- app.context.auth = {}
64
-
65
- // api routes
66
- app.use(api.router.routes())
67
-
68
43
  if (env.isProd()) {
69
44
  env._set("NODE_ENV", "production")
70
45
  Sentry.init()
@@ -103,70 +78,7 @@ server.on("close", async () => {
103
78
  })
104
79
 
105
80
  module.exports = server.listen(env.PORT || 0, async () => {
106
- console.log(`Budibase running on ${JSON.stringify(server.address())}`)
107
- env._set("PORT", server.address().port)
108
- eventEmitter.emitPort(env.PORT)
109
- fileSystem.init()
110
- await redis.init()
111
-
112
- // run migrations on startup if not done via http
113
- // not recommended in a clustered environment
114
- if (!env.HTTP_MIGRATIONS && !env.isTest()) {
115
- try {
116
- await migrations.migrate()
117
- } catch (e) {
118
- logAlert("Error performing migrations. Exiting.", e)
119
- shutdown()
120
- }
121
- }
122
-
123
- // check and create admin user if required
124
- if (
125
- env.SELF_HOSTED &&
126
- !env.MULTI_TENANCY &&
127
- env.BB_ADMIN_USER_EMAIL &&
128
- env.BB_ADMIN_USER_PASSWORD
129
- ) {
130
- const checklist = await getChecklist()
131
- if (!checklist?.adminUser?.checked) {
132
- try {
133
- const tenantId = tenancy.getTenantId()
134
- const user = await createAdminUser(
135
- env.BB_ADMIN_USER_EMAIL,
136
- env.BB_ADMIN_USER_PASSWORD,
137
- tenantId
138
- )
139
- // Need to set up an API key for automated integration tests
140
- if (env.isTest()) {
141
- await generateApiKey(user._id)
142
- }
143
-
144
- console.log(
145
- "Admin account automatically created for",
146
- env.BB_ADMIN_USER_EMAIL
147
- )
148
- } catch (e) {
149
- logAlert("Error creating initial admin user. Exiting.", e)
150
- shutdown()
151
- }
152
- }
153
- }
154
-
155
- // monitor plugin directory if required
156
- if (
157
- env.SELF_HOSTED &&
158
- !env.MULTI_TENANCY &&
159
- env.PLUGINS_DIR &&
160
- fs.existsSync(env.PLUGINS_DIR)
161
- ) {
162
- watch()
163
- }
164
-
165
- // check for version updates
166
- await installation.checkInstallVersion()
167
-
168
- // done last - this will never complete
169
- await automations.init()
81
+ await startup(app, server)
170
82
  })
171
83
 
172
84
  const shutdown = () => {
@@ -1,9 +1,9 @@
1
- const { getTable } = require("../api/controllers/table/utils")
2
1
  const {
3
2
  decodeJSBinding,
4
3
  isJSBinding,
5
4
  encodeJSBinding,
6
5
  } = require("@budibase/string-templates")
6
+ const sdk = require("../sdk")
7
7
 
8
8
  /**
9
9
  * When values are input to the system generally they will be of type string as this is required for template strings.
@@ -63,7 +63,7 @@ exports.cleanInputValues = (inputs, schema) => {
63
63
  * @returns {Promise<Object>} The cleaned up rows object, will should now have all the required primitive types.
64
64
  */
65
65
  exports.cleanUpRow = async (tableId, row) => {
66
- let table = await getTable(tableId)
66
+ let table = await sdk.tables.getTable(tableId)
67
67
  return exports.cleanInputValues(row, { properties: table.schema })
68
68
  }
69
69
 
@@ -1,39 +1,24 @@
1
1
  const { createBullBoard } = require("@bull-board/api")
2
2
  const { BullAdapter } = require("@bull-board/api/bullAdapter")
3
3
  const { KoaAdapter } = require("@bull-board/koa")
4
- const env = require("../environment")
5
- const Queue = env.isTest()
6
- ? require("../utilities/queue/inMemoryQueue")
7
- : require("bull")
8
- const { JobQueues } = require("../constants")
9
- const { utils } = require("@budibase/backend-core/redis")
10
- const { opts, redisProtocolUrl } = utils.getRedisOptions()
11
- const listeners = require("./listeners")
4
+ const { queue } = require("@budibase/backend-core")
5
+ const automation = require("../threads/automation")
6
+ const { backups } = require("@budibase/pro")
12
7
 
13
- const CLEANUP_PERIOD_MS = 60 * 1000
14
- const queueConfig = redisProtocolUrl || { redis: opts }
15
- let cleanupInternal = null
16
-
17
- let automationQueue = new Queue(JobQueues.AUTOMATIONS, queueConfig)
18
- listeners.addListeners(automationQueue)
19
-
20
- async function cleanup() {
21
- await automationQueue.clean(CLEANUP_PERIOD_MS, "completed")
22
- }
8
+ let automationQueue = queue.createQueue(
9
+ queue.JobQueue.AUTOMATION,
10
+ automation.removeStalled
11
+ )
23
12
 
24
13
  const PATH_PREFIX = "/bulladmin"
25
14
 
26
- exports.init = () => {
27
- // cleanup the events every 5 minutes
28
- if (!cleanupInternal) {
29
- cleanupInternal = setInterval(cleanup, CLEANUP_PERIOD_MS)
30
- // fire off an initial cleanup
31
- cleanup().catch(err => {
32
- console.error(`Unable to cleanup automation queue initially - ${err}`)
33
- })
34
- }
15
+ exports.init = async () => {
35
16
  // Set up queues for bull board admin
17
+ const backupQueue = await backups.getBackupQueue()
36
18
  const queues = [automationQueue]
19
+ if (backupQueue) {
20
+ queues.push(backupQueue)
21
+ }
37
22
  const adapters = []
38
23
  const serverAdapter = new KoaAdapter()
39
24
  for (let queue of queues) {
@@ -48,12 +33,7 @@ exports.init = () => {
48
33
  }
49
34
 
50
35
  exports.shutdown = async () => {
51
- if (automationQueue) {
52
- clearInterval(cleanupInternal)
53
- await automationQueue.close()
54
- automationQueue = null
55
- }
56
- console.log("Bull shutdown")
36
+ await queue.shutdown()
57
37
  }
58
38
 
59
- exports.queue = automationQueue
39
+ exports.automationQueue = automationQueue
@@ -1,5 +1,5 @@
1
1
  const { processEvent } = require("./utils")
2
- const { queue, shutdown } = require("./bullboard")
2
+ const { automationQueue, shutdown } = require("./bullboard")
3
3
  const { TRIGGER_DEFINITIONS, rebootTrigger } = require("./triggers")
4
4
  const { ACTION_DEFINITIONS } = require("./actions")
5
5
 
@@ -8,7 +8,7 @@ const { ACTION_DEFINITIONS } = require("./actions")
8
8
  */
9
9
  exports.init = async function () {
10
10
  // this promise will not complete
11
- const promise = queue.process(async job => {
11
+ const promise = automationQueue.process(async job => {
12
12
  await processEvent(job)
13
13
  })
14
14
  // on init we need to trigger any reboot automations
@@ -17,13 +17,13 @@ exports.init = async function () {
17
17
  }
18
18
 
19
19
  exports.getQueues = () => {
20
- return [queue]
20
+ return [automationQueue]
21
21
  }
22
22
 
23
23
  exports.shutdown = () => {
24
24
  return shutdown()
25
25
  }
26
26
 
27
- exports.queue = queue
27
+ exports.automationQueue = automationQueue
28
28
  exports.TRIGGER_DEFINITIONS = TRIGGER_DEFINITIONS
29
29
  exports.ACTION_DEFINITIONS = ACTION_DEFINITIONS
@@ -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()
@@ -4,7 +4,7 @@ const { coerce } = require("../utilities/rowProcessor")
4
4
  const { definitions } = require("./triggerInfo")
5
5
  const { isDevAppID } = require("../db/utils")
6
6
  // need this to call directly, so we can get a response
7
- const { queue } = require("./bullboard")
7
+ const { automationQueue } = require("./bullboard")
8
8
  const { checkTestFlag } = require("../utilities/redis")
9
9
  const utils = require("./utils")
10
10
  const env = require("../environment")
@@ -56,7 +56,7 @@ async function queueRelevantRowAutomations(event, eventType) {
56
56
  automationTrigger.inputs &&
57
57
  automationTrigger.inputs.tableId === event.row.tableId
58
58
  ) {
59
- await queue.add({ automation, event }, JOB_OPTS)
59
+ await automationQueue.add({ automation, event }, JOB_OPTS)
60
60
  }
61
61
  }
62
62
  })
@@ -110,14 +110,14 @@ exports.externalTrigger = async function (
110
110
  if (getResponses) {
111
111
  return utils.processEvent({ data })
112
112
  } else {
113
- return queue.add(data, JOB_OPTS)
113
+ return automationQueue.add(data, JOB_OPTS)
114
114
  }
115
115
  }
116
116
 
117
117
  exports.rebootTrigger = async () => {
118
118
  // reboot cron option is only available on the main thread at
119
- // startup and only usable in self host
120
- if (env.isInThread() || !env.SELF_HOSTED) {
119
+ // startup and only usable in self host and single tenant environments
120
+ if (env.isInThread() || !env.SELF_HOSTED || env.MULTI_TENANCY) {
121
121
  return
122
122
  }
123
123
  // iterate through all production apps, find the reboot crons
@@ -136,7 +136,7 @@ exports.rebootTrigger = async () => {
136
136
  timestamp: Date.now(),
137
137
  },
138
138
  }
139
- rebootEvents.push(queue.add(job, JOB_OPTS))
139
+ rebootEvents.push(automationQueue.add(job, JOB_OPTS))
140
140
  }
141
141
  }
142
142
  await Promise.all(rebootEvents)
@@ -1,10 +1,9 @@
1
1
  import { Thread, ThreadType } from "../threads"
2
2
  import { definitions } from "./triggerInfo"
3
- import * as webhooks from "../api/controllers/webhook"
4
- import { queue } from "./bullboard"
3
+ import { automationQueue } from "./bullboard"
5
4
  import newid from "../db/newid"
6
5
  import { updateEntityMetadata } from "../utilities"
7
- import { MetadataTypes, WebhookType } from "../constants"
6
+ import { MetadataTypes } from "../constants"
8
7
  import { getProdAppID, doWithDB } from "@budibase/backend-core/db"
9
8
  import { getAutomationMetadataParams } from "../db/utils"
10
9
  import { cloneDeep } from "lodash/fp"
@@ -13,9 +12,10 @@ import {
13
12
  getAppId,
14
13
  getProdAppDB,
15
14
  } from "@budibase/backend-core/context"
16
- import { tenancy } from "@budibase/backend-core"
15
+ import { context } from "@budibase/backend-core"
17
16
  import { quotas } from "@budibase/pro"
18
- import { Automation } from "@budibase/types"
17
+ import { Automation, WebhookActionType } from "@budibase/types"
18
+ import sdk from "../sdk"
19
19
 
20
20
  const REBOOT_CRON = "@reboot"
21
21
  const WH_STEP_ID = definitions.WEBHOOK.stepId
@@ -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)
@@ -77,21 +79,25 @@ export function removeDeprecated(definitions: any) {
77
79
  // end the repetition and the job itself
78
80
  export async function disableAllCrons(appId: any) {
79
81
  const promises = []
80
- const jobs = await queue.getRepeatableJobs()
82
+ const jobs = await automationQueue.getRepeatableJobs()
81
83
  for (let job of jobs) {
82
84
  if (job.key.includes(`${appId}_cron`)) {
83
- promises.push(queue.removeRepeatableByKey(job.key))
85
+ promises.push(automationQueue.removeRepeatableByKey(job.key))
84
86
  if (job.id) {
85
- promises.push(queue.removeJobs(job.id))
87
+ promises.push(automationQueue.removeJobs(job.id))
86
88
  }
87
89
  }
88
90
  }
89
91
  return Promise.all(promises)
90
92
  }
91
93
 
92
- export async function disableCron(jobId: string, jobKey: string) {
93
- await queue.removeRepeatableByKey(jobKey)
94
- await queue.removeJobs(jobId)
94
+ export async function disableCronById(jobId: number | string) {
95
+ const repeatJobs = await automationQueue.getRepeatableJobs()
96
+ for (let repeatJob of repeatJobs) {
97
+ if (repeatJob.id === jobId) {
98
+ await automationQueue.removeRepeatableByKey(repeatJob.key)
99
+ }
100
+ }
95
101
  console.log(`jobId=${jobId} disabled`)
96
102
  }
97
103
 
@@ -139,7 +145,7 @@ export async function enableCronTrigger(appId: any, automation: Automation) {
139
145
  ) {
140
146
  // make a job id rather than letting Bull decide, makes it easier to handle on way out
141
147
  const jobId = `${appId}_cron_${newid()}`
142
- const job: any = await queue.add(
148
+ const job: any = await automationQueue.add(
143
149
  {
144
150
  automation,
145
151
  event: { appId, timestamp: Date.now() },
@@ -191,16 +197,12 @@ export async function checkForWebhooks({ oldAuto, newAuto }: any) {
191
197
  let db = getAppDB()
192
198
  // need to get the webhook to get the rev
193
199
  const webhook = await db.get(oldTrigger.webhookId)
194
- const ctx = {
195
- appId,
196
- params: { id: webhook._id, rev: webhook._rev },
197
- }
198
200
  // might be updating - reset the inputs to remove the URLs
199
201
  if (newTrigger) {
200
202
  delete newTrigger.webhookId
201
203
  newTrigger.inputs = {}
202
204
  }
203
- await webhooks.destroy(ctx)
205
+ await sdk.automations.webhook.destroy(webhook._id, webhook._rev)
204
206
  } catch (err) {
205
207
  // don't worry about not being able to delete, if it doesn't exist all good
206
208
  }
@@ -210,18 +212,14 @@ export async function checkForWebhooks({ oldAuto, newAuto }: any) {
210
212
  (!isWebhookTrigger(oldAuto) || triggerChanged) &&
211
213
  isWebhookTrigger(newAuto)
212
214
  ) {
213
- const ctx: any = {
214
- appId,
215
- request: {
216
- body: new webhooks.Webhook(
217
- "Automation webhook",
218
- WebhookType.AUTOMATION,
219
- newAuto._id
220
- ),
221
- },
222
- }
223
- await webhooks.save(ctx)
224
- const id = ctx.body.webhook._id
215
+ const webhook = await sdk.automations.webhook.save(
216
+ sdk.automations.webhook.newDoc(
217
+ "Automation webhook",
218
+ WebhookActionType.AUTOMATION,
219
+ newAuto._id
220
+ )
221
+ )
222
+ const id = webhook._id
225
223
  newTrigger.webhookId = id
226
224
  // the app ID has to be development for this endpoint
227
225
  // it can only be used when building the app