@budibase/server 0.9.167-alpha.4 → 0.9.167-alpha.8

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 (178) hide show
  1. package/builder/assets/{index.60f832ce.js → index.553837db.js} +34 -34
  2. package/builder/assets/{index.18ad7651.css → index.c4a1fb7f.css} +1 -1
  3. package/builder/assets/{vendor.60887453.js → vendor.278a305c.js} +1 -1
  4. package/builder/index.html +3 -3
  5. package/coverage/clover.xml +273 -245
  6. package/coverage/coverage-final.json +9 -8
  7. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/application.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/hosting.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/index.html +26 -26
  19. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/query.js.html +129 -24
  24. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/script.js.html +12 -57
  34. package/coverage/lcov-report/api/controllers/table/index.html +10 -10
  35. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/table/utils.js.html +8 -38
  37. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  41. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  45. package/coverage/lcov-report/api/index.html +1 -1
  46. package/coverage/lcov-report/api/index.js.html +1 -1
  47. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  48. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  49. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/index.html +1 -1
  60. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/query.js.html +9 -3
  66. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/static.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  77. package/coverage/lcov-report/automations/actions.js.html +31 -10
  78. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  79. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  80. package/coverage/lcov-report/automations/index.html +19 -19
  81. package/coverage/lcov-report/automations/index.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/index.html +1 -1
  91. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  98. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  99. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  100. package/coverage/lcov-report/automations/thread.js.html +54 -12
  101. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  104. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  106. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  107. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  108. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  109. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  110. package/coverage/lcov-report/automations/utils.js.html +1 -1
  111. package/coverage/lcov-report/constants/index.html +1 -1
  112. package/coverage/lcov-report/constants/index.js.html +1 -1
  113. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  114. package/coverage/lcov-report/constants/screens.js.html +1 -1
  115. package/coverage/lcov-report/db/client.js.html +1 -1
  116. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  117. package/coverage/lcov-report/db/index.html +1 -1
  118. package/coverage/lcov-report/db/index.js.html +1 -1
  119. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +12 -12
  120. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  121. package/coverage/lcov-report/db/linkedRows/index.js.html +9 -9
  122. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  123. package/coverage/lcov-report/db/newid.js.html +1 -1
  124. package/coverage/lcov-report/db/utils.js.html +1 -1
  125. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  126. package/coverage/lcov-report/events/index.html +1 -1
  127. package/coverage/lcov-report/events/index.js.html +1 -1
  128. package/coverage/lcov-report/events/utils.js.html +1 -1
  129. package/coverage/lcov-report/index.html +37 -37
  130. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  131. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  132. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  133. package/coverage/lcov-report/middleware/authorized.js.html +1 -1
  134. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  135. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  136. package/coverage/lcov-report/middleware/index.html +1 -1
  137. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  138. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  139. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  140. package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
  141. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  142. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  143. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  144. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  145. package/coverage/lcov-report/utilities/global.js.html +1 -1
  146. package/coverage/lcov-report/utilities/index.html +22 -7
  147. package/coverage/lcov-report/utilities/index.js.html +1 -1
  148. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  149. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  150. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  151. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  152. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  153. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  154. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  155. package/coverage/lcov-report/utilities/scriptRunner.js.html +143 -0
  156. package/coverage/lcov-report/utilities/security.js.html +1 -1
  157. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  158. package/coverage/lcov-report/utilities/users.js.html +1 -1
  159. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  160. package/coverage/lcov.info +450 -402
  161. package/dist/api/controllers/query.js +26 -8
  162. package/dist/api/controllers/script.js +4 -16
  163. package/dist/api/controllers/table/utils.js +2 -10
  164. package/dist/api/routes/query.js +3 -1
  165. package/dist/automations/actions.js +9 -3
  166. package/dist/automations/thread.js +14 -3
  167. package/dist/package.json +5 -4
  168. package/dist/tsconfig.tsbuildinfo +1 -1
  169. package/dist/utilities/scriptRunner.js +19 -0
  170. package/package.json +6 -5
  171. package/src/api/controllers/query.js +46 -11
  172. package/src/api/controllers/script.js +4 -19
  173. package/src/api/controllers/table/utils.js +2 -12
  174. package/src/api/routes/query.js +3 -1
  175. package/src/automations/actions.js +10 -3
  176. package/src/automations/thread.js +17 -3
  177. package/src/integrations/tests/mongo.spec.js +10 -6
  178. package/src/utilities/scriptRunner.js +21 -0
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ const fetch = require("node-fetch");
3
+ const { VM, VMScript } = require("vm2");
4
+ class ScriptRunner {
5
+ constructor(script, context) {
6
+ const code = `let fn = () => {\n${script}\n}; results.out = fn();`;
7
+ this.vm = new VM();
8
+ this.results = { out: "" };
9
+ this.vm.setGlobals(context);
10
+ this.vm.setGlobal("fetch", fetch);
11
+ this.vm.setGlobal("results", this.results);
12
+ this.script = new VMScript(code);
13
+ }
14
+ execute() {
15
+ this.vm.run(this.script);
16
+ return this.results.out;
17
+ }
18
+ }
19
+ module.exports = ScriptRunner;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "0.9.167-alpha.4",
4
+ "version": "0.9.167-alpha.8",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.js",
7
7
  "repository": {
@@ -68,9 +68,9 @@
68
68
  "author": "Budibase",
69
69
  "license": "AGPL-3.0-or-later",
70
70
  "dependencies": {
71
- "@budibase/auth": "^0.9.167-alpha.4",
72
- "@budibase/client": "^0.9.167-alpha.4",
73
- "@budibase/string-templates": "^0.9.167-alpha.4",
71
+ "@budibase/auth": "^0.9.167-alpha.8",
72
+ "@budibase/client": "^0.9.167-alpha.8",
73
+ "@budibase/string-templates": "^0.9.167-alpha.8",
74
74
  "@elastic/elasticsearch": "7.10.0",
75
75
  "@koa/router": "8.0.0",
76
76
  "@sendgrid/mail": "7.1.1",
@@ -119,6 +119,7 @@
119
119
  "to-json-schema": "0.2.5",
120
120
  "uuid": "3.3.2",
121
121
  "validate.js": "0.13.1",
122
+ "vm2": "^3.9.3",
122
123
  "yargs": "13.2.4",
123
124
  "zlib": "1.0.5"
124
125
  },
@@ -148,5 +149,5 @@
148
149
  "typescript": "^4.3.5",
149
150
  "update-dotenv": "^1.1.1"
150
151
  },
151
- "gitHead": "a81ac3293cda24257db1543ba9696ca6d311d51c"
152
+ "gitHead": "bc396fb840e24afc2bcf01383b493bdd3d783b29"
152
153
  }
@@ -4,6 +4,7 @@ const { generateQueryID, getQueryParams } = require("../../db/utils")
4
4
  const { integrations } = require("../../integrations")
5
5
  const { BaseQueryVerbs } = require("../../constants")
6
6
  const env = require("../../environment")
7
+ const ScriptRunner = require("../../utilities/scriptRunner")
7
8
 
8
9
  // simple function to append "readable" to all read queries
9
10
  function enrichQueries(input) {
@@ -28,12 +29,39 @@ function formatResponse(resp) {
28
29
  resp = { response: resp }
29
30
  }
30
31
  }
31
- if (!Array.isArray(resp)) {
32
- resp = [resp]
33
- }
34
32
  return resp
35
33
  }
36
34
 
35
+ async function runAndTransform(
36
+ integration,
37
+ queryVerb,
38
+ enrichedQuery,
39
+ transformer
40
+ ) {
41
+ let rows = formatResponse(await integration[queryVerb](enrichedQuery))
42
+
43
+ // transform as required
44
+ if (transformer) {
45
+ const runner = new ScriptRunner(transformer, { data: rows })
46
+ rows = runner.execute()
47
+ }
48
+
49
+ // needs to an array for next step
50
+ if (!Array.isArray(rows)) {
51
+ rows = [rows]
52
+ }
53
+
54
+ // map into JSON if just raw primitive here
55
+ if (rows.find(row => typeof row !== "object")) {
56
+ rows = rows.map(value => ({ value }))
57
+ }
58
+
59
+ // get all the potential fields in the schema
60
+ let keys = rows.flatMap(Object.keys)
61
+
62
+ return { rows, keys }
63
+ }
64
+
37
65
  exports.fetch = async function (ctx) {
38
66
  const db = new CouchDB(ctx.appId)
39
67
 
@@ -122,15 +150,16 @@ exports.preview = async function (ctx) {
122
150
  ctx.throw(400, "Integration type does not exist.")
123
151
  }
124
152
 
125
- const { fields, parameters, queryVerb } = ctx.request.body
126
-
153
+ const { fields, parameters, queryVerb, transformer } = ctx.request.body
127
154
  const enrichedQuery = await enrichQueryFields(fields, parameters)
128
-
129
155
  const integration = new Integration(datasource.config)
130
- const rows = formatResponse(await integration[queryVerb](enrichedQuery))
131
156
 
132
- // get all the potential fields in the schema
133
- const keys = rows.flatMap(Object.keys)
157
+ const { rows, keys } = await runAndTransform(
158
+ integration,
159
+ queryVerb,
160
+ enrichedQuery,
161
+ transformer
162
+ )
134
163
 
135
164
  ctx.body = {
136
165
  rows,
@@ -158,10 +187,16 @@ exports.execute = async function (ctx) {
158
187
  query.fields,
159
188
  ctx.request.body.parameters
160
189
  )
161
-
162
190
  const integration = new Integration(datasource.config)
191
+
163
192
  // call the relevant CRUD method on the integration class
164
- ctx.body = formatResponse(await integration[query.queryVerb](enrichedQuery))
193
+ const { rows } = await runAndTransform(
194
+ integration,
195
+ query.queryVerb,
196
+ enrichedQuery,
197
+ query.transformer
198
+ )
199
+ ctx.body = rows
165
200
  // cleanup
166
201
  if (integration.end) {
167
202
  integration.end()
@@ -1,24 +1,9 @@
1
- const fetch = require("node-fetch")
2
- const vm = require("vm")
3
-
4
- class ScriptExecutor {
5
- constructor(body) {
6
- const code = `let fn = () => {\n${body.script}\n}; out = fn();`
7
- this.script = new vm.Script(code)
8
- this.context = vm.createContext(body.context)
9
- this.context.fetch = fetch
10
- }
11
-
12
- execute() {
13
- this.script.runInContext(this.context)
14
- return this.context.out
15
- }
16
- }
1
+ const ScriptRunner = require("../../utilities/scriptRunner")
17
2
 
18
3
  exports.execute = async function (ctx) {
19
- const executor = new ScriptExecutor(ctx.request.body)
20
-
21
- ctx.body = executor.execute()
4
+ const { script, context } = ctx.request.body
5
+ const runner = new ScriptRunner(script, context)
6
+ ctx.body = runner.execute()
22
7
  }
23
8
 
24
9
  exports.save = async function (ctx) {
@@ -1,5 +1,4 @@
1
1
  const CouchDB = require("../../../db")
2
- const linkRows = require("../../../db/linkedRows")
3
2
  const csvParser = require("../../../utilities/csvParser")
4
3
  const {
5
4
  getRowParams,
@@ -93,19 +92,10 @@ exports.handleDataImport = async (appId, user, table, dataImport) => {
93
92
  }
94
93
  }
95
94
 
96
- // make sure link rows are up to date
97
- finalData.push(
98
- linkRows.updateLinks({
99
- appId,
100
- eventType: linkRows.EventType.ROW_SAVE,
101
- row,
102
- tableId: row.tableId,
103
- table,
104
- })
105
- )
95
+ finalData.push(row)
106
96
  }
107
97
 
108
- await db.bulkDocs(await Promise.all(finalData))
98
+ await db.bulkDocs(finalData)
109
99
  let response = await db.put(table)
110
100
  table._rev = response._rev
111
101
  }
@@ -31,7 +31,8 @@ function generateQueryValidation() {
31
31
  })),
32
32
  queryVerb: Joi.string().allow().required(),
33
33
  extra: Joi.object().optional(),
34
- schema: Joi.object({}).required().unknown(true)
34
+ schema: Joi.object({}).required().unknown(true),
35
+ transformer: Joi.string().optional(),
35
36
  }))
36
37
  }
37
38
 
@@ -42,6 +43,7 @@ function generateQueryPreviewValidation() {
42
43
  queryVerb: Joi.string().allow().required(),
43
44
  extra: Joi.object().optional(),
44
45
  datasourceId: Joi.string().required(),
46
+ transformer: Joi.string().optional(),
45
47
  parameters: Joi.object({}).required().unknown(true)
46
48
  }))
47
49
  }
@@ -3,7 +3,6 @@ const createRow = require("./steps/createRow")
3
3
  const updateRow = require("./steps/updateRow")
4
4
  const deleteRow = require("./steps/deleteRow")
5
5
  const executeScript = require("./steps/executeScript")
6
- const bash = require("./steps/bash")
7
6
  const executeQuery = require("./steps/executeQuery")
8
7
  const outgoingWebhook = require("./steps/outgoingWebhook")
9
8
  const serverLog = require("./steps/serverLog")
@@ -14,6 +13,7 @@ const integromat = require("./steps/integromat")
14
13
  let filter = require("./steps/filter")
15
14
  let delay = require("./steps/delay")
16
15
  let queryRow = require("./steps/queryRows")
16
+ const env = require("../environment")
17
17
 
18
18
  const ACTION_IMPLS = {
19
19
  SEND_EMAIL_SMTP: sendSmtpEmail.run,
@@ -22,7 +22,6 @@ const ACTION_IMPLS = {
22
22
  DELETE_ROW: deleteRow.run,
23
23
  OUTGOING_WEBHOOK: outgoingWebhook.run,
24
24
  EXECUTE_SCRIPT: executeScript.run,
25
- EXECUTE_BASH: bash.run,
26
25
  EXECUTE_QUERY: executeQuery.run,
27
26
  SERVER_LOG: serverLog.run,
28
27
  DELAY: delay.run,
@@ -42,7 +41,6 @@ const ACTION_DEFINITIONS = {
42
41
  OUTGOING_WEBHOOK: outgoingWebhook.definition,
43
42
  EXECUTE_SCRIPT: executeScript.definition,
44
43
  EXECUTE_QUERY: executeQuery.definition,
45
- EXECUTE_BASH: bash.definition,
46
44
  SERVER_LOG: serverLog.definition,
47
45
  DELAY: delay.definition,
48
46
  FILTER: filter.definition,
@@ -54,6 +52,15 @@ const ACTION_DEFINITIONS = {
54
52
  integromat: integromat.definition,
55
53
  }
56
54
 
55
+ // don't add the bash script/definitions unless in self host
56
+ // the fact this isn't included in any definitions means it cannot be
57
+ // ran at all
58
+ if (env.SELF_HOSTED) {
59
+ const bash = require("./steps/bash")
60
+ ACTION_IMPLS["EXECUTE_BASH"] = bash.run
61
+ ACTION_DEFINITIONS["EXECUTE_BASH"] = bash.definition
62
+ }
63
+
57
64
  /* istanbul ignore next */
58
65
  exports.getAction = async function (actionName) {
59
66
  if (ACTION_IMPLS[actionName] != null) {
@@ -10,6 +10,7 @@ const env = require("../environment")
10
10
  const usage = require("../utilities/usageQuota")
11
11
 
12
12
  const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId
13
+ const STOPPED_STATUS = { success: false, status: "STOPPED" }
13
14
 
14
15
  /**
15
16
  * The automation orchestrator is a class responsible for executing automations.
@@ -68,7 +69,13 @@ class Orchestrator {
68
69
  async execute() {
69
70
  let automation = this._automation
70
71
  const app = await this.getApp()
72
+ let stopped = false
71
73
  for (let step of automation.definition.steps) {
74
+ // execution stopped, record state for that
75
+ if (stopped) {
76
+ this.updateExecutionOutput(step.id, step.stepId, {}, STOPPED_STATUS)
77
+ continue
78
+ }
72
79
  let stepFn = await this.getStepFunctionality(step.stepId)
73
80
  step.inputs = await processObject(step.inputs, this._context)
74
81
  step.inputs = automationUtils.cleanInputValues(
@@ -86,10 +93,17 @@ class Orchestrator {
86
93
  context: this._context,
87
94
  })
88
95
  })
96
+ this._context.steps.push(outputs)
97
+ // if filter causes us to stop execution don't break the loop, set a var
98
+ // so that we can finish iterating through the steps and record that it stopped
89
99
  if (step.stepId === FILTER_STEP_ID && !outputs.success) {
90
- break
100
+ stopped = true
101
+ this.updateExecutionOutput(step.id, step.stepId, step.inputs, {
102
+ ...outputs,
103
+ ...STOPPED_STATUS,
104
+ })
105
+ continue
91
106
  }
92
- this._context.steps.push(outputs)
93
107
  this.updateExecutionOutput(step.id, step.stepId, step.inputs, outputs)
94
108
  } catch (err) {
95
109
  console.error(`Automation error - ${step.stepId} - ${err}`)
@@ -99,7 +113,7 @@ class Orchestrator {
99
113
 
100
114
  // Increment quota for automation runs
101
115
  if (!env.SELF_HOSTED && !isDevAppID(this._appId)) {
102
- usage.update(usage.Properties.AUTOMATION, 1)
116
+ await usage.update(usage.Properties.AUTOMATION, 1)
103
117
  }
104
118
  return this.executionOutput
105
119
  }
@@ -27,7 +27,7 @@ describe("MongoDB Integration", () => {
27
27
  const body = {
28
28
  name: "Hello"
29
29
  }
30
- const response = await config.integration.create({
30
+ await config.integration.create({
31
31
  index: indexName,
32
32
  json: body,
33
33
  extra: { collection: 'testCollection', actionTypes: 'insertOne'}
@@ -54,7 +54,7 @@ describe("MongoDB Integration", () => {
54
54
  },
55
55
  extra: { collection: 'testCollection', actionTypes: 'deleteOne'}
56
56
  }
57
- const response = await config.integration.delete(query)
57
+ await config.integration.delete(query)
58
58
  expect(config.integration.client.deleteOne).toHaveBeenCalledWith(query.json)
59
59
  })
60
60
 
@@ -65,7 +65,7 @@ describe("MongoDB Integration", () => {
65
65
  },
66
66
  extra: { collection: 'testCollection', actionTypes: 'updateOne'}
67
67
  }
68
- const response = await config.integration.update(query)
68
+ await config.integration.update(query)
69
69
  expect(config.integration.client.updateOne).toHaveBeenCalledWith(query.json)
70
70
  })
71
71
 
@@ -75,10 +75,14 @@ describe("MongoDB Integration", () => {
75
75
  const query = {
76
76
  extra: { collection: 'testCollection', actionTypes: 'deleteOne'}
77
77
  }
78
- // Weird, need to do an IIFE for jest to recognize that it throws
79
- expect(() => config.integration.read(query)()).toThrow(expect.any(Object))
80
78
 
79
+ let error = null
80
+ try {
81
+ await config.integration.read(query)
82
+ } catch (err) {
83
+ error = err
84
+ }
85
+ expect(error).toBeDefined()
81
86
  restore()
82
87
  })
83
-
84
88
  })
@@ -0,0 +1,21 @@
1
+ const fetch = require("node-fetch")
2
+ const { VM, VMScript } = require("vm2")
3
+
4
+ class ScriptRunner {
5
+ constructor(script, context) {
6
+ const code = `let fn = () => {\n${script}\n}; results.out = fn();`
7
+ this.vm = new VM()
8
+ this.results = { out: "" }
9
+ this.vm.setGlobals(context)
10
+ this.vm.setGlobal("fetch", fetch)
11
+ this.vm.setGlobal("results", this.results)
12
+ this.script = new VMScript(code)
13
+ }
14
+
15
+ execute() {
16
+ this.vm.run(this.script)
17
+ return this.results.out
18
+ }
19
+ }
20
+
21
+ module.exports = ScriptRunner