2022-11-25 20:57:07 +01:00
|
|
|
import * as triggers from "../../automations/triggers"
|
2024-07-23 12:07:05 +02:00
|
|
|
import { sdk as coreSdk } from "@budibase/shared-core"
|
2024-07-17 13:32:45 +02:00
|
|
|
import { DocumentType } from "../../db/utils"
|
2024-07-17 13:26:40 +02:00
|
|
|
import { updateTestHistory, removeDeprecated } from "../../automations/utils"
|
2022-11-22 17:52:25 +01:00
|
|
|
import { setTestFlag, clearTestFlag } from "../../utilities/redis"
|
2023-11-20 16:19:31 +01:00
|
|
|
import { context, cache, events, db as dbCore } from "@budibase/backend-core"
|
2023-05-26 17:06:16 +02:00
|
|
|
import { automations, features } from "@budibase/pro"
|
2023-05-09 13:10:20 +02:00
|
|
|
import {
|
2023-07-18 11:41:51 +02:00
|
|
|
App,
|
2023-05-09 13:10:20 +02:00
|
|
|
Automation,
|
|
|
|
AutomationActionStepId,
|
|
|
|
AutomationResults,
|
2024-02-14 12:44:07 +01:00
|
|
|
UserCtx,
|
2024-02-28 17:35:15 +01:00
|
|
|
DeleteAutomationResponse,
|
2024-07-19 13:35:50 +02:00
|
|
|
FetchAutomationResponse,
|
2023-05-09 13:10:20 +02:00
|
|
|
} from "@budibase/types"
|
2023-04-11 00:48:54 +02:00
|
|
|
import { getActionDefinitions as actionDefs } from "../../automations/actions"
|
2023-05-16 17:05:37 +02:00
|
|
|
import sdk from "../../sdk"
|
2023-07-10 10:30:15 +02:00
|
|
|
import { builderSocket } from "../../websockets"
|
2024-02-14 18:15:42 +01:00
|
|
|
import env from "../../environment"
|
2021-05-18 17:37:54 +02:00
|
|
|
|
2023-04-11 00:48:54 +02:00
|
|
|
async function getActionDefinitions() {
|
|
|
|
return removeDeprecated(await actionDefs())
|
|
|
|
}
|
|
|
|
|
|
|
|
function getTriggerDefinitions() {
|
|
|
|
return removeDeprecated(triggers.TRIGGER_DEFINITIONS)
|
|
|
|
}
|
2021-12-14 18:59:02 +01:00
|
|
|
|
2020-09-10 12:06:13 +02:00
|
|
|
/*************************
|
|
|
|
* *
|
|
|
|
* BUILDER FUNCTIONS *
|
|
|
|
* *
|
|
|
|
*************************/
|
2020-05-20 18:02:46 +02:00
|
|
|
|
2024-02-28 12:46:58 +01:00
|
|
|
export async function create(
|
|
|
|
ctx: UserCtx<Automation, { message: string; automation: Automation }>
|
|
|
|
) {
|
2020-09-21 14:49:34 +02:00
|
|
|
let automation = ctx.request.body
|
2021-03-29 18:32:05 +02:00
|
|
|
automation.appId = ctx.appId
|
2020-05-20 18:02:46 +02:00
|
|
|
|
2021-03-10 12:47:39 +01:00
|
|
|
// call through to update if already exists
|
|
|
|
if (automation._id && automation._rev) {
|
2023-02-23 14:55:18 +01:00
|
|
|
await update(ctx)
|
|
|
|
return
|
2021-03-10 12:47:39 +01:00
|
|
|
}
|
|
|
|
|
2024-07-17 13:26:40 +02:00
|
|
|
const createdAutomation = await sdk.automations.create(automation)
|
2020-05-20 18:02:46 +02:00
|
|
|
|
|
|
|
ctx.status = 200
|
|
|
|
ctx.body = {
|
2020-09-21 14:49:34 +02:00
|
|
|
message: "Automation created successfully",
|
2024-07-17 13:26:40 +02:00
|
|
|
automation: createdAutomation,
|
2020-05-28 21:20:03 +02:00
|
|
|
}
|
2023-07-10 10:30:15 +02:00
|
|
|
builderSocket?.emitAutomationUpdate(ctx, automation)
|
2020-05-20 18:02:46 +02:00
|
|
|
}
|
|
|
|
|
2024-02-14 12:44:07 +01:00
|
|
|
export async function update(ctx: UserCtx) {
|
2020-09-21 14:49:34 +02:00
|
|
|
let automation = ctx.request.body
|
2021-03-29 18:32:05 +02:00
|
|
|
automation.appId = ctx.appId
|
2023-02-23 14:55:18 +01:00
|
|
|
|
|
|
|
// Call through to create if it doesn't exist
|
|
|
|
if (!automation._id || !automation._rev) {
|
|
|
|
await create(ctx)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-07-17 13:26:40 +02:00
|
|
|
const updatedAutomation = await sdk.automations.update(automation)
|
2022-04-06 14:54:57 +02:00
|
|
|
|
2020-05-22 17:32:23 +02:00
|
|
|
ctx.status = 200
|
|
|
|
ctx.body = {
|
2020-09-21 14:49:34 +02:00
|
|
|
message: `Automation ${automation._id} updated successfully.`,
|
2024-07-17 13:26:40 +02:00
|
|
|
automation: updatedAutomation,
|
2020-05-22 17:32:23 +02:00
|
|
|
}
|
2023-07-10 10:30:15 +02:00
|
|
|
builderSocket?.emitAutomationUpdate(ctx, automation)
|
2020-05-20 18:02:46 +02:00
|
|
|
}
|
|
|
|
|
2024-07-19 13:35:50 +02:00
|
|
|
export async function fetch(ctx: UserCtx<void, FetchAutomationResponse>) {
|
2024-07-22 14:39:26 +02:00
|
|
|
const query: { enrich?: string } = ctx.request.query || {}
|
|
|
|
const enrich = query.enrich === "true"
|
2024-07-19 12:24:45 +02:00
|
|
|
|
|
|
|
const automations = await sdk.automations.fetch()
|
2024-07-19 13:35:50 +02:00
|
|
|
ctx.body = { automations }
|
2024-07-19 12:24:45 +02:00
|
|
|
if (enrich) {
|
2024-07-22 10:51:18 +02:00
|
|
|
ctx.body.builderData = await sdk.automations.utils.getBuilderData(
|
|
|
|
automations
|
|
|
|
)
|
2024-07-19 12:24:45 +02:00
|
|
|
}
|
2020-05-20 18:02:46 +02:00
|
|
|
}
|
|
|
|
|
2024-02-14 12:44:07 +01:00
|
|
|
export async function find(ctx: UserCtx) {
|
2024-07-17 13:32:45 +02:00
|
|
|
ctx.body = await sdk.automations.get(ctx.params.id)
|
2020-05-20 18:02:46 +02:00
|
|
|
}
|
|
|
|
|
2024-02-28 17:35:15 +01:00
|
|
|
export async function destroy(ctx: UserCtx<void, DeleteAutomationResponse>) {
|
2021-09-13 19:03:09 +02:00
|
|
|
const automationId = ctx.params.id
|
2024-07-17 13:26:40 +02:00
|
|
|
|
2024-07-23 10:28:57 +02:00
|
|
|
const automation = await sdk.automations.get(ctx.params.id)
|
2024-07-23 12:07:05 +02:00
|
|
|
if (coreSdk.automations.isRowAction(automation)) {
|
2024-07-23 11:59:14 +02:00
|
|
|
ctx.throw("Row actions cannot be deleted", 400)
|
2024-07-23 10:28:57 +02:00
|
|
|
}
|
|
|
|
|
2024-07-17 13:26:40 +02:00
|
|
|
ctx.body = await sdk.automations.remove(automationId, ctx.params.rev)
|
2023-07-10 10:30:15 +02:00
|
|
|
builderSocket?.emitAutomationDeletion(ctx, automationId)
|
2020-09-10 12:06:13 +02:00
|
|
|
}
|
|
|
|
|
2024-02-14 12:44:07 +01:00
|
|
|
export async function logSearch(ctx: UserCtx) {
|
2022-07-04 16:44:47 +02:00
|
|
|
ctx.body = await automations.logs.logSearch(ctx.request.body)
|
2022-06-01 17:01:06 +02:00
|
|
|
}
|
|
|
|
|
2024-02-14 12:44:07 +01:00
|
|
|
export async function clearLogError(ctx: UserCtx) {
|
2022-06-22 21:23:18 +02:00
|
|
|
const { automationId, appId } = ctx.request.body
|
2022-11-22 17:52:25 +01:00
|
|
|
await context.doInAppContext(appId, async () => {
|
|
|
|
const db = context.getProdAppDB()
|
2023-07-18 11:41:51 +02:00
|
|
|
const metadata = await db.get<App>(DocumentType.APP_METADATA)
|
2022-06-22 21:23:18 +02:00
|
|
|
if (!automationId) {
|
|
|
|
delete metadata.automationErrors
|
|
|
|
} else if (
|
|
|
|
metadata.automationErrors &&
|
|
|
|
metadata.automationErrors[automationId]
|
|
|
|
) {
|
|
|
|
delete metadata.automationErrors[automationId]
|
|
|
|
}
|
|
|
|
await db.put(metadata)
|
2022-11-22 17:52:25 +01:00
|
|
|
await cache.app.invalidateAppMetadata(metadata.appId, metadata)
|
2022-06-22 21:23:18 +02:00
|
|
|
ctx.body = { message: `Error logs cleared.` }
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-02-14 12:44:07 +01:00
|
|
|
export async function getActionList(ctx: UserCtx) {
|
2023-04-11 00:48:54 +02:00
|
|
|
ctx.body = await getActionDefinitions()
|
2020-05-26 22:34:01 +02:00
|
|
|
}
|
|
|
|
|
2024-02-14 12:44:07 +01:00
|
|
|
export async function getTriggerList(ctx: UserCtx) {
|
2023-04-11 00:48:54 +02:00
|
|
|
ctx.body = getTriggerDefinitions()
|
2020-09-10 12:06:13 +02:00
|
|
|
}
|
|
|
|
|
2024-02-14 12:44:07 +01:00
|
|
|
export async function getDefinitionList(ctx: UserCtx) {
|
2020-09-14 16:34:09 +02:00
|
|
|
ctx.body = {
|
2023-04-11 00:48:54 +02:00
|
|
|
trigger: getTriggerDefinitions(),
|
|
|
|
action: await getActionDefinitions(),
|
2020-09-14 16:34:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-10 12:06:13 +02:00
|
|
|
/*********************
|
|
|
|
* *
|
|
|
|
* API FUNCTIONS *
|
|
|
|
* *
|
|
|
|
*********************/
|
|
|
|
|
2024-02-14 12:44:07 +01:00
|
|
|
export async function trigger(ctx: UserCtx) {
|
2022-11-22 17:52:25 +01:00
|
|
|
const db = context.getAppDB()
|
2023-07-18 11:41:51 +02:00
|
|
|
let automation = await db.get<Automation>(ctx.params.id)
|
2021-09-07 14:58:53 +02:00
|
|
|
|
2023-05-16 10:29:40 +02:00
|
|
|
let hasCollectStep = sdk.automations.utils.checkForCollectStep(automation)
|
2023-05-26 17:06:16 +02:00
|
|
|
if (hasCollectStep && (await features.isSyncAutomationsEnabled())) {
|
2024-05-20 16:13:08 +02:00
|
|
|
try {
|
|
|
|
const response: AutomationResults = await triggers.externalTrigger(
|
|
|
|
automation,
|
|
|
|
{
|
|
|
|
fields: ctx.request.body.fields,
|
|
|
|
timeout:
|
|
|
|
ctx.request.body.timeout * 1000 || env.AUTOMATION_THREAD_TIMEOUT,
|
|
|
|
},
|
|
|
|
{ getResponses: true }
|
|
|
|
)
|
|
|
|
|
|
|
|
let collectedValue = response.steps.find(
|
|
|
|
step => step.stepId === AutomationActionStepId.COLLECT
|
|
|
|
)
|
|
|
|
ctx.body = collectedValue?.outputs
|
|
|
|
} catch (err: any) {
|
|
|
|
if (err.message) {
|
|
|
|
ctx.throw(400, err.message)
|
|
|
|
} else {
|
|
|
|
throw err
|
|
|
|
}
|
|
|
|
}
|
2023-05-12 16:56:24 +02:00
|
|
|
} else {
|
2023-05-19 16:14:01 +02:00
|
|
|
if (ctx.appId && !dbCore.isProdAppID(ctx.appId)) {
|
2023-05-19 16:12:08 +02:00
|
|
|
ctx.throw(400, "Only apps in production support this endpoint")
|
|
|
|
}
|
2023-05-12 16:56:24 +02:00
|
|
|
await triggers.externalTrigger(automation, {
|
|
|
|
...ctx.request.body,
|
|
|
|
appId: ctx.appId,
|
|
|
|
})
|
|
|
|
ctx.body = {
|
|
|
|
message: `Automation ${automation._id} has been triggered.`,
|
|
|
|
automation,
|
|
|
|
}
|
|
|
|
}
|
2023-05-09 13:10:20 +02:00
|
|
|
}
|
|
|
|
|
2022-11-22 17:52:25 +01:00
|
|
|
function prepareTestInput(input: any) {
|
2021-09-17 18:18:52 +02:00
|
|
|
// prepare the test parameters
|
|
|
|
if (input.id && input.row) {
|
|
|
|
input.row._id = input.id
|
|
|
|
}
|
|
|
|
if (input.revision && input.row) {
|
|
|
|
input.row._rev = input.revision
|
|
|
|
}
|
|
|
|
return input
|
|
|
|
}
|
|
|
|
|
2024-02-14 12:44:07 +01:00
|
|
|
export async function test(ctx: UserCtx) {
|
2022-11-22 17:52:25 +01:00
|
|
|
const db = context.getAppDB()
|
2023-07-18 11:41:51 +02:00
|
|
|
let automation = await db.get<Automation>(ctx.params.id)
|
|
|
|
await setTestFlag(automation._id!)
|
2021-09-17 18:18:52 +02:00
|
|
|
const testInput = prepareTestInput(ctx.request.body)
|
2021-09-08 20:29:28 +02:00
|
|
|
const response = await triggers.externalTrigger(
|
2021-09-07 20:06:20 +02:00
|
|
|
automation,
|
2021-09-08 15:08:22 +02:00
|
|
|
{
|
2021-09-17 18:18:52 +02:00
|
|
|
...testInput,
|
2022-01-28 01:05:39 +01:00
|
|
|
appId: ctx.appId,
|
2021-09-08 15:08:22 +02:00
|
|
|
},
|
|
|
|
{ getResponses: true }
|
|
|
|
)
|
2021-09-08 20:29:28 +02:00
|
|
|
// save a test history run
|
2021-09-10 14:52:41 +02:00
|
|
|
await updateTestHistory(ctx.appId, automation, {
|
|
|
|
...ctx.request.body,
|
2021-09-14 17:54:42 +02:00
|
|
|
occurredAt: new Date().getTime(),
|
2021-09-10 14:52:41 +02:00
|
|
|
})
|
2023-07-18 11:41:51 +02:00
|
|
|
await clearTestFlag(automation._id!)
|
2021-09-08 20:29:28 +02:00
|
|
|
ctx.body = response
|
2022-05-31 22:04:41 +02:00
|
|
|
await events.automation.tested(automation)
|
2021-09-07 14:59:58 +02:00
|
|
|
}
|