Merge pull request #5817 from Budibase/fix/loop-hbs-usage
Fix HBS usage in automation looping action
This commit is contained in:
commit
f572afeb08
|
@ -208,5 +208,10 @@ exports.AutomationErrors = {
|
||||||
FAILURE_CONDITION: "FAILURE_CONDITION_MET",
|
FAILURE_CONDITION: "FAILURE_CONDITION_MET",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.LoopStepTypes = {
|
||||||
|
ARRAY: "Array",
|
||||||
|
STRING: "String",
|
||||||
|
}
|
||||||
|
|
||||||
// pass through the list from the auth/core lib
|
// pass through the list from the auth/core lib
|
||||||
exports.ObjectStoreBuckets = ObjectStoreBuckets
|
exports.ObjectStoreBuckets = ObjectStoreBuckets
|
||||||
|
|
|
@ -8,7 +8,7 @@ const { DocumentTypes } = require("../db/utils")
|
||||||
const { doInTenant } = require("@budibase/backend-core/tenancy")
|
const { doInTenant } = require("@budibase/backend-core/tenancy")
|
||||||
const { definitions: triggerDefs } = require("../automations/triggerInfo")
|
const { definitions: triggerDefs } = require("../automations/triggerInfo")
|
||||||
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
|
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
|
||||||
const { AutomationErrors } = require("../constants")
|
const { AutomationErrors, LoopStepTypes } = require("../constants")
|
||||||
const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId
|
const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId
|
||||||
const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId
|
const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId
|
||||||
|
|
||||||
|
@ -17,6 +17,41 @@ const STOPPED_STATUS = { success: false, status: "STOPPED" }
|
||||||
const { cloneDeep } = require("lodash/fp")
|
const { cloneDeep } = require("lodash/fp")
|
||||||
const env = require("../environment")
|
const env = require("../environment")
|
||||||
|
|
||||||
|
function typecastForLooping(loopStep, input) {
|
||||||
|
if (!input || !input.binding) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const isArray = Array.isArray(input.binding),
|
||||||
|
isString = typeof input.binding === "string"
|
||||||
|
try {
|
||||||
|
switch (loopStep.inputs.option) {
|
||||||
|
case LoopStepTypes.ARRAY:
|
||||||
|
if (isString) {
|
||||||
|
return JSON.parse(input.binding)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case LoopStepTypes.STRING:
|
||||||
|
if (isArray) {
|
||||||
|
return input.binding.join(",")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error("Unable to cast to correct type")
|
||||||
|
}
|
||||||
|
return input.binding
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLoopIterations(loopStep, input) {
|
||||||
|
const binding = typecastForLooping(loopStep, input)
|
||||||
|
if (!loopStep || !binding) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return Array.isArray(binding)
|
||||||
|
? binding.length
|
||||||
|
: automationUtils.stringSplit(binding).length
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The automation orchestrator is a class responsible for executing automations.
|
* The automation orchestrator is a class responsible for executing automations.
|
||||||
* It handles the context of the automation and makes sure each step gets the correct
|
* It handles the context of the automation and makes sure each step gets the correct
|
||||||
|
@ -107,7 +142,9 @@ class Orchestrator {
|
||||||
let loopSteps = []
|
let loopSteps = []
|
||||||
for (let step of automation.definition.steps) {
|
for (let step of automation.definition.steps) {
|
||||||
stepCount++
|
stepCount++
|
||||||
let input
|
let input,
|
||||||
|
iterations = 1,
|
||||||
|
iterationCount = 0
|
||||||
if (step.stepId === LOOP_STEP_ID) {
|
if (step.stepId === LOOP_STEP_ID) {
|
||||||
loopStep = step
|
loopStep = step
|
||||||
loopStepNumber = stepCount
|
loopStepNumber = stepCount
|
||||||
|
@ -116,13 +153,9 @@ class Orchestrator {
|
||||||
|
|
||||||
if (loopStep) {
|
if (loopStep) {
|
||||||
input = await processObject(loopStep.inputs, this._context)
|
input = await processObject(loopStep.inputs, this._context)
|
||||||
|
iterations = getLoopIterations(loopStep, input)
|
||||||
}
|
}
|
||||||
let iterations = loopStep
|
|
||||||
? Array.isArray(input.binding)
|
|
||||||
? input.binding.length
|
|
||||||
: automationUtils.stringSplit(input.binding).length
|
|
||||||
: 1
|
|
||||||
let iterationCount = 0
|
|
||||||
for (let index = 0; index < iterations; index++) {
|
for (let index = 0; index < iterations; index++) {
|
||||||
let originalStepInput = cloneDeep(step.inputs)
|
let originalStepInput = cloneDeep(step.inputs)
|
||||||
|
|
||||||
|
@ -132,18 +165,11 @@ class Orchestrator {
|
||||||
loopStep.inputs,
|
loopStep.inputs,
|
||||||
cloneDeep(this._context)
|
cloneDeep(this._context)
|
||||||
)
|
)
|
||||||
newInput = automationUtils.cleanInputValues(
|
|
||||||
newInput,
|
|
||||||
loopStep.schema.inputs
|
|
||||||
)
|
|
||||||
|
|
||||||
let tempOutput = { items: loopSteps, iterations: iterationCount }
|
let tempOutput = { items: loopSteps, iterations: iterationCount }
|
||||||
if (
|
try {
|
||||||
(loopStep.inputs.option === "Array" &&
|
newInput.binding = typecastForLooping(loopStep, newInput)
|
||||||
!Array.isArray(newInput.binding)) ||
|
} catch (err) {
|
||||||
(loopStep.inputs.option === "String" &&
|
|
||||||
typeof newInput.binding !== "string")
|
|
||||||
) {
|
|
||||||
this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
|
this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
|
||||||
status: AutomationErrors.INCORRECT_TYPE,
|
status: AutomationErrors.INCORRECT_TYPE,
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -205,21 +231,13 @@ class Orchestrator {
|
||||||
}
|
}
|
||||||
|
|
||||||
let isFailure = false
|
let isFailure = false
|
||||||
if (
|
const currentItem = this._context.steps[loopStepNumber]?.currentItem
|
||||||
typeof this._context.steps[loopStepNumber]?.currentItem === "object"
|
if (currentItem && typeof currentItem === "object") {
|
||||||
) {
|
isFailure = Object.keys(currentItem).some(value => {
|
||||||
isFailure = Object.keys(
|
return currentItem[value] === loopStep.inputs.failure
|
||||||
this._context.steps[loopStepNumber].currentItem
|
|
||||||
).some(value => {
|
|
||||||
return (
|
|
||||||
this._context.steps[loopStepNumber].currentItem[value] ===
|
|
||||||
loopStep.inputs.failure
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
isFailure =
|
isFailure = currentItem && currentItem === loopStep.inputs.failure
|
||||||
this._context.steps[loopStepNumber]?.currentItem ===
|
|
||||||
loopStep.inputs.failure
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFailure) {
|
if (isFailure) {
|
||||||
|
|
Loading…
Reference in New Issue