@budibase/server 0.9.136 → 0.9.140-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 (296) hide show
  1. package/builder/assets/discord.c14881e9.svg +10 -0
  2. package/builder/assets/{index.a0ab7774.js → index.0d1fa670.js} +35 -35
  3. package/builder/assets/{index.121692c9.css → index.79907e5c.css} +5 -5
  4. package/builder/assets/integromat.42212f11.png +0 -0
  5. package/builder/assets/slack.1e1f7cfb.svg +33 -0
  6. package/builder/assets/{vendor.7177f366.js → vendor.d39b3c1e.js} +2 -2
  7. package/builder/assets/zapier.3fbd8f5c.png +0 -0
  8. package/builder/index.html +3 -3
  9. package/coverage/clover.xml +2142 -2095
  10. package/coverage/coverage-final.json +120 -106
  11. package/coverage/lcov-report/api/controllers/analytics.js.html +3 -3
  12. package/coverage/lcov-report/api/controllers/apikeys.js.html +6 -6
  13. package/coverage/lcov-report/api/controllers/application.js.html +84 -84
  14. package/coverage/lcov-report/api/controllers/auth.js.html +6 -6
  15. package/coverage/lcov-report/api/controllers/automation.js.html +182 -356
  16. package/coverage/lcov-report/api/controllers/backup.js.html +3 -3
  17. package/coverage/lcov-report/api/controllers/component.js.html +5 -5
  18. package/coverage/lcov-report/api/controllers/datasource.js.html +12 -12
  19. package/coverage/lcov-report/api/controllers/dev.js.html +15 -15
  20. package/coverage/lcov-report/api/controllers/hosting.js.html +8 -8
  21. package/coverage/lcov-report/api/controllers/index.html +47 -32
  22. package/coverage/lcov-report/api/controllers/integration.js.html +4 -4
  23. package/coverage/lcov-report/api/controllers/layout.js.html +6 -6
  24. package/coverage/lcov-report/api/controllers/metadata.js.html +218 -0
  25. package/coverage/lcov-report/api/controllers/permission.js.html +14 -14
  26. package/coverage/lcov-report/api/controllers/query.js.html +17 -23
  27. package/coverage/lcov-report/api/controllers/role.js.html +9 -9
  28. package/coverage/lcov-report/api/controllers/routing.js.html +9 -9
  29. package/coverage/lcov-report/api/controllers/row/external.js.html +15 -15
  30. package/coverage/lcov-report/api/controllers/row/index.html +29 -44
  31. package/coverage/lcov-report/api/controllers/row/index.js.html +48 -45
  32. package/coverage/lcov-report/api/controllers/row/internal.js.html +159 -126
  33. package/coverage/lcov-report/api/controllers/row/utils.js.html +17 -17
  34. package/coverage/lcov-report/api/controllers/screen.js.html +7 -7
  35. package/coverage/lcov-report/api/controllers/script.js.html +5 -5
  36. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  37. package/coverage/lcov-report/api/controllers/table/index.js.html +40 -40
  38. package/coverage/lcov-report/api/controllers/table/utils.js.html +48 -48
  39. package/coverage/lcov-report/api/controllers/templates.js.html +5 -5
  40. package/coverage/lcov-report/api/controllers/user.js.html +14 -11
  41. package/coverage/lcov-report/api/controllers/view/exporters.js.html +3 -3
  42. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  43. package/coverage/lcov-report/api/controllers/view/index.js.html +9 -9
  44. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +6 -6
  45. package/coverage/lcov-report/api/controllers/webhook.js.html +14 -14
  46. package/coverage/lcov-report/api/index.html +1 -1
  47. package/coverage/lcov-report/api/index.js.html +23 -23
  48. package/coverage/lcov-report/api/routes/analytics.js.html +6 -6
  49. package/coverage/lcov-report/api/routes/apikeys.js.html +8 -8
  50. package/coverage/lcov-report/api/routes/application.js.html +8 -8
  51. package/coverage/lcov-report/api/routes/auth.js.html +6 -6
  52. package/coverage/lcov-report/api/routes/automation.js.html +41 -26
  53. package/coverage/lcov-report/api/routes/backup.js.html +8 -8
  54. package/coverage/lcov-report/api/routes/component.js.html +8 -8
  55. package/coverage/lcov-report/api/routes/datasource.js.html +13 -13
  56. package/coverage/lcov-report/api/routes/deploy.js.html +8 -8
  57. package/coverage/lcov-report/api/routes/dev.js.html +11 -11
  58. package/coverage/lcov-report/api/routes/hosting.js.html +8 -8
  59. package/coverage/lcov-report/api/routes/index.html +24 -9
  60. package/coverage/lcov-report/api/routes/index.js.html +36 -30
  61. package/coverage/lcov-report/api/routes/integration.js.html +8 -8
  62. package/coverage/lcov-report/api/routes/layout.js.html +8 -8
  63. package/coverage/lcov-report/api/routes/metadata.js.html +194 -0
  64. package/coverage/lcov-report/api/routes/permission.js.html +12 -12
  65. package/coverage/lcov-report/api/routes/query.js.html +13 -13
  66. package/coverage/lcov-report/api/routes/role.js.html +12 -12
  67. package/coverage/lcov-report/api/routes/routing.js.html +8 -8
  68. package/coverage/lcov-report/api/routes/row.js.html +10 -10
  69. package/coverage/lcov-report/api/routes/screen.js.html +11 -11
  70. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/static.js.html +13 -16
  72. package/coverage/lcov-report/api/routes/table.js.html +12 -12
  73. package/coverage/lcov-report/api/routes/templates.js.html +8 -8
  74. package/coverage/lcov-report/api/routes/user.js.html +9 -9
  75. package/coverage/lcov-report/api/routes/view.js.html +11 -11
  76. package/coverage/lcov-report/api/routes/webhook.js.html +11 -11
  77. package/coverage/lcov-report/automations/actions.js.html +57 -117
  78. package/coverage/lcov-report/automations/automationUtils.js.html +7 -7
  79. package/coverage/lcov-report/automations/bullboard.js.html +49 -16
  80. package/coverage/lcov-report/automations/index.html +67 -67
  81. package/coverage/lcov-report/automations/index.js.html +27 -129
  82. package/coverage/lcov-report/automations/steps/bash.js.html +37 -16
  83. package/coverage/lcov-report/automations/steps/createRow.js.html +15 -15
  84. package/coverage/lcov-report/automations/steps/delay.js.html +48 -9
  85. package/coverage/lcov-report/automations/steps/deleteRow.js.html +14 -14
  86. package/coverage/lcov-report/automations/steps/discord.js.html +329 -0
  87. package/coverage/lcov-report/automations/steps/executeQuery.js.html +22 -34
  88. package/coverage/lcov-report/automations/steps/executeScript.js.html +21 -33
  89. package/coverage/lcov-report/automations/steps/filter.js.html +28 -25
  90. package/coverage/lcov-report/automations/steps/index.html +140 -65
  91. package/coverage/lcov-report/automations/steps/integromat.js.html +341 -0
  92. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +44 -38
  93. package/coverage/lcov-report/automations/steps/queryRows.js.html +437 -0
  94. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +13 -13
  95. package/coverage/lcov-report/automations/steps/serverLog.js.html +23 -11
  96. package/coverage/lcov-report/automations/steps/{sendgridEmail.js.html → slack.js.html} +58 -88
  97. package/coverage/lcov-report/automations/steps/updateRow.js.html +12 -12
  98. package/coverage/lcov-report/automations/steps/utils.js.html +188 -0
  99. package/coverage/lcov-report/automations/steps/zapier.js.html +332 -0
  100. package/coverage/lcov-report/automations/thread.js.html +81 -78
  101. package/coverage/lcov-report/automations/triggerInfo/app.js.html +173 -0
  102. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +173 -0
  103. package/coverage/lcov-report/automations/triggerInfo/index.html +201 -0
  104. package/coverage/lcov-report/automations/triggerInfo/index.js.html +125 -0
  105. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +176 -0
  106. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +200 -0
  107. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +200 -0
  108. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +188 -0
  109. package/coverage/lcov-report/automations/triggers.js.html +67 -838
  110. package/coverage/lcov-report/automations/utils.js.html +557 -0
  111. package/coverage/lcov-report/constants/index.html +5 -5
  112. package/coverage/lcov-report/constants/index.js.html +32 -17
  113. package/coverage/lcov-report/constants/layouts.js.html +5 -5
  114. package/coverage/lcov-report/constants/screens.js.html +4 -4
  115. package/coverage/lcov-report/db/client.js.html +18 -18
  116. package/coverage/lcov-report/db/index.html +19 -19
  117. package/coverage/lcov-report/db/index.js.html +3 -3
  118. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +79 -79
  119. package/coverage/lcov-report/db/linkedRows/index.html +18 -18
  120. package/coverage/lcov-report/db/linkedRows/index.js.html +107 -149
  121. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +43 -43
  122. package/coverage/lcov-report/db/newid.js.html +4 -4
  123. package/coverage/lcov-report/db/utils.js.html +127 -76
  124. package/coverage/lcov-report/events/AutomationEmitter.js.html +7 -7
  125. package/coverage/lcov-report/events/index.html +1 -1
  126. package/coverage/lcov-report/events/index.js.html +6 -6
  127. package/coverage/lcov-report/events/utils.js.html +3 -3
  128. package/coverage/lcov-report/index.html +116 -101
  129. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  130. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  131. package/coverage/lcov-report/{automations/logic.js.html → middleware/appInfo.js.html} +35 -38
  132. package/coverage/lcov-report/middleware/authorized.js.html +16 -16
  133. package/coverage/lcov-report/middleware/builder.js.html +15 -15
  134. package/coverage/lcov-report/middleware/currentapp.js.html +33 -33
  135. package/coverage/lcov-report/middleware/index.html +23 -8
  136. package/coverage/lcov-report/middleware/joi-validator.js.html +6 -6
  137. package/coverage/lcov-report/middleware/resourceId.js.html +28 -28
  138. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  139. package/coverage/lcov-report/middleware/usageQuota.js.html +8 -8
  140. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  141. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  142. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  143. package/coverage/lcov-report/utilities/csvParser.js.html +6 -6
  144. package/coverage/lcov-report/utilities/global.js.html +33 -33
  145. package/coverage/lcov-report/utilities/index.html +28 -28
  146. package/coverage/lcov-report/utilities/index.js.html +178 -25
  147. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +18 -18
  148. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  149. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  150. package/coverage/lcov-report/utilities/routing/index.js.html +6 -6
  151. package/coverage/lcov-report/utilities/rowProcessor/index.html +14 -14
  152. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +87 -51
  153. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +10 -10
  154. package/coverage/lcov-report/utilities/security.js.html +9 -9
  155. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  156. package/coverage/lcov-report/utilities/users.js.html +5 -5
  157. package/coverage/lcov-report/utilities/workerRequests.js.html +52 -52
  158. package/coverage/lcov.info +3250 -3213
  159. package/dist/api/controllers/automation.js +60 -127
  160. package/dist/api/controllers/deploy/index.js +17 -1
  161. package/dist/api/controllers/metadata.js +49 -0
  162. package/dist/api/controllers/query.js +0 -2
  163. package/dist/api/controllers/row/ExternalRequest.js +1 -1
  164. package/dist/api/controllers/row/index.js +1 -0
  165. package/dist/api/controllers/row/internal.js +33 -23
  166. package/dist/api/controllers/static/index.js +1 -28
  167. package/dist/api/controllers/static/templates/BudibaseApp.svelte +4 -1
  168. package/dist/api/controllers/user.js +1 -1
  169. package/dist/api/routes/automation.js +4 -5
  170. package/dist/api/routes/index.js +2 -0
  171. package/dist/api/routes/metadata.js +13 -0
  172. package/dist/api/routes/static.js +0 -1
  173. package/dist/api/routes/tests/utilities/TestFunctions.js +13 -0
  174. package/dist/app.js +1 -1
  175. package/dist/automations/actions.js +29 -46
  176. package/dist/automations/bullboard.js +11 -2
  177. package/dist/automations/index.js +11 -48
  178. package/dist/automations/steps/bash.js +12 -6
  179. package/dist/automations/steps/createRow.js +5 -5
  180. package/dist/automations/steps/delay.js +16 -3
  181. package/dist/automations/steps/deleteRow.js +5 -5
  182. package/dist/automations/steps/discord.js +91 -0
  183. package/dist/automations/steps/executeQuery.js +12 -15
  184. package/dist/automations/steps/executeScript.js +12 -15
  185. package/dist/automations/steps/filter.js +19 -18
  186. package/dist/automations/steps/integromat.js +94 -0
  187. package/dist/automations/steps/outgoingWebhook.js +19 -20
  188. package/dist/automations/steps/queryRows.js +129 -0
  189. package/dist/automations/steps/sendSmtpEmail.js +4 -4
  190. package/dist/automations/steps/serverLog.js +7 -3
  191. package/dist/automations/steps/slack.js +73 -0
  192. package/dist/automations/steps/updateRow.js +4 -4
  193. package/dist/automations/steps/utils.js +46 -0
  194. package/dist/automations/steps/zapier.js +91 -0
  195. package/dist/automations/tests/utilities/index.js +2 -12
  196. package/dist/automations/thread.js +23 -25
  197. package/dist/automations/triggerInfo/app.js +32 -0
  198. package/dist/automations/triggerInfo/cron.js +32 -0
  199. package/dist/automations/triggerInfo/index.js +15 -0
  200. package/dist/automations/triggerInfo/rowDeleted.js +33 -0
  201. package/dist/automations/triggerInfo/rowSaved.js +41 -0
  202. package/dist/automations/triggerInfo/rowUpdated.js +41 -0
  203. package/dist/automations/triggerInfo/webhook.js +37 -0
  204. package/dist/automations/triggers.js +27 -285
  205. package/dist/automations/utils.js +143 -0
  206. package/dist/constants/index.js +4 -0
  207. package/dist/db/linkedRows/index.js +20 -34
  208. package/dist/db/utils.js +14 -1
  209. package/dist/environment.js +2 -1
  210. package/dist/integrations/mysql.js +14 -2
  211. package/dist/middleware/appInfo.js +17 -0
  212. package/dist/middleware/usageQuota.js +1 -1
  213. package/dist/package.json +12 -11
  214. package/dist/tsconfig.tsbuildinfo +1 -1
  215. package/dist/utilities/appDirectoryTemplate/package.json +1 -1
  216. package/dist/utilities/fileSystem/clientLibrary.js +2 -2
  217. package/dist/utilities/fileSystem/index.js +2 -27
  218. package/dist/utilities/index.js +54 -0
  219. package/dist/utilities/redis.js +16 -1
  220. package/dist/utilities/rowProcessor/index.js +7 -4
  221. package/package.json +13 -12
  222. package/scripts/jestSetup.js +1 -0
  223. package/scripts/selfhost.js +8 -0
  224. package/src/api/controllers/automation.js +87 -145
  225. package/src/api/controllers/deploy/index.js +23 -1
  226. package/src/api/controllers/metadata.js +46 -0
  227. package/src/api/controllers/query.js +0 -2
  228. package/src/api/controllers/row/ExternalRequest.ts +1 -1
  229. package/src/api/controllers/row/index.js +1 -0
  230. package/src/api/controllers/row/internal.js +34 -23
  231. package/src/api/controllers/static/index.js +1 -39
  232. package/src/api/controllers/static/templates/BudibaseApp.svelte +4 -1
  233. package/src/api/controllers/user.js +1 -0
  234. package/src/api/routes/automation.js +16 -11
  235. package/src/api/routes/index.js +2 -0
  236. package/src/api/routes/metadata.js +38 -0
  237. package/src/api/routes/static.js +0 -1
  238. package/src/api/routes/tests/automation.spec.js +4 -26
  239. package/src/api/routes/tests/metadata.spec.js +65 -0
  240. package/src/api/routes/tests/utilities/TestFunctions.js +14 -0
  241. package/src/app.ts +1 -1
  242. package/src/automations/actions.js +29 -49
  243. package/src/automations/bullboard.js +13 -2
  244. package/src/automations/index.js +11 -45
  245. package/src/automations/steps/bash.js +13 -6
  246. package/src/automations/steps/createRow.js +5 -5
  247. package/src/automations/steps/delay.js +16 -3
  248. package/src/automations/steps/deleteRow.js +5 -5
  249. package/src/automations/steps/discord.js +83 -0
  250. package/src/automations/steps/executeQuery.js +12 -16
  251. package/src/automations/steps/executeScript.js +12 -16
  252. package/src/automations/steps/filter.js +19 -18
  253. package/src/automations/steps/integromat.js +87 -0
  254. package/src/automations/steps/outgoingWebhook.js +20 -18
  255. package/src/automations/steps/queryRows.js +119 -0
  256. package/src/automations/steps/sendSmtpEmail.js +4 -4
  257. package/src/automations/steps/serverLog.js +7 -3
  258. package/src/automations/steps/slack.js +64 -0
  259. package/src/automations/steps/updateRow.js +4 -4
  260. package/src/automations/steps/utils.js +36 -0
  261. package/src/automations/steps/zapier.js +84 -0
  262. package/src/automations/tests/automation.spec.js +4 -67
  263. package/src/automations/tests/delay.spec.js +2 -2
  264. package/src/automations/tests/filter.spec.js +14 -14
  265. package/src/automations/tests/queryRows.spec.js +51 -0
  266. package/src/automations/tests/utilities/index.js +2 -13
  267. package/src/automations/thread.js +27 -26
  268. package/src/automations/triggerInfo/app.js +31 -0
  269. package/src/automations/triggerInfo/cron.js +31 -0
  270. package/src/automations/triggerInfo/index.js +15 -0
  271. package/src/automations/triggerInfo/rowDeleted.js +32 -0
  272. package/src/automations/triggerInfo/rowSaved.js +40 -0
  273. package/src/automations/triggerInfo/rowUpdated.js +40 -0
  274. package/src/automations/triggerInfo/webhook.js +36 -0
  275. package/src/automations/triggers.js +33 -290
  276. package/src/automations/utils.js +159 -0
  277. package/src/constants/index.js +5 -0
  278. package/src/db/linkedRows/index.js +21 -35
  279. package/src/db/tests/linkTests.spec.js +0 -12
  280. package/src/db/utils.js +17 -0
  281. package/src/environment.js +2 -1
  282. package/src/integrations/mysql.ts +15 -2
  283. package/src/middleware/appInfo.js +19 -0
  284. package/src/middleware/usageQuota.js +1 -1
  285. package/src/utilities/appDirectoryTemplate/package.json +1 -1
  286. package/src/utilities/fileSystem/clientLibrary.js +2 -2
  287. package/src/utilities/fileSystem/index.js +2 -36
  288. package/src/utilities/index.js +51 -0
  289. package/src/utilities/redis.js +18 -1
  290. package/src/utilities/rowProcessor/index.js +16 -4
  291. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +0 -1244
  292. package/dist/automations/logic.js +0 -17
  293. package/dist/automations/steps/sendgridEmail.js +0 -85
  294. package/src/automations/logic.js +0 -20
  295. package/src/automations/steps/sendgridEmail.js +0 -74
  296. package/src/automations/tests/sendEmail.spec.js +0 -36
@@ -1,246 +1,22 @@
1
1
  const CouchDB = require("../db")
2
2
  const emitter = require("../events/index")
3
- const env = require("../environment")
4
- const Queue = env.isTest()
5
- ? require("../utilities/queue/inMemoryQueue")
6
- : require("bull")
7
3
  const { getAutomationParams } = require("../db/utils")
8
4
  const { coerce } = require("../utilities/rowProcessor")
9
- const { utils } = require("@budibase/auth/redis")
10
- const { JobQueues } = require("../constants")
11
- const {
12
- isExternalTable,
13
- breakExternalTableId,
14
- } = require("../integrations/utils")
15
- const { getExternalTable } = require("../api/controllers/table/utils")
16
-
17
- const { opts, redisProtocolUrl } = utils.getRedisOptions()
18
-
19
- const redisConfig = redisProtocolUrl || { redis: opts }
20
- let automationQueue = new Queue(JobQueues.AUTOMATIONS, redisConfig)
21
-
22
- const FAKE_STRING = "TEST"
23
- const FAKE_BOOL = false
24
- const FAKE_NUMBER = 1
25
- const FAKE_DATETIME = "1970-01-01T00:00:00.000Z"
5
+ const { definitions } = require("./triggerInfo")
6
+ const { isDevAppID } = require("../db/utils")
7
+ // need this to call directly, so we can get a response
8
+ const { queue } = require("./bullboard")
9
+ const { checkTestFlag } = require("../utilities/redis")
10
+ const utils = require("./utils")
11
+ const env = require("../environment")
26
12
 
27
- const BUILTIN_DEFINITIONS = {
28
- ROW_SAVED: {
29
- name: "Row Created",
30
- event: "row:save",
31
- icon: "ri-save-line",
32
- tagline: "Row is added to {{inputs.enriched.table.name}}",
33
- description: "Fired when a row is added to your database",
34
- stepId: "ROW_SAVED",
35
- inputs: {},
36
- schema: {
37
- inputs: {
38
- properties: {
39
- tableId: {
40
- type: "string",
41
- customType: "table",
42
- title: "Table",
43
- },
44
- },
45
- required: ["tableId"],
46
- },
47
- outputs: {
48
- properties: {
49
- row: {
50
- type: "object",
51
- customType: "row",
52
- description: "The new row that was created",
53
- },
54
- id: {
55
- type: "string",
56
- description: "Row ID - can be used for updating",
57
- },
58
- revision: {
59
- type: "string",
60
- description: "Revision of row",
61
- },
62
- },
63
- required: ["row", "id"],
64
- },
65
- },
66
- type: "TRIGGER",
67
- },
68
- ROW_UPDATED: {
69
- name: "Row Updated",
70
- event: "row:update",
71
- icon: "ri-refresh-line",
72
- tagline: "Row is updated in {{inputs.enriched.table.name}}",
73
- description: "Fired when a row is updated in your database",
74
- stepId: "ROW_UPDATED",
75
- inputs: {},
76
- schema: {
77
- inputs: {
78
- properties: {
79
- tableId: {
80
- type: "string",
81
- customType: "table",
82
- title: "Table",
83
- },
84
- },
85
- required: ["tableId"],
86
- },
87
- outputs: {
88
- properties: {
89
- row: {
90
- type: "object",
91
- customType: "row",
92
- description: "The row that was updated",
93
- },
94
- id: {
95
- type: "string",
96
- description: "Row ID - can be used for updating",
97
- },
98
- revision: {
99
- type: "string",
100
- description: "Revision of row",
101
- },
102
- },
103
- required: ["row", "id"],
104
- },
105
- },
106
- type: "TRIGGER",
107
- },
108
- ROW_DELETED: {
109
- name: "Row Deleted",
110
- event: "row:delete",
111
- icon: "ri-delete-bin-line",
112
- tagline: "Row is deleted from {{inputs.enriched.table.name}}",
113
- description: "Fired when a row is deleted from your database",
114
- stepId: "ROW_DELETED",
115
- inputs: {},
116
- schema: {
117
- inputs: {
118
- properties: {
119
- tableId: {
120
- type: "string",
121
- customType: "table",
122
- title: "Table",
123
- },
124
- },
125
- required: ["tableId"],
126
- },
127
- outputs: {
128
- properties: {
129
- row: {
130
- type: "object",
131
- customType: "row",
132
- description: "The row that was deleted",
133
- },
134
- },
135
- required: ["row"],
136
- },
137
- },
138
- type: "TRIGGER",
139
- },
140
- WEBHOOK: {
141
- name: "Webhook",
142
- event: "web:trigger",
143
- icon: "ri-global-line",
144
- tagline: "Webhook endpoint is hit",
145
- description: "Trigger an automation when a HTTP POST webhook is hit",
146
- stepId: "WEBHOOK",
147
- inputs: {},
148
- schema: {
149
- inputs: {
150
- properties: {
151
- schemaUrl: {
152
- type: "string",
153
- customType: "webhookUrl",
154
- title: "Schema URL",
155
- },
156
- triggerUrl: {
157
- type: "string",
158
- customType: "webhookUrl",
159
- title: "Trigger URL",
160
- },
161
- },
162
- required: ["schemaUrl", "triggerUrl"],
163
- },
164
- outputs: {
165
- properties: {
166
- body: {
167
- type: "object",
168
- description: "Body of the request which hit the webhook",
169
- },
170
- },
171
- required: ["body"],
172
- },
173
- },
174
- type: "TRIGGER",
175
- },
176
- APP: {
177
- name: "App Action",
178
- event: "app:trigger",
179
- icon: "ri-window-fill",
180
- tagline: "Automation fired from the frontend",
181
- description: "Trigger an automation from an action inside your app",
182
- stepId: "APP",
183
- inputs: {},
184
- schema: {
185
- inputs: {
186
- properties: {
187
- fields: {
188
- type: "object",
189
- customType: "triggerSchema",
190
- title: "Fields",
191
- },
192
- },
193
- required: [],
194
- },
195
- outputs: {
196
- properties: {
197
- fields: {
198
- type: "object",
199
- description: "Fields submitted from the app frontend",
200
- },
201
- },
202
- required: ["fields"],
203
- },
204
- },
205
- type: "TRIGGER",
206
- },
207
- CRON: {
208
- name: "Cron Trigger",
209
- event: "cron:trigger",
210
- icon: "ri-timer-line",
211
- tagline: "Cron Trigger (<b>{{inputs.cron}}</b>)",
212
- description: "Triggers automation on a cron schedule.",
213
- stepId: "CRON",
214
- inputs: {},
215
- schema: {
216
- inputs: {
217
- properties: {
218
- cron: {
219
- type: "string",
220
- customType: "cron",
221
- title: "Expression",
222
- },
223
- },
224
- required: ["cron"],
225
- },
226
- outputs: {
227
- properties: {
228
- timestamp: {
229
- type: "number",
230
- description: "Timestamp the cron was executed",
231
- },
232
- },
233
- required: ["timestamp"],
234
- },
235
- },
236
- type: "TRIGGER",
237
- },
238
- }
13
+ const TRIGGER_DEFINITIONS = definitions
239
14
 
240
15
  async function queueRelevantRowAutomations(event, eventType) {
241
16
  if (event.appId == null) {
242
17
  throw `No appId specified for ${eventType} - check event emitters.`
243
18
  }
19
+
244
20
  const db = new CouchDB(event.appId)
245
21
  let automations = await db.allDocs(
246
22
  getAutomationParams(null, { include_docs: true })
@@ -257,14 +33,22 @@ async function queueRelevantRowAutomations(event, eventType) {
257
33
  for (let automation of automations) {
258
34
  let automationDef = automation.definition
259
35
  let automationTrigger = automationDef ? automationDef.trigger : {}
36
+ // don't queue events which are for dev apps, only way to test automations is
37
+ // running tests on them, in production the test flag will never
38
+ // be checked due to lazy evaluation (first always false)
260
39
  if (
261
- !automation.live ||
262
- !automationTrigger.inputs ||
263
- automationTrigger.inputs.tableId !== event.row.tableId
40
+ !env.ALLOW_DEV_AUTOMATIONS &&
41
+ isDevAppID(event.appId) &&
42
+ !(await checkTestFlag(automation._id))
264
43
  ) {
265
44
  continue
266
45
  }
267
- automationQueue.add({ automation, event })
46
+ if (
47
+ automationTrigger.inputs &&
48
+ automationTrigger.inputs.tableId === event.row.tableId
49
+ ) {
50
+ await queue.add({ automation, event })
51
+ }
268
52
  }
269
53
  }
270
54
 
@@ -292,51 +76,12 @@ emitter.on("row:delete", async function (event) {
292
76
  await queueRelevantRowAutomations(event, "row:delete")
293
77
  })
294
78
 
295
- async function fillRowOutput(automation, params) {
296
- let triggerSchema = automation.definition.trigger
297
- let tableId = triggerSchema.inputs.tableId
298
- try {
299
- let table
300
- if (!isExternalTable(tableId)) {
301
- const db = new CouchDB(params.appId)
302
- table = await db.get(tableId)
303
- } else {
304
- const { datasourceId, tableName } = breakExternalTableId(tableId)
305
- table = await getExternalTable(params.appId, datasourceId, tableName)
306
- }
307
- let row = {}
308
- for (let schemaKey of Object.keys(table.schema)) {
309
- const paramValue = params[schemaKey]
310
- let propSchema = table.schema[schemaKey]
311
- switch (propSchema.constraints.type) {
312
- case "string":
313
- row[schemaKey] = paramValue || FAKE_STRING
314
- break
315
- case "boolean":
316
- row[schemaKey] = paramValue || FAKE_BOOL
317
- break
318
- case "number":
319
- row[schemaKey] = paramValue || FAKE_NUMBER
320
- break
321
- case "datetime":
322
- row[schemaKey] = paramValue || FAKE_DATETIME
323
- break
324
- }
325
- }
326
- params.row = row
327
- } catch (err) {
328
- /* istanbul ignore next */
329
- throw "Failed to find table for trigger"
330
- }
331
- return params
332
- }
333
-
334
- module.exports.externalTrigger = async function (automation, params) {
335
- // TODO: replace this with allowing user in builder to input values in future
79
+ exports.externalTrigger = async function (
80
+ automation,
81
+ params,
82
+ { getResponses } = {}
83
+ ) {
336
84
  if (automation.definition != null && automation.definition.trigger != null) {
337
- if (automation.definition.trigger.inputs.tableId != null) {
338
- params = await fillRowOutput(automation, params)
339
- }
340
85
  if (automation.definition.trigger.stepId === "APP") {
341
86
  // values are likely to be submitted as strings, so we shall convert to correct type
342
87
  const coercedFields = {}
@@ -347,14 +92,12 @@ module.exports.externalTrigger = async function (automation, params) {
347
92
  params.fields = coercedFields
348
93
  }
349
94
  }
350
-
351
- automationQueue.add({ automation, event: params })
352
- }
353
-
354
- module.exports.getQueues = () => {
355
- return [automationQueue]
95
+ const data = { automation, event: params }
96
+ if (getResponses) {
97
+ return utils.processEvent({ data })
98
+ } else {
99
+ return queue.add(data)
100
+ }
356
101
  }
357
- module.exports.fillRowOutput = fillRowOutput
358
- module.exports.automationQueue = automationQueue
359
102
 
360
- module.exports.BUILTIN_DEFINITIONS = BUILTIN_DEFINITIONS
103
+ exports.TRIGGER_DEFINITIONS = TRIGGER_DEFINITIONS
@@ -0,0 +1,159 @@
1
+ const runner = require("./thread")
2
+ const { definitions } = require("./triggerInfo")
3
+ const webhooks = require("../api/controllers/webhook")
4
+ const CouchDB = require("../db")
5
+ const { queue } = require("./bullboard")
6
+ const newid = require("../db/newid")
7
+ const { updateEntityMetadata } = require("../utilities")
8
+ const { MetadataTypes } = require("../constants")
9
+
10
+ const WH_STEP_ID = definitions.WEBHOOK.stepId
11
+ const CRON_STEP_ID = definitions.CRON.stepId
12
+
13
+ exports.processEvent = async job => {
14
+ try {
15
+ // need to actually await these so that an error can be captured properly
16
+ return await runner(job)
17
+ } catch (err) {
18
+ console.error(
19
+ `${job.data.automation.appId} automation ${job.data.automation._id} was unable to run - ${err}`
20
+ )
21
+ return { err }
22
+ }
23
+ }
24
+
25
+ exports.updateTestHistory = async (appId, automation, history) => {
26
+ return updateEntityMetadata(
27
+ appId,
28
+ MetadataTypes.AUTOMATION_TEST_HISTORY,
29
+ automation._id,
30
+ metadata => {
31
+ if (metadata && Array.isArray(metadata.history)) {
32
+ metadata.history.push(history)
33
+ } else {
34
+ metadata = {
35
+ history: [history],
36
+ }
37
+ }
38
+ return metadata
39
+ }
40
+ )
41
+ }
42
+
43
+ // end the repetition and the job itself
44
+ exports.disableAllCrons = async appId => {
45
+ const promises = []
46
+ const jobs = await queue.getRepeatableJobs()
47
+ for (let job of jobs) {
48
+ if (job.key.includes(`${appId}_cron`)) {
49
+ promises.push(queue.removeRepeatableByKey(job.key))
50
+ promises.push(queue.removeJobs(job.id))
51
+ }
52
+ }
53
+ return Promise.all(promises)
54
+ }
55
+
56
+ /**
57
+ * This function handles checking of any cron jobs that need to be enabled/updated.
58
+ * @param {string} appId The ID of the app in which we are checking for webhooks
59
+ * @param {object|undefined} automation The automation object to be updated.
60
+ */
61
+ exports.enableCronTrigger = async (appId, automation) => {
62
+ const trigger = automation ? automation.definition.trigger : null
63
+ function isCronTrigger(auto) {
64
+ return (
65
+ auto &&
66
+ auto.definition.trigger &&
67
+ auto.definition.trigger.stepId === CRON_STEP_ID
68
+ )
69
+ }
70
+ // need to create cron job
71
+ if (isCronTrigger(automation)) {
72
+ // make a job id rather than letting Bull decide, makes it easier to handle on way out
73
+ const jobId = `${appId}_cron_${newid()}`
74
+ const job = await queue.add(
75
+ {
76
+ automation,
77
+ event: { appId, timestamp: Date.now() },
78
+ },
79
+ { repeat: { cron: trigger.inputs.cron }, jobId }
80
+ )
81
+ // Assign cron job ID from bull so we can remove it later if the cron trigger is removed
82
+ trigger.cronJobId = job.id
83
+ const db = new CouchDB(appId)
84
+ const response = await db.put(automation)
85
+ automation._id = response.id
86
+ automation._rev = response.rev
87
+ }
88
+ return automation
89
+ }
90
+
91
+ /**
92
+ * This function handles checking if any webhooks need to be created or deleted for automations.
93
+ * @param {string} appId The ID of the app in which we are checking for webhooks
94
+ * @param {object|undefined} oldAuto The old automation object if updating/deleting
95
+ * @param {object|undefined} newAuto The new automation object if creating/updating
96
+ * @returns {Promise<object|undefined>} After this is complete the new automation object may have been updated and should be
97
+ * written to DB (this does not write to DB as it would be wasteful to repeat).
98
+ */
99
+ exports.checkForWebhooks = async ({ appId, oldAuto, newAuto }) => {
100
+ const oldTrigger = oldAuto ? oldAuto.definition.trigger : null
101
+ const newTrigger = newAuto ? newAuto.definition.trigger : null
102
+ const triggerChanged =
103
+ oldTrigger && newTrigger && oldTrigger.id !== newTrigger.id
104
+ function isWebhookTrigger(auto) {
105
+ return (
106
+ auto &&
107
+ auto.definition.trigger &&
108
+ auto.definition.trigger.stepId === WH_STEP_ID
109
+ )
110
+ }
111
+ // need to delete webhook
112
+ if (
113
+ isWebhookTrigger(oldAuto) &&
114
+ (!isWebhookTrigger(newAuto) || triggerChanged) &&
115
+ oldTrigger.webhookId
116
+ ) {
117
+ try {
118
+ let db = new CouchDB(appId)
119
+ // need to get the webhook to get the rev
120
+ const webhook = await db.get(oldTrigger.webhookId)
121
+ const ctx = {
122
+ appId,
123
+ params: { id: webhook._id, rev: webhook._rev },
124
+ }
125
+ // might be updating - reset the inputs to remove the URLs
126
+ if (newTrigger) {
127
+ delete newTrigger.webhookId
128
+ newTrigger.inputs = {}
129
+ }
130
+ await webhooks.destroy(ctx)
131
+ } catch (err) {
132
+ // don't worry about not being able to delete, if it doesn't exist all good
133
+ }
134
+ }
135
+ // need to create webhook
136
+ if (
137
+ (!isWebhookTrigger(oldAuto) || triggerChanged) &&
138
+ isWebhookTrigger(newAuto)
139
+ ) {
140
+ const ctx = {
141
+ appId,
142
+ request: {
143
+ body: new webhooks.Webhook(
144
+ "Automation webhook",
145
+ webhooks.WebhookType.AUTOMATION,
146
+ newAuto._id
147
+ ),
148
+ },
149
+ }
150
+ await webhooks.save(ctx)
151
+ const id = ctx.body.webhook._id
152
+ newTrigger.webhookId = id
153
+ newTrigger.inputs = {
154
+ schemaUrl: `api/webhooks/schema/${appId}/${id}`,
155
+ triggerUrl: `api/webhooks/trigger/${appId}/${id}`,
156
+ }
157
+ }
158
+ return newAuto
159
+ }
@@ -123,5 +123,10 @@ exports.BaseQueryVerbs = {
123
123
  DELETE: "delete",
124
124
  }
125
125
 
126
+ exports.MetadataTypes = {
127
+ AUTOMATION_TEST_INPUT: "automationTestInput",
128
+ AUTOMATION_TEST_HISTORY: "automationTestHistory",
129
+ }
130
+
126
131
  // pass through the list from the auth/core lib
127
132
  exports.ObjectStoreBuckets = ObjectStoreBuckets
@@ -36,6 +36,18 @@ exports.IncludeDocs = IncludeDocs
36
36
  exports.getLinkDocuments = getLinkDocuments
37
37
  exports.createLinkView = createLinkView
38
38
 
39
+ function clearRelationshipFields(table, rows) {
40
+ for (let [key, field] of Object.entries(table.schema)) {
41
+ if (field.type === FieldTypes.LINK) {
42
+ rows = rows.map(row => {
43
+ delete row[key]
44
+ return row
45
+ })
46
+ }
47
+ }
48
+ return rows
49
+ }
50
+
39
51
  async function getLinksForRows(appId, rows) {
40
52
  const tableIds = [...new Set(rows.map(el => el.tableId))]
41
53
  // start by getting all the link values for performance reasons
@@ -126,33 +138,6 @@ exports.updateLinks = async function (args) {
126
138
  }
127
139
  }
128
140
 
129
- /**
130
- * Update a row with information about the links that pertain to it.
131
- * @param {string} appId The instance in which this row has been created.
132
- * @param {object} rows The row(s) themselves which is to be updated with info (if applicable). This can be
133
- * a single row object or an array of rows - both will be handled.
134
- * @returns {Promise<object>} The updated row (this may be the same if no links were found). If an array was input
135
- * then an array will be output, object input -> object output.
136
- */
137
- exports.attachLinkIDs = async (appId, rows) => {
138
- const links = await getLinksForRows(appId, rows)
139
- // now iterate through the rows and all field information
140
- for (let row of rows) {
141
- // find anything that matches the row's ID we are searching for and join it
142
- links
143
- .filter(el => el.thisId === row._id)
144
- .forEach(link => {
145
- if (row[link.fieldName] == null) {
146
- row[link.fieldName] = []
147
- }
148
- row[link.fieldName].push(link.id)
149
- })
150
- }
151
- // if it was an array when it came in then handle it as an array in response
152
- // otherwise return the first element as there was only one input
153
- return rows
154
- }
155
-
156
141
  /**
157
142
  * Given a table and a list of rows this will retrieve all of the attached docs and enrich them into the row.
158
143
  * This is required for formula fields, this may only be utilised internally (for now).
@@ -173,6 +158,9 @@ exports.attachFullLinkedDocs = async (ctx, table, rows) => {
173
158
  const links = (await getLinksForRows(appId, rows)).filter(link =>
174
159
  rows.some(row => row._id === link.thisId)
175
160
  )
161
+ // clear any existing links that could be dupe'd
162
+ rows = clearRelationshipFields(table, rows)
163
+ // now get the docs and combine into the rows
176
164
  let linked = await getFullLinkedDocs(ctx, appId, links)
177
165
  const linkedTables = []
178
166
  for (let row of rows) {
@@ -203,19 +191,17 @@ exports.attachFullLinkedDocs = async (ctx, table, rows) => {
203
191
  exports.squashLinksToPrimaryDisplay = async (appId, table, enriched) => {
204
192
  const db = new CouchDB(appId)
205
193
  // will populate this as we find them
206
- const linkedTables = []
207
- for (let [column, schema] of Object.entries(table.schema)) {
208
- if (schema.type !== FieldTypes.LINK) {
209
- continue
210
- }
211
- for (let row of enriched) {
212
- if (!row[column] || !row[column].length) {
194
+ const linkedTables = [table]
195
+ for (let row of enriched) {
196
+ // this only fetches the table if its not already in array
197
+ const rowTable = await getLinkedTable(db, row.tableId, linkedTables)
198
+ for (let [column, schema] of Object.entries(rowTable.schema)) {
199
+ if (schema.type !== FieldTypes.LINK || !Array.isArray(row[column])) {
213
200
  continue
214
201
  }
215
202
  const newLinks = []
216
203
  for (let link of row[column]) {
217
204
  const linkTblId = link.tableId || getRelatedTableForField(table, column)
218
- // this only fetches the table if its not already in array
219
205
  const linkedTable = await getLinkedTable(db, linkTblId, linkedTables)
220
206
  const obj = { _id: link._id }
221
207
  if (link[linkedTable.primaryDisplay]) {
@@ -59,16 +59,4 @@ describe("test link functionality", () => {
59
59
  expect(Array.isArray(output)).toBe(true)
60
60
  })
61
61
  })
62
-
63
- describe("attachLinkIDs", () => {
64
- it("should be able to attach linkIDs", async () => {
65
- await config.init()
66
- await config.createTable()
67
- const table = await config.createLinkedTable()
68
- const row = await config.createRow()
69
- const linkRow = await config.createRow(basicLinkedRow(table._id, row._id))
70
- const attached = await links.attachLinkIDs(config.getAppId(), [linkRow])
71
- expect(attached[0].link[0]).toBe(row._id)
72
- })
73
- })
74
62
  })
package/src/db/utils.js CHANGED
@@ -7,6 +7,8 @@ const {
7
7
  APP_PREFIX,
8
8
  SEPARATOR,
9
9
  StaticDatabases,
10
+ isDevAppID,
11
+ isProdAppID,
10
12
  } = require("@budibase/auth/db")
11
13
 
12
14
  const UNICODE_MAX = "\ufff0"
@@ -36,6 +38,7 @@ const DocumentTypes = {
36
38
  DATASOURCE_PLUS: "datasource_plus",
37
39
  QUERY: "query",
38
40
  DEPLOYMENTS: "deployments",
41
+ METADATA: "metadata",
39
42
  }
40
43
 
41
44
  const ViewNames = {
@@ -63,6 +66,8 @@ const BudibaseInternalDB = {
63
66
 
64
67
  exports.APP_PREFIX = APP_PREFIX
65
68
  exports.APP_DEV_PREFIX = APP_DEV_PREFIX
69
+ exports.isDevAppID = isDevAppID
70
+ exports.isProdAppID = isProdAppID
66
71
  exports.USER_METDATA_PREFIX = `${DocumentTypes.ROW}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`
67
72
  exports.LINK_USER_METADATA_PREFIX = `${DocumentTypes.LINK}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`
68
73
  exports.ViewNames = ViewNames
@@ -331,6 +336,18 @@ exports.getQueryParams = (datasourceId = null, otherProps = {}) => {
331
336
  )
332
337
  }
333
338
 
339
+ exports.generateMetadataID = (type, entityId) => {
340
+ return `${DocumentTypes.METADATA}${SEPARATOR}${type}${SEPARATOR}${entityId}`
341
+ }
342
+
343
+ exports.getMetadataParams = (type, entityId = null, otherProps = {}) => {
344
+ let docId = `${type}${SEPARATOR}`
345
+ if (entityId != null) {
346
+ docId += entityId
347
+ }
348
+ return getDocParams(DocumentTypes.METADATA, docId, otherProps)
349
+ }
350
+
334
351
  /**
335
352
  * This can be used with the db.allDocs to get a list of IDs
336
353
  */
@@ -26,7 +26,7 @@ module.exports = {
26
26
  COUCH_DB_URL: process.env.COUCH_DB_URL,
27
27
  MINIO_URL: process.env.MINIO_URL,
28
28
  WORKER_URL: process.env.WORKER_URL,
29
- SELF_HOSTED: process.env.SELF_HOSTED,
29
+ SELF_HOSTED: !!parseInt(process.env.SELF_HOSTED),
30
30
  AWS_REGION: process.env.AWS_REGION,
31
31
  ENABLE_ANALYTICS: process.env.ENABLE_ANALYTICS,
32
32
  MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
@@ -55,6 +55,7 @@ module.exports = {
55
55
  BUDIBASE_API_KEY: process.env.BUDIBASE_API_KEY,
56
56
  USERID_API_KEY: process.env.USERID_API_KEY,
57
57
  DEPLOYMENT_CREDENTIALS_URL: process.env.DEPLOYMENT_CREDENTIALS_URL,
58
+ ALLOW_DEV_AUTOMATIONS: process.env.ALLOW_DEV_AUTOMATIONS,
58
59
  _set(key, value) {
59
60
  process.env[key] = value
60
61
  module.exports[key] = value