1
0
Fork 0
mirror of synced 2024-06-29 11:31:06 +12:00
budibase/packages/server/src/workflows/triggers.js

154 lines
3.9 KiB
JavaScript
Raw Normal View History

const CouchDB = require("../db")
const emitter = require("../events/index")
const InMemoryQueue = require("./queue/inMemoryQueue")
let workflowQueue = new InMemoryQueue()
const FAKE_STRING = "TEST"
const FAKE_BOOL = false
const FAKE_NUMBER = 1
const FAKE_DATETIME = "1970-01-01T00:00:00.000Z"
const BUILTIN_DEFINITIONS = {
RECORD_SAVED: {
name: "Record Saved",
event: "record:save",
icon: "ri-save-line",
tagline: "Record is added to {{inputs.enriched.model.name}}",
description: "Fired when a record is saved to your database",
stepId: "RECORD_SAVED",
inputs: {},
schema: {
inputs: {
properties: {
modelId: {
type: "string",
customType: "model",
title: "Table",
},
},
required: ["modelId"],
},
outputs: {
properties: {
record: {
type: "object",
customType: "record",
description: "The new record that was saved",
},
},
required: ["record"],
},
},
type: "TRIGGER",
},
RECORD_DELETED: {
name: "Record Deleted",
event: "record:delete",
icon: "ri-delete-bin-line",
tagline: "Record is deleted from {{inputs.enriched.model.name}}",
description: "Fired when a record is deleted from your database",
stepId: "RECORD_DELETED",
inputs: {},
schema: {
inputs: {
properties: {
modelId: {
type: "string",
customType: "model",
title: "Table",
},
},
required: ["modelId"],
},
outputs: {
properties: {
record: {
type: "object",
customType: "record",
description: "The record that was deleted",
},
},
required: ["record"],
},
},
type: "TRIGGER",
},
}
async function queueRelevantWorkflows(event, eventType) {
if (event.instanceId == null) {
throw `No instanceId specified for ${eventType} - check event emitters.`
}
const db = new CouchDB(event.instanceId)
const workflowsToTrigger = await db.query("database/by_workflow_trigger", {
key: [eventType],
include_docs: true,
})
const workflows = workflowsToTrigger.rows.map(wf => wf.doc)
for (let workflow of workflows) {
if (!workflow.live) {
continue
}
workflowQueue.add({ workflow, event })
}
}
emitter.on("record:save", async function(event) {
await queueRelevantWorkflows(event, "record:save")
})
emitter.on("record:delete", async function(event) {
await queueRelevantWorkflows(event, "record:delete")
})
async function fillRecordOutput(workflow, params) {
let triggerSchema = workflow.definition.trigger
let modelId = triggerSchema.inputs.modelId
const db = new CouchDB(params.instanceId)
try {
let model = await db.get(modelId)
for (let schemaKey of Object.keys(model.schema)) {
if (params[schemaKey] != null) {
continue
}
let propSchema = model.schema[schemaKey]
switch (propSchema.constraints.type) {
case "string":
params[schemaKey] = FAKE_STRING
break
case "boolean":
params[schemaKey] = FAKE_BOOL
break
case "number":
params[schemaKey] = FAKE_NUMBER
break
case "datetime":
params[schemaKey] = FAKE_DATETIME
break
}
}
} catch (err) {
throw "Failed to find model for trigger"
}
return params
}
module.exports.externalTrigger = async function(workflow, params) {
// TODO: replace this with allowing user in builder to input values in future
if (
workflow.definition != null &&
workflow.definition.trigger != null &&
workflow.definition.trigger.inputs.modelId != null
) {
params = await fillRecordOutput(workflow, params)
}
workflowQueue.add({ workflow, event: params })
}
module.exports.workflowQueue = workflowQueue
module.exports.BUILTIN_DEFINITIONS = BUILTIN_DEFINITIONS