Merge branch 'master' into fix/import-column-issues
This commit is contained in:
commit
3128501083
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||||
"version": "2.29.26",
|
"version": "2.29.27",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*",
|
"packages/*",
|
||||||
|
|
|
@ -9,7 +9,10 @@ import { Constants } from "@budibase/frontend-core"
|
||||||
|
|
||||||
const { TypeIconMap } = Constants
|
const { TypeIconMap } = Constants
|
||||||
|
|
||||||
export { RelationshipType } from "@budibase/types"
|
export {
|
||||||
|
RelationshipType,
|
||||||
|
RowExportFormat as ROW_EXPORT_FORMATS,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const AUTO_COLUMN_SUB_TYPES = AutoFieldSubType
|
export const AUTO_COLUMN_SUB_TYPES = AutoFieldSubType
|
||||||
|
|
||||||
|
@ -307,9 +310,3 @@ export const DatasourceTypes = {
|
||||||
GRAPH: "Graph",
|
GRAPH: "Graph",
|
||||||
API: "API",
|
API: "API",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ROW_EXPORT_FORMATS = {
|
|
||||||
CSV: "csv",
|
|
||||||
JSON: "json",
|
|
||||||
JSON_WITH_SCHEMA: "jsonWithSchema",
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import { Row, TableSchema } from "@budibase/types"
|
import { Row, RowExportFormat, TableSchema } from "@budibase/types"
|
||||||
|
|
||||||
|
export { RowExportFormat as Format } from "@budibase/types"
|
||||||
|
|
||||||
function getHeaders(
|
function getHeaders(
|
||||||
headers: string[],
|
headers: string[],
|
||||||
|
@ -46,14 +48,8 @@ export function jsonWithSchema(schema: TableSchema, rows: Row[]) {
|
||||||
return JSON.stringify({ schema: newSchema, rows }, undefined, 2)
|
return JSON.stringify({ schema: newSchema, rows }, undefined, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Format {
|
export function isFormat(format: any): format is RowExportFormat {
|
||||||
CSV = "csv",
|
return Object.values(RowExportFormat).includes(format as RowExportFormat)
|
||||||
JSON = "json",
|
|
||||||
JSON_WITH_SCHEMA = "jsonWithSchema",
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isFormat(format: any): format is Format {
|
|
||||||
return Object.values(Format).includes(format as Format)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseCsvExport<T>(value: string) {
|
export function parseCsvExport<T>(value: string) {
|
||||||
|
|
|
@ -20,17 +20,21 @@ import * as triggerAutomationRun from "./steps/triggerAutomationRun"
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
import {
|
import {
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
PluginType,
|
PluginType,
|
||||||
AutomationStep,
|
AutomationStep,
|
||||||
|
AutomationActionStepId,
|
||||||
|
ActionImplementations,
|
||||||
|
Hosting,
|
||||||
|
ActionImplementation,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import sdk from "../sdk"
|
import sdk from "../sdk"
|
||||||
import { getAutomationPlugin } from "../utilities/fileSystem"
|
import { getAutomationPlugin } from "../utilities/fileSystem"
|
||||||
|
|
||||||
const ACTION_IMPLS: Record<
|
type ActionImplType = ActionImplementations<
|
||||||
string,
|
typeof env.SELF_HOSTED extends "true" ? Hosting.SELF : Hosting.CLOUD
|
||||||
(opts: AutomationStepInput) => Promise<any>
|
>
|
||||||
> = {
|
|
||||||
|
const ACTION_IMPLS: ActionImplType = {
|
||||||
SEND_EMAIL_SMTP: sendSmtpEmail.run,
|
SEND_EMAIL_SMTP: sendSmtpEmail.run,
|
||||||
CREATE_ROW: createRow.run,
|
CREATE_ROW: createRow.run,
|
||||||
UPDATE_ROW: updateRow.run,
|
UPDATE_ROW: updateRow.run,
|
||||||
|
@ -51,6 +55,7 @@ const ACTION_IMPLS: Record<
|
||||||
integromat: make.run,
|
integromat: make.run,
|
||||||
n8n: n8n.run,
|
n8n: n8n.run,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BUILTIN_ACTION_DEFINITIONS: Record<string, AutomationStepSchema> =
|
export const BUILTIN_ACTION_DEFINITIONS: Record<string, AutomationStepSchema> =
|
||||||
{
|
{
|
||||||
SEND_EMAIL_SMTP: sendSmtpEmail.definition,
|
SEND_EMAIL_SMTP: sendSmtpEmail.definition,
|
||||||
|
@ -86,7 +91,7 @@ if (env.SELF_HOSTED) {
|
||||||
ACTION_IMPLS["EXECUTE_BASH"] = bash.run
|
ACTION_IMPLS["EXECUTE_BASH"] = bash.run
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
BUILTIN_ACTION_DEFINITIONS["EXECUTE_BASH"] = bash.definition
|
BUILTIN_ACTION_DEFINITIONS["EXECUTE_BASH"] = bash.definition
|
||||||
|
// @ts-ignore
|
||||||
ACTION_IMPLS.OPENAI = openai.run
|
ACTION_IMPLS.OPENAI = openai.run
|
||||||
BUILTIN_ACTION_DEFINITIONS.OPENAI = openai.definition
|
BUILTIN_ACTION_DEFINITIONS.OPENAI = openai.definition
|
||||||
}
|
}
|
||||||
|
@ -107,10 +112,13 @@ export async function getActionDefinitions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
export async function getAction(stepId: string) {
|
export async function getAction(
|
||||||
if (ACTION_IMPLS[stepId] != null) {
|
stepId: AutomationActionStepId
|
||||||
return ACTION_IMPLS[stepId]
|
): Promise<ActionImplementation<any, any> | undefined> {
|
||||||
|
if (ACTION_IMPLS[stepId as keyof ActionImplType] != null) {
|
||||||
|
return ACTION_IMPLS[stepId as keyof ActionImplType]
|
||||||
}
|
}
|
||||||
|
|
||||||
// must be a plugin
|
// must be a plugin
|
||||||
if (env.SELF_HOSTED) {
|
if (env.SELF_HOSTED) {
|
||||||
const plugins = await sdk.plugins.fetch(PluginType.AUTOMATION)
|
const plugins = await sdk.plugins.fetch(PluginType.AUTOMATION)
|
||||||
|
|
|
@ -4,8 +4,13 @@ import {
|
||||||
encodeJSBinding,
|
encodeJSBinding,
|
||||||
} from "@budibase/string-templates"
|
} from "@budibase/string-templates"
|
||||||
import sdk from "../sdk"
|
import sdk from "../sdk"
|
||||||
import { AutomationAttachment, FieldType, Row } from "@budibase/types"
|
import {
|
||||||
import { LoopInput, LoopStepType } from "../definitions/automations"
|
AutomationAttachment,
|
||||||
|
FieldType,
|
||||||
|
Row,
|
||||||
|
LoopStepType,
|
||||||
|
} from "@budibase/types"
|
||||||
|
import { LoopInput } from "../definitions/automations"
|
||||||
import { objectStore, context } from "@budibase/backend-core"
|
import { objectStore, context } from "@budibase/backend-core"
|
||||||
import * as uuid from "uuid"
|
import * as uuid from "uuid"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
|
|
@ -7,9 +7,10 @@ import {
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
|
BashStepInputs,
|
||||||
|
BashStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -51,7 +52,13 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs, context }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
context,
|
||||||
|
}: {
|
||||||
|
inputs: BashStepInputs
|
||||||
|
context: object
|
||||||
|
}): Promise<BashStepOutputs> {
|
||||||
if (inputs.code == null) {
|
if (inputs.code == null) {
|
||||||
return {
|
return {
|
||||||
stdout: "Budibase bash automation failed: Invalid inputs",
|
stdout: "Budibase bash automation failed: Invalid inputs",
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
|
CollectStepInputs,
|
||||||
|
CollectStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -43,7 +44,11 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: CollectStepInputs
|
||||||
|
}): Promise<CollectStepOutputs> {
|
||||||
if (!inputs.collection) {
|
if (!inputs.collection) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|
|
@ -10,10 +10,12 @@ import {
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
|
CreateRowStepInputs,
|
||||||
|
CreateRowStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
import { EventEmitter } from "events"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
name: "Create Row",
|
name: "Create Row",
|
||||||
|
@ -74,7 +76,15 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs, appId, emitter }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
appId,
|
||||||
|
emitter,
|
||||||
|
}: {
|
||||||
|
inputs: CreateRowStepInputs
|
||||||
|
appId: string
|
||||||
|
emitter: EventEmitter
|
||||||
|
}): Promise<CreateRowStepOutputs> {
|
||||||
if (inputs.row == null || inputs.row.tableId == null) {
|
if (inputs.row == null || inputs.row.tableId == null) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -93,7 +103,7 @@ export async function run({ inputs, appId, emitter }: AutomationStepInput) {
|
||||||
try {
|
try {
|
||||||
inputs.row = await cleanUpRow(inputs.row.tableId, inputs.row)
|
inputs.row = await cleanUpRow(inputs.row.tableId, inputs.row)
|
||||||
inputs.row = await sendAutomationAttachmentsToStorage(
|
inputs.row = await sendAutomationAttachmentsToStorage(
|
||||||
inputs.row.tableId,
|
inputs.row.tableId!,
|
||||||
inputs.row
|
inputs.row
|
||||||
)
|
)
|
||||||
await save(ctx)
|
await save(ctx)
|
||||||
|
|
|
@ -2,9 +2,10 @@ import { wait } from "../../utilities"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
|
DelayStepInputs,
|
||||||
|
DelayStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -39,7 +40,11 @@ export const definition: AutomationStepSchema = {
|
||||||
type: AutomationStepType.LOGIC,
|
type: AutomationStepType.LOGIC,
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: DelayStepInputs
|
||||||
|
}): Promise<DelayStepOutputs> {
|
||||||
await wait(inputs.time)
|
await wait(inputs.time)
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
|
import { EventEmitter } from "events"
|
||||||
import { destroy } from "../../api/controllers/row"
|
import { destroy } from "../../api/controllers/row"
|
||||||
import { buildCtx } from "./utils"
|
import { buildCtx } from "./utils"
|
||||||
import { getError } from "../automationUtils"
|
import { getError } from "../automationUtils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
|
DeleteRowStepInputs,
|
||||||
|
DeleteRowStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -59,7 +61,15 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs, appId, emitter }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
appId,
|
||||||
|
emitter,
|
||||||
|
}: {
|
||||||
|
inputs: DeleteRowStepInputs
|
||||||
|
appId: string
|
||||||
|
emitter: EventEmitter
|
||||||
|
}): Promise<DeleteRowStepOutputs> {
|
||||||
if (inputs.id == null) {
|
if (inputs.id == null) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|
|
@ -3,10 +3,11 @@ import { getFetchResponse } from "./utils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
|
ExternalAppStepOutputs,
|
||||||
|
DiscordStepInputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
const DEFAULT_USERNAME = "Budibase Automate"
|
const DEFAULT_USERNAME = "Budibase Automate"
|
||||||
|
@ -65,7 +66,11 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: DiscordStepInputs
|
||||||
|
}): Promise<ExternalAppStepOutputs> {
|
||||||
let { url, username, avatar_url, content } = inputs
|
let { url, username, avatar_url, content } = inputs
|
||||||
if (!username) {
|
if (!username) {
|
||||||
username = DEFAULT_USERNAME
|
username = DEFAULT_USERNAME
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { EventEmitter } from "events"
|
||||||
import * as queryController from "../../api/controllers/query"
|
import * as queryController from "../../api/controllers/query"
|
||||||
import { buildCtx } from "./utils"
|
import { buildCtx } from "./utils"
|
||||||
import * as automationUtils from "../automationUtils"
|
import * as automationUtils from "../automationUtils"
|
||||||
|
@ -6,9 +7,10 @@ import {
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
|
ExecuteQueryStepInputs,
|
||||||
|
ExecuteQueryStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -62,7 +64,15 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs, appId, emitter }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
appId,
|
||||||
|
emitter,
|
||||||
|
}: {
|
||||||
|
inputs: ExecuteQueryStepInputs
|
||||||
|
appId: string
|
||||||
|
emitter: EventEmitter
|
||||||
|
}): Promise<ExecuteQueryStepOutputs> {
|
||||||
if (inputs.query == null) {
|
if (inputs.query == null) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|
|
@ -6,10 +6,12 @@ import {
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
|
ExecuteScriptStepInputs,
|
||||||
|
ExecuteScriptStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
import { EventEmitter } from "events"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
name: "JS Scripting",
|
name: "JS Scripting",
|
||||||
|
@ -55,7 +57,12 @@ export async function run({
|
||||||
appId,
|
appId,
|
||||||
context,
|
context,
|
||||||
emitter,
|
emitter,
|
||||||
}: AutomationStepInput) {
|
}: {
|
||||||
|
inputs: ExecuteScriptStepInputs
|
||||||
|
appId: string
|
||||||
|
context: object
|
||||||
|
emitter: EventEmitter
|
||||||
|
}): Promise<ExecuteScriptStepOutputs> {
|
||||||
if (inputs.code == null) {
|
if (inputs.code == null) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
|
FilterStepInputs,
|
||||||
|
FilterStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const FilterConditions = {
|
export const FilterConditions = {
|
||||||
|
@ -69,7 +70,11 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: FilterStepInputs
|
||||||
|
}): Promise<FilterStepOutputs> {
|
||||||
try {
|
try {
|
||||||
let { field, condition, value } = inputs
|
let { field, condition, value } = inputs
|
||||||
// coerce types so that we can use them
|
// coerce types so that we can use them
|
||||||
|
|
|
@ -3,10 +3,11 @@ import { getFetchResponse } from "./utils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
|
ExternalAppStepOutputs,
|
||||||
|
MakeIntegrationInputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -57,7 +58,11 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: MakeIntegrationInputs
|
||||||
|
}): Promise<ExternalAppStepOutputs> {
|
||||||
const { url, body } = inputs
|
const { url, body } = inputs
|
||||||
|
|
||||||
let payload = {}
|
let payload = {}
|
||||||
|
|
|
@ -3,11 +3,12 @@ import { getFetchResponse } from "./utils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
HttpMethod,
|
HttpMethod,
|
||||||
|
ExternalAppStepOutputs,
|
||||||
|
n8nStepInputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -67,7 +68,11 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: n8nStepInputs
|
||||||
|
}): Promise<ExternalAppStepOutputs> {
|
||||||
const { url, body, method, authorization } = inputs
|
const { url, body, method, authorization } = inputs
|
||||||
|
|
||||||
let payload = {}
|
let payload = {}
|
||||||
|
|
|
@ -3,9 +3,10 @@ import { OpenAI } from "openai"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
|
OpenAIStepInputs,
|
||||||
|
OpenAIStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { env } from "@budibase/backend-core"
|
import { env } from "@budibase/backend-core"
|
||||||
import * as automationUtils from "../automationUtils"
|
import * as automationUtils from "../automationUtils"
|
||||||
|
@ -59,7 +60,11 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: OpenAIStepInputs
|
||||||
|
}): Promise<OpenAIStepOutputs> {
|
||||||
if (!env.OPENAI_API_KEY) {
|
if (!env.OPENAI_API_KEY) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|
|
@ -6,9 +6,10 @@ import {
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
|
ExternalAppStepOutputs,
|
||||||
|
OutgoingWebhookStepInputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
enum RequestType {
|
enum RequestType {
|
||||||
|
@ -88,7 +89,13 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: OutgoingWebhookStepInputs
|
||||||
|
}): Promise<
|
||||||
|
Omit<ExternalAppStepOutputs, "httpStatus"> | ExternalAppStepOutputs
|
||||||
|
> {
|
||||||
let { requestMethod, url, requestBody, headers } = inputs
|
let { requestMethod, url, requestBody, headers } = inputs
|
||||||
if (!url.startsWith("http")) {
|
if (!url.startsWith("http")) {
|
||||||
url = `http://${url}`
|
url = `http://${url}`
|
||||||
|
|
|
@ -8,13 +8,14 @@ import {
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
EmptyFilterOption,
|
EmptyFilterOption,
|
||||||
SearchFilters,
|
SearchFilters,
|
||||||
Table,
|
Table,
|
||||||
SortOrder,
|
SortOrder,
|
||||||
|
QueryRowsStepInputs,
|
||||||
|
QueryRowsStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { db as dbCore } from "@budibase/backend-core"
|
import { db as dbCore } from "@budibase/backend-core"
|
||||||
|
|
||||||
|
@ -133,7 +134,13 @@ function hasNullFilters(filters: any[]) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs, appId }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
appId,
|
||||||
|
}: {
|
||||||
|
inputs: QueryRowsStepInputs
|
||||||
|
appId: string
|
||||||
|
}): Promise<QueryRowsStepOutputs> {
|
||||||
const { tableId, filters, sortColumn, sortOrder, limit } = inputs
|
const { tableId, filters, sortColumn, sortOrder, limit } = inputs
|
||||||
if (!tableId) {
|
if (!tableId) {
|
||||||
return {
|
return {
|
||||||
|
@ -145,7 +152,7 @@ export async function run({ inputs, appId }: AutomationStepInput) {
|
||||||
}
|
}
|
||||||
const table = await getTable(appId, tableId)
|
const table = await getTable(appId, tableId)
|
||||||
let sortType = FieldType.STRING
|
let sortType = FieldType.STRING
|
||||||
if (table && table.schema && table.schema[sortColumn] && sortColumn) {
|
if (sortColumn && table && table.schema && table.schema[sortColumn]) {
|
||||||
const fieldType = table.schema[sortColumn].type
|
const fieldType = table.schema[sortColumn].type
|
||||||
sortType =
|
sortType =
|
||||||
fieldType === FieldType.NUMBER ? FieldType.NUMBER : FieldType.STRING
|
fieldType === FieldType.NUMBER ? FieldType.NUMBER : FieldType.STRING
|
||||||
|
|
|
@ -3,11 +3,12 @@ import * as automationUtils from "../automationUtils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
|
SmtpEmailStepInputs,
|
||||||
|
BaseAutomationOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -97,7 +98,11 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: SmtpEmailStepInputs
|
||||||
|
}): Promise<BaseAutomationOutputs> {
|
||||||
let {
|
let {
|
||||||
to,
|
to,
|
||||||
from,
|
from,
|
||||||
|
@ -116,8 +121,8 @@ export async function run({ inputs }: AutomationStepInput) {
|
||||||
if (!contents) {
|
if (!contents) {
|
||||||
contents = "<h1>No content</h1>"
|
contents = "<h1>No content</h1>"
|
||||||
}
|
}
|
||||||
to = to || undefined
|
|
||||||
|
|
||||||
|
try {
|
||||||
if (attachments) {
|
if (attachments) {
|
||||||
if (Array.isArray(attachments)) {
|
if (Array.isArray(attachments)) {
|
||||||
attachments.forEach(item => automationUtils.guardAttachment(item))
|
attachments.forEach(item => automationUtils.guardAttachment(item))
|
||||||
|
@ -126,7 +131,6 @@ export async function run({ inputs }: AutomationStepInput) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
let response = await sendSmtpEmail({
|
let response = await sendSmtpEmail({
|
||||||
to,
|
to,
|
||||||
from,
|
from,
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
|
ServerLogStepInputs,
|
||||||
|
ServerLogStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,7 +54,13 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs, appId }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
appId,
|
||||||
|
}: {
|
||||||
|
inputs: ServerLogStepInputs
|
||||||
|
appId: string
|
||||||
|
}): Promise<ServerLogStepOutputs> {
|
||||||
const message = `App ${appId} - ${inputs.text}`
|
const message = `App ${appId} - ${inputs.text}`
|
||||||
console.log(message)
|
console.log(message)
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -3,10 +3,11 @@ import { getFetchResponse } from "./utils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
|
ExternalAppStepOutputs,
|
||||||
|
SlackStepInputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -54,7 +55,11 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: SlackStepInputs
|
||||||
|
}): Promise<ExternalAppStepOutputs> {
|
||||||
let { url, text } = inputs
|
let { url, text } = inputs
|
||||||
if (!url?.trim()?.length) {
|
if (!url?.trim()?.length) {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationResults,
|
AutomationResults,
|
||||||
Automation,
|
Automation,
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
|
TriggerAutomationStepInputs,
|
||||||
|
TriggerAutomationStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import * as triggers from "../triggers"
|
import * as triggers from "../triggers"
|
||||||
import { context } from "@budibase/backend-core"
|
import { context } from "@budibase/backend-core"
|
||||||
|
@ -61,7 +62,11 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: TriggerAutomationStepInputs
|
||||||
|
}): Promise<TriggerAutomationStepOutputs> {
|
||||||
const { automationId, ...fieldParams } = inputs.automation
|
const { automationId, ...fieldParams } = inputs.automation
|
||||||
|
|
||||||
if (await features.isTriggerAutomationRunEnabled()) {
|
if (await features.isTriggerAutomationRunEnabled()) {
|
||||||
|
@ -88,5 +93,9 @@ export async function run({ inputs }: AutomationStepInput) {
|
||||||
value: response.steps,
|
value: response.steps,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { EventEmitter } from "events"
|
||||||
import * as rowController from "../../api/controllers/row"
|
import * as rowController from "../../api/controllers/row"
|
||||||
import * as automationUtils from "../automationUtils"
|
import * as automationUtils from "../automationUtils"
|
||||||
import { buildCtx } from "./utils"
|
import { buildCtx } from "./utils"
|
||||||
|
@ -6,9 +7,10 @@ import {
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
|
UpdateRowStepInputs,
|
||||||
|
UpdateRowStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -70,8 +72,15 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
export async function run({
|
||||||
export async function run({ inputs, appId, emitter }: AutomationStepInput) {
|
inputs,
|
||||||
|
appId,
|
||||||
|
emitter,
|
||||||
|
}: {
|
||||||
|
inputs: UpdateRowStepInputs
|
||||||
|
appId: string
|
||||||
|
emitter: EventEmitter
|
||||||
|
}): Promise<UpdateRowStepOutputs> {
|
||||||
if (inputs.rowId == null || inputs.row == null) {
|
if (inputs.rowId == null || inputs.row == null) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|
|
@ -3,10 +3,11 @@ import { getFetchResponse } from "./utils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationFeature,
|
AutomationFeature,
|
||||||
|
ZapierStepInputs,
|
||||||
|
ZapierStepOutputs,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -50,7 +51,11 @@ export const definition: AutomationStepSchema = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
}: {
|
||||||
|
inputs: ZapierStepInputs
|
||||||
|
}): Promise<ZapierStepOutputs> {
|
||||||
const { url, body } = inputs
|
const { url, body } = inputs
|
||||||
|
|
||||||
let payload = {}
|
let payload = {}
|
||||||
|
|
|
@ -3,9 +3,9 @@ import * as triggers from "../triggers"
|
||||||
import { loopAutomation } from "../../tests/utilities/structures"
|
import { loopAutomation } from "../../tests/utilities/structures"
|
||||||
import { context } from "@budibase/backend-core"
|
import { context } from "@budibase/backend-core"
|
||||||
import * as setup from "./utilities"
|
import * as setup from "./utilities"
|
||||||
import { Table } from "@budibase/types"
|
import { Table, LoopStepType } from "@budibase/types"
|
||||||
import * as loopUtils from "../loopUtils"
|
import * as loopUtils from "../loopUtils"
|
||||||
import { LoopInput, LoopStepType } from "../../definitions/automations"
|
import { LoopInput } from "../../definitions/automations"
|
||||||
|
|
||||||
describe("Attempt to run a basic loop automation", () => {
|
describe("Attempt to run a basic loop automation", () => {
|
||||||
let config = setup.getConfig(),
|
let config = setup.getConfig(),
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
import * as automation from "../../index"
|
||||||
|
import * as setup from "../utilities"
|
||||||
|
import { Table, LoopStepType } from "@budibase/types"
|
||||||
|
import { createAutomationBuilder } from "../utilities/AutomationBuilder"
|
||||||
|
|
||||||
|
describe("Automation Scenarios", () => {
|
||||||
|
let config = setup.getConfig(),
|
||||||
|
table: Table
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await automation.init()
|
||||||
|
await config.init()
|
||||||
|
table = await config.createTable()
|
||||||
|
await config.createRow()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(setup.afterAll)
|
||||||
|
|
||||||
|
describe("Loop automations", () => {
|
||||||
|
it("should run an automation with a trigger, loop, and create row step", async () => {
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: "Test Trigger with Loop and Create Row",
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.rowSaved(
|
||||||
|
{ tableId: table._id! },
|
||||||
|
{
|
||||||
|
row: {
|
||||||
|
name: "Trigger Row",
|
||||||
|
description: "This row triggers the automation",
|
||||||
|
},
|
||||||
|
id: "1234",
|
||||||
|
revision: "1",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.loop({
|
||||||
|
option: LoopStepType.ARRAY,
|
||||||
|
binding: [1, 2, 3],
|
||||||
|
})
|
||||||
|
.createRow({
|
||||||
|
row: {
|
||||||
|
name: "Item {{ loop.currentItem }}",
|
||||||
|
description: "Created from loop",
|
||||||
|
tableId: table._id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.run()
|
||||||
|
|
||||||
|
expect(results.trigger).toBeDefined()
|
||||||
|
expect(results.steps).toHaveLength(1)
|
||||||
|
|
||||||
|
expect(results.steps[0].outputs.iterations).toBe(3)
|
||||||
|
expect(results.steps[0].outputs.items).toHaveLength(3)
|
||||||
|
|
||||||
|
results.steps[0].outputs.items.forEach((output: any, index: number) => {
|
||||||
|
expect(output).toMatchObject({
|
||||||
|
success: true,
|
||||||
|
row: {
|
||||||
|
name: `Item ${index + 1}`,
|
||||||
|
description: "Created from loop",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("Row Automations", () => {
|
||||||
|
it("should trigger an automation which then creates a row", async () => {
|
||||||
|
const table = await config.createTable()
|
||||||
|
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: "Test Row Save and Create",
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.rowUpdated(
|
||||||
|
{ tableId: table._id! },
|
||||||
|
{
|
||||||
|
row: { name: "Test", description: "TEST" },
|
||||||
|
id: "1234",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.createRow({
|
||||||
|
row: {
|
||||||
|
name: "{{trigger.row.name}}",
|
||||||
|
description: "{{trigger.row.description}}",
|
||||||
|
tableId: table._id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.run()
|
||||||
|
|
||||||
|
expect(results.steps).toHaveLength(1)
|
||||||
|
|
||||||
|
expect(results.steps[0].outputs).toMatchObject({
|
||||||
|
success: true,
|
||||||
|
row: {
|
||||||
|
name: "Test",
|
||||||
|
description: "TEST",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should trigger an automation which querys the database", async () => {
|
||||||
|
const table = await config.createTable()
|
||||||
|
const row = {
|
||||||
|
name: "Test Row",
|
||||||
|
description: "original description",
|
||||||
|
tableId: table._id,
|
||||||
|
}
|
||||||
|
await config.createRow(row)
|
||||||
|
await config.createRow(row)
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: "Test Row Save and Create",
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.appAction({ fields: {} })
|
||||||
|
.queryRows({
|
||||||
|
tableId: table._id!,
|
||||||
|
})
|
||||||
|
.run()
|
||||||
|
|
||||||
|
expect(results.steps).toHaveLength(1)
|
||||||
|
expect(results.steps[0].outputs.rows).toHaveLength(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should trigger an automation which querys the database then deletes a row", async () => {
|
||||||
|
const table = await config.createTable()
|
||||||
|
const row = {
|
||||||
|
name: "DFN",
|
||||||
|
description: "original description",
|
||||||
|
tableId: table._id,
|
||||||
|
}
|
||||||
|
await config.createRow(row)
|
||||||
|
await config.createRow(row)
|
||||||
|
const builder = createAutomationBuilder({
|
||||||
|
name: "Test Row Save and Create",
|
||||||
|
})
|
||||||
|
|
||||||
|
const results = await builder
|
||||||
|
.appAction({ fields: {} })
|
||||||
|
.queryRows({
|
||||||
|
tableId: table._id!,
|
||||||
|
})
|
||||||
|
.deleteRow({
|
||||||
|
tableId: table._id!,
|
||||||
|
id: "{{ steps.1.rows.0._id }}",
|
||||||
|
})
|
||||||
|
.queryRows({
|
||||||
|
tableId: table._id!,
|
||||||
|
})
|
||||||
|
.run()
|
||||||
|
|
||||||
|
expect(results.steps).toHaveLength(3)
|
||||||
|
expect(results.steps[1].outputs.success).toBeTruthy()
|
||||||
|
expect(results.steps[2].outputs.rows).toHaveLength(1)
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,174 @@
|
||||||
|
import { v4 as uuidv4 } from "uuid"
|
||||||
|
import { testAutomation } from "../../../api/routes/tests/utilities/TestFunctions"
|
||||||
|
import {
|
||||||
|
RowCreatedTriggerInputs,
|
||||||
|
RowCreatedTriggerOutputs,
|
||||||
|
} from "../../triggerInfo/rowSaved"
|
||||||
|
import {
|
||||||
|
RowUpdatedTriggerInputs,
|
||||||
|
RowUpdatedTriggerOutputs,
|
||||||
|
} from "../../triggerInfo/rowUpdated"
|
||||||
|
import {} from "../../steps/createRow"
|
||||||
|
import { BUILTIN_ACTION_DEFINITIONS } from "../../actions"
|
||||||
|
import { TRIGGER_DEFINITIONS } from "../../triggers"
|
||||||
|
import {
|
||||||
|
RowDeletedTriggerInputs,
|
||||||
|
RowDeletedTriggerOutputs,
|
||||||
|
} from "../../triggerInfo/rowDeleted"
|
||||||
|
import {
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationTriggerSchema,
|
||||||
|
LoopStepInputs,
|
||||||
|
DeleteRowStepInputs,
|
||||||
|
UpdateRowStepInputs,
|
||||||
|
CreateRowStepInputs,
|
||||||
|
Automation,
|
||||||
|
AutomationTrigger,
|
||||||
|
AutomationResults,
|
||||||
|
SmtpEmailStepInputs,
|
||||||
|
ExecuteQueryStepInputs,
|
||||||
|
QueryRowsStepInputs,
|
||||||
|
} from "@budibase/types"
|
||||||
|
import {} from "../../steps/loop"
|
||||||
|
import TestConfiguration from "../../../tests/utilities/TestConfiguration"
|
||||||
|
import * as setup from "../utilities"
|
||||||
|
import {
|
||||||
|
AppActionTriggerInputs,
|
||||||
|
AppActionTriggerOutputs,
|
||||||
|
} from "../../triggerInfo/app"
|
||||||
|
import { CronTriggerOutputs } from "../../triggerInfo/cron"
|
||||||
|
|
||||||
|
type TriggerOutputs =
|
||||||
|
| RowCreatedTriggerOutputs
|
||||||
|
| RowUpdatedTriggerOutputs
|
||||||
|
| RowDeletedTriggerOutputs
|
||||||
|
| AppActionTriggerOutputs
|
||||||
|
| CronTriggerOutputs
|
||||||
|
| undefined
|
||||||
|
|
||||||
|
class AutomationBuilder {
|
||||||
|
private automationConfig: Automation = {
|
||||||
|
name: "",
|
||||||
|
definition: {
|
||||||
|
steps: [],
|
||||||
|
trigger: {} as AutomationTrigger,
|
||||||
|
},
|
||||||
|
type: "automation",
|
||||||
|
appId: setup.getConfig().getAppId(),
|
||||||
|
}
|
||||||
|
private config: TestConfiguration = setup.getConfig()
|
||||||
|
private triggerOutputs: TriggerOutputs
|
||||||
|
private triggerSet: boolean = false
|
||||||
|
|
||||||
|
constructor(options: { name?: string } = {}) {
|
||||||
|
this.automationConfig.name = options.name || `Test Automation ${uuidv4()}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TRIGGERS
|
||||||
|
rowSaved(inputs: RowCreatedTriggerInputs, outputs: RowCreatedTriggerOutputs) {
|
||||||
|
this.triggerOutputs = outputs
|
||||||
|
return this.trigger(TRIGGER_DEFINITIONS.ROW_SAVED, inputs, outputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
rowUpdated(
|
||||||
|
inputs: RowUpdatedTriggerInputs,
|
||||||
|
outputs: RowUpdatedTriggerOutputs
|
||||||
|
) {
|
||||||
|
this.triggerOutputs = outputs
|
||||||
|
return this.trigger(TRIGGER_DEFINITIONS.ROW_UPDATED, inputs, outputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
rowDeleted(
|
||||||
|
inputs: RowDeletedTriggerInputs,
|
||||||
|
outputs: RowDeletedTriggerOutputs
|
||||||
|
) {
|
||||||
|
this.triggerOutputs = outputs
|
||||||
|
return this.trigger(TRIGGER_DEFINITIONS.ROW_DELETED, inputs, outputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
appAction(outputs: AppActionTriggerOutputs, inputs?: AppActionTriggerInputs) {
|
||||||
|
this.triggerOutputs = outputs
|
||||||
|
return this.trigger(TRIGGER_DEFINITIONS.APP, inputs, outputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEPS
|
||||||
|
createRow(inputs: CreateRowStepInputs): this {
|
||||||
|
return this.step(BUILTIN_ACTION_DEFINITIONS.CREATE_ROW, inputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRow(inputs: UpdateRowStepInputs): this {
|
||||||
|
return this.step(BUILTIN_ACTION_DEFINITIONS.UPDATE_ROW, inputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteRow(inputs: DeleteRowStepInputs): this {
|
||||||
|
return this.step(BUILTIN_ACTION_DEFINITIONS.DELETE_ROW, inputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
sendSmtpEmail(inputs: SmtpEmailStepInputs): this {
|
||||||
|
return this.step(BUILTIN_ACTION_DEFINITIONS.SEND_EMAIL_SMTP, inputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
executeQuery(inputs: ExecuteQueryStepInputs): this {
|
||||||
|
return this.step(BUILTIN_ACTION_DEFINITIONS.EXECUTE_QUERY, inputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
queryRows(inputs: QueryRowsStepInputs): this {
|
||||||
|
return this.step(BUILTIN_ACTION_DEFINITIONS.QUERY_ROWS, inputs)
|
||||||
|
}
|
||||||
|
loop(inputs: LoopStepInputs): this {
|
||||||
|
return this.step(BUILTIN_ACTION_DEFINITIONS.LOOP, inputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
private trigger<T extends { [key: string]: any }>(
|
||||||
|
triggerSchema: AutomationTriggerSchema,
|
||||||
|
inputs?: T,
|
||||||
|
outputs?: TriggerOutputs
|
||||||
|
): this {
|
||||||
|
if (this.triggerSet) {
|
||||||
|
throw new Error("Only one trigger can be set for an automation.")
|
||||||
|
}
|
||||||
|
this.automationConfig.definition.trigger = {
|
||||||
|
...triggerSchema,
|
||||||
|
inputs: inputs || {},
|
||||||
|
id: uuidv4(),
|
||||||
|
}
|
||||||
|
this.triggerOutputs = outputs
|
||||||
|
this.triggerSet = true
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private step<T extends { [key: string]: any }>(
|
||||||
|
stepSchema: AutomationStepSchema,
|
||||||
|
inputs: T
|
||||||
|
): this {
|
||||||
|
this.automationConfig.definition.steps.push({
|
||||||
|
...stepSchema,
|
||||||
|
inputs,
|
||||||
|
id: uuidv4(),
|
||||||
|
})
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
async run() {
|
||||||
|
const automation = await this.config.createAutomation(this.automationConfig)
|
||||||
|
const results = await testAutomation(
|
||||||
|
this.config,
|
||||||
|
automation,
|
||||||
|
this.triggerOutputs
|
||||||
|
)
|
||||||
|
return this.processResults(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
private processResults(results: { body: AutomationResults }) {
|
||||||
|
results.body.steps.shift()
|
||||||
|
return {
|
||||||
|
trigger: results.body.trigger,
|
||||||
|
steps: results.body.steps,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createAutomationBuilder(options?: { name?: string }) {
|
||||||
|
return new AutomationBuilder(options)
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ import { context } from "@budibase/backend-core"
|
||||||
import { BUILTIN_ACTION_DEFINITIONS, getAction } from "../../actions"
|
import { BUILTIN_ACTION_DEFINITIONS, getAction } from "../../actions"
|
||||||
import emitter from "../../../events/index"
|
import emitter from "../../../events/index"
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
|
import { AutomationActionStepId } from "@budibase/types"
|
||||||
|
|
||||||
let config: TestConfig
|
let config: TestConfig
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ export async function runInProd(fn: any) {
|
||||||
|
|
||||||
export async function runStep(stepId: string, inputs: any, stepContext?: any) {
|
export async function runStep(stepId: string, inputs: any, stepContext?: any) {
|
||||||
async function run() {
|
async function run() {
|
||||||
let step = await getAction(stepId)
|
let step = await getAction(stepId as AutomationActionStepId)
|
||||||
expect(step).toBeDefined()
|
expect(step).toBeDefined()
|
||||||
if (!step) {
|
if (!step) {
|
||||||
throw new Error("No step found")
|
throw new Error("No step found")
|
||||||
|
@ -41,7 +42,7 @@ export async function runStep(stepId: string, inputs: any, stepContext?: any) {
|
||||||
return step({
|
return step({
|
||||||
context: stepContext || {},
|
context: stepContext || {},
|
||||||
inputs,
|
inputs,
|
||||||
appId: config ? config.getAppId() : null,
|
appId: config ? config.getAppId() : "",
|
||||||
// don't really need an API key, mocked out usage quota, not being tested here
|
// don't really need an API key, mocked out usage quota, not being tested here
|
||||||
apiKey,
|
apiKey,
|
||||||
emitter,
|
emitter,
|
||||||
|
|
|
@ -39,3 +39,11 @@ export const definition: AutomationTriggerSchema = {
|
||||||
},
|
},
|
||||||
type: AutomationStepType.TRIGGER,
|
type: AutomationStepType.TRIGGER,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AppActionTriggerInputs = {
|
||||||
|
fields: object
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AppActionTriggerOutputs = {
|
||||||
|
fields: object
|
||||||
|
}
|
||||||
|
|
|
@ -38,3 +38,11 @@ export const definition: AutomationTriggerSchema = {
|
||||||
},
|
},
|
||||||
type: AutomationStepType.TRIGGER,
|
type: AutomationStepType.TRIGGER,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type CronTriggerInputs = {
|
||||||
|
cron: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CronTriggerOutputs = {
|
||||||
|
timestamp: number
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
AutomationTriggerSchema,
|
AutomationTriggerSchema,
|
||||||
AutomationTriggerStepId,
|
AutomationTriggerStepId,
|
||||||
AutomationEventType,
|
AutomationEventType,
|
||||||
|
Row,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationTriggerSchema = {
|
export const definition: AutomationTriggerSchema = {
|
||||||
|
@ -39,3 +40,11 @@ export const definition: AutomationTriggerSchema = {
|
||||||
},
|
},
|
||||||
type: AutomationStepType.TRIGGER,
|
type: AutomationStepType.TRIGGER,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type RowDeletedTriggerInputs = {
|
||||||
|
tableId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RowDeletedTriggerOutputs = {
|
||||||
|
row: Row
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@ import {
|
||||||
AutomationTriggerSchema,
|
AutomationTriggerSchema,
|
||||||
AutomationTriggerStepId,
|
AutomationTriggerStepId,
|
||||||
AutomationEventType,
|
AutomationEventType,
|
||||||
|
Row,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
import { SearchFilters } from "aws-sdk/clients/elasticbeanstalk"
|
||||||
|
|
||||||
export const definition: AutomationTriggerSchema = {
|
export const definition: AutomationTriggerSchema = {
|
||||||
name: "Row Created",
|
name: "Row Created",
|
||||||
|
@ -52,3 +54,14 @@ export const definition: AutomationTriggerSchema = {
|
||||||
},
|
},
|
||||||
type: AutomationStepType.TRIGGER,
|
type: AutomationStepType.TRIGGER,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type RowCreatedTriggerInputs = {
|
||||||
|
tableId: string
|
||||||
|
filters?: SearchFilters
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RowCreatedTriggerOutputs = {
|
||||||
|
row: Row
|
||||||
|
id: string
|
||||||
|
revision: string
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import {
|
||||||
AutomationTriggerSchema,
|
AutomationTriggerSchema,
|
||||||
AutomationTriggerStepId,
|
AutomationTriggerStepId,
|
||||||
AutomationEventType,
|
AutomationEventType,
|
||||||
|
Row,
|
||||||
|
SearchFilters,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationTriggerSchema = {
|
export const definition: AutomationTriggerSchema = {
|
||||||
|
@ -59,3 +61,14 @@ export const definition: AutomationTriggerSchema = {
|
||||||
},
|
},
|
||||||
type: AutomationStepType.TRIGGER,
|
type: AutomationStepType.TRIGGER,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type RowUpdatedTriggerInputs = {
|
||||||
|
tableId: string
|
||||||
|
filters?: SearchFilters
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RowUpdatedTriggerOutputs = {
|
||||||
|
row: Row
|
||||||
|
id: string
|
||||||
|
revision?: string
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { LoopStepType } from "../../definitions/automations"
|
|
||||||
import {
|
import {
|
||||||
typecastForLooping,
|
typecastForLooping,
|
||||||
cleanInputValues,
|
cleanInputValues,
|
||||||
substituteLoopStep,
|
substituteLoopStep,
|
||||||
} from "../automationUtils"
|
} from "../automationUtils"
|
||||||
|
import { LoopStepType } from "@budibase/types"
|
||||||
|
|
||||||
describe("automationUtils", () => {
|
describe("automationUtils", () => {
|
||||||
describe("substituteLoopStep", () => {
|
describe("substituteLoopStep", () => {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { AutomationResults, AutomationStep } from "@budibase/types"
|
import {
|
||||||
|
AutomationResults,
|
||||||
export enum LoopStepType {
|
AutomationStep,
|
||||||
ARRAY = "Array",
|
LoopStepType,
|
||||||
STRING = "String",
|
} from "@budibase/types"
|
||||||
}
|
|
||||||
|
|
||||||
export interface LoopStep extends AutomationStep {
|
export interface LoopStep extends AutomationStep {
|
||||||
inputs: LoopInput
|
inputs: LoopInput
|
||||||
|
|
|
@ -43,6 +43,7 @@ import {
|
||||||
} from "./filters"
|
} from "./filters"
|
||||||
import { dataFilters, PROTECTED_INTERNAL_COLUMNS } from "@budibase/shared-core"
|
import { dataFilters, PROTECTED_INTERNAL_COLUMNS } from "@budibase/shared-core"
|
||||||
import { isSearchingByRowID } from "./utils"
|
import { isSearchingByRowID } from "./utils"
|
||||||
|
import tracer from "dd-trace"
|
||||||
|
|
||||||
const builder = new sql.Sql(SqlClient.SQL_LITE)
|
const builder = new sql.Sql(SqlClient.SQL_LITE)
|
||||||
const MISSING_COLUMN_REGEX = new RegExp(`no such column: .+`)
|
const MISSING_COLUMN_REGEX = new RegExp(`no such column: .+`)
|
||||||
|
@ -72,10 +73,14 @@ function buildInternalFieldList(
|
||||||
}
|
}
|
||||||
if (isRelationship) {
|
if (isRelationship) {
|
||||||
const linkCol = col as RelationshipFieldMetadata
|
const linkCol = col as RelationshipFieldMetadata
|
||||||
const relatedTable = tables.find(table => table._id === linkCol.tableId)!
|
const relatedTable = tables.find(table => table._id === linkCol.tableId)
|
||||||
// no relationships provided, don't go more than a layer deep
|
// no relationships provided, don't go more than a layer deep
|
||||||
fieldList = fieldList.concat(buildInternalFieldList(relatedTable, tables))
|
if (relatedTable) {
|
||||||
|
fieldList = fieldList.concat(
|
||||||
|
buildInternalFieldList(relatedTable, tables)
|
||||||
|
)
|
||||||
addJunctionFields(relatedTable, ["doc1.fieldName", "doc2.fieldName"])
|
addJunctionFields(relatedTable, ["doc1.fieldName", "doc2.fieldName"])
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fieldList.push(`${table._id}.${mapToUserColumn(col.name)}`)
|
fieldList.push(`${table._id}.${mapToUserColumn(col.name)}`)
|
||||||
}
|
}
|
||||||
|
@ -221,7 +226,11 @@ async function runSqlQuery(
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
|
|
||||||
|
return await tracer.trace("sqs.runSqlQuery", async span => {
|
||||||
|
span?.addTags({ sql })
|
||||||
return await db.sql<Row>(sql, bindings)
|
return await db.sql<Row>(sql, bindings)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
const response = await alias.queryWithAliasing(json, processSQLQuery)
|
const response = await alias.queryWithAliasing(json, processSQLQuery)
|
||||||
if (opts?.countTotalRows) {
|
if (opts?.countTotalRows) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Expectations, TestAPI } from "./base"
|
import { Expectations, TestAPI } from "./base"
|
||||||
import { Row, View, ViewCalculation } from "@budibase/types"
|
import { Row, RowExportFormat, View, ViewCalculation } from "@budibase/types"
|
||||||
|
|
||||||
export class LegacyViewAPI extends TestAPI {
|
export class LegacyViewAPI extends TestAPI {
|
||||||
get = async (
|
get = async (
|
||||||
|
@ -24,7 +24,7 @@ export class LegacyViewAPI extends TestAPI {
|
||||||
|
|
||||||
export = async (
|
export = async (
|
||||||
viewName: string,
|
viewName: string,
|
||||||
format: "json" | "csv" | "jsonWithSchema",
|
format: `${RowExportFormat}`,
|
||||||
expectations?: Expectations
|
expectations?: Expectations
|
||||||
) => {
|
) => {
|
||||||
const response = await this._requestRaw("get", `/api/views/export`, {
|
const response = await this._requestRaw("get", `/api/views/export`, {
|
||||||
|
|
|
@ -25,8 +25,9 @@ import {
|
||||||
Webhook,
|
Webhook,
|
||||||
WebhookActionType,
|
WebhookActionType,
|
||||||
AutomationEventType,
|
AutomationEventType,
|
||||||
|
LoopStepType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { LoopInput, LoopStepType } from "../../definitions/automations"
|
import { LoopInput } from "../../definitions/automations"
|
||||||
import { merge } from "lodash"
|
import { merge } from "lodash"
|
||||||
import { generator } from "@budibase/backend-core/tests"
|
import { generator } from "@budibase/backend-core/tests"
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { AutomationErrors, MAX_AUTOMATION_RECURRING_ERRORS } from "../constants"
|
||||||
import { storeLog } from "../automations/logging"
|
import { storeLog } from "../automations/logging"
|
||||||
import {
|
import {
|
||||||
Automation,
|
Automation,
|
||||||
|
AutomationActionStepId,
|
||||||
AutomationData,
|
AutomationData,
|
||||||
AutomationJob,
|
AutomationJob,
|
||||||
AutomationMetadata,
|
AutomationMetadata,
|
||||||
|
@ -108,7 +109,7 @@ class Orchestrator {
|
||||||
return triggerOutput
|
return triggerOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
async getStepFunctionality(stepId: string) {
|
async getStepFunctionality(stepId: AutomationActionStepId) {
|
||||||
let step = await actions.getAction(stepId)
|
let step = await actions.getAction(stepId)
|
||||||
if (step == null) {
|
if (step == null) {
|
||||||
throw `Cannot find automation step by name ${stepId}`
|
throw `Cannot find automation step by name ${stepId}`
|
||||||
|
@ -422,7 +423,9 @@ class Orchestrator {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let stepFn = await this.getStepFunctionality(step.stepId)
|
let stepFn = await this.getStepFunctionality(
|
||||||
|
step.stepId as AutomationActionStepId
|
||||||
|
)
|
||||||
let inputs = await processObject(originalStepInput, this._context)
|
let inputs = await processObject(originalStepInput, this._context)
|
||||||
inputs = automationUtils.cleanInputValues(
|
inputs = automationUtils.cleanInputValues(
|
||||||
inputs,
|
inputs,
|
||||||
|
|
|
@ -103,8 +103,8 @@ export async function sendSmtpEmail({
|
||||||
from: string
|
from: string
|
||||||
subject: string
|
subject: string
|
||||||
contents: string
|
contents: string
|
||||||
cc: string
|
cc?: string
|
||||||
bcc: string
|
bcc?: string
|
||||||
automation: boolean
|
automation: boolean
|
||||||
attachments?: EmailAttachment[]
|
attachments?: EmailAttachment[]
|
||||||
invite?: EmailInvite
|
invite?: EmailInvite
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { Document } from "../document"
|
import { Document } from "../../document"
|
||||||
import { EventEmitter } from "events"
|
import { EventEmitter } from "events"
|
||||||
import { User } from "../global"
|
import { User } from "../../global"
|
||||||
import { ReadStream } from "fs"
|
import { ReadStream } from "fs"
|
||||||
import { Row } from "./row"
|
import { Row } from "../row"
|
||||||
import { Table } from "./table"
|
import { Table } from "../table"
|
||||||
|
|
||||||
export enum AutomationIOType {
|
export enum AutomationIOType {
|
||||||
OBJECT = "object",
|
OBJECT = "object",
|
||||||
|
@ -93,6 +93,7 @@ export interface EmailAttachment {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SendEmailOpts {
|
export interface SendEmailOpts {
|
||||||
|
to?: string
|
||||||
// workspaceId If finer grain controls being used then this will lookup config for workspace.
|
// workspaceId If finer grain controls being used then this will lookup config for workspace.
|
||||||
workspaceId?: string
|
workspaceId?: string
|
||||||
// user If sending to an existing user the object can be provided, this is used in the context.
|
// user If sending to an existing user the object can be provided, this is used in the context.
|
||||||
|
@ -102,7 +103,7 @@ export interface SendEmailOpts {
|
||||||
// contents If sending a custom email then can supply contents which will be added to it.
|
// contents If sending a custom email then can supply contents which will be added to it.
|
||||||
contents?: string
|
contents?: string
|
||||||
// subject A custom subject can be specified if the config one is not desired.
|
// subject A custom subject can be specified if the config one is not desired.
|
||||||
subject?: string
|
subject: string
|
||||||
// info Pass in a structure of information to be stored alongside the invitation.
|
// info Pass in a structure of information to be stored alongside the invitation.
|
||||||
info?: any
|
info?: any
|
||||||
cc?: boolean
|
cc?: boolean
|
||||||
|
@ -242,14 +243,18 @@ export interface AutomationLogPage {
|
||||||
nextPage?: string
|
nextPage?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AutomationStepInput = {
|
export interface AutomationStepInputBase {
|
||||||
inputs: Record<string, any>
|
|
||||||
context: Record<string, any>
|
context: Record<string, any>
|
||||||
emitter: EventEmitter
|
emitter: EventEmitter
|
||||||
appId: string
|
appId: string
|
||||||
apiKey?: string
|
apiKey?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ActionImplementation<TInputs, TOutputs> = (
|
||||||
|
params: {
|
||||||
|
inputs: TInputs
|
||||||
|
} & AutomationStepInputBase
|
||||||
|
) => Promise<TOutputs>
|
||||||
export interface AutomationMetadata extends Document {
|
export interface AutomationMetadata extends Document {
|
||||||
errorCount?: number
|
errorCount?: number
|
||||||
automationChainCount?: number
|
automationChainCount?: number
|
||||||
|
@ -286,3 +291,8 @@ export type UpdatedRowEventEmitter = {
|
||||||
table: Table
|
table: Table
|
||||||
appId: string
|
appId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum LoopStepType {
|
||||||
|
ARRAY = "Array",
|
||||||
|
STRING = "String",
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./automation"
|
||||||
|
export * from "./schema"
|
|
@ -0,0 +1,320 @@
|
||||||
|
import { SortOrder } from "../../../api"
|
||||||
|
import { EmptyFilterOption, Hosting, SearchFilters } from "../../../sdk"
|
||||||
|
import { HttpMethod } from "../query"
|
||||||
|
import { Row } from "../row"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationResults,
|
||||||
|
EmailAttachment,
|
||||||
|
LoopStepType,
|
||||||
|
ActionImplementation,
|
||||||
|
} from "./automation"
|
||||||
|
|
||||||
|
export type ActionImplementations<T extends Hosting> = {
|
||||||
|
[AutomationActionStepId.COLLECT]: ActionImplementation<
|
||||||
|
CollectStepInputs,
|
||||||
|
CollectStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.CREATE_ROW]: ActionImplementation<
|
||||||
|
CreateRowStepInputs,
|
||||||
|
CreateRowStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.DELAY]: ActionImplementation<
|
||||||
|
DelayStepInputs,
|
||||||
|
DelayStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.DELETE_ROW]: ActionImplementation<
|
||||||
|
DeleteRowStepInputs,
|
||||||
|
DeleteRowStepOutputs
|
||||||
|
>
|
||||||
|
|
||||||
|
[AutomationActionStepId.EXECUTE_QUERY]: ActionImplementation<
|
||||||
|
ExecuteQueryStepInputs,
|
||||||
|
ExecuteQueryStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.EXECUTE_SCRIPT]: ActionImplementation<
|
||||||
|
ExecuteScriptStepInputs,
|
||||||
|
ExecuteScriptStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.FILTER]: ActionImplementation<
|
||||||
|
FilterStepInputs,
|
||||||
|
FilterStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.QUERY_ROWS]: ActionImplementation<
|
||||||
|
QueryRowsStepInputs,
|
||||||
|
QueryRowsStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.SEND_EMAIL_SMTP]: ActionImplementation<
|
||||||
|
SmtpEmailStepInputs,
|
||||||
|
BaseAutomationOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.SERVER_LOG]: ActionImplementation<
|
||||||
|
ServerLogStepInputs,
|
||||||
|
ServerLogStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.TRIGGER_AUTOMATION_RUN]: ActionImplementation<
|
||||||
|
TriggerAutomationStepInputs,
|
||||||
|
TriggerAutomationStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.UPDATE_ROW]: ActionImplementation<
|
||||||
|
UpdateRowStepInputs,
|
||||||
|
UpdateRowStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.OUTGOING_WEBHOOK]: ActionImplementation<
|
||||||
|
OutgoingWebhookStepInputs,
|
||||||
|
ExternalAppStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.discord]: ActionImplementation<
|
||||||
|
DiscordStepInputs,
|
||||||
|
ExternalAppStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.slack]: ActionImplementation<
|
||||||
|
SlackStepInputs,
|
||||||
|
ExternalAppStepOutputs
|
||||||
|
>
|
||||||
|
|
||||||
|
[AutomationActionStepId.zapier]: ActionImplementation<
|
||||||
|
ZapierStepInputs,
|
||||||
|
ZapierStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.integromat]: ActionImplementation<
|
||||||
|
MakeIntegrationInputs,
|
||||||
|
ExternalAppStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.n8n]: ActionImplementation<
|
||||||
|
n8nStepInputs,
|
||||||
|
ExternalAppStepOutputs
|
||||||
|
>
|
||||||
|
} & (T extends "self"
|
||||||
|
? {
|
||||||
|
[AutomationActionStepId.EXECUTE_BASH]: ActionImplementation<
|
||||||
|
BashStepInputs,
|
||||||
|
BashStepOutputs
|
||||||
|
>
|
||||||
|
[AutomationActionStepId.OPENAI]: ActionImplementation<
|
||||||
|
OpenAIStepInputs,
|
||||||
|
OpenAIStepOutputs
|
||||||
|
>
|
||||||
|
}
|
||||||
|
: {})
|
||||||
|
|
||||||
|
export type BaseAutomationOutputs = {
|
||||||
|
success?: boolean
|
||||||
|
response?: {
|
||||||
|
[key: string]: any
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExternalAppStepOutputs = {
|
||||||
|
httpStatus?: number
|
||||||
|
response: string
|
||||||
|
success: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BashStepInputs = {
|
||||||
|
code: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BashStepOutputs = BaseAutomationOutputs & {
|
||||||
|
stdout?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CollectStepInputs = {
|
||||||
|
collection: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CollectStepOutputs = BaseAutomationOutputs & {
|
||||||
|
value?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CreateRowStepInputs = {
|
||||||
|
row: Row
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CreateRowStepOutputs = BaseAutomationOutputs & {
|
||||||
|
row?: Row
|
||||||
|
id?: string
|
||||||
|
revision?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DelayStepInputs = {
|
||||||
|
time: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DelayStepOutputs = BaseAutomationOutputs
|
||||||
|
|
||||||
|
export type DeleteRowStepInputs = {
|
||||||
|
tableId: string
|
||||||
|
id: string
|
||||||
|
revision?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DeleteRowStepOutputs = BaseAutomationOutputs & {
|
||||||
|
row?: Row
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DiscordStepInputs = {
|
||||||
|
url: string
|
||||||
|
username?: string
|
||||||
|
avatar_url?: string
|
||||||
|
content: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExecuteQueryStepInputs = {
|
||||||
|
query: {
|
||||||
|
queryId: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExecuteQueryStepOutputs = BaseAutomationOutputs & {
|
||||||
|
info?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExecuteScriptStepInputs = {
|
||||||
|
code: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExecuteScriptStepOutputs = BaseAutomationOutputs & {
|
||||||
|
value?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FilterStepInputs = {
|
||||||
|
field: any
|
||||||
|
condition: string
|
||||||
|
value: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FilterStepOutputs = BaseAutomationOutputs & {
|
||||||
|
result: boolean
|
||||||
|
refValue?: any
|
||||||
|
comparisonValue?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LoopStepInputs = {
|
||||||
|
option: LoopStepType
|
||||||
|
binding: any
|
||||||
|
iterations?: number
|
||||||
|
failure?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LoopStepOutputs = {
|
||||||
|
items: string
|
||||||
|
success: boolean
|
||||||
|
iterations: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MakeIntegrationInputs = {
|
||||||
|
url: string
|
||||||
|
body: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type n8nStepInputs = {
|
||||||
|
url: string
|
||||||
|
method: HttpMethod
|
||||||
|
authorization: string
|
||||||
|
body: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OpenAIStepInputs = {
|
||||||
|
prompt: string
|
||||||
|
model: Model
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Model {
|
||||||
|
GPT_35_TURBO = "gpt-3.5-turbo",
|
||||||
|
// will only work with api keys that have access to the GPT4 API
|
||||||
|
GPT_4 = "gpt-4",
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OpenAIStepOutputs = Omit<BaseAutomationOutputs, "response"> & {
|
||||||
|
response?: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type QueryRowsStepInputs = {
|
||||||
|
tableId: string
|
||||||
|
filters?: SearchFilters
|
||||||
|
"filters-def"?: any
|
||||||
|
sortColumn?: string
|
||||||
|
sortOrder?: SortOrder
|
||||||
|
limit?: number
|
||||||
|
onEmptyFilter?: EmptyFilterOption
|
||||||
|
}
|
||||||
|
|
||||||
|
export type QueryRowsStepOutputs = BaseAutomationOutputs & {
|
||||||
|
rows?: Row[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SmtpEmailStepInputs = {
|
||||||
|
to: string
|
||||||
|
from: string
|
||||||
|
subject: string
|
||||||
|
contents: string
|
||||||
|
cc: string
|
||||||
|
bcc: string
|
||||||
|
addInvite?: boolean
|
||||||
|
startTime: Date
|
||||||
|
endTime: Date
|
||||||
|
summary: string
|
||||||
|
location?: string
|
||||||
|
url?: string
|
||||||
|
attachments?: EmailAttachment[]
|
||||||
|
}
|
||||||
|
export type ServerLogStepInputs = {
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ServerLogStepOutputs = BaseAutomationOutputs & {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
export type SlackStepInputs = {
|
||||||
|
url: string
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TriggerAutomationStepInputs = {
|
||||||
|
automation: {
|
||||||
|
automationId: string
|
||||||
|
}
|
||||||
|
timeout: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TriggerAutomationStepOutputs = BaseAutomationOutputs & {
|
||||||
|
value?: AutomationResults["steps"]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UpdateRowStepInputs = {
|
||||||
|
meta: Record<string, any>
|
||||||
|
row: Row
|
||||||
|
rowId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UpdateRowStepOutputs = BaseAutomationOutputs & {
|
||||||
|
row?: Row
|
||||||
|
id?: string
|
||||||
|
revision?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ZapierStepInputs = {
|
||||||
|
url: string
|
||||||
|
body: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ZapierStepOutputs = Omit<ExternalAppStepOutputs, "response"> & {
|
||||||
|
response: string
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RequestType {
|
||||||
|
POST = "POST",
|
||||||
|
GET = "GET",
|
||||||
|
PUT = "PUT",
|
||||||
|
DELETE = "DELETE",
|
||||||
|
PATCH = "PATCH",
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OutgoingWebhookStepInputs = {
|
||||||
|
requestMethod: RequestType
|
||||||
|
url: string
|
||||||
|
requestBody: string
|
||||||
|
headers: string
|
||||||
|
}
|
|
@ -30,3 +30,9 @@ export interface SearchResponse<T> {
|
||||||
bookmark?: string | number
|
bookmark?: string | number
|
||||||
totalRows?: number
|
totalRows?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum RowExportFormat {
|
||||||
|
CSV = "csv",
|
||||||
|
JSON = "json",
|
||||||
|
JSON_WITH_SCHEMA = "jsonWithSchema",
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue