@budibase/server 1.0.199 → 1.0.200-alpha.2

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 (281) hide show
  1. package/Dockerfile +2 -0
  2. package/builder/assets/index.359da19e.js +1315 -0
  3. package/builder/index.html +1 -1
  4. package/coverage/clover.xml +2089 -2001
  5. package/coverage/coverage-final.json +121 -122
  6. package/coverage/lcov-report/api/controllers/apikeys.js.html +6 -6
  7. package/coverage/lcov-report/api/controllers/auth.js.html +7 -7
  8. package/coverage/lcov-report/api/controllers/automation.js.html +174 -72
  9. package/coverage/lcov-report/api/controllers/backup.js.html +30 -6
  10. package/coverage/lcov-report/api/controllers/cloud.js.html +11 -11
  11. package/coverage/lcov-report/api/controllers/component.js.html +5 -5
  12. package/coverage/lcov-report/api/controllers/datasource.js.html +53 -41
  13. package/coverage/lcov-report/api/controllers/dev.js.html +94 -70
  14. package/coverage/lcov-report/api/controllers/index.html +57 -72
  15. package/coverage/lcov-report/api/controllers/integration.js.html +8 -8
  16. package/coverage/lcov-report/api/controllers/layout.js.html +28 -19
  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 +15 -15
  20. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  21. package/coverage/lcov-report/api/controllers/query/validation.js.html +10 -10
  22. package/coverage/lcov-report/api/controllers/role.js.html +78 -48
  23. package/coverage/lcov-report/api/controllers/routing.js.html +9 -9
  24. package/coverage/lcov-report/api/controllers/row/external.js.html +19 -19
  25. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/internal.js.html +54 -54
  27. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +9 -9
  28. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +24 -24
  29. package/coverage/lcov-report/api/controllers/row/utils.js.html +24 -24
  30. package/coverage/lcov-report/api/controllers/screen.js.html +56 -20
  31. package/coverage/lcov-report/api/controllers/script.js.html +4 -4
  32. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +49 -49
  33. package/coverage/lcov-report/api/controllers/table/external.js.html +23 -17
  34. package/coverage/lcov-report/api/controllers/table/index.html +26 -26
  35. package/coverage/lcov-report/api/controllers/table/index.js.html +85 -49
  36. package/coverage/lcov-report/api/controllers/templates.js.html +6 -6
  37. package/coverage/lcov-report/api/controllers/user.js.html +19 -19
  38. package/coverage/lcov-report/api/controllers/view/exporters.js.html +11 -11
  39. package/coverage/lcov-report/api/controllers/view/index.html +21 -21
  40. package/coverage/lcov-report/api/controllers/view/index.js.html +275 -65
  41. package/coverage/lcov-report/api/controllers/view/utils.js.html +23 -23
  42. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +40 -40
  43. package/coverage/lcov-report/api/controllers/webhook.js.html +17 -17
  44. package/coverage/lcov-report/api/index.html +15 -15
  45. package/coverage/lcov-report/api/index.js.html +39 -45
  46. package/coverage/lcov-report/api/routes/analytics.js.html +7 -13
  47. package/coverage/lcov-report/api/routes/apikeys.js.html +8 -8
  48. package/coverage/lcov-report/api/routes/auth.js.html +6 -6
  49. package/coverage/lcov-report/api/routes/automation.js.html +11 -11
  50. package/coverage/lcov-report/api/routes/backup.js.html +8 -8
  51. package/coverage/lcov-report/api/routes/cloud.js.html +8 -8
  52. package/coverage/lcov-report/api/routes/component.js.html +8 -8
  53. package/coverage/lcov-report/api/routes/datasource.js.html +9 -9
  54. package/coverage/lcov-report/api/routes/deploy.js.html +8 -8
  55. package/coverage/lcov-report/api/routes/dev.js.html +13 -13
  56. package/coverage/lcov-report/api/routes/index.html +1 -1
  57. package/coverage/lcov-report/api/routes/integration.js.html +8 -8
  58. package/coverage/lcov-report/api/routes/layout.js.html +8 -8
  59. package/coverage/lcov-report/api/routes/metadata.js.html +9 -9
  60. package/coverage/lcov-report/api/routes/migrations.js.html +7 -7
  61. package/coverage/lcov-report/api/routes/permission.js.html +9 -9
  62. package/coverage/lcov-report/api/routes/query.js.html +10 -10
  63. package/coverage/lcov-report/api/routes/role.js.html +9 -9
  64. package/coverage/lcov-report/api/routes/routing.js.html +8 -8
  65. package/coverage/lcov-report/api/routes/screen.js.html +9 -9
  66. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/table.js.html +10 -10
  68. package/coverage/lcov-report/api/routes/templates.js.html +8 -8
  69. package/coverage/lcov-report/api/routes/user.js.html +8 -8
  70. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  71. package/coverage/lcov-report/api/routes/utils/validators.js.html +36 -36
  72. package/coverage/lcov-report/api/routes/view.js.html +10 -10
  73. package/coverage/lcov-report/api/routes/webhook.js.html +9 -9
  74. package/coverage/lcov-report/automations/actions.js.html +25 -25
  75. package/coverage/lcov-report/automations/automationUtils.js.html +8 -8
  76. package/coverage/lcov-report/automations/bullboard.js.html +35 -35
  77. package/coverage/lcov-report/automations/index.html +29 -29
  78. package/coverage/lcov-report/automations/index.js.html +29 -17
  79. package/coverage/lcov-report/automations/steps/bash.js.html +7 -7
  80. package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
  81. package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
  82. package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
  83. package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
  84. package/coverage/lcov-report/automations/steps/filter.js.html +7 -7
  85. package/coverage/lcov-report/automations/steps/index.html +1 -1
  86. package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
  87. package/coverage/lcov-report/automations/steps/loop.js.html +2 -2
  88. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
  89. package/coverage/lcov-report/automations/steps/queryRows.js.html +10 -10
  90. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
  91. package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
  92. package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
  93. package/coverage/lcov-report/automations/steps/updateRow.js.html +6 -6
  94. package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
  95. package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
  96. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  97. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  98. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  100. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  101. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  102. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  103. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  104. package/coverage/lcov-report/automations/triggers.js.html +18 -18
  105. package/coverage/lcov-report/constants/index.html +1 -1
  106. package/coverage/lcov-report/constants/index.js.html +30 -30
  107. package/coverage/lcov-report/constants/layouts.js.html +5 -5
  108. package/coverage/lcov-report/constants/screens.js.html +4 -4
  109. package/coverage/lcov-report/db/inMemoryView.js.html +5 -5
  110. package/coverage/lcov-report/db/index.html +1 -1
  111. package/coverage/lcov-report/db/index.js.html +9 -9
  112. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +17 -17
  113. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  114. package/coverage/lcov-report/db/linkedRows/index.js.html +36 -36
  115. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +19 -19
  116. package/coverage/lcov-report/db/newid.js.html +4 -4
  117. package/coverage/lcov-report/db/utils.js.html +81 -81
  118. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  119. package/coverage/lcov-report/events/index.html +1 -1
  120. package/coverage/lcov-report/events/index.js.html +7 -7
  121. package/coverage/lcov-report/events/utils.js.html +10 -10
  122. package/coverage/lcov-report/index.html +74 -74
  123. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  124. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  125. package/coverage/lcov-report/middleware/appInfo.js.html +5 -5
  126. package/coverage/lcov-report/middleware/builder.js.html +20 -20
  127. package/coverage/lcov-report/middleware/currentapp.js.html +49 -49
  128. package/coverage/lcov-report/middleware/index.html +1 -1
  129. package/coverage/lcov-report/middleware/joi-validator.js.html +14 -14
  130. package/coverage/lcov-report/middleware/publicApi.js.html +5 -5
  131. package/coverage/lcov-report/middleware/resourceId.js.html +29 -29
  132. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  133. package/coverage/lcov-report/middleware/utils.js.html +4 -4
  134. package/coverage/lcov-report/threads/automation.js.html +1 -1
  135. package/coverage/lcov-report/threads/index.html +1 -1
  136. package/coverage/lcov-report/threads/query.js.html +1 -1
  137. package/coverage/lcov-report/threads/utils.js.html +13 -13
  138. package/coverage/lcov-report/utilities/budibaseDir.js.html +3 -3
  139. package/coverage/lcov-report/utilities/centralPath.js.html +14 -14
  140. package/coverage/lcov-report/utilities/csvParser.js.html +34 -34
  141. package/coverage/lcov-report/utilities/global.js.html +28 -28
  142. package/coverage/lcov-report/utilities/index.html +25 -25
  143. package/coverage/lcov-report/utilities/index.js.html +41 -41
  144. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +18 -18
  145. package/coverage/lcov-report/utilities/queue/index.html +15 -15
  146. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  147. package/coverage/lcov-report/utilities/routing/index.js.html +6 -6
  148. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  149. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +59 -59
  150. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +15 -15
  151. package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
  152. package/coverage/lcov-report/utilities/security.js.html +8 -8
  153. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  154. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  155. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +30 -30
  156. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  157. package/coverage/lcov-report/utilities/users.js.html +7 -7
  158. package/coverage/lcov-report/utilities/workerRequests.js.html +29 -29
  159. package/coverage/lcov.info +2903 -2762
  160. package/dist/api/controllers/analytics.js +7 -30
  161. package/dist/api/controllers/application.js +56 -16
  162. package/dist/api/controllers/automation.js +31 -2
  163. package/dist/api/controllers/backup.js +7 -0
  164. package/dist/api/controllers/datasource.js +8 -2
  165. package/dist/api/controllers/deploy/index.js +6 -2
  166. package/dist/api/controllers/dev.js +9 -2
  167. package/dist/api/controllers/layout.js +3 -0
  168. package/dist/api/controllers/query/import/index.js +12 -2
  169. package/dist/api/controllers/query/import/sources/curl.js +3 -0
  170. package/dist/api/controllers/query/import/sources/openapi2.js +3 -0
  171. package/dist/api/controllers/query/import/sources/openapi3.js +3 -0
  172. package/dist/api/controllers/query/index.js +16 -2
  173. package/dist/api/controllers/role.js +11 -0
  174. package/dist/api/controllers/screen.js +10 -1
  175. package/dist/api/controllers/static/index.js +29 -15
  176. package/dist/api/controllers/table/external.js +2 -0
  177. package/dist/api/controllers/table/index.js +12 -0
  178. package/dist/api/controllers/table/utils.js +3 -3
  179. package/dist/api/controllers/view/index.js +62 -6
  180. package/dist/api/index.js +2 -4
  181. package/dist/api/routes/analytics.js +1 -3
  182. package/dist/app.js +16 -8
  183. package/dist/automations/index.js +4 -0
  184. package/dist/environment.js +4 -2
  185. package/dist/migrations/functions/backfill/app/automations.js +31 -0
  186. package/dist/migrations/functions/backfill/app/datasources.js +28 -0
  187. package/dist/migrations/functions/backfill/app/layouts.js +33 -0
  188. package/dist/migrations/functions/backfill/app/queries.js +32 -0
  189. package/dist/migrations/functions/backfill/app/roles.js +28 -0
  190. package/dist/migrations/functions/backfill/app/screens.js +28 -0
  191. package/dist/migrations/functions/backfill/app/tables.js +40 -0
  192. package/dist/migrations/functions/backfill/app.js +175 -0
  193. package/dist/migrations/functions/backfill/global/configs.js +61 -0
  194. package/dist/migrations/functions/backfill/global/quotas.js +60 -0
  195. package/dist/migrations/functions/backfill/global/users.js +50 -0
  196. package/dist/migrations/functions/backfill/global.js +189 -0
  197. package/dist/migrations/functions/backfill/index.js +32 -0
  198. package/dist/migrations/functions/backfill/installation.js +81 -0
  199. package/dist/migrations/index.js +95 -31
  200. package/dist/migrations/tests/helpers.js +72 -0
  201. package/dist/migrations/tests/structures.js +37 -0
  202. package/dist/package.json +79 -69
  203. package/dist/tests/utilities/TestConfiguration.js +121 -93
  204. package/dist/tests/utilities/structures.js +45 -0
  205. package/dist/tsconfig.build.tsbuildinfo +1 -1
  206. package/nodemon.json +1 -1
  207. package/package.json +80 -70
  208. package/scripts/dev/manage.js +2 -0
  209. package/scripts/jestSetup.js +7 -0
  210. package/scripts/likeCypress.ts +1 -1
  211. package/src/api/controllers/analytics.ts +8 -0
  212. package/src/api/controllers/application.ts +60 -18
  213. package/src/api/controllers/automation.js +36 -2
  214. package/src/api/controllers/backup.js +8 -0
  215. package/src/api/controllers/datasource.js +8 -4
  216. package/src/api/controllers/deploy/index.ts +6 -2
  217. package/src/api/controllers/dev.js +10 -2
  218. package/src/api/controllers/layout.js +3 -0
  219. package/src/api/controllers/query/import/index.ts +16 -3
  220. package/src/api/controllers/query/import/sources/base/index.ts +2 -1
  221. package/src/api/controllers/query/import/sources/curl.ts +4 -0
  222. package/src/api/controllers/query/import/sources/openapi2.ts +4 -0
  223. package/src/api/controllers/query/import/sources/openapi3.ts +4 -0
  224. package/src/api/controllers/query/import/tests/index.spec.js +20 -7
  225. package/src/api/controllers/query/index.ts +16 -3
  226. package/src/api/controllers/role.js +10 -0
  227. package/src/api/controllers/screen.js +13 -1
  228. package/src/api/controllers/static/index.js +28 -15
  229. package/src/api/controllers/table/external.js +2 -0
  230. package/src/api/controllers/table/index.js +12 -0
  231. package/src/api/controllers/table/utils.ts +4 -4
  232. package/src/api/controllers/view/index.js +76 -6
  233. package/src/api/index.js +2 -4
  234. package/src/api/routes/analytics.js +1 -3
  235. package/src/api/routes/public/utils/Endpoint.ts +1 -1
  236. package/src/api/routes/tests/__snapshots__/datasource.spec.js.snap +5 -1
  237. package/src/api/routes/tests/application.spec.js +64 -4
  238. package/src/api/routes/tests/automation.spec.js +168 -60
  239. package/src/api/routes/tests/backup.spec.js +2 -0
  240. package/src/api/routes/tests/data/export.txt +1 -0
  241. package/src/api/routes/tests/datasource.spec.js +5 -0
  242. package/src/api/routes/tests/deployment.spec.js +25 -0
  243. package/src/api/routes/tests/dev.spec.js +40 -0
  244. package/src/api/routes/tests/layout.spec.js +4 -0
  245. package/src/api/routes/tests/query.spec.js +56 -13
  246. package/src/api/routes/tests/role.spec.js +40 -7
  247. package/src/api/routes/tests/row.spec.js +2 -3
  248. package/src/api/routes/tests/screen.spec.js +30 -4
  249. package/src/api/routes/tests/static.spec.js +120 -54
  250. package/src/api/routes/tests/table.spec.js +102 -38
  251. package/src/api/routes/tests/view.spec.js +222 -43
  252. package/src/app.ts +18 -9
  253. package/src/automations/index.js +4 -0
  254. package/src/automations/tests/delay.spec.js +4 -0
  255. package/src/environment.js +5 -2
  256. package/src/migrations/functions/backfill/app/automations.ts +26 -0
  257. package/src/migrations/functions/backfill/app/datasources.ts +22 -0
  258. package/src/migrations/functions/backfill/app/layouts.ts +29 -0
  259. package/src/migrations/functions/backfill/app/queries.ts +33 -0
  260. package/src/migrations/functions/backfill/app/roles.ts +22 -0
  261. package/src/migrations/functions/backfill/app/screens.ts +22 -0
  262. package/src/migrations/functions/backfill/app/tables.ts +36 -0
  263. package/src/migrations/functions/backfill/app.ts +148 -0
  264. package/src/migrations/functions/backfill/global/configs.ts +66 -0
  265. package/src/migrations/functions/backfill/global/quotas.ts +60 -0
  266. package/src/migrations/functions/backfill/global/users.ts +49 -0
  267. package/src/migrations/functions/backfill/global.ts +194 -0
  268. package/src/migrations/functions/backfill/index.ts +7 -0
  269. package/src/migrations/functions/backfill/installation.ts +51 -0
  270. package/src/migrations/index.ts +120 -51
  271. package/src/migrations/tests/helpers.ts +40 -0
  272. package/src/migrations/tests/index.spec.ts +132 -0
  273. package/src/migrations/tests/structures.ts +66 -0
  274. package/src/module.d.ts +0 -1
  275. package/src/tests/utilities/TestConfiguration.js +138 -90
  276. package/src/tests/utilities/structures.js +71 -0
  277. package/tsconfig.build.json +20 -5
  278. package/tsconfig.json +22 -17
  279. package/builder/assets/index.107ba2e5.js +0 -1315
  280. package/coverage/lcov-report/api/controllers/analytics.js.html +0 -202
  281. package/src/api/controllers/analytics.js +0 -39
@@ -1,4 +1,5 @@
1
1
  const setup = require("./utilities")
2
+ const { events } = require("@budibase/backend-core")
2
3
 
3
4
  function priceTable() {
4
5
  return {
@@ -29,27 +30,70 @@ describe("/views", () => {
29
30
 
30
31
  beforeEach(async () => {
31
32
  await config.init()
33
+ table = await config.createTable(priceTable())
32
34
  })
33
35
 
36
+ const saveView = async (view) => {
37
+ const viewToSave = {
38
+ name: "TestView",
39
+ field: "Price",
40
+ calculation: "stats",
41
+ tableId: table._id,
42
+ ...view
43
+ }
44
+ return request
45
+ .post(`/api/views`)
46
+ .send(viewToSave)
47
+ .set(config.defaultHeaders())
48
+ .expect("Content-Type", /json/)
49
+ .expect(200)
50
+ }
51
+
34
52
  describe("create", () => {
35
- beforeEach(async () => {
36
- table = await config.createTable(priceTable())
37
- })
38
53
 
39
54
  it("returns a success message when the view is successfully created", async () => {
40
- const res = await request
41
- .post(`/api/views`)
42
- .send({
43
- name: "TestView",
44
- field: "Price",
45
- calculation: "stats",
46
- tableId: table._id,
47
- })
48
- .set(config.defaultHeaders())
49
- .expect("Content-Type", /json/)
50
- .expect(200)
55
+ const res = await saveView()
56
+ expect(res.body.tableId).toBe(table._id)
57
+ expect(events.view.created).toBeCalledTimes(1)
58
+ })
59
+
60
+ it("creates a view with a calculation", async () => {
61
+ jest.clearAllMocks()
62
+
63
+ const res = await saveView({ calculation: "count" })
51
64
 
52
65
  expect(res.body.tableId).toBe(table._id)
66
+ expect(events.view.created).toBeCalledTimes(1)
67
+ expect(events.view.updated).not.toBeCalled()
68
+ expect(events.view.calculationCreated).toBeCalledTimes(1)
69
+ expect(events.view.calculationUpdated).not.toBeCalled()
70
+ expect(events.view.calculationDeleted).not.toBeCalled()
71
+ expect(events.view.filterCreated).not.toBeCalled()
72
+ expect(events.view.filterUpdated).not.toBeCalled()
73
+ expect(events.view.filterDeleted).not.toBeCalled()
74
+ })
75
+
76
+ it("creates a view with a filter", async () => {
77
+ jest.clearAllMocks()
78
+
79
+ const res = await saveView({
80
+ calculation: null,
81
+ filters: [{
82
+ value: "1",
83
+ condition: "EQUALS",
84
+ key: "price"
85
+ }],
86
+ })
87
+
88
+ expect(res.body.tableId).toBe(table._id)
89
+ expect(events.view.created).toBeCalledTimes(1)
90
+ expect(events.view.updated).not.toBeCalled()
91
+ expect(events.view.calculationCreated).not.toBeCalled()
92
+ expect(events.view.calculationUpdated).not.toBeCalled()
93
+ expect(events.view.calculationDeleted).not.toBeCalled()
94
+ expect(events.view.filterCreated).toBeCalledTimes(1)
95
+ expect(events.view.filterUpdated).not.toBeCalled()
96
+ expect(events.view.filterDeleted).not.toBeCalled()
53
97
  })
54
98
 
55
99
  it("updates the table row with the new view metadata", async () => {
@@ -101,6 +145,100 @@ describe("/views", () => {
101
145
  })
102
146
  })
103
147
 
148
+ describe("update", () => {
149
+ it("updates a view with no calculation or filter changed", async () => {
150
+ await saveView()
151
+ jest.clearAllMocks()
152
+
153
+ await saveView()
154
+
155
+ expect(events.view.created).not.toBeCalled()
156
+ expect(events.view.updated).toBeCalledTimes(1)
157
+ expect(events.view.calculationCreated).not.toBeCalled()
158
+ expect(events.view.calculationUpdated).not.toBeCalled()
159
+ expect(events.view.calculationDeleted).not.toBeCalled()
160
+ expect(events.view.filterCreated).not.toBeCalled()
161
+ expect(events.view.filterUpdated).not.toBeCalled()
162
+ expect(events.view.filterDeleted).not.toBeCalled()
163
+ })
164
+
165
+ it("updates a view calculation", async () => {
166
+ await saveView({ calculation: "sum" })
167
+ jest.clearAllMocks()
168
+
169
+ await saveView({ calculation: "count" })
170
+
171
+ expect(events.view.created).not.toBeCalled()
172
+ expect(events.view.updated).toBeCalledTimes(1)
173
+ expect(events.view.calculationCreated).not.toBeCalled()
174
+ expect(events.view.calculationUpdated).toBeCalledTimes(1)
175
+ expect(events.view.calculationDeleted).not.toBeCalled()
176
+ expect(events.view.filterCreated).not.toBeCalled()
177
+ expect(events.view.filterUpdated).not.toBeCalled()
178
+ expect(events.view.filterDeleted).not.toBeCalled()
179
+ })
180
+
181
+ it("deletes a view calculation", async () => {
182
+ await saveView({ calculation: "sum" })
183
+ jest.clearAllMocks()
184
+
185
+ await saveView({ calculation: null })
186
+
187
+ expect(events.view.created).not.toBeCalled()
188
+ expect(events.view.updated).toBeCalledTimes(1)
189
+ expect(events.view.calculationCreated).not.toBeCalled()
190
+ expect(events.view.calculationUpdated).not.toBeCalled()
191
+ expect(events.view.calculationDeleted).toBeCalledTimes(1)
192
+ expect(events.view.filterCreated).not.toBeCalled()
193
+ expect(events.view.filterUpdated).not.toBeCalled()
194
+ expect(events.view.filterDeleted).not.toBeCalled()
195
+ })
196
+
197
+ it("updates a view filter", async () => {
198
+ await saveView({ filters: [{
199
+ value: "1",
200
+ condition: "EQUALS",
201
+ key: "price"
202
+ }] })
203
+ jest.clearAllMocks()
204
+
205
+ await saveView({ filters: [{
206
+ value: "2",
207
+ condition: "EQUALS",
208
+ key: "price"
209
+ }] })
210
+
211
+ expect(events.view.created).not.toBeCalled()
212
+ expect(events.view.updated).toBeCalledTimes(1)
213
+ expect(events.view.calculationCreated).not.toBeCalled()
214
+ expect(events.view.calculationUpdated).not.toBeCalled()
215
+ expect(events.view.calculationDeleted).not.toBeCalled()
216
+ expect(events.view.filterCreated).not.toBeCalled()
217
+ expect(events.view.filterUpdated).toBeCalledTimes(1)
218
+ expect(events.view.filterDeleted).not.toBeCalled()
219
+ })
220
+
221
+ it("deletes a view filter", async () => {
222
+ await saveView({ filters: [{
223
+ value: "1",
224
+ condition: "EQUALS",
225
+ key: "price"
226
+ }] })
227
+ jest.clearAllMocks()
228
+
229
+ await saveView({ filters: [] })
230
+
231
+ expect(events.view.created).not.toBeCalled()
232
+ expect(events.view.updated).toBeCalledTimes(1)
233
+ expect(events.view.calculationCreated).not.toBeCalled()
234
+ expect(events.view.calculationUpdated).not.toBeCalled()
235
+ expect(events.view.calculationDeleted).not.toBeCalled()
236
+ expect(events.view.filterCreated).not.toBeCalled()
237
+ expect(events.view.filterUpdated).not.toBeCalled()
238
+ expect(events.view.filterDeleted).toBeCalledTimes(1)
239
+ })
240
+ })
241
+
104
242
  describe("fetch", () => {
105
243
  beforeEach(async () => {
106
244
  table = await config.createTable(priceTable())
@@ -124,10 +262,6 @@ describe("/views", () => {
124
262
  })
125
263
 
126
264
  describe("query", () => {
127
- beforeEach(async () => {
128
- table = await config.createTable(priceTable())
129
- })
130
-
131
265
  it("returns data for the created view", async () => {
132
266
  await config.createView({
133
267
  name: "TestView",
@@ -201,37 +335,82 @@ describe("/views", () => {
201
335
  .expect(200)
202
336
  expect(res.body.map).toBeDefined()
203
337
  expect(res.body.meta.tableId).toEqual(table._id)
338
+ expect(events.view.deleted).toBeCalledTimes(1)
204
339
  })
205
340
  })
206
341
 
207
342
  describe("exportView", () => {
208
- it("should be able to export a view", async () => {
209
- await config.createTable(priceTable())
210
- await config.createRow()
211
- const view = await config.createView()
212
- let res = await request
213
- .get(`/api/views/export?view=${view.name}&format=json`)
214
- .set(config.defaultHeaders())
215
- .expect(200)
216
- let error
217
- try {
218
- const obj = JSON.parse(res.text)
219
- expect(obj.length).toBe(1)
220
- } catch (err) {
221
- error = err
222
- }
223
- expect(error).toBeUndefined()
224
- res = await request
225
- .get(`/api/views/export?view=${view.name}&format=csv`)
343
+
344
+ beforeEach(() => {
345
+ jest.clearAllMocks()
346
+ })
347
+
348
+ const setupExport = async () => {
349
+ const table = await config.createTable()
350
+ await config.createRow({ name: "test-name", description: "test-desc" })
351
+ return table
352
+ }
353
+
354
+ const exportView = async (viewName, format) => {
355
+ return request
356
+ .get(`/api/views/export?view=${viewName}&format=${format}`)
226
357
  .set(config.defaultHeaders())
227
358
  .expect(200)
228
- // this shouldn't be JSON
229
- try {
230
- JSON.parse(res.text)
231
- } catch (err) {
232
- error = err
233
- }
234
- expect(error).toBeDefined()
359
+ }
360
+
361
+ const assertJsonExport = (res) => {
362
+ const rows = JSON.parse(res.text)
363
+ expect(rows.length).toBe(1)
364
+ expect(rows[0].name).toBe("test-name")
365
+ expect(rows[0].description).toBe("test-desc")
366
+ }
367
+
368
+ const assertCSVExport = (res) => {
369
+ expect(res.text).toBe("\"name\",\"description\"\n\"test-name\",\"test-desc\"")
370
+ }
371
+
372
+ it("should be able to export a table as JSON", async () => {
373
+ const table = await setupExport()
374
+
375
+ const res = await exportView(table._id, "json")
376
+
377
+ assertJsonExport(res)
378
+ expect(events.table.exported).toBeCalledTimes(1)
379
+ expect(events.table.exported).toBeCalledWith(table, "json")
380
+ })
381
+
382
+ it("should be able to export a table as CSV", async () => {
383
+ const table = await setupExport()
384
+
385
+ const res = await exportView(table._id, "csv")
386
+
387
+ assertCSVExport(res)
388
+ expect(events.table.exported).toBeCalledTimes(1)
389
+ expect(events.table.exported).toBeCalledWith(table, "csv")
390
+ })
391
+
392
+ it("should be able to export a view as JSON", async () => {
393
+ let table = await setupExport()
394
+ const view = await config.createView()
395
+ table = await config.getTable(table._id)
396
+
397
+ let res = await exportView(view.name, "json")
398
+
399
+ assertJsonExport(res)
400
+ expect(events.view.exported).toBeCalledTimes(1)
401
+ expect(events.view.exported).toBeCalledWith(table, "json")
402
+ })
403
+
404
+ it("should be able to export a view as CSV", async () => {
405
+ let table = await setupExport()
406
+ const view = await config.createView()
407
+ table = await config.getTable(table._id)
408
+
409
+ let res = await exportView(view.name, "csv")
410
+
411
+ assertCSVExport(res)
412
+ expect(events.view.exported).toBeCalledTimes(1)
413
+ expect(events.view.exported).toBeCalledWith(table, "csv")
235
414
  })
236
415
  })
237
416
  })
package/src/app.ts CHANGED
@@ -18,6 +18,7 @@ const { logAlert } = require("@budibase/backend-core/logging")
18
18
  const { Thread } = require("./threads")
19
19
  import redis from "./utilities/redis"
20
20
  import * as migrations from "./migrations"
21
+ import { events, installation } from "@budibase/backend-core"
21
22
 
22
23
  const app = new Koa()
23
24
 
@@ -83,6 +84,7 @@ server.on("close", async () => {
83
84
  }
84
85
  await automations.shutdown()
85
86
  await redis.shutdown()
87
+ await events.shutdown()
86
88
  await Thread.shutdown()
87
89
  api.shutdown()
88
90
  if (!env.isTest()) {
@@ -96,6 +98,22 @@ module.exports = server.listen(env.PORT || 0, async () => {
96
98
  eventEmitter.emitPort(env.PORT)
97
99
  fileSystem.init()
98
100
  await redis.init()
101
+
102
+ // run migrations on startup if not done via http
103
+ // not recommended in a clustered environment
104
+ if (!env.HTTP_MIGRATIONS && !env.isTest()) {
105
+ try {
106
+ await migrations.migrate()
107
+ } catch (e) {
108
+ logAlert("Error performing migrations. Exiting.", e)
109
+ shutdown()
110
+ }
111
+ }
112
+
113
+ // check for version updates
114
+ await installation.checkInstallVersion()
115
+
116
+ // done last - this will never complete
99
117
  await automations.init()
100
118
  })
101
119
 
@@ -118,12 +136,3 @@ process.on("uncaughtException", err => {
118
136
  process.on("SIGTERM", () => {
119
137
  shutdown()
120
138
  })
121
-
122
- // run migrations on startup if not done via http
123
- // not recommended in a clustered environment
124
- if (!env.HTTP_MIGRATIONS) {
125
- migrations.migrate().catch(err => {
126
- logAlert("Error performing migrations. Exiting.", err)
127
- shutdown()
128
- })
129
- }
@@ -1,5 +1,7 @@
1
1
  const { processEvent } = require("./utils")
2
2
  const { queue, shutdown } = require("./bullboard")
3
+ const { TRIGGER_DEFINITIONS } = require("./triggers")
4
+ const { ACTION_DEFINITIONS } = require("./actions")
3
5
 
4
6
  /**
5
7
  * This module is built purely to kick off the worker farm and manage the inputs/outputs
@@ -20,3 +22,5 @@ exports.shutdown = () => {
20
22
  }
21
23
 
22
24
  exports.queue = queue
25
+ exports.TRIGGER_DEFINITIONS = TRIGGER_DEFINITIONS
26
+ exports.ACTION_DEFINITIONS = ACTION_DEFINITIONS
@@ -1,5 +1,9 @@
1
1
  const setup = require("./utilities")
2
2
 
3
+ // need real Date for this test
4
+ const tk = require('timekeeper');
5
+ tk.reset()
6
+
3
7
  describe("test the delay logic", () => {
4
8
  it("should be able to run the delay", async () => {
5
9
  const time = 100
@@ -1,9 +1,12 @@
1
1
  const { join } = require("path")
2
2
 
3
3
  function isTest() {
4
+ return isCypress() || isJest()
5
+ }
6
+
7
+ function isJest() {
4
8
  return (
5
9
  process.env.NODE_ENV === "jest" ||
6
- process.env.NODE_ENV === "cypress" ||
7
10
  (process.env.JEST_WORKER_ID != null &&
8
11
  process.env.JEST_WORKER_ID !== "null")
9
12
  )
@@ -67,7 +70,6 @@ module.exports = {
67
70
  AUTOMATION_MAX_ITERATIONS: process.env.AUTOMATION_MAX_ITERATIONS,
68
71
  SENDGRID_API_KEY: process.env.SENDGRID_API_KEY,
69
72
  DYNAMO_ENDPOINT: process.env.DYNAMO_ENDPOINT,
70
- POSTHOG_TOKEN: process.env.POSTHOG_TOKEN,
71
73
  QUERY_THREAD_TIMEOUT: parseIntSafe(process.env.QUERY_THREAD_TIMEOUT),
72
74
  SQL_MAX_ROWS: process.env.SQL_MAX_ROWS,
73
75
  // flags
@@ -84,6 +86,7 @@ module.exports = {
84
86
  module.exports[key] = value
85
87
  },
86
88
  isTest,
89
+ isJest,
87
90
  isCypress,
88
91
  isDev,
89
92
  isProd: () => {
@@ -0,0 +1,26 @@
1
+ import { events } from "@budibase/backend-core"
2
+ import { getAutomationParams } from "../../../../db/utils"
3
+ import { Automation } from "@budibase/types"
4
+
5
+ const getAutomations = async (appDb: any): Promise<Automation[]> => {
6
+ const response = await appDb.allDocs(
7
+ getAutomationParams(null, {
8
+ include_docs: true,
9
+ })
10
+ )
11
+ return response.rows.map((row: any) => row.doc)
12
+ }
13
+
14
+ export const backfill = async (appDb: any, timestamp: string | number) => {
15
+ const automations = await getAutomations(appDb)
16
+
17
+ for (const automation of automations) {
18
+ await events.automation.created(automation, timestamp)
19
+
20
+ for (const step of automation.definition.steps) {
21
+ await events.automation.stepCreated(automation, step, timestamp)
22
+ }
23
+ }
24
+
25
+ return automations.length
26
+ }
@@ -0,0 +1,22 @@
1
+ import { events } from "@budibase/backend-core"
2
+ import { getDatasourceParams } from "../../../../db/utils"
3
+ import { Datasource } from "@budibase/types"
4
+
5
+ const getDatasources = async (appDb: any): Promise<Datasource[]> => {
6
+ const response = await appDb.allDocs(
7
+ getDatasourceParams(null, {
8
+ include_docs: true,
9
+ })
10
+ )
11
+ return response.rows.map((row: any) => row.doc)
12
+ }
13
+
14
+ export const backfill = async (appDb: any, timestamp: string | number) => {
15
+ const datasources: Datasource[] = await getDatasources(appDb)
16
+
17
+ for (const datasource of datasources) {
18
+ await events.datasource.created(datasource, timestamp)
19
+ }
20
+
21
+ return datasources.length
22
+ }
@@ -0,0 +1,29 @@
1
+ import { events } from "@budibase/backend-core"
2
+ import { getLayoutParams } from "../../../../db/utils"
3
+ import { Layout } from "@budibase/types"
4
+
5
+ const getLayouts = async (appDb: any): Promise<Layout[]> => {
6
+ const response = await appDb.allDocs(
7
+ getLayoutParams(null, {
8
+ include_docs: true,
9
+ })
10
+ )
11
+ return response.rows.map((row: any) => row.doc)
12
+ }
13
+
14
+ export const backfill = async (appDb: any, timestamp: string | number) => {
15
+ const layouts: Layout[] = await getLayouts(appDb)
16
+
17
+ for (const layout of layouts) {
18
+ // exclude default layouts
19
+ if (
20
+ layout._id === "layout_private_master" ||
21
+ layout._id === "layout_public_master"
22
+ ) {
23
+ continue
24
+ }
25
+ await events.layout.created(layout, timestamp)
26
+ }
27
+
28
+ return layouts.length
29
+ }
@@ -0,0 +1,33 @@
1
+ import { events } from "@budibase/backend-core"
2
+ import { getQueryParams } from "../../../../db/utils"
3
+ import { Query, Datasource } from "@budibase/types"
4
+
5
+ const getQueries = async (appDb: any): Promise<Query[]> => {
6
+ const response = await appDb.allDocs(
7
+ getQueryParams(null, {
8
+ include_docs: true,
9
+ })
10
+ )
11
+ return response.rows.map((row: any) => row.doc)
12
+ }
13
+
14
+ const getDatasource = async (
15
+ appDb: any,
16
+ datasourceId: string
17
+ ): Promise<Datasource> => {
18
+ return appDb.get(datasourceId)
19
+ }
20
+
21
+ export const backfill = async (appDb: any, timestamp: string | number) => {
22
+ const queries: Query[] = await getQueries(appDb)
23
+
24
+ for (const query of queries) {
25
+ const datasource: Datasource = await getDatasource(
26
+ appDb,
27
+ query.datasourceId
28
+ )
29
+ await events.query.created(datasource, query, timestamp)
30
+ }
31
+
32
+ return queries.length
33
+ }
@@ -0,0 +1,22 @@
1
+ import { events } from "@budibase/backend-core"
2
+ import { getRoleParams } from "../../../../db/utils"
3
+ import { Role } from "@budibase/types"
4
+
5
+ const getRoles = async (appDb: any): Promise<Role[]> => {
6
+ const response = await appDb.allDocs(
7
+ getRoleParams(null, {
8
+ include_docs: true,
9
+ })
10
+ )
11
+ return response.rows.map((row: any) => row.doc)
12
+ }
13
+
14
+ export const backfill = async (appDb: any, timestamp: string | number) => {
15
+ const roles = await getRoles(appDb)
16
+
17
+ for (const role of roles) {
18
+ await events.role.created(role, timestamp)
19
+ }
20
+
21
+ return roles.length
22
+ }
@@ -0,0 +1,22 @@
1
+ import { events } from "@budibase/backend-core"
2
+ import { getScreenParams } from "../../../../db/utils"
3
+ import { Screen } from "@budibase/types"
4
+
5
+ const getScreens = async (appDb: any): Promise<Screen[]> => {
6
+ const response = await appDb.allDocs(
7
+ getScreenParams(null, {
8
+ include_docs: true,
9
+ })
10
+ )
11
+ return response.rows.map((row: any) => row.doc)
12
+ }
13
+
14
+ export const backfill = async (appDb: any, timestamp: string | number) => {
15
+ const screens = await getScreens(appDb)
16
+
17
+ for (const screen of screens) {
18
+ await events.screen.created(screen, timestamp)
19
+ }
20
+
21
+ return screens.length
22
+ }
@@ -0,0 +1,36 @@
1
+ import { events } from "@budibase/backend-core"
2
+ import { getTableParams } from "../../../../db/utils"
3
+ import { Table } from "@budibase/types"
4
+
5
+ const getTables = async (appDb: any): Promise<Table[]> => {
6
+ const response = await appDb.allDocs(
7
+ getTableParams(null, {
8
+ include_docs: true,
9
+ })
10
+ )
11
+ return response.rows.map((row: any) => row.doc)
12
+ }
13
+
14
+ export const backfill = async (appDb: any, timestamp: string | number) => {
15
+ const tables = await getTables(appDb)
16
+
17
+ for (const table of tables) {
18
+ await events.table.created(table, timestamp)
19
+
20
+ if (table.views) {
21
+ for (const view of Object.values(table.views)) {
22
+ await events.view.created(view, timestamp)
23
+
24
+ if (view.calculation) {
25
+ await events.view.calculationCreated(view, timestamp)
26
+ }
27
+
28
+ if (view.filters?.length) {
29
+ await events.view.filterCreated(view, timestamp)
30
+ }
31
+ }
32
+ }
33
+ }
34
+
35
+ return tables.length
36
+ }