diff --git a/.github/workflows/smoke_test.yaml b/.github/workflows/smoke_test.yaml index b26d0386fc..79c97b69af 100644 --- a/.github/workflows/smoke_test.yaml +++ b/.github/workflows/smoke_test.yaml @@ -32,7 +32,9 @@ jobs: uses: cypress-io/github-action@v2 with: install: false - command: yarn test:e2e:ci + command: yarn test:e2e:ci:record + env: + CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} # TODO: upload recordings to s3 # - name: Configure AWS Credentials diff --git a/charts/budibase/templates/app-service-deployment.yaml b/charts/budibase/templates/app-service-deployment.yaml index c80cfa2ecc..8763274c50 100644 --- a/charts/budibase/templates/app-service-deployment.yaml +++ b/charts/budibase/templates/app-service-deployment.yaml @@ -112,6 +112,8 @@ spec: value: {{ .Values.globals.google.secret | quote }} - name: AUTOMATION_MAX_ITERATIONS value: {{ .Values.globals.automationMaxIterations | quote }} + - name: EXCLUDE_QUOTAS_TENANTS + value: {{ .Values.globals.excludeQuotasTenants | quote }} image: budibase/apps:{{ .Values.globals.appVersion }} imagePullPolicy: Always diff --git a/lerna.json b/lerna.json index fc5a317263..2f7203e4cf 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.0.130-alpha.6", + "version": "1.0.138", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/package.json b/package.json index 727104d830..fb6d9da990 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "lint:fix": "yarn run lint:fix:prettier && yarn run lint:fix:eslint", "test:e2e": "lerna run cy:test --stream", "test:e2e:ci": "lerna run cy:ci --stream", + "test:e2e:ci:record": "lerna run cy:ci:record --stream", "build:specs": "lerna run specs", "build:docker": "lerna run build:docker && npm run build:docker:proxy:compose && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh $BUDIBASE_RELEASE_VERSION && cd -", "build:docker:proxy": "docker build hosting/proxy -t proxy-service", diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index fd77e41f91..9ab70185e0 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "1.0.130-alpha.6", + "version": "1.0.138", "description": "Budibase backend core libraries used in server and worker", "main": "src/index.js", "author": "Budibase", diff --git a/packages/backend-core/src/environment.js b/packages/backend-core/src/environment.js index 26e0d486f7..c4fc4a87c8 100644 --- a/packages/backend-core/src/environment.js +++ b/packages/backend-core/src/environment.js @@ -6,6 +6,10 @@ function isTest() { ) } +function isDev() { + return process.env.NODE_ENV !== "production" +} + module.exports = { JWT_SECRET: process.env.JWT_SECRET, COUCH_DB_URL: process.env.COUCH_DB_URL || "http://localhost:4005", @@ -32,6 +36,7 @@ module.exports = { TENANT_FEATURE_FLAGS: process.env.TENANT_FEATURE_FLAGS, USE_COUCH: process.env.USE_COUCH || true, isTest, + isDev, _set(key, value) { process.env[key] = value module.exports[key] = value diff --git a/packages/bbui/package.json b/packages/bbui/package.json index c41e3e477d..b6283ab345 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.130-alpha.6", + "version": "1.0.138", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", @@ -38,7 +38,7 @@ ], "dependencies": { "@adobe/spectrum-css-workflow-icons": "^1.2.1", - "@budibase/string-templates": "^1.0.130-alpha.6", + "@budibase/string-templates": "^1.0.138", "@spectrum-css/actionbutton": "^1.0.1", "@spectrum-css/actiongroup": "^1.0.1", "@spectrum-css/avatar": "^3.0.2", diff --git a/packages/bbui/src/Table/DateTimeRenderer.svelte b/packages/bbui/src/Table/DateTimeRenderer.svelte index 5d856968e7..f4b0821069 100644 --- a/packages/bbui/src/Table/DateTimeRenderer.svelte +++ b/packages/bbui/src/Table/DateTimeRenderer.svelte @@ -2,17 +2,22 @@ import dayjs from "dayjs" export let value + export let schema // 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) + $: isTimeOnly = !isNaN(time) || schema?.timeOnly + $: isDateOnly = schema?.dateOnly + $: format = isTimeOnly + ? "HH:mm:ss" + : isDateOnly + ? "MMMM D YYYY" + : "MMMM D YYYY, HH:mm"
- {dayjs(isTime ? time : value).format( - isTime ? "HH:mm:ss" : "MMMM D YYYY, HH:mm" - )} + {dayjs(isTimeOnly ? time : value).format(format)}
diff --git a/packages/builder/src/components/backend/DatasourceNavigator/_components/GoogleSignIn.svelte b/packages/builder/src/components/backend/DatasourceNavigator/_components/GoogleSignIn.svelte new file mode 100644 index 0000000000..c30e8fc2ee --- /dev/null +++ b/packages/builder/src/components/backend/DatasourceNavigator/_components/GoogleSignIn.svelte @@ -0,0 +1,145 @@ + + + + + btn_google_dark_normal_ios + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte index 1441d3834b..95a5f54e32 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte @@ -49,6 +49,10 @@ filters = [...filters, duplicate] } + const getSchema = filter => { + return schemaFields.find(field => field.name === filter.field) + } + const onFieldChange = (expression, field) => { // Update the field type expression.type = enrichedSchemaFields.find(x => x.name === field)?.type @@ -150,7 +154,12 @@ bind:value={filter.value} /> {:else if filter.type === "datetime"} - + {:else} {/if} diff --git a/packages/cli/package.json b/packages/cli/package.json index 3ef8b0ab9f..d15a2d1b14 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "1.0.130-alpha.6", + "version": "1.0.138", "description": "Budibase CLI, for developers, self hosting and migrations.", "main": "src/index.js", "bin": { diff --git a/packages/client/package.json b/packages/client/package.json index bc86e4d549..128c4f66a5 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "1.0.130-alpha.6", + "version": "1.0.138", "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.130-alpha.6", - "@budibase/frontend-core": "^1.0.130-alpha.6", - "@budibase/string-templates": "^1.0.130-alpha.6", + "@budibase/bbui": "^1.0.138", + "@budibase/frontend-core": "^1.0.138", + "@budibase/string-templates": "^1.0.138", "@spectrum-css/button": "^3.0.3", "@spectrum-css/card": "^3.0.3", "@spectrum-css/divider": "^1.0.3", diff --git a/packages/client/src/components/app/dynamic-filter/FilterModal.svelte b/packages/client/src/components/app/dynamic-filter/FilterModal.svelte index 54ad1f3a80..b8815279dd 100644 --- a/packages/client/src/components/app/dynamic-filter/FilterModal.svelte +++ b/packages/client/src/components/app/dynamic-filter/FilterModal.svelte @@ -88,6 +88,10 @@ const schema = schemaFields.find(x => x.name === field) return schema?.constraints?.inclusion || [] } + + const getSchema = filter => { + return schemaFields.find(field => field.name === filter.field) + }
@@ -134,7 +138,12 @@ bind:value={filter.value} /> {:else if filter.type === "datetime"} - + {:else} {/if} diff --git a/packages/client/src/components/app/forms/FormStep.svelte b/packages/client/src/components/app/forms/FormStep.svelte index 4441f515ee..22972c5c48 100644 --- a/packages/client/src/components/app/forms/FormStep.svelte +++ b/packages/client/src/components/app/forms/FormStep.svelte @@ -22,7 +22,7 @@ if ( formContext && $builderStore.inBuilder && - $componentStore.selectedComponentPath?.includes($component.id) + $componentStore?.selectedComponentPath?.includes($component.id) ) { formContext.formApi.setStep(step) } diff --git a/packages/frontend-core/package.json b/packages/frontend-core/package.json index 55665a9804..2f54e127cb 100644 --- a/packages/frontend-core/package.json +++ b/packages/frontend-core/package.json @@ -1,12 +1,12 @@ { "name": "@budibase/frontend-core", - "version": "1.0.130-alpha.6", + "version": "1.0.138", "description": "Budibase frontend core libraries used in builder and client", "author": "Budibase", "license": "MPL-2.0", "svelte": "src/index.js", "dependencies": { - "@budibase/bbui": "^1.0.130-alpha.6", + "@budibase/bbui": "^1.0.138", "lodash": "^4.17.21", "svelte": "^3.46.2" } diff --git a/packages/server/package.json b/packages/server/package.json index ef02ad5600..9307a7358d 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.130-alpha.6", + "version": "1.0.138", "description": "Budibase Web Server", "main": "src/index.ts", "repository": { @@ -68,10 +68,10 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/swagger-parser": "^10.0.3", - "@budibase/backend-core": "^1.0.130-alpha.6", - "@budibase/client": "^1.0.130-alpha.6", - "@budibase/pro": "1.0.130-alpha.6", - "@budibase/string-templates": "^1.0.130-alpha.6", + "@budibase/backend-core": "^1.0.138", + "@budibase/client": "^1.0.138", + "@budibase/pro": "1.0.138", + "@budibase/string-templates": "^1.0.138", "@bull-board/api": "^3.7.0", "@bull-board/koa": "^3.7.0", "@elastic/elasticsearch": "7.10.0", diff --git a/packages/server/src/automations/automationUtils.js b/packages/server/src/automations/automationUtils.js index 0d858741dd..a3bcae0cee 100644 --- a/packages/server/src/automations/automationUtils.js +++ b/packages/server/src/automations/automationUtils.js @@ -86,3 +86,15 @@ exports.substituteLoopStep = (hbsString, substitute) => { return hbsString } + +exports.stringSplit = value => { + if (value == null) { + return [] + } + if (value.split("\n").length > 1) { + value = value.split("\n") + } else { + value = value.split(",") + } + return value +} diff --git a/packages/server/src/integrations/microsoftSqlServer.ts b/packages/server/src/integrations/microsoftSqlServer.ts index 1b37b5df9a..a7b9906481 100644 --- a/packages/server/src/integrations/microsoftSqlServer.ts +++ b/packages/server/src/integrations/microsoftSqlServer.ts @@ -242,12 +242,10 @@ module MSSQLModule { if (typeof name !== "string") { continue } - const type: string = convertSqlType(def.DATA_TYPE) - schema[name] = { autocolumn: !!autoColumns.find((col: string) => col === name), name: name, - type, + ...convertSqlType(def.DATA_TYPE), } } tables[tableName] = { diff --git a/packages/server/src/integrations/mysql.ts b/packages/server/src/integrations/mysql.ts index 065a1b2333..4fe996a019 100644 --- a/packages/server/src/integrations/mysql.ts +++ b/packages/server/src/integrations/mysql.ts @@ -15,6 +15,7 @@ import { } from "./utils" import { DatasourcePlus } from "./base/datasourcePlus" import dayjs from "dayjs" +import { FieldTypes } from "../constants" const { NUMBER_REGEX } = require("../utilities") module MySQLModule { @@ -101,7 +102,7 @@ module MySQLModule { } // if not a number, see if it is a date - important to do in this order as any // integer will be considered a valid date - else if (dayjs(binding).isValid()) { + else if (/^\d/.test(binding) && dayjs(binding).isValid()) { bindings[i] = dayjs(binding).toDate() } } @@ -151,20 +152,24 @@ module MySQLModule { async internalQuery( query: SqlQuery, - connect: boolean = true + opts: { connect?: boolean; disableCoercion?: boolean } = { + connect: true, + disableCoercion: false, + } ): Promise { try { - if (connect) { + if (opts?.connect) { await this.connect() } + const baseBindings = query.bindings || [] + const bindings = opts?.disableCoercion + ? baseBindings + : bindingTypeCoerce(baseBindings) // Node MySQL is callback based, so we must wrap our call in a promise - const response = await this.client.query( - query.sql, - bindingTypeCoerce(query.bindings || []) - ) + const response = await this.client.query(query.sql, bindings) return response[0] } finally { - if (connect) { + if (opts?.connect) { await this.disconnect() } } @@ -179,7 +184,7 @@ module MySQLModule { // get the tables first const tablesResp = await this.internalQuery( { sql: "SHOW TABLES;" }, - false + { connect: false } ) const tableNames = tablesResp.map( (obj: any) => @@ -191,7 +196,7 @@ module MySQLModule { const schema: TableSchema = {} const descResp = await this.internalQuery( { sql: `DESCRIBE \`${tableName}\`;` }, - false + { connect: false } ) for (let column of descResp) { const columnName = column.Field @@ -211,8 +216,8 @@ module MySQLModule { schema[columnName] = { name: columnName, autocolumn: isAuto, - type: convertSqlType(column.Type), constraints, + ...convertSqlType(column.Type), } } if (!tables[tableName]) { @@ -254,7 +259,8 @@ module MySQLModule { async query(json: QueryJson) { await this.connect() try { - const queryFn = (query: any) => this.internalQuery(query, false) + const queryFn = (query: any) => + this.internalQuery(query, { connect: false, disableCoercion: true }) return await this.queryWithReturning(json, queryFn) } finally { await this.disconnect() diff --git a/packages/server/src/integrations/oracle.ts b/packages/server/src/integrations/oracle.ts index 7cb7ba88cf..94e51694c1 100644 --- a/packages/server/src/integrations/oracle.ts +++ b/packages/server/src/integrations/oracle.ts @@ -279,9 +279,9 @@ module OracleModule { ) } - private internalConvertType(column: OracleColumn): string { + private internalConvertType(column: OracleColumn): { type: string } { if (this.isBooleanType(column)) { - return FieldTypes.BOOLEAN + return { type: FieldTypes.BOOLEAN } } return convertSqlType(column.type) @@ -328,7 +328,7 @@ module OracleModule { fieldSchema = { autocolumn: OracleIntegration.isAutoColumn(oracleColumn), name: columnName, - type: this.internalConvertType(oracleColumn), + ...this.internalConvertType(oracleColumn), } table.schema[columnName] = fieldSchema } diff --git a/packages/server/src/integrations/postgres.ts b/packages/server/src/integrations/postgres.ts index 1dc6fd9d2d..01257f3aa0 100644 --- a/packages/server/src/integrations/postgres.ts +++ b/packages/server/src/integrations/postgres.ts @@ -227,7 +227,6 @@ module PostgresModule { } } - const type: string = convertSqlType(column.data_type) const identity = !!( column.identity_generation || column.identity_start || @@ -242,7 +241,7 @@ module PostgresModule { tables[tableName].schema[columnName] = { autocolumn: isAuto, name: columnName, - type, + ...convertSqlType(column.data_type), } } diff --git a/packages/server/src/integrations/utils.ts b/packages/server/src/integrations/utils.ts index 326b213bc7..7e4efad84f 100644 --- a/packages/server/src/integrations/utils.ts +++ b/packages/server/src/integrations/utils.ts @@ -35,6 +35,9 @@ const SQL_DATE_TYPE_MAP = { date: FieldTypes.DATETIME, } +const SQL_DATE_ONLY_TYPES = ["date"] +const SQL_TIME_ONLY_TYPES = ["time"] + const SQL_STRING_TYPE_MAP = { varchar: FieldTypes.STRING, char: FieldTypes.STRING, @@ -85,9 +88,9 @@ export function breakExternalTableId(tableId: string | undefined) { return {} } const parts = tableId.split(DOUBLE_SEPARATOR) - let tableName = parts.pop() + let datasourceId = parts.shift() // if they need joined - let datasourceId = parts.join(DOUBLE_SEPARATOR) + let tableName = parts.join(DOUBLE_SEPARATOR) return { datasourceId, tableName } } @@ -137,12 +140,20 @@ export function breakRowIdField(_id: string | { _id: string }): any[] { } export function convertSqlType(type: string) { + let foundType = FieldTypes.STRING + const lcType = type.toLowerCase() for (let [external, internal] of Object.entries(SQL_TYPE_MAP)) { - if (type.toLowerCase().includes(external)) { - return internal + if (lcType.includes(external)) { + foundType = internal + break } } - return FieldTypes.STRING + const schema: any = { type: foundType } + if (foundType === FieldTypes.DATETIME) { + schema.dateOnly = SQL_DATE_ONLY_TYPES.includes(lcType) + schema.timeOnly = SQL_TIME_ONLY_TYPES.includes(lcType) + } + return schema } export function getSqlQuery(query: SqlQuery | string): SqlQuery { diff --git a/packages/server/src/threads/automation.js b/packages/server/src/threads/automation.js index db462f5a8d..63a3ea8bf3 100644 --- a/packages/server/src/threads/automation.js +++ b/packages/server/src/threads/automation.js @@ -100,10 +100,10 @@ class Orchestrator { let automation = this._automation const app = await this.getApp() let stopped = false - let loopStep + let loopStep = null let stepCount = 0 - let loopStepNumber + let loopStepNumber = null let loopSteps = [] for (let step of automation.definition.steps) { stepCount++ @@ -117,15 +117,17 @@ class Orchestrator { if (loopStep) { input = await processObject(loopStep.inputs, this._context) } - let iterations = loopStep ? input.binding.length : 1 + 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++) { let originalStepInput = cloneDeep(step.inputs) // Handle if the user has set a max iteration count or if it reaches the max limit set by us if (loopStep) { - // lets first of all handle the input - // if the input is array then use it, if it is a string then split it on every new line let newInput = await processObject( loopStep.inputs, cloneDeep(this._context) @@ -134,9 +136,6 @@ class Orchestrator { newInput, loopStep.schema.inputs ) - this._context.steps[loopStepNumber] = { - currentItem: newInput.binding[index], - } let tempOutput = { items: loopSteps, iterations: iterationCount } if ( @@ -154,6 +153,20 @@ class Orchestrator { break } + let item + if ( + typeof loopStep.inputs.binding === "string" && + loopStep.inputs.option === "String" + ) { + item = automationUtils.stringSplit(newInput.binding) + } else { + item = loopStep.inputs.binding + } + + this._context.steps[loopStepNumber] = { + currentItem: item[index], + } + // 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, value] of Object.entries(originalStepInput)) { @@ -286,18 +299,16 @@ class Orchestrator { module.exports = (input, callback) => { const appId = input.data.event.appId - doInAppContext(appId, () => { + doInAppContext(appId, async () => { const automationOrchestrator = new Orchestrator( input.data.automation, input.data.event ) - automationOrchestrator - .execute() - .then(response => { - callback(null, response) - }) - .catch(err => { - callback(err) - }) + try { + const response = await automationOrchestrator.execute() + callback(null, response) + } catch (err) { + callback(err) + } }) } diff --git a/packages/server/src/threads/query.js b/packages/server/src/threads/query.js index 71994a7244..ec9d9a6fa6 100644 --- a/packages/server/src/threads/query.js +++ b/packages/server/src/threads/query.js @@ -191,14 +191,13 @@ class QueryRunner { } module.exports = (input, callback) => { - doInAppContext(input.appId, () => { + doInAppContext(input.appId, async () => { const Runner = new QueryRunner(input) - Runner.execute() - .then(response => { - callback(null, response) - }) - .catch(err => { - callback(err) - }) + try { + const response = await Runner.execute() + callback(null, response) + } catch (err) { + callback(err) + } }) } diff --git a/packages/server/src/utilities/fileSystem/index.js b/packages/server/src/utilities/fileSystem/index.js index 8a02afc5b3..e2a76c49a1 100644 --- a/packages/server/src/utilities/fileSystem/index.js +++ b/packages/server/src/utilities/fileSystem/index.js @@ -2,7 +2,11 @@ const { budibaseTempDir } = require("../budibaseDir") const fs = require("fs") const { join } = require("path") const uuid = require("uuid/v4") -const { doWithDB } = require("@budibase/backend-core/db") +const { + doWithDB, + dangerousGetDB, + closeDB, +} = require("@budibase/backend-core/db") const { ObjectStoreBuckets } = require("../../constants") const { upload, @@ -151,14 +155,18 @@ exports.streamBackup = async appId => { * @return {*} either a readable stream or a string */ exports.exportDB = async (dbName, { stream, filter, exportName } = {}) => { - return doWithDB(dbName, async db => { - // Stream the dump if required - if (stream) { - const memStream = new MemoryStream() - db.dump(memStream, { filter }) - return memStream - } + // streaming a DB dump is a bit more complicated, can't close DB + if (stream) { + const db = dangerousGetDB(dbName) + const memStream = new MemoryStream() + memStream.on("end", async () => { + await closeDB(db) + }) + db.dump(memStream, { filter }) + return memStream + } + return doWithDB(dbName, async db => { // Write the dump to file if required if (exportName) { const path = join(budibaseTempDir(), exportName) diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index afb240d194..e24b226eda 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -1014,38 +1014,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@1.0.130-alpha.1": - version "1.0.130-alpha.1" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.130-alpha.1.tgz#670c090b91edef708fa77f63d0288f9a2f8733c1" - integrity sha512-Twhy7YtK7URjrw948UVO0MkxRtz8GWAROGTf/uZkla2visuinKVlmXvsnjK/eDKWVfzN+WBqoMjgslEpDqLLtg== - dependencies: - "@techpass/passport-openidconnect" "^0.3.0" - aws-sdk "^2.901.0" - bcryptjs "^2.4.3" - cls-hooked "^4.2.2" - ioredis "^4.27.1" - jsonwebtoken "^8.5.1" - koa-passport "^4.1.4" - lodash "^4.17.21" - lodash.isarguments "^3.1.0" - node-fetch "^2.6.1" - passport-google-auth "^1.0.2" - passport-google-oauth "^2.0.0" - passport-jwt "^4.0.0" - passport-local "^1.0.0" - posthog-node "^1.3.0" - pouchdb "7.3.0" - pouchdb-find "^7.2.2" - pouchdb-replication-stream "^1.2.9" - sanitize-s3-objectkey "^0.0.1" - tar-fs "^2.1.1" - uuid "^8.3.2" - zlib "^1.0.5" - -"@budibase/backend-core@^1.0.130-alpha.1": - version "1.0.134" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.134.tgz#c5fa1b179d7545339d6c5f2d69b0cd3f99d43c5c" - integrity sha512-otv40D1q6UOozv38XcXpyXzyIdqdNJA3PxJ7hQDUEoEQXy8xSdzvWy/wiC/paDy5zh4pCVYyIHPGZQtodHmbXQ== +"@budibase/backend-core@1.0.138": + version "1.0.138" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.138.tgz#5297d6cf5b9ec8c15f0a6df4c7d8273b8ac900f0" + integrity sha512-1qN/5urKX8bBXwEz266Z94rco8dTI7VqIh75m8ZcqrAfoUpjvZJS76gZxfc5U/QWPwrgVFnLtYvnEjaLbGEflg== dependencies: "@techpass/passport-openidconnect" "^0.3.0" aws-sdk "^2.901.0" @@ -1119,128 +1091,12 @@ svelte-flatpickr "^3.2.3" svelte-portal "^1.0.0" -"@budibase/bbui@^1.0.134": - version "1.0.134" - resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-1.0.134.tgz#bd7cec68ccca9392829dccf7c6154b6979e278d1" - integrity sha512-KcZwUy22jCrePb39yUsz8kiSXK458rpRL2iDdsdZD+GIHITP3qrUu5uu6HfcHrlDQHBgPcI/vJfppjBspCC79A== +"@budibase/pro@1.0.138": + version "1.0.138" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.138.tgz#cacbebe5ce93eb533af62a794a638944c2c61544" + integrity sha512-4ABlUZvl2h8sd8awJATf3KJeoFWV/8SoqdbKiH1ICdUcM/6dad7nhbJ15QqJL+Uuh/+mN2yEbr8V6Un2+yF+CA== dependencies: - "@adobe/spectrum-css-workflow-icons" "^1.2.1" - "@budibase/string-templates" "^1.0.134" - "@spectrum-css/actionbutton" "^1.0.1" - "@spectrum-css/actiongroup" "^1.0.1" - "@spectrum-css/avatar" "^3.0.2" - "@spectrum-css/button" "^3.0.1" - "@spectrum-css/buttongroup" "^3.0.2" - "@spectrum-css/checkbox" "^3.0.2" - "@spectrum-css/dialog" "^3.0.1" - "@spectrum-css/divider" "^1.0.3" - "@spectrum-css/dropzone" "^3.0.2" - "@spectrum-css/fieldgroup" "^3.0.2" - "@spectrum-css/fieldlabel" "^3.0.1" - "@spectrum-css/icon" "^3.0.1" - "@spectrum-css/illustratedmessage" "^3.0.2" - "@spectrum-css/inlinealert" "^2.0.1" - "@spectrum-css/inputgroup" "^3.0.2" - "@spectrum-css/label" "^2.0.10" - "@spectrum-css/link" "^3.1.1" - "@spectrum-css/menu" "^3.0.1" - "@spectrum-css/modal" "^3.0.1" - "@spectrum-css/pagination" "^3.0.3" - "@spectrum-css/picker" "^1.0.1" - "@spectrum-css/popover" "^3.0.1" - "@spectrum-css/progressbar" "^1.0.2" - "@spectrum-css/progresscircle" "^1.0.2" - "@spectrum-css/radio" "^3.0.2" - "@spectrum-css/search" "^3.0.2" - "@spectrum-css/sidenav" "^3.0.2" - "@spectrum-css/statuslight" "^3.0.2" - "@spectrum-css/stepper" "^3.0.3" - "@spectrum-css/switch" "^1.0.2" - "@spectrum-css/table" "^3.0.1" - "@spectrum-css/tabs" "^3.0.1" - "@spectrum-css/tags" "^3.0.2" - "@spectrum-css/textfield" "^3.0.1" - "@spectrum-css/toast" "^3.0.1" - "@spectrum-css/tooltip" "^3.0.3" - "@spectrum-css/treeview" "^3.0.2" - "@spectrum-css/typography" "^3.0.1" - "@spectrum-css/underlay" "^2.0.9" - "@spectrum-css/vars" "^3.0.1" - dayjs "^1.10.4" - easymde "^2.16.1" - svelte-flatpickr "^3.2.3" - svelte-portal "^1.0.0" - -"@budibase/client@^1.0.130-alpha.1": - version "1.0.134" - resolved "https://registry.yarnpkg.com/@budibase/client/-/client-1.0.134.tgz#b1dfd9137045e80e4f6c6982d7d28ae3053f0910" - integrity sha512-SYBDaybFyoJalabjzgvqG80l/bZjI8lG1rzR4bGGqyHf0wDYbHbHWeDvj/4pLhCSpcjGabi7eC+wvjxejIqQng== - dependencies: - "@budibase/bbui" "^1.0.134" - "@budibase/frontend-core" "^1.0.134" - "@budibase/string-templates" "^1.0.134" - "@spectrum-css/button" "^3.0.3" - "@spectrum-css/card" "^3.0.3" - "@spectrum-css/divider" "^1.0.3" - "@spectrum-css/link" "^3.1.3" - "@spectrum-css/page" "^3.0.1" - "@spectrum-css/tag" "^3.1.4" - "@spectrum-css/typography" "^3.0.2" - "@spectrum-css/vars" "^3.0.1" - apexcharts "^3.22.1" - dayjs "^1.10.5" - downloadjs "1.4.7" - leaflet "^1.7.1" - regexparam "^1.3.0" - rollup-plugin-polyfill-node "^0.8.0" - sanitize-html "^2.7.0" - screenfull "^6.0.1" - shortid "^2.2.15" - svelte "^3.38.2" - svelte-apexcharts "^1.0.2" - svelte-flatpickr "^3.1.0" - svelte-spa-router "^3.0.5" - -"@budibase/frontend-core@^1.0.134": - version "1.0.134" - resolved "https://registry.yarnpkg.com/@budibase/frontend-core/-/frontend-core-1.0.134.tgz#3d5efbddea60cf8fd479ad396dd41ab82d794cad" - integrity sha512-PZxUVNXSHngBASfsNXx5TWy6JiGlqJrnAqux9Unc7oeQcHFkoDH21BcJjNZlX5TgCmAMQCeNksB42q9nfkMlgg== - dependencies: - "@budibase/bbui" "^1.0.134" - lodash "^4.17.21" - svelte "^3.46.2" - -"@budibase/handlebars-helpers@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.11.8.tgz#6953d29673a8c5c407e096c0a84890465c7ce841" - integrity sha512-ggWJUt0GqsHFAEup5tlWlcrmYML57nKhpNGGLzVsqXVYN8eVmf3xluYmmMe7fDYhQH0leSprrdEXmsdFQF3HAQ== - dependencies: - array-sort "^1.0.0" - define-property "^2.0.2" - extend-shallow "^3.0.2" - for-in "^1.0.2" - get-object "^0.2.0" - get-value "^3.0.1" - handlebars "^4.7.7" - handlebars-utils "^1.0.6" - has-value "^2.0.2" - helper-md "^0.2.2" - html-tag "^2.0.0" - is-even "^1.0.0" - is-glob "^4.0.1" - kind-of "^6.0.3" - micromatch "^3.1.5" - relative "^3.0.2" - striptags "^3.1.1" - to-gfm-code-block "^0.1.1" - year "^0.2.1" - -"@budibase/pro@1.0.130-alpha.1": - version "1.0.130-alpha.1" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.130-alpha.1.tgz#12112ef0c178b25cbc24d2e42a644fdcf948cd80" - integrity sha512-TMcfMPM8DSSgoh7WfyPyXvWqOLYBnK8/8LsUcnDsvlEx22YsY/UNQX8eDZ+U9unE+pyCNR1dhP78uvQiFwiq3w== - dependencies: - "@budibase/backend-core" "1.0.130-alpha.1" + "@budibase/backend-core" "1.0.138" node-fetch "^2.6.1" "@budibase/standard-components@^0.9.139": diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index 9a263e0d6a..7b6071d639 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "1.0.130-alpha.6", + "version": "1.0.138", "description": "Handlebars wrapper for Budibase templating.", "main": "src/index.cjs", "module": "dist/bundle.mjs", diff --git a/packages/string-templates/src/index.js b/packages/string-templates/src/index.js index 6e464c27c4..f4feceac4b 100644 --- a/packages/string-templates/src/index.js +++ b/packages/string-templates/src/index.js @@ -70,7 +70,7 @@ function createTemplate(string, opts) { * @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. - * @param {object|undefined} opts optional - specify some options for processing. + * @param {object|undefined} [opts] optional - specify some options for processing. * @returns {Promise} The structure input, as fully updated as possible. */ module.exports.processObject = async (object, context, opts) => { @@ -101,7 +101,7 @@ module.exports.processObject = async (object, context, opts) => { * then nothing will occur. * @param {string} string The template string which is the filled from the context object. * @param {object} context An object of information which will be used to enrich the string. - * @param {object|undefined} opts optional - specify some options for processing. + * @param {object|undefined} [opts] optional - specify some options for processing. * @returns {Promise} The enriched string, all templates should have been replaced if they can be. */ module.exports.processString = async (string, context, opts) => { @@ -115,7 +115,7 @@ module.exports.processString = async (string, context, opts) => { * @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. - * @param {object|undefined} opts optional - specify some options for processing. + * @param {object|undefined} [opts] optional - specify some options for processing. * @returns {object|array} The structure input, as fully updated as possible. */ module.exports.processObjectSync = (object, context, opts) => { @@ -136,7 +136,7 @@ module.exports.processObjectSync = (object, context, opts) => { * then nothing will occur. This is a pure sync call and therefore does not have the full functionality of the async call. * @param {string} string The template string which is the filled from the context object. * @param {object} context An object of information which will be used to enrich the string. - * @param {object|undefined} opts optional - specify some options for processing. + * @param {object|undefined} [opts] optional - specify some options for processing. * @returns {string} The enriched string, all templates should have been replaced if they can be. */ module.exports.processStringSync = (string, context, opts) => { @@ -194,7 +194,7 @@ module.exports.makePropSafe = property => { /** * Checks whether or not a template string contains totally valid syntax (simply tries running it) * @param string The string to test for valid syntax - this may contain no templates and will be considered valid. - * @param opts optional - specify some options for processing. + * @param [opts] optional - specify some options for processing. * @returns {boolean} Whether or not the input string is valid. */ module.exports.isValid = (string, opts) => { @@ -205,6 +205,7 @@ module.exports.isValid = (string, opts) => { "array", "cannot read property", "undefined", + "json at position 0", ] // this is a portion of a specific string always output by handlebars in the case of a syntax error const invalidCases = [`expecting '`] diff --git a/packages/string-templates/test/helpers.spec.js b/packages/string-templates/test/helpers.spec.js index 0d39660d59..17e6876bba 100644 --- a/packages/string-templates/test/helpers.spec.js +++ b/packages/string-templates/test/helpers.spec.js @@ -360,6 +360,13 @@ describe("Test the literal helper", () => { }) }) +describe("Test that JSONpase helper", () => { + it("should state that the JSONparse helper is valid", async () => { + const output = isValid(`{{ JSONparse input }}`) + expect(output).toBe(true) + }) +}) + describe("Cover a few complex use cases", () => { it("should allow use of three different collection helpers", async () => { const output = await processString( diff --git a/packages/worker/package.json b/packages/worker/package.json index 1dfbf7b43d..03282f44c0 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.130-alpha.6", + "version": "1.0.138", "description": "Budibase background service", "main": "src/index.ts", "repository": { @@ -31,9 +31,9 @@ "author": "Budibase", "license": "GPL-3.0", "dependencies": { - "@budibase/backend-core": "^1.0.130-alpha.6", - "@budibase/pro": "1.0.130-alpha.6", - "@budibase/string-templates": "^1.0.130-alpha.6", + "@budibase/backend-core": "^1.0.138", + "@budibase/pro": "1.0.138", + "@budibase/string-templates": "^1.0.138", "@koa/router": "^8.0.0", "@sentry/node": "6.17.7", "@techpass/passport-openidconnect": "^0.3.0", diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index da118da79a..a2a29f5f77 100644 --- a/packages/worker/yarn.lock +++ b/packages/worker/yarn.lock @@ -293,10 +293,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@1.0.130-alpha.1": - version "1.0.130-alpha.1" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.130-alpha.1.tgz#670c090b91edef708fa77f63d0288f9a2f8733c1" - integrity sha512-Twhy7YtK7URjrw948UVO0MkxRtz8GWAROGTf/uZkla2visuinKVlmXvsnjK/eDKWVfzN+WBqoMjgslEpDqLLtg== +"@budibase/backend-core@1.0.138": + version "1.0.138" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.138.tgz#5297d6cf5b9ec8c15f0a6df4c7d8273b8ac900f0" + integrity sha512-1qN/5urKX8bBXwEz266Z94rco8dTI7VqIh75m8ZcqrAfoUpjvZJS76gZxfc5U/QWPwrgVFnLtYvnEjaLbGEflg== dependencies: "@techpass/passport-openidconnect" "^0.3.0" aws-sdk "^2.901.0" @@ -321,12 +321,12 @@ uuid "^8.3.2" zlib "^1.0.5" -"@budibase/pro@1.0.130-alpha.1": - version "1.0.130-alpha.1" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.130-alpha.1.tgz#12112ef0c178b25cbc24d2e42a644fdcf948cd80" - integrity sha512-TMcfMPM8DSSgoh7WfyPyXvWqOLYBnK8/8LsUcnDsvlEx22YsY/UNQX8eDZ+U9unE+pyCNR1dhP78uvQiFwiq3w== +"@budibase/pro@1.0.138": + version "1.0.138" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.138.tgz#cacbebe5ce93eb533af62a794a638944c2c61544" + integrity sha512-4ABlUZvl2h8sd8awJATf3KJeoFWV/8SoqdbKiH1ICdUcM/6dad7nhbJ15QqJL+Uuh/+mN2yEbr8V6Un2+yF+CA== dependencies: - "@budibase/backend-core" "1.0.130-alpha.1" + "@budibase/backend-core" "1.0.138" node-fetch "^2.6.1" "@cspotcode/source-map-consumer@0.8.0":