budibase/packages/core/src/actionsApi/initialise.js

104 lines
2.5 KiB
JavaScript

import {
isFunction,
filter,
map,
uniqBy,
keys,
difference,
join,
reduce,
find,
} from "lodash/fp"
import { compileExpression, compileCode } from "../common/compileCode"
import { $ } from "../common"
import { _executeAction } from "./execute"
import { BadRequestError, NotFoundError } from "../common/errors"
export const initialiseActions = (
subscribe,
behaviourSources,
actions,
triggers,
apis
) => {
validateSources(behaviourSources, actions)
subscribeTriggers(subscribe, behaviourSources, actions, triggers, apis)
return createActionsCollection(behaviourSources, actions)
}
const createActionsCollection = (behaviourSources, actions) =>
$(actions, [
reduce((all, a) => {
all[a.name] = opts => _executeAction(behaviourSources, a, opts)
return all
}, {}),
])
const subscribeTriggers = (
subscribe,
behaviourSources,
actions,
triggers,
apis
) => {
const createOptions = (optionsCreator, eventContext) => {
if (!optionsCreator) return {}
const create = compileCode(optionsCreator)
return create({ context: eventContext, apis })
}
const shouldRunTrigger = (trigger, eventContext) => {
if (!trigger.condition) return true
const shouldRun = compileExpression(trigger.condition)
return shouldRun({ context: eventContext })
}
for (let trig of triggers) {
subscribe(trig.eventName, async (ev, ctx) => {
if (shouldRunTrigger(trig, ctx)) {
await _executeAction(
behaviourSources,
find(a => a.name === trig.actionName)(actions),
createOptions(trig.optionsCreator, ctx)
)
}
})
}
}
const validateSources = (behaviourSources, actions) => {
const declaredSources = $(actions, [
uniqBy(a => a.behaviourSource),
map(a => a.behaviourSource),
])
const suppliedSources = keys(behaviourSources)
const missingSources = difference(declaredSources, suppliedSources)
if (missingSources.length > 0) {
throw new BadRequestError(
`Declared behaviour sources are not supplied: ${join(
", ",
missingSources
)}`
)
}
const missingBehaviours = $(actions, [
filter(
a => !isFunction(behaviourSources[a.behaviourSource][a.behaviourName])
),
map(a => `Action: ${a.name} : ${a.behaviourSource}.${a.behaviourName}`),
])
if (missingBehaviours.length > 0) {
throw new NotFoundError(
`Missing behaviours: could not find behaviour functions: ${join(
", ",
missingBehaviours
)}`
)
}
}