Improve handling of loop handlebars string replacement

This commit is contained in:
Peter Clement 2022-04-18 09:22:23 +01:00
parent 43b4dd8737
commit 1000ef35e1
5 changed files with 43 additions and 17 deletions

View File

@ -103,7 +103,7 @@ globals:
google:
clientId: ""
secret: ""
automationMaxIterations: "0"
automationMaxIterations: "500"
createSecrets: true # creates an internal API key, JWT secrets and redis password for you

View File

@ -1,4 +1,5 @@
const { getTable } = require("../api/controllers/table/utils")
const { findHBSBlocks } = require("@budibase/string-templates")
/**
* When values are input to the system generally they will be of type string as this is required for template strings.
@ -74,3 +75,14 @@ exports.getError = err => {
}
return typeof err !== "string" ? err.toString() : err
}
exports.substituteLoopStep = (hbsString, substitute) => {
let blocks = findHBSBlocks(hbsString)
for (let block of blocks) {
let oldBlock = block
block = block.replace(/loop/, substitute)
hbsString = hbsString.replace(new RegExp(oldBlock, "g"), block)
}
return hbsString
}

View File

@ -32,7 +32,7 @@ exports.definition = {
properties: {
items: {
customType: "item",
description: "the item currently being executed",
description: "The item currently being executed",
},
success: {
type: "boolean",
@ -43,7 +43,7 @@ exports.definition = {
descriptions: "The amount of times the block ran",
},
},
required: ["success"],
required: ["success, items, iterations"],
},
},
type: "LOGIC",

View File

@ -190,5 +190,11 @@ exports.WebhookType = {
AUTOMATION: "automation",
}
exports.AutomationErrors = {
INCORRECT_TYPE: "INCORRECT_TYPE",
MAX_ITERATIONS: "MAX_ITERATIONS_REACHED",
FAILURE_CONDITION: "FAILURE_CONDITION_MET",
}
// pass through the list from the auth/core lib
exports.ObjectStoreBuckets = ObjectStoreBuckets

View File

@ -8,7 +8,7 @@ const { DocumentTypes } = require("../db/utils")
const { doInTenant } = require("@budibase/backend-core/tenancy")
const { definitions: triggerDefs } = require("../automations/triggerInfo")
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
const { AutomationErrors } = require("../constants")
const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId
const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId
@ -146,7 +146,7 @@ class Orchestrator {
typeof newInput.binding !== "string")
) {
this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
status: "INCORRECT_TYPE",
status: AutomationErrors.INCORRECT_TYPE,
success: false,
})
loopSteps = null
@ -156,27 +156,35 @@ class Orchestrator {
// The "Loop" binding in the front end is "fake", so replace it here so the context can understand it
// Pretty hacky because we need to account for the row object
for (let key in originalStepInput) {
if (key === "row") {
for (let val in originalStepInput["row"]) {
originalStepInput["row"][val] = originalStepInput["row"][
val
].replace(/loop/, `steps.${loopStepNumber}`)
}
} else {
originalStepInput[key] = originalStepInput[key].replace(
/loop/,
for (let [key, value] of Object.entries(originalStepInput)) {
if (typeof value === "object") {
for (let [innerKey, innerValue] of Object.entries(
originalStepInput[key]
)) {
if (typeof innerValue === "string") {
originalStepInput[key][innerKey] =
automationUtils.substituteLoopStep(
innerValue,
`steps.${loopStepNumber}`
)
}
}
} else {
if (typeof value === "string") {
originalStepInput[key] = automationUtils.substituteLoopStep(
value,
`steps.${loopStepNumber}`
)
}
}
}
if (
index === parseInt(env.AUTOMATION_MAX_ITERATIONS) ||
index === loopStep.inputs.iterations
) {
this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
status: "MAX_ITERATIONS_REACHED",
status: AutomationErrors.MAX_ITERATIONS,
success: true,
})
loopSteps = null
@ -189,7 +197,7 @@ class Orchestrator {
loopStep.inputs.failure
) {
this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
status: "FAILURE_CONDITION_MET",
status: AutomationErrors.FAILURE_CONDITION,
success: false,
})
loopSteps = null