diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/AutomationBlockTagline.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/AutomationBlockTagline.svelte
index b63cea4f9d..2afe7dbbfa 100644
--- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/AutomationBlockTagline.svelte
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/AutomationBlockTagline.svelte
@@ -1,5 +1,5 @@
diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js
index b2caf83d1c..878a91a6d2 100644
--- a/packages/client/src/utils/buttonActions.js
+++ b/packages/client/src/utils/buttonActions.js
@@ -5,26 +5,31 @@ import { saveRow, deleteRow, triggerAutomation } from "../api"
const saveRowHandler = async (action, context) => {
let draft = context[`${action.parameters.contextPath}_draft`]
if (action.parameters.fields) {
- Object.entries(action.parameters.fields).forEach(([key, entry]) => {
- draft[key] = enrichDataBinding(entry.value, context)
- })
+ for (let [key, entry] of Object.entries(action.parameters.fields)) {
+ draft[key] = await enrichDataBinding(entry.value, context)
+ }
}
await saveRow(draft)
}
const deleteRowHandler = async (action, context) => {
const { tableId, revId, rowId } = action.parameters
+ const [ enrichTable, enrichRow, enrichRev ] = await Promise.all([
+ enrichDataBinding(tableId, context),
+ enrichDataBinding(rowId, context),
+ enrichDataBinding(revId, context)
+ ])
await deleteRow({
- tableId: enrichDataBinding(tableId, context),
- rowId: enrichDataBinding(rowId, context),
- revId: enrichDataBinding(revId, context),
+ tableId: enrichTable,
+ rowId: enrichRow,
+ revId: enrichRev,
})
}
const triggerAutomationHandler = async (action, context) => {
const params = {}
for (let field in action.parameters.fields) {
- params[field] = enrichDataBinding(
+ params[field] = await enrichDataBinding(
action.parameters.fields[field].value,
context
)
diff --git a/packages/client/src/utils/componentProps.js b/packages/client/src/utils/componentProps.js
index be65ad2bfe..170faf47a1 100644
--- a/packages/client/src/utils/componentProps.js
+++ b/packages/client/src/utils/componentProps.js
@@ -5,7 +5,7 @@ import { enrichButtonActions } from "./buttonActions"
* Enriches component props.
* Data bindings are enriched, and button actions are enriched.
*/
-export const enrichProps = (props, dataContexts, dataBindings) => {
+export const enrichProps = async (props, dataContexts, dataBindings) => {
// Exclude all private props that start with an underscore
let validProps = {}
Object.entries(props)
@@ -24,7 +24,7 @@ export const enrichProps = (props, dataContexts, dataBindings) => {
}
// Enrich all data bindings in top level props
- let enrichedProps = enrichDataBindings(validProps, context)
+ let enrichedProps = await enrichDataBindings(validProps, context)
// Enrich button actions if they exist
if (props._component.endsWith("/button") && enrichedProps.onClick) {
diff --git a/packages/client/src/utils/enrichDataBinding.js b/packages/client/src/utils/enrichDataBinding.js
index 0a8ea0092b..f6682777b5 100644
--- a/packages/client/src/utils/enrichDataBinding.js
+++ b/packages/client/src/utils/enrichDataBinding.js
@@ -6,7 +6,7 @@ const looksLikeTemplate = /{{.*}}/
/**
* Enriches a given input with a row from the database.
*/
-export const enrichDataBinding = (input, context) => {
+export const enrichDataBinding = async (input, context) => {
// Only accept string inputs
if (!input || typeof input !== "string") {
return input
@@ -21,10 +21,10 @@ export const enrichDataBinding = (input, context) => {
/**
* Enriches each prop in a props object
*/
-export const enrichDataBindings = (props, context) => {
+export const enrichDataBindings = async (props, context) => {
let enrichedProps = {}
- Object.entries(props).forEach(([key, value]) => {
- enrichedProps[key] = enrichDataBinding(value, context)
- })
+ for (let [key, value] of Object.entries(props)) {
+ enrichedProps[key] = await enrichDataBinding(value, context)
+ }
return enrichedProps
}
diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js
index 357e1b2e0d..952a949645 100644
--- a/packages/server/src/api/controllers/application.js
+++ b/packages/server/src/api/controllers/application.js
@@ -31,7 +31,7 @@ const {
createLoginScreen,
} = require("../../constants/screens")
const { cloneDeep } = require("lodash/fp")
-const { objectTemplate } = require("../../utilities/stringTemplating")
+const { processObject } = require("@budibase/string-templates")
const { USERS_TABLE_SCHEMA } = require("../../constants")
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
@@ -213,7 +213,7 @@ const createEmptyAppPackage = async (ctx, app) => {
let screensAndLayouts = []
for (let layout of BASE_LAYOUTS) {
const cloned = cloneDeep(layout)
- screensAndLayouts.push(objectTemplate(cloned, app))
+ screensAndLayouts.push(await processObject(cloned, app))
}
const homeScreen = createHomeScreen(app)
diff --git a/packages/server/src/api/controllers/static/index.js b/packages/server/src/api/controllers/static/index.js
index 6ba1bdbd4e..4db9ac627b 100644
--- a/packages/server/src/api/controllers/static/index.js
+++ b/packages/server/src/api/controllers/static/index.js
@@ -7,7 +7,7 @@ const fs = require("fs-extra")
const uuid = require("uuid")
const AWS = require("aws-sdk")
const { prepareUpload } = require("../deploy/utils")
-const { stringTemplate } = require("../../../utilities/stringTemplating")
+const { processString } = require("@budibase/string-templates")
const {
budibaseAppsDir,
budibaseTempDir,
@@ -161,7 +161,7 @@ exports.serveApp = async function(ctx) {
})
const appHbs = fs.readFileSync(`${__dirname}/templates/app.hbs`, "utf8")
- ctx.body = stringTemplate(appHbs, {
+ ctx.body = await processString(appHbs, {
head,
body: html,
style: css.code,
diff --git a/packages/server/src/automations/thread.js b/packages/server/src/automations/thread.js
index 8fcfd346db..7dbf9272ec 100644
--- a/packages/server/src/automations/thread.js
+++ b/packages/server/src/automations/thread.js
@@ -2,7 +2,7 @@ const actions = require("./actions")
const logic = require("./logic")
const automationUtils = require("./automationUtils")
const AutomationEmitter = require("../events/AutomationEmitter")
-const { objectTemplate } = require("../utilities/stringTemplating")
+const { processObject } = require("@budibase/string-templates")
const FILTER_STEP_ID = logic.BUILTIN_DEFINITIONS.FILTER.stepId
@@ -44,7 +44,7 @@ class Orchestrator {
let automation = this._automation
for (let step of automation.definition.steps) {
let stepFn = await this.getStepFunctionality(step.type, step.stepId)
- step.inputs = objectTemplate(step.inputs, this._context)
+ step.inputs = await processObject(step.inputs, this._context)
step.inputs = automationUtils.cleanInputValues(
step.inputs,
step.schema.inputs
diff --git a/packages/server/src/utilities/initialiseBudibase.js b/packages/server/src/utilities/initialiseBudibase.js
index c9a87a1edc..bdbd194eaa 100644
--- a/packages/server/src/utilities/initialiseBudibase.js
+++ b/packages/server/src/utilities/initialiseBudibase.js
@@ -1,6 +1,6 @@
const { existsSync, readFile, writeFile, ensureDir } = require("fs-extra")
const { join, resolve } = require("./centralPath")
-const { stringTemplate } = require("./stringTemplating")
+const { processString } = require("@budibase/string-templates")
const uuid = require("uuid")
module.exports = async opts => {
@@ -31,7 +31,7 @@ const createDevEnvFile = async opts => {
}
)
opts.cookieKey1 = opts.cookieKey1 || uuid.v4()
- const config = stringTemplate(template, opts)
+ const config = await processString(template, opts)
await writeFile(destConfigFile, config, { flag: "w+" })
}
}
diff --git a/packages/server/src/utilities/stringTemplating.js b/packages/server/src/utilities/stringTemplating.js
deleted file mode 100644
index a807850abb..0000000000
--- a/packages/server/src/utilities/stringTemplating.js
+++ /dev/null
@@ -1,4 +0,0 @@
-const stringTemplates = require("@budibase/string-templates")
-
-exports.objectTemplate = stringTemplates.processObject
-exports.stringTemplate = stringTemplates.processString
diff --git a/packages/string-templates/src/index.js b/packages/string-templates/src/index.js
index 4ef7cf5b3b..033fe5c1a8 100644
--- a/packages/string-templates/src/index.js
+++ b/packages/string-templates/src/index.js
@@ -7,10 +7,6 @@ const FIND_HBS_REGEX = /{{.*}}/
const hbsInstance = handlebars.create()
registerAll(hbsInstance)
-function attemptToCorrectError(string) {
- return string
-}
-
/**
* When running handlebars statements to execute on the context of the automation it possible user's may input handlebars
* in a few different forms, some of which are invalid but are logically valid. An example of this would be the handlebars
@@ -54,28 +50,34 @@ function cleanHandlebars(string) {
}
/**
- * Given an input object this will recurse through all props to try and update
- * any handlebars statements within.
- * @param {object|array} object The input structure which is to be recursed, it is important to note that
- * if the structure contains any cycles then this will fail.
- * @param {object} context The context that handlebars should fill data from.
- * @returns {object|array} The structure input, as fully updated as possible.
+ * utility function to check if the object is valid
*/
-module.exports.processObject = (object, context) => {
+function testObject(object) {
// JSON stringify will fail if there are any cycles, stops infinite recursion
try {
JSON.stringify(object)
} catch (err) {
throw "Unable to process inputs to JSON, cannot recurse"
}
+}
+
+/**
+ * Given an input object this will recurse through all props to try and update any handlebars statements within.
+ * @param {object|array} object The input structure which is to be recursed, it is important to note that
+ * if the structure contains any cycles then this will fail.
+ * @param {object} context The context that handlebars should fill data from.
+ * @returns {Promise