diff --git a/packages/server/src/api/controllers/rowAction/run.ts b/packages/server/src/api/controllers/rowAction/run.ts
index 06c4b36f86..c4b6a276bf 100644
--- a/packages/server/src/api/controllers/rowAction/run.ts
+++ b/packages/server/src/api/controllers/rowAction/run.ts
@@ -1,3 +1,10 @@
-export function run() {
- throw new Error("Function not implemented.")
+import { RowActionTriggerRequest, Ctx } from "@budibase/types"
+import sdk from "../../../sdk"
+
+export async function run(ctx: Ctx
) {
+ const { tableId, actionId } = ctx.params
+ const { rowId } = ctx.request.body
+
+ await sdk.rowActions.run(tableId, actionId, rowId)
+ ctx.status = 200
}
diff --git a/packages/server/src/api/routes/rowAction.ts b/packages/server/src/api/routes/rowAction.ts
index f4f20822d1..c84d94c007 100644
--- a/packages/server/src/api/routes/rowAction.ts
+++ b/packages/server/src/api/routes/rowAction.ts
@@ -1,13 +1,12 @@
import Router from "@koa/router"
+import Joi from "joi"
+import { middleware, permissions } from "@budibase/backend-core"
import * as rowActionController from "../controllers/rowAction"
import { authorizedResource } from "../../middleware/authorized"
-import { middleware, permissions } from "@budibase/backend-core"
-import Joi from "joi"
-
const { PermissionLevel, PermissionType } = permissions
-export function rowActionValidator() {
+function rowActionValidator() {
return middleware.joiValidator.body(
Joi.object({
name: Joi.string().required(),
@@ -16,6 +15,15 @@ export function rowActionValidator() {
)
}
+function rowTriggerValidator() {
+ return middleware.joiValidator.body(
+ Joi.object({
+ rowId: Joi.string().required(),
+ }),
+ { allowUnknown: false }
+ )
+}
+
const router: Router = new Router()
// CRUD endpoints
@@ -45,7 +53,8 @@ router
// Other endpoints
.post(
- "/api/tables/:tableId/actions/:actionId/run",
+ "/api/tables/:tableId/actions/:actionId/trigger",
+ rowTriggerValidator(),
authorizedResource(PermissionType.TABLE, PermissionLevel.READ, "tableId"),
rowActionController.run
)
diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts
index 7ed4c7d640..9cc53168d0 100644
--- a/packages/server/src/api/routes/tests/row.spec.ts
+++ b/packages/server/src/api/routes/tests/row.spec.ts
@@ -1,3 +1,5 @@
+import * as setup from "./utilities"
+
import {
DatabaseName,
getDatasource,
@@ -7,7 +9,6 @@ import {
import tk from "timekeeper"
import emitter from "../../../../src/events"
import { outputProcessing } from "../../../utilities/rowProcessor"
-import * as setup from "./utilities"
import { context, InternalTable, tenancy } from "@budibase/backend-core"
import { quotas } from "@budibase/pro"
import {
diff --git a/packages/server/src/automations/triggerInfo/rowAction.ts b/packages/server/src/automations/triggerInfo/rowAction.ts
index a7454e8606..862812fe2c 100644
--- a/packages/server/src/automations/triggerInfo/rowAction.ts
+++ b/packages/server/src/automations/triggerInfo/rowAction.ts
@@ -9,11 +9,12 @@ import {
export const definition: AutomationTriggerSchema = {
type: AutomationStepType.TRIGGER,
+ name: "Row Action",
+ event: AutomationEventType.ROW_ACTION, // TODO
+ icon: "Workflow", // TODO
tagline:
"Row action triggered in {{inputs.enriched.table.name}} by {{inputs.enriched.row._id}}",
- name: "Row Action",
- description: "TODO description",
- icon: "Workflow",
+ description: "TODO description", // TODO
stepId: AutomationTriggerStepId.ROW_ACTION,
inputs: {},
schema: {
@@ -28,8 +29,27 @@ export const definition: AutomationTriggerSchema = {
},
required: ["tableId"],
},
- outputs: { properties: {} },
+ outputs: {
+ properties: {
+ id: {
+ type: AutomationIOType.STRING,
+ description: "Row ID - can be used for updating",
+ },
+ revision: {
+ type: AutomationIOType.STRING,
+ description: "Revision of row",
+ },
+ table: {
+ type: AutomationIOType.OBJECT,
+ customType: AutomationCustomIOType.TABLE,
+ title: "The table linked to the row action",
+ },
+ row: {
+ type: AutomationIOType.OBJECT,
+ customType: AutomationCustomIOType.ROW,
+ description: "The row linked to the row action",
+ },
+ },
+ },
},
-
- event: AutomationEventType.ROW_SAVE,
}
diff --git a/packages/server/src/automations/triggers.ts b/packages/server/src/automations/triggers.ts
index 99fc7f02f2..febc8b6a56 100644
--- a/packages/server/src/automations/triggers.ts
+++ b/packages/server/src/automations/triggers.ts
@@ -20,7 +20,7 @@ import {
AutomationStatus,
} from "@budibase/types"
import { executeInThread } from "../threads/automation"
-import { dataFilters } from "@budibase/shared-core"
+import { dataFilters, sdk } from "@budibase/shared-core"
export const TRIGGER_DEFINITIONS = definitions
const JOB_OPTS = {
@@ -121,17 +121,15 @@ function rowPassesFilters(row: Row, filters: SearchFilters) {
export async function externalTrigger(
automation: Automation,
- params: { fields: Record; timeout?: number },
+ params: { fields: Record; timeout?: number; appId?: string },
{ getResponses }: { getResponses?: boolean } = {}
): Promise {
if (automation.disabled) {
throw new Error("Automation is disabled")
}
+
if (
- automation.definition != null &&
- automation.definition.trigger != null &&
- automation.definition.trigger.stepId === definitions.APP.stepId &&
- automation.definition.trigger.stepId === "APP" &&
+ sdk.automations.isAppAction(automation) &&
!(await checkTestFlag(automation._id!))
) {
// values are likely to be submitted as strings, so we shall convert to correct type
@@ -141,6 +139,13 @@ export async function externalTrigger(
coercedFields[key] = coerce(params.fields[key], fields[key])
}
params.fields = coercedFields
+ } else if (sdk.automations.isRowAction(automation)) {
+ params = {
+ ...params,
+ // Until we don't refactor all the types, we want to flatten the nested "fields" object
+ ...params.fields,
+ fields: {},
+ }
}
const data: AutomationData = { automation, event: params }
diff --git a/packages/server/src/sdk/app/automations/tests/index.spec.ts b/packages/server/src/sdk/app/automations/tests/index.spec.ts
index 868dfb30ac..bf4c886cf0 100644
--- a/packages/server/src/sdk/app/automations/tests/index.spec.ts
+++ b/packages/server/src/sdk/app/automations/tests/index.spec.ts
@@ -1,9 +1,9 @@
import { sample } from "lodash/fp"
import { Automation, AutomationTriggerStepId } from "@budibase/types"
import { generator } from "@budibase/backend-core/tests"
+import TestConfiguration from "../../../../tests/utilities/TestConfiguration"
import automationSdk from "../"
import { structures } from "../../../../api/routes/tests/utilities"
-import TestConfiguration from "../../../../tests/utilities/TestConfiguration"
describe("automation sdk", () => {
const config = new TestConfiguration()
diff --git a/packages/server/src/sdk/app/automations/utils.ts b/packages/server/src/sdk/app/automations/utils.ts
index ad06e55418..e89006d618 100644
--- a/packages/server/src/sdk/app/automations/utils.ts
+++ b/packages/server/src/sdk/app/automations/utils.ts
@@ -5,6 +5,7 @@ import {
TableRowActions,
} from "@budibase/types"
import { sdk as coreSdk } from "@budibase/shared-core"
+import sdk from "../../../sdk"
export function checkForCollectStep(automation: Automation) {
return automation.definition.steps.some(
@@ -15,8 +16,6 @@ export function checkForCollectStep(automation: Automation) {
export async function getBuilderData(
automations: Automation[]
): Promise> {
- const sdk = (await import("../../../sdk")).default
-
const tableNameCache: Record = {}
async function getTableName(tableId: string) {
if (!tableNameCache[tableId]) {
diff --git a/packages/server/src/sdk/app/rowActions.ts b/packages/server/src/sdk/app/rowActions.ts
index e59337a7c9..36d2ed7b92 100644
--- a/packages/server/src/sdk/app/rowActions.ts
+++ b/packages/server/src/sdk/app/rowActions.ts
@@ -1,13 +1,15 @@
import { context, HTTPError, utils } from "@budibase/backend-core"
-import { generateRowActionsID } from "../../db/utils"
import {
SEPARATOR,
TableRowActions,
VirtualDocumentType,
} from "@budibase/types"
+import { generateRowActionsID } from "../../db/utils"
import automations from "./automations"
import { definitions as TRIGGER_DEFINITIONS } from "../../automations/triggerInfo"
+import * as triggers from "../../automations/triggers"
+import sdk from ".."
function ensureUniqueAndThrow(
doc: TableRowActions,
@@ -143,3 +145,28 @@ export async function remove(tableId: string, rowActionId: string) {
const db = context.getAppDB()
await db.put(actionsDoc)
}
+
+export async function run(tableId: any, rowActionId: any, rowId: string) {
+ const table = await sdk.tables.getTable(tableId)
+ if (!table) {
+ throw new HTTPError("Table not found", 404)
+ }
+
+ const { actions } = await get(tableId)
+
+ const rowAction = actions[rowActionId]
+ if (!rowAction) {
+ throw new HTTPError("Row action not found", 404)
+ }
+
+ const automation = await sdk.automations.get(rowAction.automationId)
+
+ const row = await sdk.rows.find(tableId, rowId)
+ await triggers.externalTrigger(automation, {
+ fields: {
+ row,
+ table,
+ },
+ appId: context.getAppId(),
+ })
+}
diff --git a/packages/shared-core/src/sdk/documents/automations.ts b/packages/shared-core/src/sdk/documents/automations.ts
index 93e08c86e0..3663f7ae46 100644
--- a/packages/shared-core/src/sdk/documents/automations.ts
+++ b/packages/shared-core/src/sdk/documents/automations.ts
@@ -5,3 +5,9 @@ export function isRowAction(automation: Automation) {
automation.definition.trigger.stepId === AutomationTriggerStepId.ROW_ACTION
return result
}
+
+export function isAppAction(automation: Automation) {
+ const result =
+ automation.definition.trigger.stepId === AutomationTriggerStepId.APP
+ return result
+}
diff --git a/packages/types/src/api/web/app/rowAction.ts b/packages/types/src/api/web/app/rowAction.ts
index 305c42b473..2b2b6e1927 100644
--- a/packages/types/src/api/web/app/rowAction.ts
+++ b/packages/types/src/api/web/app/rowAction.ts
@@ -13,3 +13,7 @@ export interface RowActionResponse extends RowActionData {
export interface RowActionsResponse {
actions: Record
}
+
+export interface RowActionTriggerRequest {
+ rowId: string
+}
diff --git a/packages/types/src/documents/app/automation.ts b/packages/types/src/documents/app/automation.ts
index dd9990951e..b53895e57b 100644
--- a/packages/types/src/documents/app/automation.ts
+++ b/packages/types/src/documents/app/automation.ts
@@ -279,6 +279,7 @@ export enum AutomationEventType {
APP_TRIGGER = "app:trigger",
CRON_TRIGGER = "cron:trigger",
WEBHOOK_TRIGGER = "web:trigger",
+ ROW_ACTION = "row:action",
}
export type UpdatedRowEventEmitter = {