@budibase/server 2.6.19-alpha.20 → 2.6.19-alpha.21
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.
- package/builder/assets/{index.9a9bace2.js → index.47cc7efc.js} +273 -272
- package/builder/assets/{index.46d94ca7.css → index.ffb6a106.css} +1 -1
- package/builder/index.html +2 -2
- package/dist/automation.js +205 -49
- package/dist/automation.js.map +4 -4
- package/dist/index.js +338 -137
- package/dist/index.js.map +4 -4
- package/dist/query.js +26 -8
- package/dist/query.js.map +4 -4
- package/package.json +8 -8
- package/src/api/controllers/automation.ts +37 -9
- package/src/api/controllers/webhook.ts +33 -9
- package/src/api/routes/automation.ts +0 -1
- package/src/api/routes/tests/{automation.spec.js → automation.spec.ts} +106 -31
- package/src/api/routes/tests/{webhook.spec.js → webhook.spec.ts} +33 -11
- package/src/automations/actions.ts +3 -0
- package/src/automations/steps/bash.ts +4 -0
- package/src/automations/steps/collect.ts +58 -0
- package/src/automations/steps/createRow.ts +4 -0
- package/src/automations/steps/delay.ts +1 -0
- package/src/automations/steps/deleteRow.ts +4 -0
- package/src/automations/steps/discord.ts +4 -0
- package/src/automations/steps/executeQuery.ts +4 -0
- package/src/automations/steps/executeScript.ts +4 -0
- package/src/automations/steps/filter.ts +1 -0
- package/src/automations/steps/loop.ts +1 -0
- package/src/automations/steps/make.ts +4 -0
- package/src/automations/steps/openai.ts +1 -0
- package/src/automations/steps/outgoingWebhook.ts +4 -0
- package/src/automations/steps/queryRows.ts +4 -0
- package/src/automations/steps/sendSmtpEmail.ts +4 -0
- package/src/automations/steps/serverLog.ts +4 -0
- package/src/automations/steps/slack.ts +4 -0
- package/src/automations/steps/updateRow.ts +4 -0
- package/src/automations/steps/zapier.ts +4 -0
- package/src/automations/triggers.ts +3 -2
- package/src/sdk/app/automations/index.ts +2 -0
- package/src/sdk/app/automations/utils.ts +7 -0
- package/src/tests/utilities/TestConfiguration.ts +4 -2
- package/src/tests/utilities/structures.ts +42 -0
- package/src/threads/automation.ts +39 -0
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
AutomationStepInput,
|
|
7
7
|
AutomationStepType,
|
|
8
8
|
AutomationIOType,
|
|
9
|
+
AutomationFeature,
|
|
9
10
|
} from "@budibase/types"
|
|
10
11
|
|
|
11
12
|
const DEFAULT_USERNAME = "Budibase Automate"
|
|
@@ -19,6 +20,9 @@ export const definition: AutomationStepSchema = {
|
|
|
19
20
|
stepId: AutomationActionStepId.discord,
|
|
20
21
|
type: AutomationStepType.ACTION,
|
|
21
22
|
internal: false,
|
|
23
|
+
features: {
|
|
24
|
+
[AutomationFeature.LOOPING]: true,
|
|
25
|
+
},
|
|
22
26
|
inputs: {},
|
|
23
27
|
schema: {
|
|
24
28
|
inputs: {
|
|
@@ -4,6 +4,7 @@ import * as automationUtils from "../automationUtils"
|
|
|
4
4
|
import {
|
|
5
5
|
AutomationActionStepId,
|
|
6
6
|
AutomationCustomIOType,
|
|
7
|
+
AutomationFeature,
|
|
7
8
|
AutomationIOType,
|
|
8
9
|
AutomationStepInput,
|
|
9
10
|
AutomationStepSchema,
|
|
@@ -18,6 +19,9 @@ export const definition: AutomationStepSchema = {
|
|
|
18
19
|
type: AutomationStepType.ACTION,
|
|
19
20
|
stepId: AutomationActionStepId.EXECUTE_QUERY,
|
|
20
21
|
internal: true,
|
|
22
|
+
features: {
|
|
23
|
+
[AutomationFeature.LOOPING]: true,
|
|
24
|
+
},
|
|
21
25
|
inputs: {},
|
|
22
26
|
schema: {
|
|
23
27
|
inputs: {
|
|
@@ -4,6 +4,7 @@ import * as automationUtils from "../automationUtils"
|
|
|
4
4
|
import {
|
|
5
5
|
AutomationActionStepId,
|
|
6
6
|
AutomationCustomIOType,
|
|
7
|
+
AutomationFeature,
|
|
7
8
|
AutomationIOType,
|
|
8
9
|
AutomationStepInput,
|
|
9
10
|
AutomationStepSchema,
|
|
@@ -19,6 +20,9 @@ export const definition: AutomationStepSchema = {
|
|
|
19
20
|
internal: true,
|
|
20
21
|
stepId: AutomationActionStepId.EXECUTE_SCRIPT,
|
|
21
22
|
inputs: {},
|
|
23
|
+
features: {
|
|
24
|
+
[AutomationFeature.LOOPING]: true,
|
|
25
|
+
},
|
|
22
26
|
schema: {
|
|
23
27
|
inputs: {
|
|
24
28
|
properties: {
|
|
@@ -28,6 +28,7 @@ export const definition: AutomationStepSchema = {
|
|
|
28
28
|
"Conditionally halt automations which do not meet certain conditions",
|
|
29
29
|
type: AutomationStepType.LOGIC,
|
|
30
30
|
internal: true,
|
|
31
|
+
features: {},
|
|
31
32
|
stepId: AutomationActionStepId.FILTER,
|
|
32
33
|
inputs: {
|
|
33
34
|
condition: FilterConditions.EQUAL,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
AutomationStepInput,
|
|
7
7
|
AutomationStepType,
|
|
8
8
|
AutomationIOType,
|
|
9
|
+
AutomationFeature,
|
|
9
10
|
} from "@budibase/types"
|
|
10
11
|
|
|
11
12
|
export const definition: AutomationStepSchema = {
|
|
@@ -18,6 +19,9 @@ export const definition: AutomationStepSchema = {
|
|
|
18
19
|
stepId: AutomationActionStepId.integromat,
|
|
19
20
|
type: AutomationStepType.ACTION,
|
|
20
21
|
internal: false,
|
|
22
|
+
features: {
|
|
23
|
+
[AutomationFeature.LOOPING]: true,
|
|
24
|
+
},
|
|
21
25
|
inputs: {},
|
|
22
26
|
schema: {
|
|
23
27
|
inputs: {
|
|
@@ -4,6 +4,7 @@ import * as automationUtils from "../automationUtils"
|
|
|
4
4
|
import {
|
|
5
5
|
AutomationActionStepId,
|
|
6
6
|
AutomationCustomIOType,
|
|
7
|
+
AutomationFeature,
|
|
7
8
|
AutomationIOType,
|
|
8
9
|
AutomationStepInput,
|
|
9
10
|
AutomationStepSchema,
|
|
@@ -32,6 +33,9 @@ export const definition: AutomationStepSchema = {
|
|
|
32
33
|
description: "Send a request of specified method to a URL",
|
|
33
34
|
type: AutomationStepType.ACTION,
|
|
34
35
|
internal: true,
|
|
36
|
+
features: {
|
|
37
|
+
[AutomationFeature.LOOPING]: true,
|
|
38
|
+
},
|
|
35
39
|
stepId: AutomationActionStepId.OUTGOING_WEBHOOK,
|
|
36
40
|
inputs: {
|
|
37
41
|
requestMethod: "POST",
|
|
@@ -6,6 +6,7 @@ import * as automationUtils from "../automationUtils"
|
|
|
6
6
|
import {
|
|
7
7
|
AutomationActionStepId,
|
|
8
8
|
AutomationCustomIOType,
|
|
9
|
+
AutomationFeature,
|
|
9
10
|
AutomationIOType,
|
|
10
11
|
AutomationStepInput,
|
|
11
12
|
AutomationStepSchema,
|
|
@@ -42,6 +43,9 @@ export const definition: AutomationStepSchema = {
|
|
|
42
43
|
type: AutomationStepType.ACTION,
|
|
43
44
|
stepId: AutomationActionStepId.QUERY_ROWS,
|
|
44
45
|
internal: true,
|
|
46
|
+
features: {
|
|
47
|
+
[AutomationFeature.LOOPING]: true,
|
|
48
|
+
},
|
|
45
49
|
inputs: {},
|
|
46
50
|
schema: {
|
|
47
51
|
inputs: {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
AutomationStepInput,
|
|
7
7
|
AutomationStepType,
|
|
8
8
|
AutomationIOType,
|
|
9
|
+
AutomationFeature,
|
|
9
10
|
} from "@budibase/types"
|
|
10
11
|
|
|
11
12
|
export const definition: AutomationStepSchema = {
|
|
@@ -15,6 +16,9 @@ export const definition: AutomationStepSchema = {
|
|
|
15
16
|
name: "Send Email (SMTP)",
|
|
16
17
|
type: AutomationStepType.ACTION,
|
|
17
18
|
internal: true,
|
|
19
|
+
features: {
|
|
20
|
+
[AutomationFeature.LOOPING]: true,
|
|
21
|
+
},
|
|
18
22
|
stepId: AutomationActionStepId.SEND_EMAIL_SMTP,
|
|
19
23
|
inputs: {},
|
|
20
24
|
schema: {
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
AutomationStepInput,
|
|
5
5
|
AutomationStepType,
|
|
6
6
|
AutomationIOType,
|
|
7
|
+
AutomationFeature,
|
|
7
8
|
} from "@budibase/types"
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -19,6 +20,9 @@ export const definition: AutomationStepSchema = {
|
|
|
19
20
|
description: "Logs the given text to the server (using console.log)",
|
|
20
21
|
type: AutomationStepType.ACTION,
|
|
21
22
|
internal: true,
|
|
23
|
+
features: {
|
|
24
|
+
[AutomationFeature.LOOPING]: true,
|
|
25
|
+
},
|
|
22
26
|
stepId: AutomationActionStepId.SERVER_LOG,
|
|
23
27
|
inputs: {
|
|
24
28
|
text: "",
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
AutomationStepInput,
|
|
7
7
|
AutomationStepType,
|
|
8
8
|
AutomationIOType,
|
|
9
|
+
AutomationFeature,
|
|
9
10
|
} from "@budibase/types"
|
|
10
11
|
|
|
11
12
|
export const definition: AutomationStepSchema = {
|
|
@@ -16,6 +17,9 @@ export const definition: AutomationStepSchema = {
|
|
|
16
17
|
stepId: AutomationActionStepId.slack,
|
|
17
18
|
type: AutomationStepType.ACTION,
|
|
18
19
|
internal: false,
|
|
20
|
+
features: {
|
|
21
|
+
[AutomationFeature.LOOPING]: true,
|
|
22
|
+
},
|
|
19
23
|
inputs: {},
|
|
20
24
|
schema: {
|
|
21
25
|
inputs: {
|
|
@@ -4,6 +4,7 @@ import { buildCtx } from "./utils"
|
|
|
4
4
|
import {
|
|
5
5
|
AutomationActionStepId,
|
|
6
6
|
AutomationCustomIOType,
|
|
7
|
+
AutomationFeature,
|
|
7
8
|
AutomationIOType,
|
|
8
9
|
AutomationStepInput,
|
|
9
10
|
AutomationStepSchema,
|
|
@@ -17,6 +18,9 @@ export const definition: AutomationStepSchema = {
|
|
|
17
18
|
description: "Update a row in your database",
|
|
18
19
|
type: AutomationStepType.ACTION,
|
|
19
20
|
internal: true,
|
|
21
|
+
features: {
|
|
22
|
+
[AutomationFeature.LOOPING]: true,
|
|
23
|
+
},
|
|
20
24
|
stepId: AutomationActionStepId.UPDATE_ROW,
|
|
21
25
|
inputs: {},
|
|
22
26
|
schema: {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
AutomationStepInput,
|
|
7
7
|
AutomationStepType,
|
|
8
8
|
AutomationIOType,
|
|
9
|
+
AutomationFeature,
|
|
9
10
|
} from "@budibase/types"
|
|
10
11
|
|
|
11
12
|
export const definition: AutomationStepSchema = {
|
|
@@ -13,6 +14,9 @@ export const definition: AutomationStepSchema = {
|
|
|
13
14
|
stepId: AutomationActionStepId.zapier,
|
|
14
15
|
type: AutomationStepType.ACTION,
|
|
15
16
|
internal: false,
|
|
17
|
+
features: {
|
|
18
|
+
[AutomationFeature.LOOPING]: true,
|
|
19
|
+
},
|
|
16
20
|
description: "Trigger a Zapier Zap via webhooks",
|
|
17
21
|
tagline: "Trigger a Zapier Zap",
|
|
18
22
|
icon: "ri-flashlight-line",
|
|
@@ -10,6 +10,7 @@ import * as utils from "./utils"
|
|
|
10
10
|
import env from "../environment"
|
|
11
11
|
import { context, db as dbCore } from "@budibase/backend-core"
|
|
12
12
|
import { Automation, Row, AutomationData, AutomationJob } from "@budibase/types"
|
|
13
|
+
import { executeSynchronously } from "../threads/automation"
|
|
13
14
|
|
|
14
15
|
export const TRIGGER_DEFINITIONS = definitions
|
|
15
16
|
const JOB_OPTS = {
|
|
@@ -91,7 +92,7 @@ emitter.on("row:delete", async function (event) {
|
|
|
91
92
|
|
|
92
93
|
export async function externalTrigger(
|
|
93
94
|
automation: Automation,
|
|
94
|
-
params: { fields: Record<string, any
|
|
95
|
+
params: { fields: Record<string, any>; timeout?: number },
|
|
95
96
|
{ getResponses }: { getResponses?: boolean } = {}
|
|
96
97
|
) {
|
|
97
98
|
if (
|
|
@@ -118,7 +119,7 @@ export async function externalTrigger(
|
|
|
118
119
|
automation,
|
|
119
120
|
}
|
|
120
121
|
const job = { data } as AutomationJob
|
|
121
|
-
return
|
|
122
|
+
return executeSynchronously(job)
|
|
122
123
|
} else {
|
|
123
124
|
return automationQueue.add(data, JOB_OPTS)
|
|
124
125
|
}
|
|
@@ -373,7 +373,7 @@ class TestConfiguration {
|
|
|
373
373
|
|
|
374
374
|
// HEADERS
|
|
375
375
|
|
|
376
|
-
defaultHeaders(extras = {}) {
|
|
376
|
+
defaultHeaders(extras = {}, prodApp = false) {
|
|
377
377
|
const tenantId = this.getTenantId()
|
|
378
378
|
const authObj: AuthToken = {
|
|
379
379
|
userId: this.defaultUserValues.globalUserId,
|
|
@@ -390,7 +390,9 @@ class TestConfiguration {
|
|
|
390
390
|
...extras,
|
|
391
391
|
}
|
|
392
392
|
|
|
393
|
-
if (
|
|
393
|
+
if (prodApp) {
|
|
394
|
+
headers[constants.Header.APP_ID] = this.prodAppId
|
|
395
|
+
} else if (this.appId) {
|
|
394
396
|
headers[constants.Header.APP_ID] = this.appId
|
|
395
397
|
}
|
|
396
398
|
return headers
|
|
@@ -199,6 +199,48 @@ export function loopAutomation(tableId: string, loopOpts?: any): Automation {
|
|
|
199
199
|
return automation as Automation
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
export function collectAutomation(tableId?: string): Automation {
|
|
203
|
+
const automation: any = {
|
|
204
|
+
name: "looping",
|
|
205
|
+
type: "automation",
|
|
206
|
+
definition: {
|
|
207
|
+
steps: [
|
|
208
|
+
{
|
|
209
|
+
id: "b",
|
|
210
|
+
type: "ACTION",
|
|
211
|
+
internal: true,
|
|
212
|
+
stepId: AutomationActionStepId.EXECUTE_SCRIPT,
|
|
213
|
+
inputs: {
|
|
214
|
+
code: "return [1,2,3]",
|
|
215
|
+
},
|
|
216
|
+
schema: BUILTIN_ACTION_DEFINITIONS.EXECUTE_SCRIPT.schema,
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
id: "c",
|
|
220
|
+
type: "ACTION",
|
|
221
|
+
internal: true,
|
|
222
|
+
stepId: AutomationActionStepId.COLLECT,
|
|
223
|
+
inputs: {
|
|
224
|
+
collection: "{{ literal steps.1.value }}",
|
|
225
|
+
},
|
|
226
|
+
schema: BUILTIN_ACTION_DEFINITIONS.SERVER_LOG.schema,
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
trigger: {
|
|
230
|
+
id: "a",
|
|
231
|
+
type: "TRIGGER",
|
|
232
|
+
event: "row:save",
|
|
233
|
+
stepId: AutomationTriggerStepId.ROW_SAVED,
|
|
234
|
+
inputs: {
|
|
235
|
+
tableId,
|
|
236
|
+
},
|
|
237
|
+
schema: TRIGGER_DEFINITIONS.ROW_SAVED.schema,
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
}
|
|
241
|
+
return automation as Automation
|
|
242
|
+
}
|
|
243
|
+
|
|
202
244
|
export function basicRow(tableId: string) {
|
|
203
245
|
return {
|
|
204
246
|
name: "Test Contact",
|
|
@@ -68,6 +68,7 @@ class Orchestrator {
|
|
|
68
68
|
constructor(job: AutomationJob) {
|
|
69
69
|
let automation = job.data.automation
|
|
70
70
|
let triggerOutput = job.data.event
|
|
71
|
+
let timeout = job.data.event.timeout
|
|
71
72
|
const metadata = triggerOutput.metadata
|
|
72
73
|
this._chainCount = metadata ? metadata.automationChainCount! : 0
|
|
73
74
|
this._appId = triggerOutput.appId as string
|
|
@@ -240,7 +241,9 @@ class Orchestrator {
|
|
|
240
241
|
let loopStepNumber: any = undefined
|
|
241
242
|
let loopSteps: LoopStep[] | undefined = []
|
|
242
243
|
let metadata
|
|
244
|
+
let timeoutFlag = false
|
|
243
245
|
let wasLoopStep = false
|
|
246
|
+
let timeout = this._job.data.event.timeout
|
|
244
247
|
// check if this is a recurring automation,
|
|
245
248
|
if (isProdAppID(this._appId) && isRecurring(automation)) {
|
|
246
249
|
metadata = await this.getMetadata()
|
|
@@ -251,6 +254,16 @@ class Orchestrator {
|
|
|
251
254
|
}
|
|
252
255
|
|
|
253
256
|
for (let step of automation.definition.steps) {
|
|
257
|
+
if (timeoutFlag) {
|
|
258
|
+
break
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (timeout) {
|
|
262
|
+
setTimeout(() => {
|
|
263
|
+
timeoutFlag = true
|
|
264
|
+
}, timeout || 12000)
|
|
265
|
+
}
|
|
266
|
+
|
|
254
267
|
stepCount++
|
|
255
268
|
let input: any,
|
|
256
269
|
iterations = 1,
|
|
@@ -495,6 +508,32 @@ export function execute(job: Job, callback: WorkerCallback) {
|
|
|
495
508
|
})
|
|
496
509
|
}
|
|
497
510
|
|
|
511
|
+
export function executeSynchronously(job: Job) {
|
|
512
|
+
const appId = job.data.event.appId
|
|
513
|
+
if (!appId) {
|
|
514
|
+
throw new Error("Unable to execute, event doesn't contain app ID.")
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
const timeoutPromise = new Promise((resolve, reject) => {
|
|
518
|
+
setTimeout(() => {
|
|
519
|
+
reject(new Error("Timeout exceeded"))
|
|
520
|
+
}, job.data.event.timeout || 12000)
|
|
521
|
+
})
|
|
522
|
+
|
|
523
|
+
return context.doInAppContext(appId, async () => {
|
|
524
|
+
const envVars = await sdkUtils.getEnvironmentVariables()
|
|
525
|
+
// put into automation thread for whole context
|
|
526
|
+
return context.doInEnvironmentContext(envVars, async () => {
|
|
527
|
+
const automationOrchestrator = new Orchestrator(job)
|
|
528
|
+
const response = await Promise.race([
|
|
529
|
+
automationOrchestrator.execute(),
|
|
530
|
+
timeoutPromise,
|
|
531
|
+
])
|
|
532
|
+
return response
|
|
533
|
+
})
|
|
534
|
+
})
|
|
535
|
+
}
|
|
536
|
+
|
|
498
537
|
export const removeStalled = async (job: Job) => {
|
|
499
538
|
const appId = job.data.event.appId
|
|
500
539
|
if (!appId) {
|