diff --git a/packages/server/src/api/controllers/record.js b/packages/server/src/api/controllers/record.js index c8ef9e96fa..2626667ef3 100644 --- a/packages/server/src/api/controllers/record.js +++ b/packages/server/src/api/controllers/record.js @@ -3,18 +3,18 @@ const validateJs = require("validate.js") const newid = require("../../db/newid") function emitEvent(eventType, ctx, record) { + let event = { + record, + instanceId: ctx.user.instanceId, + } // add syntactic sugar for mustache later if (record._id) { - record.id = record._id + event.id = record._id } if (record._rev) { - record.revision = record._rev + event.revision = record._rev } - ctx.eventEmitter && - ctx.eventEmitter.emit(eventType, { - record, - instanceId: ctx.user.instanceId, - }) + ctx.eventEmitter && ctx.eventEmitter.emit(eventType, event) } validateJs.extend(validateJs.validators.datetime, { diff --git a/packages/server/src/automations/actions.js b/packages/server/src/automations/actions.js index ac0ae63c36..b626919ff6 100644 --- a/packages/server/src/automations/actions.js +++ b/packages/server/src/automations/actions.js @@ -1,5 +1,6 @@ const sendEmail = require("./steps/sendEmail") const saveRecord = require("./steps/saveRecord") +const updateRecord = require("./steps/updateRecord") const deleteRecord = require("./steps/deleteRecord") const createUser = require("./steps/createUser") const environment = require("../environment") @@ -17,12 +18,14 @@ const AUTOMATION_MANIFEST = "manifest.json" const BUILTIN_ACTIONS = { SEND_EMAIL: sendEmail.run, SAVE_RECORD: saveRecord.run, + UPDATE_RECORD: updateRecord.run, DELETE_RECORD: deleteRecord.run, CREATE_USER: createUser.run, } const BUILTIN_DEFINITIONS = { SEND_EMAIL: sendEmail.definition, SAVE_RECORD: saveRecord.definition, + UPDATE_RECORD: updateRecord.definition, DELETE_RECORD: deleteRecord.definition, CREATE_USER: createUser.definition, } diff --git a/packages/server/src/automations/steps/updateRecord.js b/packages/server/src/automations/steps/updateRecord.js new file mode 100644 index 0000000000..5afe2b7f5d --- /dev/null +++ b/packages/server/src/automations/steps/updateRecord.js @@ -0,0 +1,94 @@ +const recordController = require("../../api/controllers/record") + +module.exports.definition = { + name: "Update Record", + tagline: "Update a {{inputs.enriched.model.name}} record", + icon: "ri-refresh-fill", + description: "Update a record to your database", + type: "ACTION", + stepId: "UPDATE_RECORD", + inputs: {}, + schema: { + inputs: { + properties: { + record: { + type: "object", + customType: "record", + title: "Record", + }, + recordId: { + type: "string", + title: "Record ID", + }, + }, + required: ["record", "recordId"], + }, + outputs: { + properties: { + record: { + type: "object", + customType: "record", + description: "The updated record", + }, + response: { + type: "object", + description: "The response from the table", + }, + success: { + type: "boolean", + description: "Whether the action was successful", + }, + id: { + type: "string", + description: "The identifier of the updated record", + }, + revision: { + type: "string", + description: "The revision of the updated record", + }, + }, + required: ["success", "id", "revision"], + }, + }, +} + +module.exports.run = async function({ inputs, instanceId }) { + if (inputs.recordId == null || inputs.record == null) { + return + } + + // clear any falsy properties so that they aren't updated + for (let propKey of Object.keys(inputs.record)) { + if (!inputs.record[propKey] || inputs.record[propKey] === "") { + delete inputs.record[propKey] + } + } + + // have to clean up the record, remove the model from it + const ctx = { + params: { + id: inputs.recordId, + }, + request: { + body: inputs.record, + }, + user: { instanceId }, + } + + try { + await recordController.patch(ctx) + return { + record: ctx.body, + response: ctx.message, + id: ctx.body._id, + revision: ctx.body._rev, + success: ctx.status === 200, + } + } catch (err) { + console.error(err) + return { + success: false, + response: err, + } + } +} diff --git a/packages/server/src/automations/thread.js b/packages/server/src/automations/thread.js index 30eed75aa4..e4fef62211 100644 --- a/packages/server/src/automations/thread.js +++ b/packages/server/src/automations/thread.js @@ -109,14 +109,18 @@ class Orchestrator { step.inputs = recurseMustache(step.inputs, this._context) step.inputs = cleanInputValue(step.inputs, step.schema.inputs) // instanceId is always passed - const outputs = await stepFn({ - inputs: step.inputs, - instanceId: this._instanceId, - }) - if (step.stepId === FILTER_STEP_ID && !outputs.success) { - break + try { + const outputs = await stepFn({ + inputs: step.inputs, + instanceId: this._instanceId, + }) + if (step.stepId === FILTER_STEP_ID && !outputs.success) { + break + } + this._context.steps.push(outputs) + } catch (err) { + console.error(`Automation error - ${step.stepId} - ${err}`) } - this._context.steps.push(outputs) } } } diff --git a/packages/server/src/automations/triggers.js b/packages/server/src/automations/triggers.js index e57ae66a82..d1d393347c 100644 --- a/packages/server/src/automations/triggers.js +++ b/packages/server/src/automations/triggers.js @@ -36,8 +36,16 @@ const BUILTIN_DEFINITIONS = { customType: "record", description: "The new record that was saved", }, + id: { + type: "string", + description: "Record ID - can be used for updating", + }, + revision: { + type: "string", + description: "Revision of record", + }, }, - required: ["record"], + required: ["record", "id"], }, }, type: "TRIGGER", @@ -69,7 +77,7 @@ const BUILTIN_DEFINITIONS = { description: "The record that was deleted", }, }, - required: ["record"], + required: ["record", "id"], }, }, type: "TRIGGER",