2020-09-10 16:00:21 +02:00
|
|
|
const CouchDB = require("../db")
|
|
|
|
const emitter = require("../events/index")
|
|
|
|
const InMemoryQueue = require("./queue/inMemoryQueue")
|
|
|
|
|
2020-09-21 14:49:34 +02:00
|
|
|
let automationQueue = new InMemoryQueue()
|
2020-09-10 16:00:21 +02:00
|
|
|
|
2020-09-17 16:14:08 +02:00
|
|
|
const FAKE_STRING = "TEST"
|
|
|
|
const FAKE_BOOL = false
|
|
|
|
const FAKE_NUMBER = 1
|
|
|
|
const FAKE_DATETIME = "1970-01-01T00:00:00.000Z"
|
|
|
|
|
2020-09-16 15:00:04 +02:00
|
|
|
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",
|
2020-09-16 20:25:52 +02:00
|
|
|
stepId: "RECORD_SAVED",
|
2020-09-16 15:00:04 +02:00
|
|
|
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",
|
|
|
|
},
|
2020-09-23 13:29:20 +02:00
|
|
|
id: {
|
|
|
|
type: "string",
|
|
|
|
description: "Record ID - can be used for updating",
|
|
|
|
},
|
|
|
|
revision: {
|
|
|
|
type: "string",
|
|
|
|
description: "Revision of record",
|
|
|
|
},
|
2020-09-16 15:00:04 +02:00
|
|
|
},
|
2020-09-23 13:29:20 +02:00
|
|
|
required: ["record", "id"],
|
2020-09-16 15:00:04 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
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",
|
2020-09-16 20:25:52 +02:00
|
|
|
stepId: "RECORD_DELETED",
|
2020-09-16 15:00:04 +02:00
|
|
|
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",
|
|
|
|
},
|
|
|
|
},
|
2020-09-23 13:29:20 +02:00
|
|
|
required: ["record", "id"],
|
2020-09-16 15:00:04 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
type: "TRIGGER",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2020-09-21 14:49:34 +02:00
|
|
|
async function queueRelevantRecordAutomations(event, eventType) {
|
2020-09-14 11:30:35 +02:00
|
|
|
if (event.instanceId == null) {
|
|
|
|
throw `No instanceId specified for ${eventType} - check event emitters.`
|
|
|
|
}
|
2020-09-10 16:00:21 +02:00
|
|
|
const db = new CouchDB(event.instanceId)
|
2020-09-21 14:49:34 +02:00
|
|
|
const automationsToTrigger = await db.query(
|
|
|
|
"database/by_automation_trigger",
|
|
|
|
{
|
|
|
|
key: [eventType],
|
|
|
|
include_docs: true,
|
|
|
|
}
|
|
|
|
)
|
2020-09-10 16:00:21 +02:00
|
|
|
|
2020-09-21 14:49:34 +02:00
|
|
|
const automations = automationsToTrigger.rows.map(wf => wf.doc)
|
|
|
|
for (let automation of automations) {
|
|
|
|
let automationDef = automation.definition
|
|
|
|
let automationTrigger = automationDef ? automationDef.trigger : {}
|
2020-09-18 14:51:56 +02:00
|
|
|
if (
|
2020-09-21 14:49:34 +02:00
|
|
|
!automation.live ||
|
|
|
|
!automationTrigger.inputs ||
|
|
|
|
automationTrigger.inputs.modelId !== event.record.modelId
|
2020-09-18 14:51:56 +02:00
|
|
|
) {
|
2020-09-11 19:47:22 +02:00
|
|
|
continue
|
|
|
|
}
|
2020-09-21 14:49:34 +02:00
|
|
|
automationQueue.add({ automation, event })
|
2020-09-10 16:00:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
emitter.on("record:save", async function(event) {
|
2020-09-18 14:51:56 +02:00
|
|
|
if (!event || !event.record || !event.record.modelId) {
|
|
|
|
return
|
|
|
|
}
|
2020-09-21 14:49:34 +02:00
|
|
|
await queueRelevantRecordAutomations(event, "record:save")
|
2020-09-10 16:00:21 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
emitter.on("record:delete", async function(event) {
|
2020-09-18 14:51:56 +02:00
|
|
|
if (!event || !event.record || !event.record.modelId) {
|
|
|
|
return
|
|
|
|
}
|
2020-09-21 14:49:34 +02:00
|
|
|
await queueRelevantRecordAutomations(event, "record:delete")
|
2020-09-10 16:00:21 +02:00
|
|
|
})
|
|
|
|
|
2020-09-21 14:49:34 +02:00
|
|
|
async function fillRecordOutput(automation, params) {
|
|
|
|
let triggerSchema = automation.definition.trigger
|
2020-09-17 16:14:08 +02:00
|
|
|
let modelId = triggerSchema.inputs.modelId
|
|
|
|
const db = new CouchDB(params.instanceId)
|
|
|
|
try {
|
|
|
|
let model = await db.get(modelId)
|
2020-09-22 16:25:26 +02:00
|
|
|
let record = {}
|
2020-09-17 16:14:08 +02:00
|
|
|
for (let schemaKey of Object.keys(model.schema)) {
|
|
|
|
if (params[schemaKey] != null) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
let propSchema = model.schema[schemaKey]
|
|
|
|
switch (propSchema.constraints.type) {
|
|
|
|
case "string":
|
2020-09-22 16:25:26 +02:00
|
|
|
record[schemaKey] = FAKE_STRING
|
2020-09-17 16:14:08 +02:00
|
|
|
break
|
|
|
|
case "boolean":
|
2020-09-22 16:25:26 +02:00
|
|
|
record[schemaKey] = FAKE_BOOL
|
2020-09-17 16:14:08 +02:00
|
|
|
break
|
|
|
|
case "number":
|
2020-09-22 16:25:26 +02:00
|
|
|
record[schemaKey] = FAKE_NUMBER
|
2020-09-17 16:14:08 +02:00
|
|
|
break
|
|
|
|
case "datetime":
|
2020-09-22 16:25:26 +02:00
|
|
|
record[schemaKey] = FAKE_DATETIME
|
2020-09-17 16:14:08 +02:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2020-09-22 16:25:26 +02:00
|
|
|
params.record = record
|
2020-09-17 16:14:08 +02:00
|
|
|
} catch (err) {
|
|
|
|
throw "Failed to find model for trigger"
|
|
|
|
}
|
|
|
|
return params
|
|
|
|
}
|
|
|
|
|
2020-09-21 14:49:34 +02:00
|
|
|
module.exports.externalTrigger = async function(automation, params) {
|
2020-09-17 16:14:08 +02:00
|
|
|
// TODO: replace this with allowing user in builder to input values in future
|
|
|
|
if (
|
2020-09-21 14:49:34 +02:00
|
|
|
automation.definition != null &&
|
|
|
|
automation.definition.trigger != null &&
|
|
|
|
automation.definition.trigger.inputs.modelId != null
|
2020-09-17 16:14:08 +02:00
|
|
|
) {
|
2020-09-21 14:49:34 +02:00
|
|
|
params = await fillRecordOutput(automation, params)
|
2020-09-17 16:14:08 +02:00
|
|
|
}
|
|
|
|
|
2020-09-21 14:49:34 +02:00
|
|
|
automationQueue.add({ automation, event: params })
|
2020-09-10 16:00:21 +02:00
|
|
|
}
|
|
|
|
|
2020-09-21 14:49:34 +02:00
|
|
|
module.exports.automationQueue = automationQueue
|
2020-09-16 15:00:04 +02:00
|
|
|
|
|
|
|
module.exports.BUILTIN_DEFINITIONS = BUILTIN_DEFINITIONS
|