diff --git a/lerna.json b/lerna.json index a9e7e849df..ef5aa714e6 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.0.50-alpha.4", + "version": "1.0.50-alpha.5", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index b89fdbe593..ffb8277464 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "1.0.50-alpha.4", + "version": "1.0.50-alpha.5", "description": "Budibase backend core libraries used in server and worker", "main": "src/index.js", "author": "Budibase", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 5de946fbcf..f9be4f22de 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/bbui", "description": "A UI solution used in the different Budibase projects.", - "version": "1.0.50-alpha.4", + "version": "1.0.50-alpha.5", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", diff --git a/packages/bbui/src/Button/Button.svelte b/packages/bbui/src/Button/Button.svelte index da4d405f02..67930b8030 100644 --- a/packages/bbui/src/Button/Button.svelte +++ b/packages/bbui/src/Button/Button.svelte @@ -1,5 +1,6 @@ - + {#if showTooltip && tooltip} +
+
+ +
+
{/if} - {#if $$slots} - - {/if} - + diff --git a/packages/bbui/src/Form/Core/DatePicker.svelte b/packages/bbui/src/Form/Core/DatePicker.svelte index e179eb81dc..c1c4cc866f 100644 --- a/packages/bbui/src/Form/Core/DatePicker.svelte +++ b/packages/bbui/src/Form/Core/DatePicker.svelte @@ -14,16 +14,20 @@ export let value = null export let placeholder = null export let appendTo = undefined + export let timeOnly = false const dispatch = createEventDispatcher() const flatpickrId = `${uuid()}-wrapper` let open = false - let flatpickr + let flatpickr, flatpickrOptions, isTimeOnly + + $: isTimeOnly = !timeOnly && value ? !isNaN(new Date(`0-${value}`)) : timeOnly $: flatpickrOptions = { element: `#${flatpickrId}`, - enableTime: enableTime || false, + enableTime: isTimeOnly || enableTime || false, + noCalendar: isTimeOnly || false, altInput: true, - altFormat: enableTime ? "F j Y, H:i" : "F j, Y", + altFormat: isTimeOnly ? "H:i" : enableTime ? "F j Y, H:i" : "F j, Y", wrap: true, appendTo, disableMobile: "true", @@ -35,6 +39,11 @@ if (newValue) { newValue = newValue.toISOString() } + // if time only set date component to today + if (timeOnly) { + const todayDate = new Date().toISOString().split("T")[0] + newValue = `${todayDate}T${newValue.split("T")[1]}` + } dispatch("change", newValue) } @@ -67,7 +76,11 @@ return null } let date - if (val instanceof Date) { + let time = new Date(`0-${val}`) + // it is a string like 00:00:00, just time + if (timeOnly || (typeof val === "string" && !isNaN(time))) { + date = time + } else if (val instanceof Date) { // Use real date obj if already parsed date = val } else if (isNaN(val)) { @@ -77,7 +90,7 @@ // Treat as numerical timestamp date = new Date(parseInt(val)) } - const time = date.getTime() + time = date.getTime() if (isNaN(time)) { return null } @@ -88,69 +101,71 @@ } - -
- {#if !!error} +
+ {#if !!error} + + {/if} + +
+
- -
-
+ +{/key} {#if open}
{/if} diff --git a/packages/bbui/src/Form/DatePicker.svelte b/packages/bbui/src/Form/DatePicker.svelte index 7d5656a22d..9298c49177 100644 --- a/packages/bbui/src/Form/DatePicker.svelte +++ b/packages/bbui/src/Form/DatePicker.svelte @@ -9,6 +9,7 @@ export let disabled = false export let error = null export let enableTime = true + export let timeOnly = false export let placeholder = null export let appendTo = undefined @@ -27,6 +28,7 @@ {value} {placeholder} {enableTime} + {timeOnly} {appendTo} on:change={onChange} /> diff --git a/packages/bbui/src/Table/DateTimeRenderer.svelte b/packages/bbui/src/Table/DateTimeRenderer.svelte index 8a06082d58..ff750cecd8 100644 --- a/packages/bbui/src/Table/DateTimeRenderer.svelte +++ b/packages/bbui/src/Table/DateTimeRenderer.svelte @@ -2,9 +2,18 @@ import dayjs from "dayjs" export let value + + // adding the 0- will turn a string like 00:00:00 into a valid ISO + // date, but will make actual ISO dates invalid + $: time = new Date(`0-${value}`) + $: isTime = !isNaN(time) -
{dayjs(value).format("MMMM D YYYY, HH:mm")}
+
+ {dayjs(isTime ? time : value).format( + isTime ? "HH:mm:ss" : "MMMM D YYYY, HH:mm" + )} +
diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte index 85ae8a11f5..a0df3a9d07 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte @@ -59,6 +59,9 @@ $: schemaReadOnly = !responseSuccess $: variablesReadOnly = !responseSuccess $: showVariablesTab = shouldShowVariables(dynamicVariables, variablesReadOnly) + $: hasSchema = + Object.keys(schema || {}).length !== 0 || + Object.keys(query?.schema || {}).length !== 0 function getSelectedQuery() { return cloneDeep( @@ -307,6 +310,7 @@ bind:value={query.name} defaultValue="Untitled" on:change={() => (query.flags.urlName = false)} + on:save={saveQuery} />
@@ -326,7 +330,15 @@
- + +
@@ -539,9 +551,6 @@ >{response?.info.size} -
{/if} diff --git a/packages/cli/package.json b/packages/cli/package.json index b14d4d311f..8a1ce573ff 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "1.0.50-alpha.4", + "version": "1.0.50-alpha.5", "description": "Budibase CLI, for developers, self hosting and migrations.", "main": "src/index.js", "bin": { diff --git a/packages/client/manifest.json b/packages/client/manifest.json index ab48142ad5..29cbc0536c 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -2453,6 +2453,12 @@ "key": "enableTime", "defaultValue": true }, + { + "type": "boolean", + "label": "Time Only", + "key": "timeOnly", + "defaultValue": false + }, { "type": "text", "label": "Default value", diff --git a/packages/client/package.json b/packages/client/package.json index 7a91d1618b..c1cd6aec73 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "1.0.50-alpha.4", + "version": "1.0.50-alpha.5", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -19,9 +19,9 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "^1.0.50-alpha.4", - "@budibase/frontend-core": "^1.0.50-alpha.4", - "@budibase/string-templates": "^1.0.50-alpha.4", + "@budibase/bbui": "^1.0.50-alpha.5", + "@budibase/frontend-core": "^1.0.50-alpha.5", + "@budibase/string-templates": "^1.0.50-alpha.5", "regexparam": "^1.3.0", "rollup-plugin-polyfill-node": "^0.8.0", "shortid": "^2.2.15", diff --git a/packages/client/src/components/app/forms/DateTimeField.svelte b/packages/client/src/components/app/forms/DateTimeField.svelte index 515b6adc77..022a634bc5 100644 --- a/packages/client/src/components/app/forms/DateTimeField.svelte +++ b/packages/client/src/components/app/forms/DateTimeField.svelte @@ -7,6 +7,7 @@ export let placeholder export let disabled = false export let enableTime = false + export let timeOnly = false export let validation export let defaultValue @@ -33,6 +34,7 @@ id={fieldState.fieldId} appendTo={document.getElementById("flatpickr-root")} {enableTime} + {timeOnly} {placeholder} /> {/if} diff --git a/packages/server/package.json b/packages/server/package.json index ea07aed010..171f1b74bf 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "1.0.50-alpha.4", + "version": "1.0.50-alpha.5", "description": "Budibase Web Server", "main": "src/index.ts", "repository": { @@ -70,9 +70,9 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/swagger-parser": "^10.0.3", - "@budibase/backend-core": "^1.0.50-alpha.4", - "@budibase/client": "^1.0.50-alpha.4", - "@budibase/string-templates": "^1.0.50-alpha.4", + "@budibase/backend-core": "^1.0.50-alpha.5", + "@budibase/client": "^1.0.50-alpha.5", + "@budibase/string-templates": "^1.0.50-alpha.5", "@bull-board/api": "^3.7.0", "@bull-board/koa": "^3.7.0", "@elastic/elasticsearch": "7.10.0", diff --git a/packages/server/scripts/integrations/mssql/data/setup.sql b/packages/server/scripts/integrations/mssql/data/setup.sql index d0b4cfc39c..b6ab4f5274 100644 --- a/packages/server/scripts/integrations/mssql/data/setup.sql +++ b/packages/server/scripts/integrations/mssql/data/setup.sql @@ -36,13 +36,9 @@ CREATE TABLE people INSERT products (name, description) VALUES - ('Bananas', 'Fruit thing'); - -INSERT products - (name, description) -VALUES + ('Bananas', 'Fruit thing'), ('Meat', 'Animal thing'); - + INSERT tasks (taskname, productid) VALUES diff --git a/packages/server/scripts/integrations/mysql/init.sql b/packages/server/scripts/integrations/mysql/init.sql index 4dd75c36d3..f37ef0d532 100644 --- a/packages/server/scripts/integrations/mysql/init.sql +++ b/packages/server/scripts/integrations/mysql/init.sql @@ -19,6 +19,12 @@ CREATE TABLE Tasks ( FOREIGN KEY(PersonID) REFERENCES Persons(PersonID) ); +CREATE TABLE Products ( + id serial primary key, + name text, + updated time +); INSERT INTO Persons (FirstName, LastName, Age, Address, City, CreatedAt) VALUES ('Mike', 'Hughes', 28.2, '123 Fake Street', 'Belfast', '2021-01-19 03:14:07'); INSERT INTO Tasks (PersonID, TaskName) VALUES (1, 'assembling'); INSERT INTO Tasks (PersonID, TaskName) VALUES (1, 'processing'); +INSERT INTO Products (name, updated) VALUES ('Meat', '11:00:22'), ('Fruit', '10:00:00'); diff --git a/packages/server/src/api/controllers/view/exporters.js b/packages/server/src/api/controllers/view/exporters.js index 0cca3b5f89..1232640d0a 100644 --- a/packages/server/src/api/controllers/view/exporters.js +++ b/packages/server/src/api/controllers/view/exporters.js @@ -5,8 +5,11 @@ exports.csv = function (headers, rows) { csv = `${csv}\n${headers .map(header => { let val = row[header] - val = typeof val === "object" ? JSON.stringify(val) : val - return `"${val}"`.trim() + val = + typeof val === "object" + ? `"${JSON.stringify(val).replace(/"/g, "'")}"` + : `"${val}"` + return val.trim() }) .join(",")}` } diff --git a/packages/server/src/api/routes/tests/query.spec.js b/packages/server/src/api/routes/tests/query.spec.js index 9357d53cde..dac576836e 100644 --- a/packages/server/src/api/routes/tests/query.spec.js +++ b/packages/server/src/api/routes/tests/query.spec.js @@ -230,7 +230,6 @@ describe("/queries", () => { }) describe("variables", () => { - async function preview(datasource, fields) { return config.previewQuery(request, config, datasource, fields) } diff --git a/packages/server/src/threads/query.js b/packages/server/src/threads/query.js index 23b4dc1ef8..5b1a30b57d 100644 --- a/packages/server/src/threads/query.js +++ b/packages/server/src/threads/query.js @@ -161,10 +161,16 @@ class QueryRunner { const responses = await Promise.all(dynamics) for (let i = 0; i < foundVars.length; i++) { const variable = foundVars[i] - parameters[variable.name] = processStringSync(variable.value, { - data: responses[i].rows, - info: responses[i].extra, - }) + parameters[variable.name] = processStringSync( + variable.value, + { + data: responses[i].rows, + info: responses[i].extra, + }, + { + escapeNewlines: true, + } + ) // make sure its known that this uses dynamic variables in case it fails this.hasDynamicVariables = true } @@ -188,6 +194,7 @@ class QueryRunner { enrichedQuery[key] = processStringSync(fields[key], parameters, { noEscaping: true, noHelpers: true, + escapeNewlines: true, }) } else { enrichedQuery[key] = fields[key] diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index fe17d7d317..ec1052b0b5 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -1163,19 +1163,7 @@ svelte-apexcharts "^1.0.2" svelte-flatpickr "^3.1.0" -"@budibase/string-templates@1.0.50-alpha.1": - version "1.0.50-alpha.1" - resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.50-alpha.1.tgz#ea05a74a3031850652812be21f44d40249e21d43" - integrity sha512-TM6WNzGBlwV0FhR8luejg8CQGa9IaMrMLrW+gfkl4fqEafoWIeKueVhT/lVuPtUK2NzGxmKfNRoasZu6wM6grA== - dependencies: - "@budibase/handlebars-helpers" "^0.11.7" - dayjs "^1.10.4" - handlebars "^4.7.6" - handlebars-utils "^1.0.6" - lodash "^4.17.20" - vm2 "^3.9.4" - -"@budibase/string-templates@^1.0.50": +"@budibase/string-templates@^1.0.50", "@budibase/string-templates@^1.0.50-alpha.1": version "1.0.50" resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.50.tgz#53386f3c09891ef21bd47870d25cf7e12f6fac86" integrity sha512-jmqmikU3Xt0I0hY1S1QI8x5770Z+Tu6zGxb9iQsk3PUCkKCpHz70Rl3Q7x5nYsDfOlhT4YHaHKgYYQYJ6hRafw== diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index 4e25849374..725214d8e4 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "1.0.50-alpha.4", + "version": "1.0.50-alpha.5", "description": "Handlebars wrapper for Budibase templating.", "main": "src/index.cjs", "module": "dist/bundle.mjs", diff --git a/packages/string-templates/src/helpers/index.js b/packages/string-templates/src/helpers/index.js index 6b9195047e..ad4082e3a4 100644 --- a/packages/string-templates/src/helpers/index.js +++ b/packages/string-templates/src/helpers/index.js @@ -21,7 +21,7 @@ const HELPERS = [ // javascript helper new Helper(HelperFunctionNames.JS, processJS, false), // this help is applied to all statements - new Helper(HelperFunctionNames.ALL, value => { + new Helper(HelperFunctionNames.ALL, (value, { __opts }) => { if ( value != null && typeof value === "object" && @@ -36,7 +36,11 @@ const HELPERS = [ if (value && value.string) { value = value.string } - let text = new SafeString(value.replace(/&/g, "&")) + let text = value + if (__opts && __opts.escapeNewlines) { + text = value.replace(/\n/g, "\\n") + } + text = new SafeString(text.replace(/&/g, "&")) if (text == null || typeof text !== "string") { return text } @@ -62,10 +66,14 @@ module.exports.HelperNames = () => { ) } -module.exports.registerAll = handlebars => { +module.exports.registerMinimum = handlebars => { for (let helper of HELPERS) { helper.register(handlebars) } +} + +module.exports.registerAll = handlebars => { + module.exports.registerMinimum(handlebars) // register imported helpers externalHandlebars.registerAll(handlebars) } diff --git a/packages/string-templates/src/index.js b/packages/string-templates/src/index.js index 5ffd1bf1cc..7996bb9f1f 100644 --- a/packages/string-templates/src/index.js +++ b/packages/string-templates/src/index.js @@ -1,5 +1,5 @@ const handlebars = require("handlebars") -const { registerAll } = require("./helpers/index") +const { registerAll, registerMinimum } = require("./helpers/index") const processors = require("./processors") const { atob, btoa } = require("./utilities") const manifest = require("../manifest.json") @@ -8,6 +8,7 @@ const { FIND_HBS_REGEX, FIND_DOUBLE_HBS_REGEX } = require("./utilities") const hbsInstance = handlebars.create() registerAll(hbsInstance) const hbsInstanceNoHelpers = handlebars.create() +registerMinimum(hbsInstanceNoHelpers) const defaultOpts = { noHelpers: false, noEscaping: false } /** @@ -105,9 +106,7 @@ module.exports.processStringSync = (string, context, opts) => { throw "Cannot process non-string types." } try { - // finalising adds a helper, can't do this with no helpers - const shouldFinalise = !opts.noHelpers - string = processors.preprocess(string, shouldFinalise) + string = processors.preprocess(string, opts) // this does not throw an error when template can't be fulfilled, have to try correct beforehand const instance = opts.noHelpers ? hbsInstanceNoHelpers : hbsInstance const templateString = @@ -119,8 +118,10 @@ module.exports.processStringSync = (string, context, opts) => { return processors.postprocess( template({ now: new Date(now).toISOString(), + __opts: opts, ...context, - }) + }), + { escapeNewlines: opts ? opts.escapeNewlines : false } ) } catch (err) { return input @@ -176,7 +177,9 @@ module.exports.isValid = (string, opts) => { const context = {} try { const instance = opts.noHelpers ? hbsInstanceNoHelpers : hbsInstance - instance.compile(processors.preprocess(string, false))(context) + instance.compile(processors.preprocess(string, { noFinalise: true }))( + context + ) return true } catch (err) { const msg = err && err.message ? err.message : err diff --git a/packages/string-templates/src/processors/index.js b/packages/string-templates/src/processors/index.js index 174041133a..aae18aed8b 100644 --- a/packages/string-templates/src/processors/index.js +++ b/packages/string-templates/src/processors/index.js @@ -2,7 +2,7 @@ const { FIND_HBS_REGEX } = require("../utilities") const preprocessor = require("./preprocessor") const postprocessor = require("./postprocessor") -function process(output, processors) { +function process(output, processors, opts) { for (let processor of processors) { // if a literal statement has occurred stop if (typeof output !== "string") { @@ -15,24 +15,22 @@ function process(output, processors) { continue } for (let match of matches) { - output = processor.process(output, match) + output = processor.process(output, match, opts) } } return output } -module.exports.preprocess = (string, finalise = true) => { +module.exports.preprocess = (string, opts) => { let processors = preprocessor.processors - // the pre-processor finalisation stops handlebars from ever throwing an error - // might want to pre-process for other benefits but still want to see errors - if (!finalise) { + if (opts.noFinalise) { processors = processors.filter( processor => processor.name !== preprocessor.PreprocessorNames.FINALISE ) } + return process(string, processors, opts) +} +module.exports.postprocess = string => { + let processors = postprocessor.processors return process(string, processors) } - -module.exports.postprocess = string => { - return process(string, postprocessor.processors) -} diff --git a/packages/string-templates/src/processors/postprocessor.js b/packages/string-templates/src/processors/postprocessor.js index 7fc3f663fe..f78a572d07 100644 --- a/packages/string-templates/src/processors/postprocessor.js +++ b/packages/string-templates/src/processors/postprocessor.js @@ -16,6 +16,8 @@ class Postprocessor { } } +module.exports.PostProcessorNames = PostProcessorNames + module.exports.processors = [ new Postprocessor(PostProcessorNames.CONVERT_LITERALS, statement => { if (typeof statement !== "string" || !statement.includes(LITERAL_MARKER)) { diff --git a/packages/string-templates/src/processors/preprocessor.js b/packages/string-templates/src/processors/preprocessor.js index 6f6537674a..4b296d0fc7 100644 --- a/packages/string-templates/src/processors/preprocessor.js +++ b/packages/string-templates/src/processors/preprocessor.js @@ -16,8 +16,8 @@ class Preprocessor { this.fn = fn } - process(fullString, statement) { - const output = this.fn(statement) + process(fullString, statement, opts) { + const output = this.fn(statement, opts) const idx = fullString.indexOf(statement) return swapStrings(fullString, idx, statement.length, output) } @@ -48,7 +48,8 @@ module.exports.processors = [ return statement }), - new Preprocessor(PreprocessorNames.FINALISE, statement => { + new Preprocessor(PreprocessorNames.FINALISE, (statement, opts) => { + const noHelpers = opts && opts.noHelpers let insideStatement = statement.slice(2, statement.length - 2) if (insideStatement.charAt(0) === " ") { insideStatement = insideStatement.slice(1) @@ -63,7 +64,10 @@ module.exports.processors = [ return statement } } - if (HelperNames().some(option => option.includes(possibleHelper))) { + if ( + !noHelpers && + HelperNames().some(option => option.includes(possibleHelper)) + ) { insideStatement = `(${insideStatement})` } return `{{ all ${insideStatement} }}` diff --git a/packages/string-templates/test/escapes.spec.js b/packages/string-templates/test/escapes.spec.js index 7e55b66b88..b845fddec9 100644 --- a/packages/string-templates/test/escapes.spec.js +++ b/packages/string-templates/test/escapes.spec.js @@ -59,3 +59,33 @@ describe("attempt some complex problems", () => { expect(output).toBe("nulltest") }) }) + +describe("check behaviour with newlines", () => { + const context = { + binding: `Hello + there` + } + it("should escape new line to \\n with double brace", async () => { + const hbs = JSON.stringify({ + body: "{{ binding }}" + }) + const output = await processString(hbs, context, { escapeNewlines: true }) + expect(JSON.parse(output).body).toBe(context.binding) + }) + + it("should work the same with triple brace", async () => { + const hbs = JSON.stringify({ + body: "{{{ binding }}}" + }) + const output = await processString(hbs, context, { escapeNewlines: true }) + expect(JSON.parse(output).body).toBe(context.binding) + }) + + it("should still work with helpers disabled", async () => { + const hbs = JSON.stringify({ + body: "{{ binding }}" + }) + const output = await processString(hbs, context, { escapeNewlines: true, noHelpers: true }) + expect(JSON.parse(output).body).toBe(context.binding) + }) +}) diff --git a/packages/string-templates/test/helpers.spec.js b/packages/string-templates/test/helpers.spec.js index b4179475fb..0d39660d59 100644 --- a/packages/string-templates/test/helpers.spec.js +++ b/packages/string-templates/test/helpers.spec.js @@ -20,7 +20,7 @@ describe("test that it can run without helpers", () => { ) const valid = await processString("{{ avg 1 1 1 }}", {}) expect(valid).toBe("1") - expect(output).toBe("{{ avg 1 1 1 }}") + expect(output).toBe("") }) }) diff --git a/packages/worker/package.json b/packages/worker/package.json index 35f78c2c5b..4c0f682f28 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/worker", "email": "hi@budibase.com", - "version": "1.0.50-alpha.4", + "version": "1.0.50-alpha.5", "description": "Budibase background service", "main": "src/index.ts", "repository": { @@ -34,8 +34,8 @@ "author": "Budibase", "license": "GPL-3.0", "dependencies": { - "@budibase/backend-core": "^1.0.50-alpha.4", - "@budibase/string-templates": "^1.0.50-alpha.4", + "@budibase/backend-core": "^1.0.50-alpha.5", + "@budibase/string-templates": "^1.0.50-alpha.5", "@koa/router": "^8.0.0", "@sentry/node": "^6.0.0", "@techpass/passport-openidconnect": "^0.3.0",