@budibase/server 1.1.32 → 1.1.33-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 (204) hide show
  1. package/builder/assets/index.48c7836d.js +977 -0
  2. package/builder/assets/{index.192adf4c.css → index.4d57d3d4.css} +2 -2
  3. package/builder/assets/{vendor.162098da.js → vendor.1611f2e1.js} +28 -28
  4. package/builder/index.html +3 -3
  5. package/coverage/clover.xml +381 -696
  6. package/coverage/coverage-final.json +13 -16
  7. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/index.html +1 -1
  16. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  22. package/coverage/lcov-report/api/controllers/query/validation.js.html +4 -4
  23. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/index.html +18 -18
  27. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +94 -49
  29. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  36. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  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 +15 -15
  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/auth.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/index.html +1 -1
  58. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  72. package/coverage/lcov-report/api/routes/utils/validators.js.html +2 -2
  73. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  75. package/coverage/lcov-report/automations/actions.js.html +1 -1
  76. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  77. package/coverage/lcov-report/automations/bullboard.js.html +17 -17
  78. package/coverage/lcov-report/automations/index.html +1 -1
  79. package/coverage/lcov-report/automations/index.js.html +1 -1
  80. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  81. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/executeQuery.js.html +5 -2
  84. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/index.html +1 -1
  87. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  97. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  98. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggers.js.html +18 -18
  106. package/coverage/lcov-report/constants/index.html +1 -1
  107. package/coverage/lcov-report/constants/index.js.html +5 -14
  108. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  109. package/coverage/lcov-report/constants/screens.js.html +1 -1
  110. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  111. package/coverage/lcov-report/db/index.html +19 -19
  112. package/coverage/lcov-report/db/index.js.html +1 -1
  113. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  114. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  115. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  116. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  117. package/coverage/lcov-report/db/newid.js.html +1 -1
  118. package/coverage/lcov-report/db/utils.js.html +61 -13
  119. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  120. package/coverage/lcov-report/events/index.html +1 -1
  121. package/coverage/lcov-report/events/index.js.html +1 -1
  122. package/coverage/lcov-report/events/utils.js.html +1 -1
  123. package/coverage/lcov-report/index.html +57 -72
  124. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  125. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  126. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  127. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  128. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  129. package/coverage/lcov-report/middleware/index.html +21 -21
  130. package/coverage/lcov-report/middleware/joi-validator.js.html +43 -43
  131. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  132. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  133. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  134. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  135. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  136. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  137. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  138. package/coverage/lcov-report/utilities/global.js.html +68 -14
  139. package/coverage/lcov-report/utilities/index.html +19 -19
  140. package/coverage/lcov-report/utilities/index.js.html +1 -1
  141. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +26 -14
  142. package/coverage/lcov-report/utilities/queue/index.html +17 -17
  143. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  144. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  145. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  146. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  147. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  148. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  149. package/coverage/lcov-report/utilities/security.js.html +2 -2
  150. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  151. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  152. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  153. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  154. package/coverage/lcov-report/utilities/users.js.html +1 -1
  155. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  156. package/coverage/lcov.info +695 -1214
  157. package/dist/api/controllers/deploy/index.js +1 -0
  158. package/dist/api/controllers/query/index.js +1 -1
  159. package/dist/api/controllers/query/validation.js +3 -3
  160. package/dist/api/controllers/row/internalSearch.js +30 -16
  161. package/dist/api/routes/utils/validators.js +1 -1
  162. package/dist/automations/utils.js +47 -1
  163. package/dist/constants/index.js +1 -4
  164. package/dist/db/utils.js +14 -1
  165. package/dist/definitions/automations.js +8 -0
  166. package/dist/integrations/base/sql.js +43 -14
  167. package/dist/package.json +8 -8
  168. package/dist/threads/automation.js +147 -54
  169. package/dist/threads/definitions.js +2 -0
  170. package/dist/threads/index.js +27 -20
  171. package/dist/threads/query.js +23 -15
  172. package/dist/threads/utils.js +47 -24
  173. package/dist/tsconfig.build.tsbuildinfo +1 -1
  174. package/dist/utilities/global.js +24 -5
  175. package/dist/utilities/queue/inMemoryQueue.js +5 -0
  176. package/package.json +9 -9
  177. package/src/api/controllers/deploy/index.ts +6 -1
  178. package/src/api/controllers/query/index.ts +1 -1
  179. package/src/api/controllers/query/validation.js +3 -3
  180. package/src/api/controllers/row/internalSearch.js +35 -20
  181. package/src/api/routes/tests/user.spec.js +2 -0
  182. package/src/api/routes/utils/validators.js +1 -1
  183. package/src/automations/steps/executeQuery.js +1 -0
  184. package/src/automations/tests/automation.spec.js +2 -2
  185. package/src/automations/utils.ts +54 -1
  186. package/src/constants/index.js +2 -5
  187. package/src/db/utils.js +16 -0
  188. package/src/definitions/automations.ts +49 -0
  189. package/src/definitions/datasource.ts +3 -0
  190. package/src/integrations/base/sql.ts +44 -13
  191. package/src/integrations/tests/sql.spec.js +50 -4
  192. package/src/middleware/tests/currentapp.spec.js +11 -0
  193. package/src/threads/{automation.js → automation.ts} +172 -48
  194. package/src/threads/definitions.ts +18 -0
  195. package/src/threads/index.ts +31 -23
  196. package/src/threads/{query.js → query.ts} +32 -12
  197. package/src/threads/{utils.js → utils.ts} +31 -12
  198. package/src/utilities/global.js +21 -3
  199. package/src/utilities/queue/inMemoryQueue.js +4 -0
  200. package/builder/assets/index.133db51f.js +0 -978
  201. package/coverage/lcov-report/threads/automation.js.html +0 -1114
  202. package/coverage/lcov-report/threads/index.html +0 -146
  203. package/coverage/lcov-report/threads/query.js.html +0 -916
  204. package/coverage/lcov-report/threads/utils.js.html +0 -319
@@ -8,36 +8,45 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- require("./utils").threadSetup();
12
- const actions = require("../automations/actions");
13
- const automationUtils = require("../automations/automationUtils");
14
- const AutomationEmitter = require("../events/AutomationEmitter");
15
- const { processObject } = require("@budibase/string-templates");
16
- const { DocumentTypes } = require("../db/utils");
17
- const { definitions: triggerDefs } = require("../automations/triggerInfo");
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.execute = void 0;
16
+ const utils_1 = __importDefault(require("./utils"));
17
+ utils_1.default.threadSetup();
18
+ const utils_2 = require("../automations/utils");
19
+ const actions_1 = __importDefault(require("../automations/actions"));
20
+ const automationUtils_1 = __importDefault(require("../automations/automationUtils"));
21
+ const AutomationEmitter_1 = __importDefault(require("../events/AutomationEmitter"));
22
+ const utils_3 = require("../db/utils");
23
+ const triggerInfo_1 = require("../automations/triggerInfo");
24
+ const constants_1 = require("../constants");
25
+ const logging_1 = require("../automations/logging");
26
+ const types_1 = require("@budibase/types");
27
+ const automations_1 = require("../definitions/automations");
18
28
  const { doInAppContext, getAppDB } = require("@budibase/backend-core/context");
19
- const { AutomationErrors, LoopStepTypes } = require("../constants");
20
- const { storeLog } = require("../automations/logging");
21
- const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId;
22
- const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId;
23
- const CRON_STEP_ID = triggerDefs.CRON.stepId;
24
- const STOPPED_STATUS = { success: true, status: "STOPPED" };
29
+ const { logAlertWithInfo, logWarn } = require("@budibase/backend-core/logging");
30
+ const { processObject } = require("@budibase/string-templates");
31
+ const FILTER_STEP_ID = actions_1.default.ACTION_DEFINITIONS.FILTER.stepId;
32
+ const LOOP_STEP_ID = actions_1.default.ACTION_DEFINITIONS.LOOP.stepId;
33
+ const CRON_STEP_ID = triggerInfo_1.definitions.CRON.stepId;
34
+ const STOPPED_STATUS = { success: true, status: types_1.AutomationStatus.STOPPED };
25
35
  const { cloneDeep } = require("lodash/fp");
26
36
  const env = require("../environment");
27
37
  function typecastForLooping(loopStep, input) {
28
38
  if (!input || !input.binding) {
29
39
  return null;
30
40
  }
31
- const isArray = Array.isArray(input.binding), isString = typeof input.binding === "string";
32
41
  try {
33
42
  switch (loopStep.inputs.option) {
34
- case LoopStepTypes.ARRAY:
35
- if (isString) {
43
+ case automations_1.LoopStepTypes.ARRAY:
44
+ if (typeof input.binding === "string") {
36
45
  return JSON.parse(input.binding);
37
46
  }
38
47
  break;
39
- case LoopStepTypes.STRING:
40
- if (isArray) {
48
+ case automations_1.LoopStepTypes.STRING:
49
+ if (Array.isArray(input.binding)) {
41
50
  return input.binding.join(",");
42
51
  }
43
52
  break;
@@ -55,7 +64,7 @@ function getLoopIterations(loopStep, input) {
55
64
  }
56
65
  return Array.isArray(binding)
57
66
  ? binding.length
58
- : automationUtils.stringSplit(binding).length;
67
+ : automationUtils_1.default.stringSplit(binding).length;
59
68
  }
60
69
  /**
61
70
  * The automation orchestrator is a class responsible for executing automations.
@@ -63,11 +72,16 @@ function getLoopIterations(loopStep, input) {
63
72
  * inputs and handles any outputs.
64
73
  */
65
74
  class Orchestrator {
66
- constructor(automation, triggerOutput = {}) {
67
- this._metadata = triggerOutput.metadata;
68
- this._chainCount = this._metadata ? this._metadata.automationChainCount : 0;
75
+ constructor(automation, triggerOutput, opts) {
76
+ const metadata = triggerOutput.metadata;
77
+ this._chainCount = metadata ? metadata.automationChainCount : 0;
69
78
  this._appId = triggerOutput.appId;
70
- this._app = null;
79
+ if (opts === null || opts === void 0 ? void 0 : opts.repeat) {
80
+ this._repeat = {
81
+ jobId: opts.repeat.jobId,
82
+ jobKey: opts.repeat.key,
83
+ };
84
+ }
71
85
  const triggerStepId = automation.definition.trigger.stepId;
72
86
  triggerOutput = this.cleanupTriggerOutputs(triggerStepId, triggerOutput);
73
87
  // remove from context
@@ -78,7 +92,7 @@ class Orchestrator {
78
92
  this._automation = automation;
79
93
  // create an emitter which has the chain count for this automation run in it, so it can block
80
94
  // excessive chaining if required
81
- this._emitter = new AutomationEmitter(this._chainCount + 1);
95
+ this._emitter = new AutomationEmitter_1.default(this._chainCount + 1);
82
96
  this.executionOutput = { trigger: {}, steps: [] };
83
97
  // setup the execution output
84
98
  const triggerId = automation.definition.trigger.id;
@@ -92,32 +106,98 @@ class Orchestrator {
92
106
  }
93
107
  getStepFunctionality(stepId) {
94
108
  return __awaiter(this, void 0, void 0, function* () {
95
- let step = yield actions.getAction(stepId);
109
+ let step = yield actions_1.default.getAction(stepId);
96
110
  if (step == null) {
97
111
  throw `Cannot find automation step by name ${stepId}`;
98
112
  }
99
113
  return step;
100
114
  });
101
115
  }
102
- getApp() {
116
+ getMetadata() {
117
+ return __awaiter(this, void 0, void 0, function* () {
118
+ const metadataId = (0, utils_3.generateAutomationMetadataID)(this._automation._id);
119
+ const db = getAppDB();
120
+ let metadata;
121
+ try {
122
+ metadata = yield db.get(metadataId);
123
+ }
124
+ catch (err) {
125
+ metadata = {
126
+ _id: metadataId,
127
+ errorCount: 0,
128
+ };
129
+ }
130
+ return metadata;
131
+ });
132
+ }
133
+ checkIfShouldStop(metadata) {
134
+ var _a, _b;
135
+ return __awaiter(this, void 0, void 0, function* () {
136
+ if (!metadata.errorCount || !this._repeat) {
137
+ return false;
138
+ }
139
+ const automation = this._automation;
140
+ const trigger = automation.definition.trigger;
141
+ if (metadata.errorCount >= constants_1.MAX_AUTOMATION_RECURRING_ERRORS) {
142
+ logWarn(`CRON disabled due to errors - ${this._appId}/${this._automation._id}`);
143
+ yield (0, utils_2.disableCron)((_a = this._repeat) === null || _a === void 0 ? void 0 : _a.jobId, (_b = this._repeat) === null || _b === void 0 ? void 0 : _b.jobKey);
144
+ this.updateExecutionOutput(trigger.id, trigger.stepId, {}, {
145
+ status: types_1.AutomationStatus.STOPPED_ERROR,
146
+ success: false,
147
+ });
148
+ yield (0, logging_1.storeLog)(automation, this.executionOutput);
149
+ return true;
150
+ }
151
+ return false;
152
+ });
153
+ }
154
+ updateMetadata(metadata) {
103
155
  return __awaiter(this, void 0, void 0, function* () {
104
- if (this._app) {
105
- return this._app;
156
+ const output = this.executionOutput, automation = this._automation;
157
+ if (!output || !(0, utils_2.isRecurring)(automation)) {
158
+ return;
159
+ }
160
+ const count = metadata.errorCount;
161
+ const isError = (0, utils_2.isErrorInOutput)(output);
162
+ // nothing to do in this scenario, escape
163
+ if (!count && !isError) {
164
+ return;
165
+ }
166
+ if (isError) {
167
+ metadata.errorCount = count ? count + 1 : 1;
168
+ }
169
+ else {
170
+ metadata.errorCount = 0;
106
171
  }
107
172
  const db = getAppDB();
108
- this._app = yield db.get(DocumentTypes.APP_METADATA);
109
- return this._app;
173
+ try {
174
+ yield db.put(metadata);
175
+ }
176
+ catch (err) {
177
+ logAlertWithInfo("Failed to write automation metadata", db.name, automation._id, err);
178
+ }
110
179
  });
111
180
  }
112
181
  updateExecutionOutput(id, stepId, inputs, outputs) {
113
182
  const stepObj = { id, stepId, inputs, outputs };
183
+ // replacing trigger when disabling CRON
184
+ if (stepId === CRON_STEP_ID &&
185
+ outputs.status === types_1.AutomationStatus.STOPPED_ERROR) {
186
+ this.executionOutput.trigger = stepObj;
187
+ this.executionOutput.steps = [stepObj];
188
+ return;
189
+ }
114
190
  // first entry is always the trigger (constructor)
115
- if (this.executionOutput.steps.length === 0) {
191
+ if (this.executionOutput.steps.length === 0 ||
192
+ this.executionOutput.trigger.id === id) {
116
193
  this.executionOutput.trigger = stepObj;
117
194
  }
118
195
  this.executionOutput.steps.push(stepObj);
119
196
  }
120
197
  updateContextAndOutput(loopStepNumber, step, output, result) {
198
+ if (!loopStepNumber) {
199
+ throw new Error("No loop step number provided.");
200
+ }
121
201
  this.executionOutput.steps.splice(loopStepNumber, 0, {
122
202
  id: step.id,
123
203
  stepId: step.stepId,
@@ -131,10 +211,19 @@ class Orchestrator {
131
211
  return __awaiter(this, void 0, void 0, function* () {
132
212
  let automation = this._automation;
133
213
  let stopped = false;
134
- let loopStep = null;
214
+ let loopStep = undefined;
135
215
  let stepCount = 0;
136
- let loopStepNumber = null;
216
+ let loopStepNumber = undefined;
137
217
  let loopSteps = [];
218
+ let metadata;
219
+ // check if this is a recurring automation,
220
+ if ((0, utils_3.isProdAppID)(this._appId) && (0, utils_2.isRecurring)(automation)) {
221
+ metadata = yield this.getMetadata();
222
+ const shouldStop = yield this.checkIfShouldStop(metadata);
223
+ if (shouldStop) {
224
+ return;
225
+ }
226
+ }
138
227
  for (let step of automation.definition.steps) {
139
228
  stepCount++;
140
229
  let input, iterations = 1, iterationCount = 0;
@@ -158,17 +247,17 @@ class Orchestrator {
158
247
  }
159
248
  catch (err) {
160
249
  this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
161
- status: AutomationErrors.INCORRECT_TYPE,
250
+ status: constants_1.AutomationErrors.INCORRECT_TYPE,
162
251
  success: false,
163
252
  });
164
- loopSteps = null;
165
- loopStep = null;
253
+ loopSteps = undefined;
254
+ loopStep = undefined;
166
255
  break;
167
256
  }
168
257
  let item;
169
258
  if (typeof loopStep.inputs.binding === "string" &&
170
259
  loopStep.inputs.option === "String") {
171
- item = automationUtils.stringSplit(newInput.binding);
260
+ item = automationUtils_1.default.stringSplit(newInput.binding);
172
261
  }
173
262
  else {
174
263
  item = loopStep.inputs.binding;
@@ -183,31 +272,31 @@ class Orchestrator {
183
272
  for (let [innerKey, innerValue] of Object.entries(originalStepInput[key])) {
184
273
  if (typeof innerValue === "string") {
185
274
  originalStepInput[key][innerKey] =
186
- automationUtils.substituteLoopStep(innerValue, `steps.${loopStepNumber}`);
275
+ automationUtils_1.default.substituteLoopStep(innerValue, `steps.${loopStepNumber}`);
187
276
  }
188
277
  }
189
278
  }
190
279
  else {
191
280
  if (typeof value === "string") {
192
- originalStepInput[key] = automationUtils.substituteLoopStep(value, `steps.${loopStepNumber}`);
281
+ originalStepInput[key] = automationUtils_1.default.substituteLoopStep(value, `steps.${loopStepNumber}`);
193
282
  }
194
283
  }
195
284
  }
196
285
  if (index === env.AUTOMATION_MAX_ITERATION ||
197
286
  index === parseInt(loopStep.inputs.iterations)) {
198
287
  this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
199
- status: AutomationErrors.MAX_ITERATIONS,
288
+ status: constants_1.AutomationErrors.MAX_ITERATIONS,
200
289
  success: true,
201
290
  });
202
- loopSteps = null;
203
- loopStep = null;
291
+ loopSteps = undefined;
292
+ loopStep = undefined;
204
293
  break;
205
294
  }
206
295
  let isFailure = false;
207
296
  const currentItem = (_a = this._context.steps[loopStepNumber]) === null || _a === void 0 ? void 0 : _a.currentItem;
208
297
  if (currentItem && typeof currentItem === "object") {
209
298
  isFailure = Object.keys(currentItem).some(value => {
210
- return currentItem[value] === loopStep.inputs.failure;
299
+ return currentItem[value] === (loopStep === null || loopStep === void 0 ? void 0 : loopStep.inputs.failure);
211
300
  });
212
301
  }
213
302
  else {
@@ -215,11 +304,11 @@ class Orchestrator {
215
304
  }
216
305
  if (isFailure) {
217
306
  this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
218
- status: AutomationErrors.FAILURE_CONDITION,
307
+ status: constants_1.AutomationErrors.FAILURE_CONDITION,
219
308
  success: false,
220
309
  });
221
- loopSteps = null;
222
- loopStep = null;
310
+ loopSteps = undefined;
311
+ loopStep = undefined;
223
312
  break;
224
313
  }
225
314
  }
@@ -231,7 +320,7 @@ class Orchestrator {
231
320
  // If it's a loop step, we need to manually add the bindings to the context
232
321
  let stepFn = yield this.getStepFunctionality(step.stepId);
233
322
  let inputs = yield processObject(originalStepInput, this._context);
234
- inputs = automationUtils.cleanInputValues(inputs, step.schema.inputs);
323
+ inputs = automationUtils_1.default.cleanInputValues(inputs, step.schema.inputs);
235
324
  try {
236
325
  // appId is always passed
237
326
  const outputs = yield stepFn({
@@ -262,7 +351,7 @@ class Orchestrator {
262
351
  if (loopStep) {
263
352
  iterationCount++;
264
353
  if (index === iterations - 1) {
265
- loopStep = null;
354
+ loopStep = undefined;
266
355
  this._context.steps.splice(loopStepNumber, 1);
267
356
  break;
268
357
  }
@@ -281,19 +370,22 @@ class Orchestrator {
281
370
  inputs: step.inputs,
282
371
  });
283
372
  this._context.steps.splice(loopStepNumber, 0, tempOutput);
284
- loopSteps = null;
373
+ loopSteps = undefined;
285
374
  }
286
375
  }
287
376
  // store the logs for the automation run
288
- yield storeLog(this._automation, this.executionOutput);
377
+ yield (0, logging_1.storeLog)(this._automation, this.executionOutput);
378
+ if ((0, utils_3.isProdAppID)(this._appId) && (0, utils_2.isRecurring)(automation) && metadata) {
379
+ yield this.updateMetadata(metadata);
380
+ }
289
381
  return this.executionOutput;
290
382
  });
291
383
  }
292
384
  }
293
- module.exports = (input, callback) => {
385
+ function execute(input, callback) {
294
386
  const appId = input.data.event.appId;
295
- doInAppContext(appId, () => __awaiter(void 0, void 0, void 0, function* () {
296
- const automationOrchestrator = new Orchestrator(input.data.automation, input.data.event);
387
+ doInAppContext(appId, () => __awaiter(this, void 0, void 0, function* () {
388
+ const automationOrchestrator = new Orchestrator(input.data.automation, input.data.event, input.opts);
297
389
  try {
298
390
  const response = yield automationOrchestrator.execute();
299
391
  callback(null, response);
@@ -302,4 +394,5 @@ module.exports = (input, callback) => {
302
394
  callback(err);
303
395
  }
304
396
  }));
305
- };
397
+ }
398
+ exports.execute = execute;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -54,17 +54,14 @@ function typeToFile(type) {
54
54
  default:
55
55
  throw "Unknown thread type";
56
56
  }
57
+ // have to use require here, to make it work with worker-farm
57
58
  return require.resolve(filename);
58
59
  }
59
60
  class Thread {
60
61
  constructor(type, opts = { timeoutMs: null, count: 1 }) {
61
62
  this.type = type;
62
63
  this.count = opts.count ? opts.count : 1;
63
- this.disableThreading =
64
- env.isTest() ||
65
- env.DISABLE_THREADING ||
66
- this.count === 0 ||
67
- env.isInThread();
64
+ this.disableThreading = this.shouldDisableThreading();
68
65
  if (!this.disableThreading) {
69
66
  const workerOpts = {
70
67
  autoStart: true,
@@ -74,31 +71,41 @@ class Thread {
74
71
  this.timeoutMs = opts.timeoutMs;
75
72
  workerOpts.maxCallTime = opts.timeoutMs;
76
73
  }
77
- this.workers = (0, worker_farm_1.default)(workerOpts, typeToFile(type));
74
+ this.workers = (0, worker_farm_1.default)(workerOpts, typeToFile(type), ["execute"]);
78
75
  Thread.workerRefs.push(this.workers);
79
76
  }
80
77
  }
78
+ shouldDisableThreading() {
79
+ return !!(env.isTest() ||
80
+ env.DISABLE_THREADING ||
81
+ this.count === 0 ||
82
+ env.isInThread());
83
+ }
81
84
  run(data) {
85
+ const timeout = this.timeoutMs;
82
86
  return new Promise((resolve, reject) => {
83
- let fncToCall;
87
+ function fire(worker) {
88
+ worker.execute(data, (err, response) => {
89
+ if (err && err.type === "TimeoutError") {
90
+ reject(new Error(`Query response time exceeded ${timeout}ms timeout.`));
91
+ }
92
+ else if (err) {
93
+ reject(err);
94
+ }
95
+ else {
96
+ resolve(response);
97
+ }
98
+ });
99
+ }
84
100
  // if in test then don't use threading
85
101
  if (this.disableThreading) {
86
- fncToCall = require(typeToFile(this.type));
102
+ Promise.resolve().then(() => __importStar(require(typeToFile(this.type)))).then((thread) => {
103
+ fire(thread);
104
+ });
87
105
  }
88
106
  else {
89
- fncToCall = this.workers;
107
+ fire(this.workers);
90
108
  }
91
- fncToCall(data, (err, response) => {
92
- if (err && err.type === "TimeoutError") {
93
- reject(new Error(`Query response time exceeded ${this.timeoutMs}ms timeout.`));
94
- }
95
- else if (err) {
96
- reject(err);
97
- }
98
- else {
99
- resolve(response);
100
- }
101
- });
102
109
  });
103
110
  }
104
111
  static stopThreads() {
@@ -8,8 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- const threadUtils = require("./utils");
12
- threadUtils.threadSetup();
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.execute = void 0;
16
+ const utils_1 = __importDefault(require("./utils"));
17
+ utils_1.default.threadSetup();
13
18
  const ScriptRunner = require("../utilities/scriptRunner");
14
19
  const { integrations } = require("../integrations");
15
20
  const { processStringSync } = require("@budibase/string-templates");
@@ -39,6 +44,7 @@ class QueryRunner {
39
44
  this.queryResponse = {};
40
45
  this.hasRerun = false;
41
46
  this.hasRefreshedOAuth = false;
47
+ this.hasDynamicVariables = false;
42
48
  }
43
49
  execute() {
44
50
  var _a;
@@ -52,7 +58,7 @@ class QueryRunner {
52
58
  }
53
59
  if (datasourceClone.config.authConfigs) {
54
60
  datasourceClone.config.authConfigs =
55
- datasourceClone.config.authConfigs.map(config => {
61
+ datasourceClone.config.authConfigs.map((config) => {
56
62
  return enrichQueryFields(config, this.ctx);
57
63
  });
58
64
  }
@@ -79,9 +85,9 @@ class QueryRunner {
79
85
  if (this.pagination) {
80
86
  query.paginationValues = this.pagination;
81
87
  }
82
- let output = threadUtils.formatResponse(yield integration[queryVerb](query));
88
+ let output = utils_1.default.formatResponse(yield integration[queryVerb](query));
83
89
  let rows = output, info = undefined, extra = undefined, pagination = undefined;
84
- if (threadUtils.hasExtraData(output)) {
90
+ if (utils_1.default.hasExtraData(output)) {
85
91
  rows = output.data;
86
92
  info = output.info;
87
93
  extra = output.extra;
@@ -107,7 +113,7 @@ class QueryRunner {
107
113
  else {
108
114
  this.hasRerun = true;
109
115
  }
110
- yield threadUtils.invalidateDynamicVariables(this.cachedVariables);
116
+ yield utils_1.default.invalidateDynamicVariables(this.cachedVariables);
111
117
  return this.execute();
112
118
  }
113
119
  // check for undefined response
@@ -119,8 +125,8 @@ class QueryRunner {
119
125
  rows = [rows];
120
126
  }
121
127
  // map into JSON if just raw primitive here
122
- if (rows.find(row => typeof row !== "object")) {
123
- rows = rows.map(value => ({ value }));
128
+ if (rows.find((row) => typeof row !== "object")) {
129
+ rows = rows.map((value) => ({ value }));
124
130
  }
125
131
  // get all the potential fields in the schema
126
132
  let keys = rows.flatMap(Object.keys);
@@ -141,6 +147,7 @@ class QueryRunner {
141
147
  fields: query.fields,
142
148
  parameters,
143
149
  transformer: query.transformer,
150
+ queryId,
144
151
  }, { noRecursiveQuery: true }).execute();
145
152
  });
146
153
  }
@@ -172,14 +179,14 @@ class QueryRunner {
172
179
  return __awaiter(this, void 0, void 0, function* () {
173
180
  let { parameters } = this;
174
181
  const queryId = variable.queryId, name = variable.name;
175
- let value = yield threadUtils.checkCacheForDynamicVariable(queryId, name);
182
+ let value = yield utils_1.default.checkCacheForDynamicVariable(queryId, name);
176
183
  if (!value) {
177
184
  value = this.queryResponse[queryId]
178
185
  ? this.queryResponse[queryId]
179
186
  : yield this.runAnotherQuery(queryId, parameters);
180
187
  // store incase this query is to be called again
181
188
  this.queryResponse[queryId] = value;
182
- yield threadUtils.storeDynamicVariable(queryId, name, value);
189
+ yield utils_1.default.storeDynamicVariable(queryId, name, value);
183
190
  }
184
191
  else {
185
192
  this.cachedVariables.push({ queryId, name });
@@ -203,7 +210,7 @@ class QueryRunner {
203
210
  if (!this.noRecursiveQuery) {
204
211
  // need to see if this uses any variables
205
212
  const stringFields = JSON.stringify(fields);
206
- const foundVars = dynamicVars.filter(variable => {
213
+ const foundVars = dynamicVars.filter((variable) => {
207
214
  // don't allow a query to use its own dynamic variable (loop)
208
215
  if (variable.queryId === this.queryId) {
209
216
  return false;
@@ -212,7 +219,7 @@ class QueryRunner {
212
219
  const regex = new RegExp(`{{[ ]*${variable.name}[ ]*}}`);
213
220
  return regex.test(stringFields);
214
221
  });
215
- const dynamics = foundVars.map(dynVar => this.getDynamicVariable(dynVar));
222
+ const dynamics = foundVars.map((dynVar) => this.getDynamicVariable(dynVar));
216
223
  const responses = yield Promise.all(dynamics);
217
224
  for (let i = 0; i < foundVars.length; i++) {
218
225
  const variable = foundVars[i];
@@ -230,8 +237,8 @@ class QueryRunner {
230
237
  });
231
238
  }
232
239
  }
233
- module.exports = (input, callback) => {
234
- doInAppContext(input.appId, () => __awaiter(void 0, void 0, void 0, function* () {
240
+ function execute(input, callback) {
241
+ doInAppContext(input.appId, () => __awaiter(this, void 0, void 0, function* () {
235
242
  const Runner = new QueryRunner(input);
236
243
  try {
237
244
  const response = yield Runner.execute();
@@ -241,4 +248,5 @@ module.exports = (input, callback) => {
241
248
  callback(err);
242
249
  }
243
250
  }));
244
- };
251
+ }
252
+ exports.execute = execute;
@@ -8,6 +8,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.hasExtraData = exports.formatResponse = exports.storeDynamicVariable = exports.invalidateDynamicVariables = exports.checkCacheForDynamicVariable = exports.threadSetup = void 0;
11
13
  const env = require("../environment");
12
14
  const db = require("../db");
13
15
  const redis = require("@budibase/backend-core/redis");
@@ -23,10 +25,14 @@ function getClient() {
23
25
  });
24
26
  }
25
27
  process.on("exit", () => __awaiter(void 0, void 0, void 0, function* () {
26
- if (client)
28
+ if (client) {
27
29
  yield client.finish();
30
+ }
28
31
  }));
29
- exports.threadSetup = () => {
32
+ function makeVariableKey(queryId, variable) {
33
+ return `${queryId}${SEPARATOR}${variable}`;
34
+ }
35
+ function threadSetup() {
30
36
  // don't run this if not threading
31
37
  if (env.isTest() || env.DISABLE_THREADING) {
32
38
  return;
@@ -34,27 +40,34 @@ exports.threadSetup = () => {
34
40
  // when thread starts, make sure it is recorded
35
41
  env.setInThread();
36
42
  db.init();
37
- };
38
- function makeVariableKey(queryId, variable) {
39
- return `${queryId}${SEPARATOR}${variable}`;
40
43
  }
41
- exports.checkCacheForDynamicVariable = (queryId, variable) => __awaiter(void 0, void 0, void 0, function* () {
42
- const cache = yield getClient();
43
- return cache.get(makeVariableKey(queryId, variable));
44
- });
45
- exports.invalidateDynamicVariables = (cachedVars) => __awaiter(void 0, void 0, void 0, function* () {
46
- const cache = yield getClient();
47
- let promises = [];
48
- for (let variable of cachedVars) {
49
- promises.push(cache.delete(makeVariableKey(variable.queryId, variable.name)));
50
- }
51
- yield Promise.all(promises);
52
- });
53
- exports.storeDynamicVariable = (queryId, variable, value) => __awaiter(void 0, void 0, void 0, function* () {
54
- const cache = yield getClient();
55
- yield cache.store(makeVariableKey(queryId, variable), value, VARIABLE_TTL_SECONDS);
56
- });
57
- exports.formatResponse = resp => {
44
+ exports.threadSetup = threadSetup;
45
+ function checkCacheForDynamicVariable(queryId, variable) {
46
+ return __awaiter(this, void 0, void 0, function* () {
47
+ const cache = yield getClient();
48
+ return cache.get(makeVariableKey(queryId, variable));
49
+ });
50
+ }
51
+ exports.checkCacheForDynamicVariable = checkCacheForDynamicVariable;
52
+ function invalidateDynamicVariables(cachedVars) {
53
+ return __awaiter(this, void 0, void 0, function* () {
54
+ const cache = yield getClient();
55
+ let promises = [];
56
+ for (let variable of cachedVars) {
57
+ promises.push(cache.delete(makeVariableKey(variable.queryId, variable.name)));
58
+ }
59
+ yield Promise.all(promises);
60
+ });
61
+ }
62
+ exports.invalidateDynamicVariables = invalidateDynamicVariables;
63
+ function storeDynamicVariable(queryId, variable, value) {
64
+ return __awaiter(this, void 0, void 0, function* () {
65
+ const cache = yield getClient();
66
+ yield cache.store(makeVariableKey(queryId, variable), value, VARIABLE_TTL_SECONDS);
67
+ });
68
+ }
69
+ exports.storeDynamicVariable = storeDynamicVariable;
70
+ function formatResponse(resp) {
58
71
  if (typeof resp === "string") {
59
72
  try {
60
73
  resp = JSON.parse(resp);
@@ -64,11 +77,21 @@ exports.formatResponse = resp => {
64
77
  }
65
78
  }
66
79
  return resp;
67
- };
68
- exports.hasExtraData = response => {
80
+ }
81
+ exports.formatResponse = formatResponse;
82
+ function hasExtraData(response) {
69
83
  return (typeof response === "object" &&
70
84
  !Array.isArray(response) &&
71
85
  response &&
72
86
  response.data != null &&
73
87
  response.info != null);
88
+ }
89
+ exports.hasExtraData = hasExtraData;
90
+ exports.default = {
91
+ hasExtraData,
92
+ formatResponse,
93
+ storeDynamicVariable,
94
+ invalidateDynamicVariables,
95
+ checkCacheForDynamicVariable,
96
+ threadSetup,
74
97
  };