Automation overhaul to Typescript, plus type updates.
This commit is contained in:
parent
eeebd0fe70
commit
a3bb2e0d77
|
@ -25,7 +25,7 @@ const DefaultBucketName = {
|
||||||
PLUGINS: "plugins",
|
PLUGINS: "plugins",
|
||||||
}
|
}
|
||||||
|
|
||||||
const env = {
|
const environment = {
|
||||||
isTest,
|
isTest,
|
||||||
isDev,
|
isDev,
|
||||||
JS_BCRYPT: process.env.JS_BCRYPT,
|
JS_BCRYPT: process.env.JS_BCRYPT,
|
||||||
|
@ -80,7 +80,7 @@ const env = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up any environment variable edge cases
|
// clean up any environment variable edge cases
|
||||||
for (let [key, value] of Object.entries(env)) {
|
for (let [key, value] of Object.entries(environment)) {
|
||||||
// handle the edge case of "0" to disable an environment variable
|
// handle the edge case of "0" to disable an environment variable
|
||||||
if (value === "0") {
|
if (value === "0") {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -88,4 +88,4 @@ for (let [key, value] of Object.entries(env)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export = env
|
export = environment
|
||||||
|
|
|
@ -39,7 +39,7 @@ export function createQueue<T>(
|
||||||
return queue
|
return queue
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.shutdown = async () => {
|
export async function shutdown() {
|
||||||
if (QUEUES.length) {
|
if (QUEUES.length) {
|
||||||
clearInterval(cleanupInterval)
|
clearInterval(cleanupInterval)
|
||||||
for (let queue of QUEUES) {
|
for (let queue of QUEUES) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import actions from "../../automations/actions"
|
import * as actions from "../../automations/actions"
|
||||||
import triggers from "../../automations/triggers"
|
import * as triggers from "../../automations/triggers"
|
||||||
import {
|
import {
|
||||||
getAutomationParams,
|
getAutomationParams,
|
||||||
generateAutomationID,
|
generateAutomationID,
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
const sendSmtpEmail = require("./steps/sendSmtpEmail")
|
import * as sendSmtpEmail from "./steps/sendSmtpEmail"
|
||||||
const createRow = require("./steps/createRow")
|
import * as createRow from "./steps/createRow"
|
||||||
const updateRow = require("./steps/updateRow")
|
import * as updateRow from "./steps/updateRow"
|
||||||
const deleteRow = require("./steps/deleteRow")
|
import * as deleteRow from "./steps/deleteRow"
|
||||||
const executeScript = require("./steps/executeScript")
|
import * as executeScript from "./steps/executeScript"
|
||||||
const executeQuery = require("./steps/executeQuery")
|
import * as executeQuery from "./steps/executeQuery"
|
||||||
const outgoingWebhook = require("./steps/outgoingWebhook")
|
import * as outgoingWebhook from "./steps/outgoingWebhook"
|
||||||
const serverLog = require("./steps/serverLog")
|
import * as serverLog from "./steps/serverLog"
|
||||||
const discord = require("./steps/discord")
|
import * as discord from "./steps/discord"
|
||||||
const slack = require("./steps/slack")
|
import * as slack from "./steps/slack"
|
||||||
const zapier = require("./steps/zapier")
|
import * as zapier from "./steps/zapier"
|
||||||
const integromat = require("./steps/integromat")
|
import * as integromat from "./steps/integromat"
|
||||||
let filter = require("./steps/filter")
|
import * as filter from "./steps/filter"
|
||||||
let delay = require("./steps/delay")
|
import * as delay from "./steps/delay"
|
||||||
let queryRow = require("./steps/queryRows")
|
import * as queryRow from "./steps/queryRows"
|
||||||
let loop = require("./steps/loop")
|
import * as loop from "./steps/loop"
|
||||||
const env = require("../environment")
|
import env from "../environment"
|
||||||
|
import { AutomationStep, AutomationStepInput } from "@budibase/types"
|
||||||
|
|
||||||
const ACTION_IMPLS = {
|
const ACTION_IMPLS: Record<
|
||||||
|
string,
|
||||||
|
(opts: AutomationStepInput) => Promise<any>
|
||||||
|
> = {
|
||||||
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,
|
||||||
|
@ -28,14 +32,13 @@ const ACTION_IMPLS = {
|
||||||
DELAY: delay.run,
|
DELAY: delay.run,
|
||||||
FILTER: filter.run,
|
FILTER: filter.run,
|
||||||
QUERY_ROWS: queryRow.run,
|
QUERY_ROWS: queryRow.run,
|
||||||
LOOP: loop.run,
|
|
||||||
// these used to be lowercase step IDs, maintain for backwards compat
|
// these used to be lowercase step IDs, maintain for backwards compat
|
||||||
discord: discord.run,
|
discord: discord.run,
|
||||||
slack: slack.run,
|
slack: slack.run,
|
||||||
zapier: zapier.run,
|
zapier: zapier.run,
|
||||||
integromat: integromat.run,
|
integromat: integromat.run,
|
||||||
}
|
}
|
||||||
const ACTION_DEFINITIONS = {
|
export const ACTION_DEFINITIONS: Record<string, AutomationStep> = {
|
||||||
SEND_EMAIL_SMTP: sendSmtpEmail.definition,
|
SEND_EMAIL_SMTP: sendSmtpEmail.definition,
|
||||||
CREATE_ROW: createRow.definition,
|
CREATE_ROW: createRow.definition,
|
||||||
UPDATE_ROW: updateRow.definition,
|
UPDATE_ROW: updateRow.definition,
|
||||||
|
@ -60,15 +63,15 @@ const ACTION_DEFINITIONS = {
|
||||||
// ran at all
|
// ran at all
|
||||||
if (env.SELF_HOSTED) {
|
if (env.SELF_HOSTED) {
|
||||||
const bash = require("./steps/bash")
|
const bash = require("./steps/bash")
|
||||||
|
// @ts-ignore
|
||||||
ACTION_IMPLS["EXECUTE_BASH"] = bash.run
|
ACTION_IMPLS["EXECUTE_BASH"] = bash.run
|
||||||
|
// @ts-ignore
|
||||||
ACTION_DEFINITIONS["EXECUTE_BASH"] = bash.definition
|
ACTION_DEFINITIONS["EXECUTE_BASH"] = bash.definition
|
||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
exports.getAction = async function (actionName) {
|
export async function getAction(actionName: string) {
|
||||||
if (ACTION_IMPLS[actionName] != null) {
|
if (ACTION_IMPLS[actionName] != null) {
|
||||||
return ACTION_IMPLS[actionName]
|
return ACTION_IMPLS[actionName]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.ACTION_DEFINITIONS = ACTION_DEFINITIONS
|
|
|
@ -1,9 +1,10 @@
|
||||||
const {
|
import {
|
||||||
decodeJSBinding,
|
decodeJSBinding,
|
||||||
isJSBinding,
|
isJSBinding,
|
||||||
encodeJSBinding,
|
encodeJSBinding,
|
||||||
} = require("@budibase/string-templates")
|
} from "@budibase/string-templates"
|
||||||
const sdk = require("../sdk")
|
import sdk from "../sdk"
|
||||||
|
import { Row } from "@budibase/types"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When values are input to the system generally they will be of type string as this is required for template strings.
|
* When values are input to the system generally they will be of type string as this is required for template strings.
|
||||||
|
@ -21,7 +22,7 @@ const sdk = require("../sdk")
|
||||||
* @returns {object} The inputs object which has had all the various types supported by this function converted to their
|
* @returns {object} The inputs object which has had all the various types supported by this function converted to their
|
||||||
* primitive types.
|
* primitive types.
|
||||||
*/
|
*/
|
||||||
exports.cleanInputValues = (inputs, schema) => {
|
export function cleanInputValues(inputs: Record<string, any>, schema: any) {
|
||||||
if (schema == null) {
|
if (schema == null) {
|
||||||
return inputs
|
return inputs
|
||||||
}
|
}
|
||||||
|
@ -62,12 +63,12 @@ exports.cleanInputValues = (inputs, schema) => {
|
||||||
* @param {object} row The input row structure which requires clean-up after having been through template statements.
|
* @param {object} row The input row structure which requires clean-up after having been through template statements.
|
||||||
* @returns {Promise<Object>} The cleaned up rows object, will should now have all the required primitive types.
|
* @returns {Promise<Object>} The cleaned up rows object, will should now have all the required primitive types.
|
||||||
*/
|
*/
|
||||||
exports.cleanUpRow = async (tableId, row) => {
|
export async function cleanUpRow(tableId: string, row: Row) {
|
||||||
let table = await sdk.tables.getTable(tableId)
|
let table = await sdk.tables.getTable(tableId)
|
||||||
return exports.cleanInputValues(row, { properties: table.schema })
|
return cleanInputValues(row, { properties: table.schema })
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getError = err => {
|
export function getError(err: any) {
|
||||||
if (err == null) {
|
if (err == null) {
|
||||||
return "No error provided."
|
return "No error provided."
|
||||||
}
|
}
|
||||||
|
@ -80,13 +81,13 @@ exports.getError = err => {
|
||||||
return typeof err !== "string" ? err.toString() : err
|
return typeof err !== "string" ? err.toString() : err
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.substituteLoopStep = (hbsString, substitute) => {
|
export function substituteLoopStep(hbsString: string, substitute: string) {
|
||||||
let checkForJS = isJSBinding(hbsString)
|
let checkForJS = isJSBinding(hbsString)
|
||||||
let substitutedHbsString = ""
|
let substitutedHbsString = ""
|
||||||
let open = checkForJS ? `$("` : "{{"
|
let open = checkForJS ? `$("` : "{{"
|
||||||
let closed = checkForJS ? `")` : "}}"
|
let closed = checkForJS ? `")` : "}}"
|
||||||
if (checkForJS) {
|
if (checkForJS) {
|
||||||
hbsString = decodeJSBinding(hbsString)
|
hbsString = decodeJSBinding(hbsString) as string
|
||||||
}
|
}
|
||||||
let pointer = 0,
|
let pointer = 0,
|
||||||
openPointer = 0,
|
openPointer = 0,
|
||||||
|
@ -111,9 +112,9 @@ exports.substituteLoopStep = (hbsString, substitute) => {
|
||||||
return substitutedHbsString
|
return substitutedHbsString
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.stringSplit = value => {
|
export function stringSplit(value: string | string[]) {
|
||||||
if (value == null) {
|
if (value == null || Array.isArray(value)) {
|
||||||
return []
|
return value || []
|
||||||
}
|
}
|
||||||
if (value.split("\n").length > 1) {
|
if (value.split("\n").length > 1) {
|
||||||
value = value.split("\n")
|
value = value.split("\n")
|
|
@ -1,39 +0,0 @@
|
||||||
const { createBullBoard } = require("@bull-board/api")
|
|
||||||
const { BullAdapter } = require("@bull-board/api/bullAdapter")
|
|
||||||
const { KoaAdapter } = require("@bull-board/koa")
|
|
||||||
const { queue } = require("@budibase/backend-core")
|
|
||||||
const automation = require("../threads/automation")
|
|
||||||
const { backups } = require("@budibase/pro")
|
|
||||||
|
|
||||||
let automationQueue = queue.createQueue(
|
|
||||||
queue.JobQueue.AUTOMATION,
|
|
||||||
automation.removeStalled
|
|
||||||
)
|
|
||||||
|
|
||||||
const PATH_PREFIX = "/bulladmin"
|
|
||||||
|
|
||||||
exports.init = async () => {
|
|
||||||
// Set up queues for bull board admin
|
|
||||||
const backupQueue = await backups.getBackupQueue()
|
|
||||||
const queues = [automationQueue]
|
|
||||||
if (backupQueue) {
|
|
||||||
queues.push(backupQueue)
|
|
||||||
}
|
|
||||||
const adapters = []
|
|
||||||
const serverAdapter = new KoaAdapter()
|
|
||||||
for (let queue of queues) {
|
|
||||||
adapters.push(new BullAdapter(queue))
|
|
||||||
}
|
|
||||||
createBullBoard({
|
|
||||||
queues: adapters,
|
|
||||||
serverAdapter,
|
|
||||||
})
|
|
||||||
serverAdapter.setBasePath(PATH_PREFIX)
|
|
||||||
return serverAdapter.registerPlugin()
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.shutdown = async () => {
|
|
||||||
await queue.shutdown()
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.automationQueue = automationQueue
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { BullAdapter } from "@bull-board/api/bullAdapter"
|
||||||
|
import { KoaAdapter } from "@bull-board/koa"
|
||||||
|
import { queue } from "@budibase/backend-core"
|
||||||
|
import * as automation from "../threads/automation"
|
||||||
|
import { backups } from "@budibase/pro"
|
||||||
|
import { createBullBoard } from "@bull-board/api"
|
||||||
|
import BullQueue from "bull"
|
||||||
|
|
||||||
|
export const automationQueue: BullQueue.Queue = queue.createQueue(
|
||||||
|
queue.JobQueue.AUTOMATION,
|
||||||
|
{ removeStalledCb: automation.removeStalled }
|
||||||
|
)
|
||||||
|
|
||||||
|
const PATH_PREFIX = "/bulladmin"
|
||||||
|
|
||||||
|
export async function init() {
|
||||||
|
// Set up queues for bull board admin
|
||||||
|
const backupQueue = await backups.getBackupQueue()
|
||||||
|
const queues = [automationQueue]
|
||||||
|
if (backupQueue) {
|
||||||
|
queues.push(backupQueue)
|
||||||
|
}
|
||||||
|
const adapters = []
|
||||||
|
const serverAdapter: any = new KoaAdapter()
|
||||||
|
for (let queue of queues) {
|
||||||
|
adapters.push(new BullAdapter(queue))
|
||||||
|
}
|
||||||
|
createBullBoard({
|
||||||
|
queues: adapters,
|
||||||
|
serverAdapter,
|
||||||
|
})
|
||||||
|
serverAdapter.setBasePath(PATH_PREFIX)
|
||||||
|
return serverAdapter.registerPlugin()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function shutdown() {
|
||||||
|
await queue.shutdown()
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
const { processEvent } = require("./utils")
|
|
||||||
const { automationQueue, shutdown } = require("./bullboard")
|
|
||||||
const { TRIGGER_DEFINITIONS, rebootTrigger } = require("./triggers")
|
|
||||||
const { ACTION_DEFINITIONS } = require("./actions")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This module is built purely to kick off the worker farm and manage the inputs/outputs
|
|
||||||
*/
|
|
||||||
exports.init = async function () {
|
|
||||||
// this promise will not complete
|
|
||||||
const promise = automationQueue.process(async job => {
|
|
||||||
await processEvent(job)
|
|
||||||
})
|
|
||||||
// on init we need to trigger any reboot automations
|
|
||||||
await rebootTrigger()
|
|
||||||
return promise
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getQueues = () => {
|
|
||||||
return [automationQueue]
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.shutdown = () => {
|
|
||||||
return shutdown()
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.automationQueue = automationQueue
|
|
||||||
exports.TRIGGER_DEFINITIONS = TRIGGER_DEFINITIONS
|
|
||||||
exports.ACTION_DEFINITIONS = ACTION_DEFINITIONS
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { processEvent } from "./utils"
|
||||||
|
import { automationQueue } from "./bullboard"
|
||||||
|
import { rebootTrigger } from "./triggers"
|
||||||
|
import BullQueue from "bull"
|
||||||
|
|
||||||
|
export { automationQueue } from "./bullboard"
|
||||||
|
export { shutdown } from "./bullboard"
|
||||||
|
export { TRIGGER_DEFINITIONS } from "./triggers"
|
||||||
|
export { ACTION_DEFINITIONS } from "./actions"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This module is built purely to kick off the worker farm and manage the inputs/outputs
|
||||||
|
*/
|
||||||
|
export async function init() {
|
||||||
|
// this promise will not complete
|
||||||
|
const promise = automationQueue.process(async job => {
|
||||||
|
await processEvent(job)
|
||||||
|
})
|
||||||
|
// on init we need to trigger any reboot automations
|
||||||
|
await rebootTrigger()
|
||||||
|
return promise
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getQueues(): BullQueue.Queue[] {
|
||||||
|
return [automationQueue]
|
||||||
|
}
|
|
@ -1,16 +1,21 @@
|
||||||
const { execSync } = require("child_process")
|
import { execSync } from "child_process"
|
||||||
const { processStringSync } = require("@budibase/string-templates")
|
import { processStringSync } from "@budibase/string-templates"
|
||||||
const automationUtils = require("../automationUtils")
|
import automationUtils from "../automationUtils"
|
||||||
const environment = require("../../environment")
|
import environment from "../../environment"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
name: "Bash Scripting",
|
name: "Bash Scripting",
|
||||||
tagline: "Execute a bash command",
|
tagline: "Execute a bash command",
|
||||||
icon: "JourneyEvent",
|
icon: "JourneyEvent",
|
||||||
description: "Run a bash script",
|
description: "Run a bash script",
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: "EXECUTE_BASH",
|
stepId: AutomationActionStepId.EXECUTE_BASH,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
||||||
|
@ -39,7 +44,7 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs, context }) {
|
export async function run({ inputs, context }: AutomationStepInput) {
|
||||||
if (inputs.code == null) {
|
if (inputs.code == null) {
|
||||||
return {
|
return {
|
||||||
stdout: "Budibase bash automation failed: Invalid inputs",
|
stdout: "Budibase bash automation failed: Invalid inputs",
|
||||||
|
@ -55,7 +60,7 @@ exports.run = async function ({ inputs, context }) {
|
||||||
stdout = execSync(command, {
|
stdout = execSync(command, {
|
||||||
timeout: environment.QUERY_THREAD_TIMEOUT || 500,
|
timeout: environment.QUERY_THREAD_TIMEOUT || 500,
|
||||||
}).toString()
|
}).toString()
|
||||||
} catch (err) {
|
} catch (err: any) {
|
||||||
stdout = err.message
|
stdout = err.message
|
||||||
success = false
|
success = false
|
||||||
}
|
}
|
|
@ -1,15 +1,20 @@
|
||||||
import { save } from "../../api/controllers/row"
|
import { save } from "../../api/controllers/row"
|
||||||
import { cleanUpRow, getError } from "../automationUtils"
|
import { cleanUpRow, getError } from "../automationUtils"
|
||||||
import { buildCtx } from "./utils"
|
import { buildCtx } from "./utils"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition = {
|
export const definition: AutomationStep = {
|
||||||
name: "Create Row",
|
name: "Create Row",
|
||||||
tagline: "Create a {{inputs.enriched.table.name}} row",
|
tagline: "Create a {{inputs.enriched.table.name}} row",
|
||||||
icon: "TableRowAddBottom",
|
icon: "TableRowAddBottom",
|
||||||
description: "Add a row to your database",
|
description: "Add a row to your database",
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: "CREATE_ROW",
|
stepId: AutomationActionStepId.CREATE_ROW,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
||||||
|
@ -58,7 +63,7 @@ export const definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs, appId, emitter }: any) {
|
export async function run({ inputs, appId, emitter }: AutomationStepInput) {
|
||||||
if (inputs.row == null || inputs.row.tableId == null) {
|
if (inputs.row == null || inputs.row.tableId == null) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
let { wait } = require("../../utilities")
|
import { wait } from "../../utilities"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
name: "Delay",
|
name: "Delay",
|
||||||
icon: "Clock",
|
icon: "Clock",
|
||||||
tagline: "Delay for {{inputs.time}} milliseconds",
|
tagline: "Delay for {{inputs.time}} milliseconds",
|
||||||
description: "Delay the automation until an amount of time has passed",
|
description: "Delay the automation until an amount of time has passed",
|
||||||
stepId: "DELAY",
|
stepId: AutomationActionStepId.DELAY,
|
||||||
internal: true,
|
internal: true,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
|
@ -31,7 +36,7 @@ exports.definition = {
|
||||||
type: "LOGIC",
|
type: "LOGIC",
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function delay({ inputs }) {
|
export async function run({ inputs }: AutomationStepInput) {
|
||||||
await wait(inputs.time)
|
await wait(inputs.time)
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
|
@ -1,14 +1,19 @@
|
||||||
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 {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition = {
|
export const definition: AutomationStep = {
|
||||||
description: "Delete a row from your database",
|
description: "Delete a row from your database",
|
||||||
icon: "TableRowRemoveCenter",
|
icon: "TableRowRemoveCenter",
|
||||||
name: "Delete Row",
|
name: "Delete Row",
|
||||||
tagline: "Delete a {{inputs.enriched.table.name}} row",
|
tagline: "Delete a {{inputs.enriched.table.name}} row",
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
stepId: "DELETE_ROW",
|
stepId: AutomationActionStepId.DELETE_ROW,
|
||||||
internal: true,
|
internal: true,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
|
@ -47,7 +52,7 @@ export const definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs, appId, emitter }: any) {
|
export async function run({ inputs, appId, emitter }: AutomationStepInput) {
|
||||||
if (inputs.id == null) {
|
if (inputs.id == null) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
const fetch = require("node-fetch")
|
import fetch from "node-fetch"
|
||||||
const { getFetchResponse } = require("./utils")
|
import { getFetchResponse } from "./utils"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
const DEFAULT_USERNAME = "Budibase Automate"
|
const DEFAULT_USERNAME = "Budibase Automate"
|
||||||
const DEFAULT_AVATAR_URL = "https://i.imgur.com/a1cmTKM.png"
|
const DEFAULT_AVATAR_URL = "https://i.imgur.com/a1cmTKM.png"
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
name: "Discord Message",
|
name: "Discord Message",
|
||||||
tagline: "Send a message to a Discord server",
|
tagline: "Send a message to a Discord server",
|
||||||
description: "Send a message to a Discord server",
|
description: "Send a message to a Discord server",
|
||||||
icon: "ri-discord-line",
|
icon: "ri-discord-line",
|
||||||
stepId: "discord",
|
stepId: AutomationActionStepId.discord,
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
internal: false,
|
internal: false,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
@ -54,7 +59,7 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs }) {
|
export async function run({ inputs }: AutomationStepInput) {
|
||||||
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,14 +1,19 @@
|
||||||
const queryController = require("../../api/controllers/query")
|
import * as queryController from "../../api/controllers/query"
|
||||||
const { buildCtx } = require("./utils")
|
import { buildCtx } from "./utils"
|
||||||
const automationUtils = require("../automationUtils")
|
import automationUtils from "../automationUtils"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
name: "External Data Connector",
|
name: "External Data Connector",
|
||||||
tagline: "Execute Data Connector",
|
tagline: "Execute Data Connector",
|
||||||
icon: "Data",
|
icon: "Data",
|
||||||
description: "Execute a query in an external data connector",
|
description: "Execute a query in an external data connector",
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
stepId: "EXECUTE_QUERY",
|
stepId: AutomationActionStepId.EXECUTE_QUERY,
|
||||||
internal: true,
|
internal: true,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
|
@ -50,7 +55,7 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs, appId, emitter }) {
|
export async function run({ inputs, appId, emitter }: AutomationStepInput) {
|
||||||
if (inputs.query == null) {
|
if (inputs.query == null) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -62,7 +67,7 @@ exports.run = async function ({ inputs, appId, emitter }) {
|
||||||
|
|
||||||
const { queryId, ...rest } = inputs.query
|
const { queryId, ...rest } = inputs.query
|
||||||
|
|
||||||
const ctx = buildCtx(appId, emitter, {
|
const ctx: any = buildCtx(appId, emitter, {
|
||||||
body: {
|
body: {
|
||||||
parameters: rest,
|
parameters: rest,
|
||||||
},
|
},
|
|
@ -1,15 +1,20 @@
|
||||||
const scriptController = require("../../api/controllers/script")
|
import * as scriptController from "../../api/controllers/script"
|
||||||
const { buildCtx } = require("./utils")
|
import { buildCtx } from "./utils"
|
||||||
const automationUtils = require("../automationUtils")
|
import automationUtils from "../automationUtils"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
name: "JS Scripting",
|
name: "JS Scripting",
|
||||||
tagline: "Execute JavaScript Code",
|
tagline: "Execute JavaScript Code",
|
||||||
icon: "Code",
|
icon: "Code",
|
||||||
description: "Run a piece of JavaScript code in your automation",
|
description: "Run a piece of JavaScript code in your automation",
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: "EXECUTE_SCRIPT",
|
stepId: AutomationActionStepId.EXECUTE_SCRIPT,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
||||||
|
@ -38,7 +43,12 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs, appId, context, emitter }) {
|
export async function run({
|
||||||
|
inputs,
|
||||||
|
appId,
|
||||||
|
context,
|
||||||
|
emitter,
|
||||||
|
}: AutomationStepInput) {
|
||||||
if (inputs.code == null) {
|
if (inputs.code == null) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -48,7 +58,7 @@ exports.run = async function ({ inputs, appId, context, emitter }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ctx = buildCtx(appId, emitter, {
|
const ctx: any = buildCtx(appId, emitter, {
|
||||||
body: {
|
body: {
|
||||||
script: inputs.code,
|
script: inputs.code,
|
||||||
context,
|
context,
|
|
@ -1,21 +1,24 @@
|
||||||
const FilterConditions = {
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
|
export const FilterConditions = {
|
||||||
EQUAL: "EQUAL",
|
EQUAL: "EQUAL",
|
||||||
NOT_EQUAL: "NOT_EQUAL",
|
NOT_EQUAL: "NOT_EQUAL",
|
||||||
GREATER_THAN: "GREATER_THAN",
|
GREATER_THAN: "GREATER_THAN",
|
||||||
LESS_THAN: "LESS_THAN",
|
LESS_THAN: "LESS_THAN",
|
||||||
}
|
}
|
||||||
|
|
||||||
const PrettyFilterConditions = {
|
export const PrettyFilterConditions = {
|
||||||
[FilterConditions.EQUAL]: "Equals",
|
[FilterConditions.EQUAL]: "Equals",
|
||||||
[FilterConditions.NOT_EQUAL]: "Not equals",
|
[FilterConditions.NOT_EQUAL]: "Not equals",
|
||||||
[FilterConditions.GREATER_THAN]: "Greater than",
|
[FilterConditions.GREATER_THAN]: "Greater than",
|
||||||
[FilterConditions.LESS_THAN]: "Less than",
|
[FilterConditions.LESS_THAN]: "Less than",
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.FilterConditions = FilterConditions
|
export const definition: AutomationStep = {
|
||||||
exports.PrettyFilterConditions = PrettyFilterConditions
|
|
||||||
|
|
||||||
exports.definition = {
|
|
||||||
name: "Condition",
|
name: "Condition",
|
||||||
tagline: "{{inputs.field}} {{inputs.condition}} {{inputs.value}}",
|
tagline: "{{inputs.field}} {{inputs.condition}} {{inputs.value}}",
|
||||||
icon: "Branch2",
|
icon: "Branch2",
|
||||||
|
@ -23,9 +26,9 @@ exports.definition = {
|
||||||
"Conditionally halt automations which do not meet certain conditions",
|
"Conditionally halt automations which do not meet certain conditions",
|
||||||
type: "LOGIC",
|
type: "LOGIC",
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: "FILTER",
|
stepId: AutomationActionStepId.FILTER,
|
||||||
inputs: {
|
inputs: {
|
||||||
condition: FilterConditions.EQUALS,
|
condition: FilterConditions.EQUAL,
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
||||||
|
@ -63,7 +66,7 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function filter({ inputs }) {
|
export async function run({ inputs }: AutomationStepInput) {
|
||||||
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
|
|
@ -1,13 +1,18 @@
|
||||||
const fetch = require("node-fetch")
|
import fetch from "node-fetch"
|
||||||
const { getFetchResponse } = require("./utils")
|
import { getFetchResponse } from "./utils"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
name: "Integromat Integration",
|
name: "Integromat Integration",
|
||||||
tagline: "Trigger an Integromat scenario",
|
tagline: "Trigger an Integromat scenario",
|
||||||
description:
|
description:
|
||||||
"Performs a webhook call to Integromat and gets the response (if configured)",
|
"Performs a webhook call to Integromat and gets the response (if configured)",
|
||||||
icon: "ri-shut-down-line",
|
icon: "ri-shut-down-line",
|
||||||
stepId: "integromat",
|
stepId: AutomationActionStepId.integromat,
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
internal: false,
|
internal: false,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
@ -61,7 +66,7 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs }) {
|
export async function run({ inputs }: AutomationStepInput) {
|
||||||
const { url, value1, value2, value3, value4, value5 } = inputs
|
const { url, value1, value2, value3, value4, value5 } = inputs
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
|
@ -1,9 +1,11 @@
|
||||||
exports.definition = {
|
import { AutomationActionStepId, AutomationStep } from "@budibase/types"
|
||||||
|
|
||||||
|
export const definition: AutomationStep = {
|
||||||
name: "Looping",
|
name: "Looping",
|
||||||
icon: "Reuse",
|
icon: "Reuse",
|
||||||
tagline: "Loop the block",
|
tagline: "Loop the block",
|
||||||
description: "Loop",
|
description: "Loop",
|
||||||
stepId: "LOOP",
|
stepId: AutomationActionStepId.LOOP,
|
||||||
internal: true,
|
internal: true,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
|
@ -1,13 +1,18 @@
|
||||||
const fetch = require("node-fetch")
|
import fetch from "node-fetch"
|
||||||
const { getFetchResponse } = require("./utils")
|
import { getFetchResponse } from "./utils"
|
||||||
const automationUtils = require("../automationUtils")
|
import automationUtils from "../automationUtils"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
const RequestType = {
|
enum RequestType {
|
||||||
POST: "POST",
|
POST = "POST",
|
||||||
GET: "GET",
|
GET = "GET",
|
||||||
PUT: "PUT",
|
PUT = "PUT",
|
||||||
DELETE: "DELETE",
|
DELETE = "DELETE",
|
||||||
PATCH: "PATCH",
|
PATCH = "PATCH",
|
||||||
}
|
}
|
||||||
|
|
||||||
const BODY_REQUESTS = [RequestType.POST, RequestType.PUT, RequestType.PATCH]
|
const BODY_REQUESTS = [RequestType.POST, RequestType.PUT, RequestType.PATCH]
|
||||||
|
@ -16,7 +21,7 @@ const BODY_REQUESTS = [RequestType.POST, RequestType.PUT, RequestType.PATCH]
|
||||||
* NOTE: this functionality is deprecated - it no longer should be used.
|
* NOTE: this functionality is deprecated - it no longer should be used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
deprecated: true,
|
deprecated: true,
|
||||||
name: "Outgoing webhook",
|
name: "Outgoing webhook",
|
||||||
tagline: "Send a {{inputs.requestMethod}} request",
|
tagline: "Send a {{inputs.requestMethod}} request",
|
||||||
|
@ -24,7 +29,7 @@ exports.definition = {
|
||||||
description: "Send a request of specified method to a URL",
|
description: "Send a request of specified method to a URL",
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: "OUTGOING_WEBHOOK",
|
stepId: AutomationActionStepId.OUTGOING_WEBHOOK,
|
||||||
inputs: {
|
inputs: {
|
||||||
requestMethod: "POST",
|
requestMethod: "POST",
|
||||||
url: "http://",
|
url: "http://",
|
||||||
|
@ -76,12 +81,12 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs }) {
|
export async function run({ inputs }: AutomationStepInput) {
|
||||||
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}`
|
||||||
}
|
}
|
||||||
const request = {
|
const request: any = {
|
||||||
method: requestMethod,
|
method: requestMethod,
|
||||||
}
|
}
|
||||||
if (headers) {
|
if (headers) {
|
|
@ -1,36 +1,43 @@
|
||||||
const rowController = require("../../api/controllers/row")
|
import * as rowController from "../../api/controllers/row"
|
||||||
const tableController = require("../../api/controllers/table")
|
import * as tableController from "../../api/controllers/table"
|
||||||
const { FieldTypes } = require("../../constants")
|
import { FieldTypes } from "../../constants"
|
||||||
const { buildCtx } = require("./utils")
|
import { buildCtx } from "./utils"
|
||||||
const automationUtils = require("../automationUtils")
|
import automationUtils from "../automationUtils"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
SearchFilters,
|
||||||
|
Table,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
const SortOrders = {
|
enum SortOrder {
|
||||||
ASCENDING: "ascending",
|
ASCENDING = "ascending",
|
||||||
DESCENDING: "descending",
|
DESCENDING = "descending",
|
||||||
}
|
}
|
||||||
|
|
||||||
const SortOrdersPretty = {
|
const SortOrderPretty = {
|
||||||
[SortOrders.ASCENDING]: "Ascending",
|
[SortOrder.ASCENDING]: "Ascending",
|
||||||
[SortOrders.DESCENDING]: "Descending",
|
[SortOrder.DESCENDING]: "Descending",
|
||||||
}
|
}
|
||||||
|
|
||||||
const EmptyFilterOptions = {
|
enum EmptyFilterOption {
|
||||||
RETURN_ALL: "all",
|
RETURN_ALL = "all",
|
||||||
RETURN_NONE: "none",
|
RETURN_NONE = "none",
|
||||||
}
|
}
|
||||||
|
|
||||||
const EmptyFilterOptionsPretty = {
|
const EmptyFilterOptionPretty = {
|
||||||
[EmptyFilterOptions.RETURN_ALL]: "Return all table rows",
|
[EmptyFilterOption.RETURN_ALL]: "Return all table rows",
|
||||||
[EmptyFilterOptions.RETURN_NONE]: "Return no rows",
|
[EmptyFilterOption.RETURN_NONE]: "Return no rows",
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
description: "Query rows from the database",
|
description: "Query rows from the database",
|
||||||
icon: "Search",
|
icon: "Search",
|
||||||
name: "Query rows",
|
name: "Query rows",
|
||||||
tagline: "Query rows from {{inputs.enriched.table.name}} table",
|
tagline: "Query rows from {{inputs.enriched.table.name}} table",
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
stepId: "QUERY_ROWS",
|
stepId: AutomationActionStepId.QUERY_ROWS,
|
||||||
internal: true,
|
internal: true,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
|
@ -54,8 +61,8 @@ exports.definition = {
|
||||||
sortOrder: {
|
sortOrder: {
|
||||||
type: "string",
|
type: "string",
|
||||||
title: "Sort Order",
|
title: "Sort Order",
|
||||||
enum: Object.values(SortOrders),
|
enum: Object.values(SortOrder),
|
||||||
pretty: Object.values(SortOrdersPretty),
|
pretty: Object.values(SortOrderPretty),
|
||||||
},
|
},
|
||||||
limit: {
|
limit: {
|
||||||
type: "number",
|
type: "number",
|
||||||
|
@ -63,8 +70,8 @@ exports.definition = {
|
||||||
customType: "queryLimit",
|
customType: "queryLimit",
|
||||||
},
|
},
|
||||||
onEmptyFilter: {
|
onEmptyFilter: {
|
||||||
pretty: Object.values(EmptyFilterOptionsPretty),
|
pretty: Object.values(EmptyFilterOptionPretty),
|
||||||
enum: Object.values(EmptyFilterOptions),
|
enum: Object.values(EmptyFilterOption),
|
||||||
type: "string",
|
type: "string",
|
||||||
title: "When Filter Empty",
|
title: "When Filter Empty",
|
||||||
},
|
},
|
||||||
|
@ -88,8 +95,8 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getTable(appId, tableId) {
|
async function getTable(appId: string, tableId: string) {
|
||||||
const ctx = buildCtx(appId, null, {
|
const ctx: any = buildCtx(appId, null, {
|
||||||
params: {
|
params: {
|
||||||
tableId,
|
tableId,
|
||||||
},
|
},
|
||||||
|
@ -98,20 +105,22 @@ async function getTable(appId, tableId) {
|
||||||
return ctx.body
|
return ctx.body
|
||||||
}
|
}
|
||||||
|
|
||||||
function typeCoercion(filters, table) {
|
function typeCoercion(filters: SearchFilters, table: Table) {
|
||||||
if (!filters || !table) {
|
if (!filters || !table) {
|
||||||
return filters
|
return filters
|
||||||
}
|
}
|
||||||
for (let key of Object.keys(filters)) {
|
for (let key of Object.keys(filters)) {
|
||||||
if (typeof filters[key] === "object") {
|
// @ts-ignore
|
||||||
for (let [property, value] of Object.entries(filters[key])) {
|
const searchParam = filters[key]
|
||||||
|
if (typeof searchParam === "object") {
|
||||||
|
for (let [property, value] of Object.entries(searchParam)) {
|
||||||
const column = table.schema[property]
|
const column = table.schema[property]
|
||||||
// convert string inputs
|
// convert string inputs
|
||||||
if (!column || typeof value !== "string") {
|
if (!column || typeof value !== "string") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (column.type === FieldTypes.NUMBER) {
|
if (column.type === FieldTypes.NUMBER) {
|
||||||
filters[key][property] = parseFloat(value)
|
searchParam[property] = parseFloat(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,11 +128,14 @@ function typeCoercion(filters, table) {
|
||||||
return filters
|
return filters
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasNullFilters = filters =>
|
function hasNullFilters(filters: any[]) {
|
||||||
filters.length === 0 ||
|
return (
|
||||||
filters.some(filter => filter.value === null || filter.value === "")
|
filters.length === 0 ||
|
||||||
|
filters.some(filter => filter.value === null || filter.value === "")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs, appId }) {
|
export async function run({ inputs, appId }: AutomationStepInput) {
|
||||||
const { tableId, filters, sortColumn, sortOrder, limit } = inputs
|
const { tableId, filters, sortColumn, sortOrder, limit } = inputs
|
||||||
if (!tableId) {
|
if (!tableId) {
|
||||||
return {
|
return {
|
||||||
|
@ -140,7 +152,7 @@ exports.run = async function ({ inputs, appId }) {
|
||||||
sortType =
|
sortType =
|
||||||
fieldType === FieldTypes.NUMBER ? FieldTypes.NUMBER : FieldTypes.STRING
|
fieldType === FieldTypes.NUMBER ? FieldTypes.NUMBER : FieldTypes.STRING
|
||||||
}
|
}
|
||||||
const ctx = buildCtx(appId, null, {
|
const ctx: any = buildCtx(appId, null, {
|
||||||
params: {
|
params: {
|
||||||
tableId,
|
tableId,
|
||||||
},
|
},
|
||||||
|
@ -150,7 +162,7 @@ exports.run = async function ({ inputs, appId }) {
|
||||||
sort: sortColumn,
|
sort: sortColumn,
|
||||||
query: typeCoercion(filters || {}, table),
|
query: typeCoercion(filters || {}, table),
|
||||||
// default to ascending, like data tab
|
// default to ascending, like data tab
|
||||||
sortOrder: sortOrder || SortOrders.ASCENDING,
|
sortOrder: sortOrder || SortOrder.ASCENDING,
|
||||||
},
|
},
|
||||||
version: "1",
|
version: "1",
|
||||||
})
|
})
|
||||||
|
@ -158,7 +170,7 @@ exports.run = async function ({ inputs, appId }) {
|
||||||
let rows
|
let rows
|
||||||
|
|
||||||
if (
|
if (
|
||||||
inputs.onEmptyFilter === EmptyFilterOptions.RETURN_NONE &&
|
inputs.onEmptyFilter === EmptyFilterOption.RETURN_NONE &&
|
||||||
inputs["filters-def"] &&
|
inputs["filters-def"] &&
|
||||||
hasNullFilters(inputs["filters-def"])
|
hasNullFilters(inputs["filters-def"])
|
||||||
) {
|
) {
|
|
@ -1,14 +1,19 @@
|
||||||
const { sendSmtpEmail } = require("../../utilities/workerRequests")
|
import { sendSmtpEmail } from "../../utilities/workerRequests"
|
||||||
const automationUtils = require("../automationUtils")
|
import automationUtils from "../automationUtils"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
description: "Send an email using SMTP",
|
description: "Send an email using SMTP",
|
||||||
tagline: "Send SMTP email to {{inputs.to}}",
|
tagline: "Send SMTP email to {{inputs.to}}",
|
||||||
icon: "Email",
|
icon: "Email",
|
||||||
name: "Send Email (SMTP)",
|
name: "Send Email (SMTP)",
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: "SEND_EMAIL_SMTP",
|
stepId: AutomationActionStepId.SEND_EMAIL_SMTP,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
||||||
|
@ -56,7 +61,7 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs }) {
|
export async function run({ inputs }: AutomationStepInput) {
|
||||||
let { to, from, subject, contents, cc, bcc } = inputs
|
let { to, from, subject, contents, cc, bcc } = inputs
|
||||||
if (!contents) {
|
if (!contents) {
|
||||||
contents = "<h1>No content</h1>"
|
contents = "<h1>No content</h1>"
|
|
@ -1,17 +1,23 @@
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note, there is some functionality in this that is not currently exposed as it
|
* Note, there is some functionality in this that is not currently exposed as it
|
||||||
* is complex and maybe better to be opinionated here.
|
* is complex and maybe better to be opinionated here.
|
||||||
* GET/DELETE requests cannot handle body elements so they will not be sent if configured.
|
* GET/DELETE requests cannot handle body elements so they will not be sent if configured.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
name: "Backend log",
|
name: "Backend log",
|
||||||
tagline: "Console log a value in the backend",
|
tagline: "Console log a value in the backend",
|
||||||
icon: "Monitoring",
|
icon: "Monitoring",
|
||||||
description: "Logs the given text to the server (using console.log)",
|
description: "Logs the given text to the server (using console.log)",
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: "SERVER_LOG",
|
stepId: AutomationActionStepId.SERVER_LOG,
|
||||||
inputs: {
|
inputs: {
|
||||||
text: "",
|
text: "",
|
||||||
},
|
},
|
||||||
|
@ -41,7 +47,7 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs, appId }) {
|
export async function run({ inputs, appId }: AutomationStepInput) {
|
||||||
const message = `App ${appId} - ${inputs.text}`
|
const message = `App ${appId} - ${inputs.text}`
|
||||||
console.log(message)
|
console.log(message)
|
||||||
return {
|
return {
|
|
@ -1,12 +1,17 @@
|
||||||
const fetch = require("node-fetch")
|
import fetch from "node-fetch"
|
||||||
const { getFetchResponse } = require("./utils")
|
import { getFetchResponse } from "./utils"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
name: "Slack Message",
|
name: "Slack Message",
|
||||||
tagline: "Send a message to Slack",
|
tagline: "Send a message to Slack",
|
||||||
description: "Send a message to Slack",
|
description: "Send a message to Slack",
|
||||||
icon: "ri-slack-line",
|
icon: "ri-slack-line",
|
||||||
stepId: "slack",
|
stepId: AutomationActionStepId.slack,
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
internal: false,
|
internal: false,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
@ -43,7 +48,7 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs }) {
|
export async function run({ inputs }: AutomationStepInput) {
|
||||||
let { url, text } = inputs
|
let { url, text } = inputs
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "post",
|
method: "post",
|
|
@ -1,15 +1,20 @@
|
||||||
const rowController = require("../../api/controllers/row")
|
import * as rowController from "../../api/controllers/row"
|
||||||
const automationUtils = require("../automationUtils")
|
import automationUtils from "../automationUtils"
|
||||||
const { buildCtx } = require("./utils")
|
import { buildCtx } from "./utils"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
name: "Update Row",
|
name: "Update Row",
|
||||||
tagline: "Update a {{inputs.enriched.table.name}} row",
|
tagline: "Update a {{inputs.enriched.table.name}} row",
|
||||||
icon: "Refresh",
|
icon: "Refresh",
|
||||||
description: "Update a row in your database",
|
description: "Update a row in your database",
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: "UPDATE_ROW",
|
stepId: AutomationActionStepId.UPDATE_ROW,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
||||||
|
@ -55,7 +60,7 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs, appId, emitter }) {
|
export async function run({ inputs, appId, emitter }: AutomationStepInput) {
|
||||||
if (inputs.rowId == null || inputs.row == null) {
|
if (inputs.rowId == null || inputs.row == null) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -74,7 +79,7 @@ exports.run = async function ({ inputs, appId, emitter }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// have to clean up the row, remove the table from it
|
// have to clean up the row, remove the table from it
|
||||||
const ctx = buildCtx(appId, emitter, {
|
const ctx: any = buildCtx(appId, emitter, {
|
||||||
body: {
|
body: {
|
||||||
...inputs.row,
|
...inputs.row,
|
||||||
_id: inputs.rowId,
|
_id: inputs.rowId,
|
|
@ -1,4 +1,6 @@
|
||||||
exports.getFetchResponse = async fetched => {
|
import { EventEmitter } from "events"
|
||||||
|
|
||||||
|
export async function getFetchResponse(fetched: any) {
|
||||||
let status = fetched.status,
|
let status = fetched.status,
|
||||||
message
|
message
|
||||||
const contentType = fetched.headers.get("content-type")
|
const contentType = fetched.headers.get("content-type")
|
||||||
|
@ -18,12 +20,16 @@ exports.getFetchResponse = async fetched => {
|
||||||
// throw added to them, so that controllers don't
|
// throw added to them, so that controllers don't
|
||||||
// throw a ctx.throw undefined when error occurs
|
// throw a ctx.throw undefined when error occurs
|
||||||
// opts can contain, body, params and version
|
// opts can contain, body, params and version
|
||||||
exports.buildCtx = (appId, emitter, opts = {}) => {
|
export async function buildCtx(
|
||||||
const ctx = {
|
appId: string,
|
||||||
|
emitter?: EventEmitter | null,
|
||||||
|
opts: any = {}
|
||||||
|
) {
|
||||||
|
const ctx: any = {
|
||||||
appId,
|
appId,
|
||||||
user: { appId },
|
user: { appId },
|
||||||
eventEmitter: emitter,
|
eventEmitter: emitter,
|
||||||
throw: (code, error) => {
|
throw: (code: string, error: any) => {
|
||||||
throw error
|
throw error
|
||||||
},
|
},
|
||||||
}
|
}
|
|
@ -1,14 +1,20 @@
|
||||||
const fetch = require("node-fetch")
|
import fetch from "node-fetch"
|
||||||
const { getFetchResponse } = require("./utils")
|
import { getFetchResponse } from "./utils"
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepInput,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
exports.definition = {
|
export const definition: AutomationStep = {
|
||||||
name: "Zapier Webhook",
|
name: "Zapier Webhook",
|
||||||
stepId: "zapier",
|
stepId: AutomationActionStepId.zapier,
|
||||||
type: "ACTION",
|
type: "ACTION",
|
||||||
internal: false,
|
internal: false,
|
||||||
description: "Trigger a Zapier Zap via webhooks",
|
description: "Trigger a Zapier Zap via webhooks",
|
||||||
tagline: "Trigger a Zapier Zap",
|
tagline: "Trigger a Zapier Zap",
|
||||||
icon: "ri-flashlight-line",
|
icon: "ri-flashlight-line",
|
||||||
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
|
@ -54,7 +60,7 @@ exports.definition = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run = async function ({ inputs }) {
|
export async function run({ inputs }: AutomationStepInput) {
|
||||||
const { url, value1, value2, value3, value4, value5 } = inputs
|
const { url, value1, value2, value3, value4, value5 } = inputs
|
||||||
|
|
||||||
// send the platform to make sure zaps always work, even
|
// send the platform to make sure zaps always work, even
|
|
@ -1,10 +1,12 @@
|
||||||
exports.definition = {
|
import { AutomationTrigger, AutomationTriggerStepId } from "@budibase/types"
|
||||||
|
|
||||||
|
export const definition: AutomationTrigger = {
|
||||||
name: "App Action",
|
name: "App Action",
|
||||||
event: "app:trigger",
|
event: "app:trigger",
|
||||||
icon: "Apps",
|
icon: "Apps",
|
||||||
tagline: "Automation fired from the frontend",
|
tagline: "Automation fired from the frontend",
|
||||||
description: "Trigger an automation from an action inside your app",
|
description: "Trigger an automation from an action inside your app",
|
||||||
stepId: "APP",
|
stepId: AutomationTriggerStepId.APP,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
|
@ -1,10 +1,12 @@
|
||||||
exports.definition = {
|
import { AutomationTrigger, AutomationTriggerStepId } from "@budibase/types"
|
||||||
|
|
||||||
|
export const definition: AutomationTrigger = {
|
||||||
name: "Cron Trigger",
|
name: "Cron Trigger",
|
||||||
event: "cron:trigger",
|
event: "cron:trigger",
|
||||||
icon: "Clock",
|
icon: "Clock",
|
||||||
tagline: "Cron Trigger (<b>{{inputs.cron}}</b>)",
|
tagline: "Cron Trigger (<b>{{inputs.cron}}</b>)",
|
||||||
description: "Triggers automation on a cron schedule.",
|
description: "Triggers automation on a cron schedule.",
|
||||||
stepId: "CRON",
|
stepId: AutomationTriggerStepId.CRON,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
|
@ -1,15 +0,0 @@
|
||||||
const app = require("./app")
|
|
||||||
const cron = require("./cron")
|
|
||||||
const rowDeleted = require("./rowDeleted")
|
|
||||||
const rowSaved = require("./rowSaved")
|
|
||||||
const rowUpdated = require("./rowUpdated")
|
|
||||||
const webhook = require("./webhook")
|
|
||||||
|
|
||||||
exports.definitions = {
|
|
||||||
ROW_SAVED: rowSaved.definition,
|
|
||||||
ROW_UPDATED: rowUpdated.definition,
|
|
||||||
ROW_DELETED: rowDeleted.definition,
|
|
||||||
WEBHOOK: webhook.definition,
|
|
||||||
APP: app.definition,
|
|
||||||
CRON: cron.definition,
|
|
||||||
}
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import app from "./app"
|
||||||
|
import cron from "./cron"
|
||||||
|
import rowDeleted from "./rowDeleted"
|
||||||
|
import rowSaved from "./rowSaved"
|
||||||
|
import rowUpdated from "./rowUpdated"
|
||||||
|
import webhook from "./webhook"
|
||||||
|
|
||||||
|
export const definitions = {
|
||||||
|
ROW_SAVED: rowSaved.definition,
|
||||||
|
ROW_UPDATED: rowUpdated.definition,
|
||||||
|
ROW_DELETED: rowDeleted.definition,
|
||||||
|
WEBHOOK: webhook.definition,
|
||||||
|
APP: app.definition,
|
||||||
|
CRON: cron.definition,
|
||||||
|
}
|
|
@ -1,10 +1,12 @@
|
||||||
exports.definition = {
|
import { AutomationTrigger, AutomationTriggerStepId } from "@budibase/types"
|
||||||
|
|
||||||
|
export const definition: AutomationTrigger = {
|
||||||
name: "Row Deleted",
|
name: "Row Deleted",
|
||||||
event: "row:delete",
|
event: "row:delete",
|
||||||
icon: "TableRowRemoveCenter",
|
icon: "TableRowRemoveCenter",
|
||||||
tagline: "Row is deleted from {{inputs.enriched.table.name}}",
|
tagline: "Row is deleted from {{inputs.enriched.table.name}}",
|
||||||
description: "Fired when a row is deleted from your database",
|
description: "Fired when a row is deleted from your database",
|
||||||
stepId: "ROW_DELETED",
|
stepId: AutomationTriggerStepId.ROW_DELETED,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
|
@ -1,10 +1,12 @@
|
||||||
exports.definition = {
|
import { AutomationTrigger, AutomationTriggerStepId } from "@budibase/types"
|
||||||
|
|
||||||
|
export const definition: AutomationTrigger = {
|
||||||
name: "Row Created",
|
name: "Row Created",
|
||||||
event: "row:save",
|
event: "row:save",
|
||||||
icon: "TableRowAddBottom",
|
icon: "TableRowAddBottom",
|
||||||
tagline: "Row is added to {{inputs.enriched.table.name}}",
|
tagline: "Row is added to {{inputs.enriched.table.name}}",
|
||||||
description: "Fired when a row is added to your database",
|
description: "Fired when a row is added to your database",
|
||||||
stepId: "ROW_SAVED",
|
stepId: AutomationTriggerStepId.ROW_SAVED,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
|
@ -1,10 +1,12 @@
|
||||||
exports.definition = {
|
import { AutomationTrigger, AutomationTriggerStepId } from "@budibase/types"
|
||||||
|
|
||||||
|
export const definition: AutomationTrigger = {
|
||||||
name: "Row Updated",
|
name: "Row Updated",
|
||||||
event: "row:update",
|
event: "row:update",
|
||||||
icon: "Refresh",
|
icon: "Refresh",
|
||||||
tagline: "Row is updated in {{inputs.enriched.table.name}}",
|
tagline: "Row is updated in {{inputs.enriched.table.name}}",
|
||||||
description: "Fired when a row is updated in your database",
|
description: "Fired when a row is updated in your database",
|
||||||
stepId: "ROW_UPDATED",
|
stepId: AutomationTriggerStepId.ROW_UPDATED,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
|
@ -1,10 +1,12 @@
|
||||||
exports.definition = {
|
import { AutomationTrigger, AutomationTriggerStepId } from "@budibase/types"
|
||||||
|
|
||||||
|
export const definition: AutomationTrigger = {
|
||||||
name: "Webhook",
|
name: "Webhook",
|
||||||
event: "web:trigger",
|
event: "web:trigger",
|
||||||
icon: "Send",
|
icon: "Send",
|
||||||
tagline: "Webhook endpoint is hit",
|
tagline: "Webhook endpoint is hit",
|
||||||
description: "Trigger an automation when a HTTP POST webhook is hit",
|
description: "Trigger an automation when a HTTP POST webhook is hit",
|
||||||
stepId: "WEBHOOK",
|
stepId: AutomationTriggerStepId.WEBHOOK,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
|
@ -1,16 +1,17 @@
|
||||||
const emitter = require("../events/index")
|
import emitter from "../events/index"
|
||||||
const { getAutomationParams } = require("../db/utils")
|
import { getAutomationParams } from "../db/utils"
|
||||||
const { coerce } = require("../utilities/rowProcessor")
|
import { coerce } from "../utilities/rowProcessor"
|
||||||
const { definitions } = require("./triggerInfo")
|
import { definitions } from "./triggerInfo"
|
||||||
const { isDevAppID } = require("../db/utils")
|
import { isDevAppID } from "../db/utils"
|
||||||
// need this to call directly, so we can get a response
|
// need this to call directly, so we can get a response
|
||||||
const { automationQueue } = require("./bullboard")
|
import { automationQueue } from "./bullboard"
|
||||||
const { checkTestFlag } = require("../utilities/redis")
|
import { checkTestFlag } from "../utilities/redis"
|
||||||
const utils = require("./utils")
|
import * as utils from "./utils"
|
||||||
const env = require("../environment")
|
import env from "../environment"
|
||||||
const { context, db: dbCore } = require("@budibase/backend-core")
|
import { context, db as dbCore } from "@budibase/backend-core"
|
||||||
|
import { Automation, Row } from "@budibase/types"
|
||||||
|
|
||||||
const TRIGGER_DEFINITIONS = definitions
|
export const TRIGGER_DEFINITIONS = definitions
|
||||||
const JOB_OPTS = {
|
const JOB_OPTS = {
|
||||||
removeOnComplete: true,
|
removeOnComplete: true,
|
||||||
removeOnFail: true,
|
removeOnFail: true,
|
||||||
|
@ -24,12 +25,15 @@ async function getAllAutomations() {
|
||||||
return automations.rows.map(row => row.doc)
|
return automations.rows.map(row => row.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function queueRelevantRowAutomations(event, eventType) {
|
async function queueRelevantRowAutomations(
|
||||||
|
event: { appId: string; row: Row },
|
||||||
|
eventType: string
|
||||||
|
) {
|
||||||
if (event.appId == null) {
|
if (event.appId == null) {
|
||||||
throw `No appId specified for ${eventType} - check event emitters.`
|
throw `No appId specified for ${eventType} - check event emitters.`
|
||||||
}
|
}
|
||||||
|
|
||||||
context.doInAppContext(event.appId, async () => {
|
await context.doInAppContext(event.appId, async () => {
|
||||||
let automations = await getAllAutomations()
|
let automations = await getAllAutomations()
|
||||||
|
|
||||||
// filter down to the correct event type
|
// filter down to the correct event type
|
||||||
|
@ -85,20 +89,20 @@ emitter.on("row:delete", async function (event) {
|
||||||
await queueRelevantRowAutomations(event, "row:delete")
|
await queueRelevantRowAutomations(event, "row:delete")
|
||||||
})
|
})
|
||||||
|
|
||||||
exports.externalTrigger = async function (
|
export async function externalTrigger(
|
||||||
automation,
|
automation: Automation,
|
||||||
params,
|
params: { fields: Record<string, any> },
|
||||||
{ getResponses } = {}
|
{ getResponses }: { getResponses?: boolean } = {}
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
automation.definition != null &&
|
automation.definition != null &&
|
||||||
automation.definition.trigger != null &&
|
automation.definition.trigger != null &&
|
||||||
automation.definition.trigger.stepId === definitions.APP.stepId &&
|
automation.definition.trigger.stepId === definitions.APP.stepId &&
|
||||||
automation.definition.trigger.stepId === "APP" &&
|
automation.definition.trigger.stepId === "APP" &&
|
||||||
!(await checkTestFlag(automation._id))
|
!(await checkTestFlag(automation._id!))
|
||||||
) {
|
) {
|
||||||
// values are likely to be submitted as strings, so we shall convert to correct type
|
// values are likely to be submitted as strings, so we shall convert to correct type
|
||||||
const coercedFields = {}
|
const coercedFields: any = {}
|
||||||
const fields = automation.definition.trigger.inputs.fields
|
const fields = automation.definition.trigger.inputs.fields
|
||||||
for (let key of Object.keys(fields || {})) {
|
for (let key of Object.keys(fields || {})) {
|
||||||
coercedFields[key] = coerce(params.fields[key], fields[key])
|
coercedFields[key] = coerce(params.fields[key], fields[key])
|
||||||
|
@ -113,7 +117,7 @@ exports.externalTrigger = async function (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.rebootTrigger = async () => {
|
export async function rebootTrigger() {
|
||||||
// reboot cron option is only available on the main thread at
|
// reboot cron option is only available on the main thread at
|
||||||
// startup and only usable in self host and single tenant environments
|
// startup and only usable in self host and single tenant environments
|
||||||
if (env.isInThread() || !env.SELF_HOSTED || env.MULTI_TENANCY) {
|
if (env.isInThread() || !env.SELF_HOSTED || env.MULTI_TENANCY) {
|
||||||
|
@ -121,7 +125,10 @@ exports.rebootTrigger = async () => {
|
||||||
}
|
}
|
||||||
// iterate through all production apps, find the reboot crons
|
// iterate through all production apps, find the reboot crons
|
||||||
// and trigger events for them
|
// and trigger events for them
|
||||||
const appIds = await dbCore.getAllApps({ dev: false, idsOnly: true })
|
const appIds = (await dbCore.getAllApps({
|
||||||
|
dev: false,
|
||||||
|
idsOnly: true,
|
||||||
|
})) as string[]
|
||||||
for (let prodAppId of appIds) {
|
for (let prodAppId of appIds) {
|
||||||
await context.doInAppContext(prodAppId, async () => {
|
await context.doInAppContext(prodAppId, async () => {
|
||||||
let automations = await getAllAutomations()
|
let automations = await getAllAutomations()
|
||||||
|
@ -142,5 +149,3 @@ exports.rebootTrigger = async () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.TRIGGER_DEFINITIONS = TRIGGER_DEFINITIONS
|
|
|
@ -1,4 +1,4 @@
|
||||||
const { join } = require("path")
|
import { join } from "path"
|
||||||
|
|
||||||
function isTest() {
|
function isTest() {
|
||||||
return isCypress() || isJest()
|
return isCypress() || isJest()
|
||||||
|
@ -28,7 +28,7 @@ if (!LOADED && isDev() && !isTest()) {
|
||||||
LOADED = true
|
LOADED = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseIntSafe(number) {
|
function parseIntSafe(number?: string) {
|
||||||
if (number) {
|
if (number) {
|
||||||
return parseInt(number)
|
return parseInt(number)
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ function parseIntSafe(number) {
|
||||||
|
|
||||||
let inThread = false
|
let inThread = false
|
||||||
|
|
||||||
module.exports = {
|
const environment = {
|
||||||
// important - prefer app port to generic port
|
// important - prefer app port to generic port
|
||||||
PORT: process.env.APP_PORT || process.env.PORT,
|
PORT: process.env.APP_PORT || process.env.PORT,
|
||||||
JWT_SECRET: process.env.JWT_SECRET,
|
JWT_SECRET: process.env.JWT_SECRET,
|
||||||
|
@ -86,7 +86,7 @@ module.exports = {
|
||||||
SELF_HOSTED: process.env.SELF_HOSTED,
|
SELF_HOSTED: process.env.SELF_HOSTED,
|
||||||
// old
|
// old
|
||||||
CLIENT_ID: process.env.CLIENT_ID,
|
CLIENT_ID: process.env.CLIENT_ID,
|
||||||
_set(key, value) {
|
_set(key: string, value: any) {
|
||||||
process.env[key] = value
|
process.env[key] = value
|
||||||
module.exports[key] = value
|
module.exports[key] = value
|
||||||
},
|
},
|
||||||
|
@ -108,13 +108,16 @@ module.exports = {
|
||||||
|
|
||||||
// threading can cause memory issues with node-ts in development
|
// threading can cause memory issues with node-ts in development
|
||||||
if (isDev() && module.exports.DISABLE_THREADING == null) {
|
if (isDev() && module.exports.DISABLE_THREADING == null) {
|
||||||
module.exports._set("DISABLE_THREADING", "1")
|
environment._set("DISABLE_THREADING", "1")
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up any environment variable edge cases
|
// clean up any environment variable edge cases
|
||||||
for (let [key, value] of Object.entries(module.exports)) {
|
for (let [key, value] of Object.entries(module.exports)) {
|
||||||
// handle the edge case of "0" to disable an environment variable
|
// handle the edge case of "0" to disable an environment variable
|
||||||
if (value === "0") {
|
if (value === "0") {
|
||||||
module.exports[key] = 0
|
// @ts-ignore
|
||||||
|
environment[key] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export = environment
|
|
@ -62,7 +62,7 @@ export async function sendSmtpEmail(
|
||||||
contents: string,
|
contents: string,
|
||||||
cc: string,
|
cc: string,
|
||||||
bcc: string,
|
bcc: string,
|
||||||
automation: Automation
|
automation: boolean
|
||||||
) {
|
) {
|
||||||
// tenant ID will be set in header
|
// tenant ID will be set in header
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Document } from "../document"
|
import { Document } from "../document"
|
||||||
|
import { EventEmitter } from "events"
|
||||||
|
|
||||||
export enum AutomationTriggerStepId {
|
export enum AutomationTriggerStepId {
|
||||||
ROW_SAVED = "ROW_SAVED",
|
ROW_SAVED = "ROW_SAVED",
|
||||||
|
@ -14,6 +15,7 @@ export enum AutomationActionStepId {
|
||||||
CREATE_ROW = "CREATE_ROW",
|
CREATE_ROW = "CREATE_ROW",
|
||||||
UPDATE_ROW = "UPDATE_ROW",
|
UPDATE_ROW = "UPDATE_ROW",
|
||||||
DELETE_ROW = "DELETE_ROW",
|
DELETE_ROW = "DELETE_ROW",
|
||||||
|
EXECUTE_BASH = "EXECUTE_BASH",
|
||||||
OUTGOING_WEBHOOK = "OUTGOING_WEBHOOK",
|
OUTGOING_WEBHOOK = "OUTGOING_WEBHOOK",
|
||||||
EXECUTE_SCRIPT = "EXECUTE_SCRIPT",
|
EXECUTE_SCRIPT = "EXECUTE_SCRIPT",
|
||||||
EXECUTE_QUERY = "EXECUTE_QUERY",
|
EXECUTE_QUERY = "EXECUTE_QUERY",
|
||||||
|
@ -40,7 +42,14 @@ export interface Automation extends Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AutomationStep {
|
export interface AutomationStep {
|
||||||
id: string
|
id?: string
|
||||||
|
name: string
|
||||||
|
tagline: string
|
||||||
|
icon: string
|
||||||
|
description: string
|
||||||
|
type: string
|
||||||
|
internal?: boolean
|
||||||
|
deprecated?: boolean
|
||||||
stepId: AutomationTriggerStepId | AutomationActionStepId
|
stepId: AutomationTriggerStepId | AutomationActionStepId
|
||||||
inputs: {
|
inputs: {
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
|
@ -52,10 +61,12 @@ export interface AutomationStep {
|
||||||
outputs: {
|
outputs: {
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
required?: string[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AutomationTrigger extends AutomationStep {
|
export interface AutomationTrigger extends AutomationStep {
|
||||||
|
event?: string
|
||||||
cronJobId?: string
|
cronJobId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,3 +102,10 @@ export interface AutomationLogPage {
|
||||||
hasNextPage: boolean
|
hasNextPage: boolean
|
||||||
nextPage?: string
|
nextPage?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AutomationStepInput = {
|
||||||
|
inputs: Record<string, any>
|
||||||
|
context: Record<string, any>
|
||||||
|
emitter: EventEmitter
|
||||||
|
appId: string
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ function parseIntSafe(number: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const env = {
|
const environment = {
|
||||||
// auth
|
// auth
|
||||||
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
|
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
|
||||||
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
|
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
|
||||||
|
@ -77,8 +77,10 @@ const env = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if some var haven't been set, define them
|
// if some var haven't been set, define them
|
||||||
if (!env.APPS_URL) {
|
if (!environment.APPS_URL) {
|
||||||
env.APPS_URL = isDev() ? "http://localhost:4001" : "http://app-service:4002"
|
environment.APPS_URL = isDev()
|
||||||
|
? "http://localhost:4001"
|
||||||
|
: "http://app-service:4002"
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up any environment variable edge cases
|
// clean up any environment variable edge cases
|
||||||
|
@ -90,4 +92,4 @@ for (let [key, value] of Object.entries(module.exports)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export = env
|
export = environment
|
||||||
|
|
Loading…
Reference in New Issue