From f4f2a035038d502935928a7babd772d96a224e8b Mon Sep 17 00:00:00 2001 From: Budibase Release Bot <> Date: Wed, 7 Jul 2021 12:19:03 +0000 Subject: [PATCH 01/24] v0.9.72 --- lerna.json | 2 +- packages/auth/package.json | 2 +- packages/bbui/package.json | 2 +- packages/builder/package.json | 8 ++++---- packages/cli/package.json | 2 +- packages/client/package.json | 8 ++++---- packages/server/package.json | 10 +++++----- packages/standard-components/package.json | 4 ++-- packages/string-templates/package.json | 2 +- packages/worker/package.json | 6 +++--- 10 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lerna.json b/lerna.json index 78f7618651..3ececd6c41 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "0.9.71", + "version": "0.9.72", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/auth/package.json b/packages/auth/package.json index c8dbe3f918..8f1a9da30c 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/auth", - "version": "0.9.71", + "version": "0.9.72", "description": "Authentication middlewares for budibase builder and apps", "main": "src/index.js", "author": "Budibase", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index a4b6349128..02bd67f0e6 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": "0.9.71", + "version": "0.9.72", "license": "AGPL-3.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", diff --git a/packages/builder/package.json b/packages/builder/package.json index cf856552ce..2a7bd86531 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "0.9.71", + "version": "0.9.72", "license": "AGPL-3.0", "private": true, "scripts": { @@ -65,10 +65,10 @@ } }, "dependencies": { - "@budibase/bbui": "^0.9.71", - "@budibase/client": "^0.9.71", + "@budibase/bbui": "^0.9.72", + "@budibase/client": "^0.9.72", "@budibase/colorpicker": "1.1.2", - "@budibase/string-templates": "^0.9.71", + "@budibase/string-templates": "^0.9.72", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/cli/package.json b/packages/cli/package.json index b798198f5b..4550f8ab0b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "0.9.71", + "version": "0.9.72", "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 c2d680d31b..33998632f7 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "0.9.71", + "version": "0.9.72", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -18,9 +18,9 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "^0.9.71", - "@budibase/standard-components": "^0.9.71", - "@budibase/string-templates": "^0.9.71", + "@budibase/bbui": "^0.9.72", + "@budibase/standard-components": "^0.9.72", + "@budibase/string-templates": "^0.9.72", "regexparam": "^1.3.0", "shortid": "^2.2.15", "svelte-spa-router": "^3.0.5" diff --git a/packages/server/package.json b/packages/server/package.json index 55729058fa..3be231b1ed 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "0.9.71", + "version": "0.9.72", "description": "Budibase Web Server", "main": "src/index.js", "repository": { @@ -59,9 +59,9 @@ "author": "Budibase", "license": "AGPL-3.0-or-later", "dependencies": { - "@budibase/auth": "^0.9.71", - "@budibase/client": "^0.9.71", - "@budibase/string-templates": "^0.9.71", + "@budibase/auth": "^0.9.72", + "@budibase/client": "^0.9.72", + "@budibase/string-templates": "^0.9.72", "@elastic/elasticsearch": "7.10.0", "@koa/router": "8.0.0", "@sendgrid/mail": "7.1.1", @@ -114,7 +114,7 @@ "devDependencies": { "@babel/core": "^7.14.3", "@babel/preset-env": "^7.14.4", - "@budibase/standard-components": "^0.9.71", + "@budibase/standard-components": "^0.9.72", "@jest/test-sequencer": "^24.8.0", "@types/bull": "^3.15.1", "@types/jest": "^26.0.23", diff --git a/packages/standard-components/package.json b/packages/standard-components/package.json index c17e25aca8..cd050717b8 100644 --- a/packages/standard-components/package.json +++ b/packages/standard-components/package.json @@ -29,11 +29,11 @@ "keywords": [ "svelte" ], - "version": "0.9.71", + "version": "0.9.72", "license": "MIT", "gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc", "dependencies": { - "@budibase/bbui": "^0.9.71", + "@budibase/bbui": "^0.9.72", "@spectrum-css/link": "^3.1.3", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index a37f8fcc59..b9b40da67c 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "0.9.71", + "version": "0.9.72", "description": "Handlebars wrapper for Budibase templating.", "main": "src/index.cjs", "module": "dist/bundle.mjs", diff --git a/packages/worker/package.json b/packages/worker/package.json index aef9be9ded..073a03689d 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/worker", "email": "hi@budibase.com", - "version": "0.9.71", + "version": "0.9.72", "description": "Budibase background service", "main": "src/index.js", "repository": { @@ -21,8 +21,8 @@ "author": "Budibase", "license": "AGPL-3.0-or-later", "dependencies": { - "@budibase/auth": "^0.9.71", - "@budibase/string-templates": "^0.9.71", + "@budibase/auth": "^0.9.72", + "@budibase/string-templates": "^0.9.72", "@koa/router": "^8.0.0", "aws-sdk": "^2.811.0", "bcryptjs": "^2.4.3", From 9bf6600ccd93dbfdc312cd62ac27e759fcdc7041 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 7 Jul 2021 13:53:59 +0100 Subject: [PATCH 02/24] Add feature flags to manifest --- packages/server/src/api/controllers/component.js | 12 ++++++++---- packages/standard-components/manifest.json | 4 ++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/server/src/api/controllers/component.js b/packages/server/src/api/controllers/component.js index c678d8e587..06cb2cd211 100644 --- a/packages/server/src/api/controllers/component.js +++ b/packages/server/src/api/controllers/component.js @@ -20,10 +20,14 @@ exports.fetchAppComponentDefinitions = async function (ctx) { const definitions = {} for (let { manifest, library } of componentManifests) { for (let key of Object.keys(manifest)) { - const fullComponentName = `${library}/${key}`.toLowerCase() - definitions[fullComponentName] = { - component: fullComponentName, - ...manifest[key], + if (key === "features") { + definitions[key] = manifest[key] + } else { + const fullComponentName = `${library}/${key}`.toLowerCase() + definitions[fullComponentName] = { + component: fullComponentName, + ...manifest[key], + } } } } diff --git a/packages/standard-components/manifest.json b/packages/standard-components/manifest.json index be66a4ce87..ec32a5879d 100644 --- a/packages/standard-components/manifest.json +++ b/packages/standard-components/manifest.json @@ -1,4 +1,8 @@ { + "features": { + "spectrumThemes": true, + "intelligentLoading": true + }, "layout": { "name": "Layout", "description": "This component is specific only to layouts", From 24a2c547ebef662490b21b6b660908cf966ab8ab Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 7 Jul 2021 13:54:21 +0100 Subject: [PATCH 03/24] Store client features in frontend store --- packages/builder/src/builderStore/store/frontend.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index ac837978a9..c33a1d653a 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -32,6 +32,10 @@ const INITIAL_FRONTEND_STATE = { layouts: [], screens: [], components: [], + clientFeatures: { + spectrumThemes: false, + intelligentLoading: false, + }, currentFrontEndType: "none", selectedScreenId: "", selectedLayoutId: "", @@ -56,6 +60,10 @@ export const getFrontendStore = () => { ...state, libraries: application.componentLibraries, components, + clientFeatures: { + ...state.clientFeatures, + ...components.features, + }, name: application.name, description: application.description, appId: application.appId, From cc7b07a02021aeebfd2ad36d577324dbffc4ad7f Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 7 Jul 2021 13:54:44 +0100 Subject: [PATCH 04/24] Use client features to determine when to show client preview on initial load --- .../AppPreview/CurrentItemPreview.svelte | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index 3e4789a31d..607061013d 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -74,14 +74,14 @@ // Initialise the app when mounted iframe.contentWindow.addEventListener( "ready", - () => refreshContent(strippedJson), - { once: true } - ) - - // Display the client app once the iframe is initialised - iframe.contentWindow.addEventListener( - "iframe-loaded", - () => (loading = false), + () => { + // Display preview immediately if the intelligent loading feature + // is not supported + if (!$store.clientFeatures.intelligentLoading) { + loading = false + } + refreshContent(strippedJson) + }, { once: true } ) @@ -106,11 +106,9 @@ idToDelete = data.id confirmDeleteDialog.show() } else if (type === "preview-loaded") { - // We can use this in future to delay displaying the preview - // until the client app has actually initialised. - // This makes a smoother loading experience, but is not backwards - // compatible with old client library versions. - // So do nothing with this for now. + // Wait for this event to show the client library if intelligent + // loading is supported + loading = false } else { console.warning(`Client sent unknown event type: ${type}`) } From fb6c115adf46e0f06e82de7a67870e1b83c0eac8 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 7 Jul 2021 13:55:05 +0100 Subject: [PATCH 05/24] Use client feature flags to conditionally show theme picker --- .../app/[application]/design/[assetType]/_layout.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte index 533522af3c..241b0d5200 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte @@ -150,7 +150,9 @@ {#if $currentAsset}
- + {#if $store.clientFeatures.spectrumThemes} + + {/if}
From 0ff1f0fbe949b8fba080205abec1188132408024 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 7 Jul 2021 17:07:16 +0100 Subject: [PATCH 06/24] Fix crash when referencing a component definition that doesn't exist --- .../design/NavigationPanel/ComponentDropdownMenu.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte index df30a17640..24050e1088 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte @@ -65,7 +65,7 @@ } -{#if definition.editable !== false} +{#if definition?.editable !== false}
From 0a44b1e3d83dbae2f0ebe8c08b626cdb34bbd766 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 7 Jul 2021 17:07:42 +0100 Subject: [PATCH 07/24] Add client libary update management from inside the builder --- .../src/builderStore/store/frontend.js | 1 + .../src/components/deploy/VersionModal.svelte | 83 +++++++++++++++++++ .../builder/app/[application]/_layout.svelte | 2 + .../server/src/api/controllers/application.js | 56 ++++++++----- packages/server/src/api/routes/application.js | 5 ++ .../server/src/utilities/fileSystem/index.js | 16 +++- .../server/src/utilities/fileSystem/newApp.js | 47 +++++------ 7 files changed, 158 insertions(+), 52 deletions(-) create mode 100644 packages/builder/src/components/deploy/VersionModal.svelte diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index c33a1d653a..cea4e98dfe 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -75,6 +75,7 @@ export const getFrontendStore = () => { appInstance: application.instance, clientLibPath, previousTopNavPath: {}, + version: application.version, })) await hostingStore.actions.fetch() diff --git a/packages/builder/src/components/deploy/VersionModal.svelte b/packages/builder/src/components/deploy/VersionModal.svelte new file mode 100644 index 0000000000..4a42fac0c1 --- /dev/null +++ b/packages/builder/src/components/deploy/VersionModal.svelte @@ -0,0 +1,83 @@ + + +
+ +
+ + + {#if updateAvailable} + + This app is currently using version {$store.version}, but version + {clientPackage.version} is available. Updates can contain new + features, performance improvements and bug fixes. +

+ Would you like to update this app? + + {:else} + + This app is currently using version {$store.version} which is the + latest version available. + + {/if} +
+
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/_layout.svelte index eab765b502..f3ae6e7c8e 100644 --- a/packages/builder/src/pages/builder/app/[application]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_layout.svelte @@ -4,6 +4,7 @@ import { Icon, ActionGroup, Tabs, Tab } from "@budibase/bbui" import DeployModal from "components/deploy/DeployModal.svelte" import RevertModal from "components/deploy/RevertModal.svelte" + import VersionModal from "components/deploy/VersionModal.svelte" import { get } from "builderStore/api" import { isActive, goto, layout } from "@roxi/routify" import Logo from "assets/bb-emblem.svg" @@ -80,6 +81,7 @@
+ { + const url = await getAppUrlIfNotInUse(ctx) + const db = new CouchDB(appId) + const application = await db.get(DocumentTypes.APP_METADATA) + + const newAppPackage = { ...application, ...appPackage, url } + if (appPackage._rev !== application._rev) { + newAppPackage._rev = application._rev + } + + // the locked by property is attached by server but generated from + // Redis, shouldn't ever store it + if (newAppPackage.lockedBy) { + delete newAppPackage.lockedBy + } + + const response = await db.put(newAppPackage) + console.log(response) + + return response +} + const createEmptyAppPackage = async (ctx, app) => { const db = new CouchDB(app.appId) diff --git a/packages/server/src/api/routes/application.js b/packages/server/src/api/routes/application.js index a7209df3e9..6ffd3a4b5b 100644 --- a/packages/server/src/api/routes/application.js +++ b/packages/server/src/api/routes/application.js @@ -11,6 +11,11 @@ router .get("/api/applications/:appId/appPackage", controller.fetchAppPackage) .put("/api/applications/:appId", authorized(BUILDER), controller.update) .post("/api/applications", authorized(BUILDER), controller.create) + .post( + "/api/applications/:appId/client/update", + authorized(BUILDER), + controller.updateClient + ) .delete("/api/applications/:appId", authorized(BUILDER), controller.delete) module.exports = router diff --git a/packages/server/src/utilities/fileSystem/index.js b/packages/server/src/utilities/fileSystem/index.js index afacbf8cdf..c64d83dd67 100644 --- a/packages/server/src/utilities/fileSystem/index.js +++ b/packages/server/src/utilities/fileSystem/index.js @@ -13,7 +13,7 @@ const { deleteFolder, downloadTarball, } = require("./utilities") -const { downloadLibraries, uploadClientLibrary } = require("./newApp") +const { uploadClientLibrary } = require("./newApp") const download = require("download") const env = require("../../environment") const { homedir } = require("os") @@ -144,7 +144,6 @@ exports.performBackup = async (appId, backupName) => { * @return {Promise} once promise completes app resources should be ready in object store. */ exports.createApp = async appId => { - await downloadLibraries(appId) await uploadClientLibrary(appId) } @@ -193,8 +192,17 @@ exports.getComponentLibraryManifest = async (appId, library) => { delete require.cache[require.resolve(path)] return require(path) } - const path = join(appId, "node_modules", library, "package", filename) - let resp = await retrieve(ObjectStoreBuckets.APPS, path) + + let resp + try { + // Try to load the manifest from the new file location + const path = join(appId, filename) + resp = await retrieve(ObjectStoreBuckets.APPS, path) + } catch (error) { + // Fallback to loading it from the old location for old apps + const path = join(appId, "node_modules", library, "package", filename) + resp = await retrieve(ObjectStoreBuckets.APPS, path) + } if (typeof resp !== "string") { resp = resp.toString("utf8") } diff --git a/packages/server/src/utilities/fileSystem/newApp.js b/packages/server/src/utilities/fileSystem/newApp.js index 735f0d523e..749e7a278d 100644 --- a/packages/server/src/utilities/fileSystem/newApp.js +++ b/packages/server/src/utilities/fileSystem/newApp.js @@ -1,36 +1,27 @@ -const packageJson = require("../../../package.json") const { join } = require("path") const { ObjectStoreBuckets } = require("../../constants") -const { streamUpload, downloadTarball } = require("./utilities") +const { streamUpload } = require("./utilities") const fs = require("fs") const BUCKET_NAME = ObjectStoreBuckets.APPS -// can't really test this due to the downloading nature of it, wouldn't be a great test case -/* istanbul ignore next */ -exports.downloadLibraries = async appId => { - const LIBRARIES = ["standard-components"] - - const paths = {} - // Need to download tarballs directly from NPM as our users may not have node on their machine - for (let lib of LIBRARIES) { - // download tarball - const registryUrl = `https://registry.npmjs.org/@budibase/${lib}/-/${lib}-${packageJson.version}.tgz` - const path = join(appId, "node_modules", "@budibase", lib) - paths[`@budibase/${lib}`] = await downloadTarball( - registryUrl, - BUCKET_NAME, - path - ) - } - return paths -} - exports.uploadClientLibrary = async appId => { - const sourcepath = require.resolve("@budibase/client") - const destPath = join(appId, "budibase-client.js") - - await streamUpload(BUCKET_NAME, destPath, fs.createReadStream(sourcepath), { - ContentType: "application/javascript", - }) + await streamUpload( + BUCKET_NAME, + join(appId, "budibase-client.js"), + fs.createReadStream(require.resolve("@budibase/client")), + { + ContentType: "application/javascript", + } + ) + await streamUpload( + BUCKET_NAME, + join(appId, "manifest.json"), + fs.createReadStream( + require.resolve("@budibase/standard-components/manifest.json") + ), + { + ContentType: "application/javascript", + } + ) } From 9440e4a5bf2f927636d3ddef21da72665e8746fd Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 7 Jul 2021 17:35:28 +0100 Subject: [PATCH 08/24] Add UI to revert app version and initial work on app revert backend --- .../src/builderStore/store/frontend.js | 1 + .../src/components/deploy/VersionModal.svelte | 64 ++++++++++++++----- .../server/src/api/controllers/application.js | 13 +++- 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index cea4e98dfe..b9cd134067 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -76,6 +76,7 @@ export const getFrontendStore = () => { clientLibPath, previousTopNavPath: {}, version: application.version, + revertableVersion: application.revertableVersion, })) await hostingStore.actions.fetch() diff --git a/packages/builder/src/components/deploy/VersionModal.svelte b/packages/builder/src/components/deploy/VersionModal.svelte index 4a42fac0c1..541f37ad50 100644 --- a/packages/builder/src/components/deploy/VersionModal.svelte +++ b/packages/builder/src/components/deploy/VersionModal.svelte @@ -5,6 +5,7 @@ notifications, ModalContent, Body, + Button, } from "@budibase/bbui" import { store } from "builderStore" import api from "builderStore/api" @@ -14,6 +15,19 @@ $: appId = $store.appId $: updateAvailable = clientPackage.version !== $store.version + $: revertAvailable = $store.revertableVersion != null + + const refreshAppPackage = async () => { + const applicationPkg = await api.get( + `/api/applications/${appId}/appPackage` + ) + const pkg = await applicationPkg.json() + if (applicationPkg.ok) { + await store.actions.initialise(pkg) + } else { + throw new Error(pkg) + } + } const update = async () => { try { @@ -24,18 +38,7 @@ if (response.status !== 200) { throw json.message } - - // Reset frontend state after revert - const applicationPkg = await api.get( - `/api/applications/${appId}/appPackage` - ) - const pkg = await applicationPkg.json() - if (applicationPkg.ok) { - await store.actions.initialise(pkg) - } else { - throw new Error(pkg) - } - + await refreshAppPackage() notifications.success( `App updated successfully to version ${clientPackage.version}` ) @@ -43,6 +46,25 @@ notifications.error(`Error updating app: ${err}`) } } + + const revert = async () => { + try { + const response = await api.post( + `/api/applications/${appId}/client/revert` + ) + const json = await response.json() + if (response.status !== 200) { + throw json.message + } + await refreshAppPackage() + notifications.success( + `App reverted successfully to version ${$store.revertableVersion}` + ) + } catch (err) { + notifications.error(`Error reverting app: ${err}`) + } + updateModal.hide() + }
@@ -56,13 +78,16 @@ onConfirm={update} showConfirmButton={updateAvailable} > +
+ {#if revertAvailable} + + {/if} +
{#if updateAvailable} This app is currently using version {$store.version}, but version - {clientPackage.version} is available. Updates can contain new - features, performance improvements and bug fixes. -

- Would you like to update this app? + {clientPackage.version} is available. Updates can contain new features, + performance improvements and bug fixes. {:else} @@ -70,6 +95,13 @@ latest version available. {/if} + {#if revertAvailable} + + You can revert this app to version + {$store.revertableVersion} + if you're experiencing issues with the current version. + + {/if} diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js index 6719a95211..e8ace42bcd 100644 --- a/packages/server/src/api/controllers/application.js +++ b/packages/server/src/api/controllers/application.js @@ -241,8 +241,19 @@ exports.update = async function (ctx) { } exports.updateClient = async function (ctx) { + // Get current app version + const db = new CouchDB(ctx.params.appId) + const application = await db.get(DocumentTypes.APP_METADATA) + const currentVersion = application.version + + // Update client library and manifest await uploadClientLibrary(ctx.params.appId) - const appPackageUpdates = { version: packageJson.version } + + // Update versions in app package + const appPackageUpdates = { + version: packageJson.version, + revertableVersion: currentVersion, + } const data = await updateAppPackage(ctx, appPackageUpdates, ctx.params.appId) ctx.status = 200 ctx.body = data From a7a081da8c3ae7953ed70587a20cbd2baa30d6e5 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 8 Jul 2021 12:55:51 +0100 Subject: [PATCH 09/24] Add application/json as a known file type --- packages/auth/src/objectStore/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/auth/src/objectStore/index.js b/packages/auth/src/objectStore/index.js index 80875fdfee..81bdd06b62 100644 --- a/packages/auth/src/objectStore/index.js +++ b/packages/auth/src/objectStore/index.js @@ -22,11 +22,13 @@ const CONTENT_TYPE_MAP = { html: "text/html", css: "text/css", js: "application/javascript", + json: "application/json", } const STRING_CONTENT_TYPES = [ CONTENT_TYPE_MAP.html, CONTENT_TYPE_MAP.css, CONTENT_TYPE_MAP.js, + CONTENT_TYPE_MAP.json, ] // does normal sanitization and then swaps dev apps to apps From 4eb6d1e624edf10dc2c53fc9f1794196ca01732c Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 8 Jul 2021 12:56:35 +0100 Subject: [PATCH 10/24] Fix modal flashing when reverting app version and fix version number being incorrect --- .../builder/src/components/deploy/VersionModal.svelte | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/components/deploy/VersionModal.svelte b/packages/builder/src/components/deploy/VersionModal.svelte index 541f37ad50..0fb061face 100644 --- a/packages/builder/src/components/deploy/VersionModal.svelte +++ b/packages/builder/src/components/deploy/VersionModal.svelte @@ -38,7 +38,9 @@ if (response.status !== 200) { throw json.message } - await refreshAppPackage() + + // Don't wait for the async refresh, since this causes modal flashing + refreshAppPackage() notifications.success( `App updated successfully to version ${clientPackage.version}` ) @@ -49,6 +51,7 @@ const revert = async () => { try { + const revertableVersion = $store.revertableVersion const response = await api.post( `/api/applications/${appId}/client/revert` ) @@ -56,9 +59,11 @@ if (response.status !== 200) { throw json.message } - await refreshAppPackage() + + // Don't wait for the async refresh, since this causes modal flashing + refreshAppPackage() notifications.success( - `App reverted successfully to version ${$store.revertableVersion}` + `App reverted successfully to version ${revertableVersion}` ) } catch (err) { notifications.error(`Error reverting app: ${err}`) From 0ce553eaf2852993980575ec5d4a845d0f6d265a Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 8 Jul 2021 12:56:54 +0100 Subject: [PATCH 11/24] Add endpoint to revert client app version --- .../server/src/api/controllers/application.js | 36 ++++- packages/server/src/api/routes/application.js | 5 + .../src/utilities/fileSystem/clientLibrary.js | 149 ++++++++++++++++++ .../server/src/utilities/fileSystem/index.js | 6 +- .../server/src/utilities/fileSystem/newApp.js | 27 ---- 5 files changed, 185 insertions(+), 38 deletions(-) create mode 100644 packages/server/src/utilities/fileSystem/clientLibrary.js delete mode 100644 packages/server/src/utilities/fileSystem/newApp.js diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js index e8ace42bcd..d8e1e232d3 100644 --- a/packages/server/src/api/controllers/application.js +++ b/packages/server/src/api/controllers/application.js @@ -34,9 +34,10 @@ const { const { clientLibraryPath } = require("../../utilities") const { getAllLocks } = require("../../utilities/redis") const { - uploadClientLibrary, - downloadLibraries, -} = require("../../utilities/fileSystem/newApp") + updateClientLibrary, + backupClientLibrary, + revertClientLibrary, +} = require("../../utilities/fileSystem/clientLibrary") const URL_REGEX_SLASH = /\/|\\/g @@ -247,7 +248,8 @@ exports.updateClient = async function (ctx) { const currentVersion = application.version // Update client library and manifest - await uploadClientLibrary(ctx.params.appId) + await backupClientLibrary(ctx.params.appId) + await updateClientLibrary(ctx.params.appId) // Update versions in app package const appPackageUpdates = { @@ -259,6 +261,27 @@ exports.updateClient = async function (ctx) { ctx.body = data } +exports.revertClient = async function (ctx) { + // Check app can be reverted + const db = new CouchDB(ctx.params.appId) + const application = await db.get(DocumentTypes.APP_METADATA) + if (!application.revertableVersion) { + ctx.throw(400, "There is no version to revert to") + } + + // Update client library and manifest + await revertClientLibrary(ctx.params.appId) + + // Update versions in app package + const appPackageUpdates = { + version: application.revertableVersion, + revertableVersion: null, + } + const data = await updateAppPackage(ctx, appPackageUpdates, ctx.params.appId) + ctx.status = 200 + ctx.body = data +} + exports.delete = async function (ctx) { const db = new CouchDB(ctx.params.appId) @@ -290,10 +313,7 @@ const updateAppPackage = async (ctx, appPackage, appId) => { delete newAppPackage.lockedBy } - const response = await db.put(newAppPackage) - console.log(response) - - return response + return await db.put(newAppPackage) } const createEmptyAppPackage = async (ctx, app) => { diff --git a/packages/server/src/api/routes/application.js b/packages/server/src/api/routes/application.js index 6ffd3a4b5b..c2eb19e101 100644 --- a/packages/server/src/api/routes/application.js +++ b/packages/server/src/api/routes/application.js @@ -16,6 +16,11 @@ router authorized(BUILDER), controller.updateClient ) + .post( + "/api/applications/:appId/client/revert", + authorized(BUILDER), + controller.revertClient + ) .delete("/api/applications/:appId", authorized(BUILDER), controller.delete) module.exports = router diff --git a/packages/server/src/utilities/fileSystem/clientLibrary.js b/packages/server/src/utilities/fileSystem/clientLibrary.js new file mode 100644 index 0000000000..6b7e8d837d --- /dev/null +++ b/packages/server/src/utilities/fileSystem/clientLibrary.js @@ -0,0 +1,149 @@ +const { join } = require("path") +const { ObjectStoreBuckets } = require("../../constants") +const fs = require("fs") +const { upload, retrieveToTmp, streamUpload } = require("./utilities") + +/** + * Client library paths in the object store: + * Previously, the entire standard-components package was downloaded from NPM + * as a tarball and extracted to the object store, even though only the manifest + * was ever needed. Therefore we need to support old apps which may still have + * the manifest at this location for the first update. + * + * The new paths for the in-use version are: + * {appId}/manifest.json + * {appId}/budibase-client.js + * + * The paths for the backups are: + * {appId}/manifest.json.bak + * {appId}/budibase-client.js.bak + * + * We don't rely on NPM at all any more, as when updating to the latest version + * we pull both the manifest and client bundle from the server's dependencies + * in the local file system. + */ + +/** + * Backs up the current client library version by copying both the manifest + * and client bundle to .bak extensions in the object store. Only the one + * previous version is stored as a backup, which can be reverted to. + * @param appId The app ID to backup + * @returns {Promise} + */ +exports.backupClientLibrary = async appId => { + let tmpManifestPath + let tmpClientPath + + // Copy existing manifest to tmp + try { + // Try to load the manifest from the new file location + tmpManifestPath = await retrieveToTmp( + ObjectStoreBuckets.APPS, + join(appId, "manifest.json") + ) + } catch (error) { + // Fallback to loading it from the old location for old apps + tmpManifestPath = await retrieveToTmp( + ObjectStoreBuckets.APPS, + join( + appId, + "node_modules", + "budibase", + "standard-components", + "package", + "manifest.json" + ) + ) + } + + // Copy existing client lib to tmp + tmpClientPath = await retrieveToTmp( + ObjectStoreBuckets.APPS, + join(appId, "budibase-client.js") + ) + + // Upload manifest as backup + await upload({ + bucket: ObjectStoreBuckets.APPS, + filename: join(appId, "manifest.json.bak"), + path: tmpManifestPath, + type: "application/json", + }) + + // Upload client library as backup + await upload({ + bucket: ObjectStoreBuckets.APPS, + filename: join(appId, "budibase-client.js.bak"), + path: tmpClientPath, + type: "application/javascript", + }) +} + +/** + * Uploads the latest version of the component manifest and the client library + * to the object store, overwriting the existing version. + * @param appId The app ID to update + * @returns {Promise} + */ +exports.updateClientLibrary = async appId => { + // Upload latest component manifest + await streamUpload( + ObjectStoreBuckets.APPS, + join(appId, "manifest.json"), + fs.createReadStream( + require.resolve("@budibase/standard-components/manifest.json") + ), + { + ContentType: "application/json", + } + ) + + // Upload latest component library + await streamUpload( + ObjectStoreBuckets.APPS, + join(appId, "budibase-client.js"), + fs.createReadStream(require.resolve("@budibase/client")), + { + ContentType: "application/javascript", + } + ) +} + +/** + * Reverts the version of the client library and manifest to the previously + * used version for an app. + * @param appId The app ID to revert + * @returns {Promise} + */ +exports.revertClientLibrary = async appId => { + let tmpManifestPath + let tmpClientPath + + // Copy backup manifest to tmp + tmpManifestPath = await retrieveToTmp( + ObjectStoreBuckets.APPS, + join(appId, "manifest.json.bak") + ) + + // Copy backup client lib to tmp + tmpClientPath = await retrieveToTmp( + ObjectStoreBuckets.APPS, + join(appId, "budibase-client.js.bak") + ) + + // Upload manifest backup + await upload({ + bucket: ObjectStoreBuckets.APPS, + filename: join(appId, "manifest.json"), + path: tmpManifestPath, + type: "application/json", + }) + + // Upload client library backup + await upload({ + bucket: ObjectStoreBuckets.APPS, + filename: join(appId, "budibase-client.js"), + path: tmpClientPath, + type: "application/javascript", + }) +} diff --git a/packages/server/src/utilities/fileSystem/index.js b/packages/server/src/utilities/fileSystem/index.js index c64d83dd67..b83ff03854 100644 --- a/packages/server/src/utilities/fileSystem/index.js +++ b/packages/server/src/utilities/fileSystem/index.js @@ -13,7 +13,7 @@ const { deleteFolder, downloadTarball, } = require("./utilities") -const { uploadClientLibrary } = require("./newApp") +const { updateClientLibrary } = require("./clientLibrary") const download = require("download") const env = require("../../environment") const { homedir } = require("os") @@ -139,12 +139,12 @@ exports.performBackup = async (appId, backupName) => { } /** - * Downloads required libraries and creates a new path in the object store. + * Uploads the latest client library to the object store. * @param {string} appId The ID of the app which is being created. * @return {Promise} once promise completes app resources should be ready in object store. */ exports.createApp = async appId => { - await uploadClientLibrary(appId) + await updateClientLibrary(appId) } /** diff --git a/packages/server/src/utilities/fileSystem/newApp.js b/packages/server/src/utilities/fileSystem/newApp.js deleted file mode 100644 index 749e7a278d..0000000000 --- a/packages/server/src/utilities/fileSystem/newApp.js +++ /dev/null @@ -1,27 +0,0 @@ -const { join } = require("path") -const { ObjectStoreBuckets } = require("../../constants") -const { streamUpload } = require("./utilities") -const fs = require("fs") - -const BUCKET_NAME = ObjectStoreBuckets.APPS - -exports.uploadClientLibrary = async appId => { - await streamUpload( - BUCKET_NAME, - join(appId, "budibase-client.js"), - fs.createReadStream(require.resolve("@budibase/client")), - { - ContentType: "application/javascript", - } - ) - await streamUpload( - BUCKET_NAME, - join(appId, "manifest.json"), - fs.createReadStream( - require.resolve("@budibase/standard-components/manifest.json") - ), - { - ContentType: "application/javascript", - } - ) -} From 959405332d6a3a674bb28aff377d3caf7695cc8d Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 8 Jul 2021 13:20:52 +0100 Subject: [PATCH 12/24] Add tests for updating and reverting client library version --- .../server/src/api/controllers/application.js | 10 ++++--- .../src/api/routes/tests/application.spec.js | 26 ++++++++++++++++++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js index d8e1e232d3..1a1b8d51c3 100644 --- a/packages/server/src/api/controllers/application.js +++ b/packages/server/src/api/controllers/application.js @@ -248,8 +248,10 @@ exports.updateClient = async function (ctx) { const currentVersion = application.version // Update client library and manifest - await backupClientLibrary(ctx.params.appId) - await updateClientLibrary(ctx.params.appId) + if (!env.isTest()) { + await backupClientLibrary(ctx.params.appId) + await updateClientLibrary(ctx.params.appId) + } // Update versions in app package const appPackageUpdates = { @@ -270,7 +272,9 @@ exports.revertClient = async function (ctx) { } // Update client library and manifest - await revertClientLibrary(ctx.params.appId) + if (!env.isTest()) { + await revertClientLibrary(ctx.params.appId) + } // Update versions in app package const appPackageUpdates = { diff --git a/packages/server/src/api/routes/tests/application.spec.js b/packages/server/src/api/routes/tests/application.spec.js index 2333787e6e..05e0bc231b 100644 --- a/packages/server/src/api/routes/tests/application.spec.js +++ b/packages/server/src/api/routes/tests/application.spec.js @@ -94,7 +94,7 @@ describe("/applications", () => { }) describe("update", () => { - it("should be able to fetch the app package", async () => { + it("should be able to update the app package", async () => { const res = await request .put(`/api/applications/${config.getAppId()}`) .send({ @@ -107,6 +107,30 @@ describe("/applications", () => { }) }) + describe("manage client library version", () => { + it("should be able to update the app client library version", async () => { + console.log(config.getAppId()) + await request + .post(`/api/applications/${config.getAppId()}/client/update`) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + }) + it("should be able to revert the app client library version", async () => { + // We need to first update the version so that we can then revert + await request + .post(`/api/applications/${config.getAppId()}/client/update`) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + await request + .post(`/api/applications/${config.getAppId()}/client/revert`) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + }) + }) + describe("edited at", () => { it("middleware should set edited at", async () => { const headers = config.defaultHeaders() From bd27aa0caf69e8e853f24de1d33eedeb1c314e7b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 8 Jul 2021 14:00:14 +0100 Subject: [PATCH 13/24] Move standard components from server dev dependencies to real dependencies --- packages/server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/package.json b/packages/server/package.json index 26ba52e656..ace5fe693f 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -61,6 +61,7 @@ "dependencies": { "@budibase/auth": "^0.9.71", "@budibase/client": "^0.9.71", + "@budibase/standard-components": "^0.9.71", "@budibase/string-templates": "^0.9.71", "@elastic/elasticsearch": "7.10.0", "@koa/router": "8.0.0", @@ -114,7 +115,6 @@ "devDependencies": { "@babel/core": "^7.14.3", "@babel/preset-env": "^7.14.4", - "@budibase/standard-components": "^0.9.71", "@jest/test-sequencer": "^24.8.0", "@types/bull": "^3.15.1", "@types/jest": "^26.0.23", From ef4a0f8c79076b3a01ee08aac6549e837f8e587f Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 9 Jul 2021 12:33:09 +0100 Subject: [PATCH 14/24] Bundle latest client library with the server and use it when updating apps in production --- packages/server/.gitignore | 1 + packages/server/package.json | 3 ++- .../src/utilities/fileSystem/clientLibrary.js | 24 +++++++++++++++---- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/server/.gitignore b/packages/server/.gitignore index c737d00466..e8589f631d 100644 --- a/packages/server/.gitignore +++ b/packages/server/.gitignore @@ -2,6 +2,7 @@ node_modules/ myapps/ .env builder/* +client/* public/ db/dev.db/ dist diff --git a/packages/server/package.json b/packages/server/package.json index ace5fe693f..d3d99a5b16 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -13,7 +13,8 @@ "postbuild": "copyfiles -u 1 src/**/*.svelte dist/ && copyfiles -u 1 src/**/*.hbs dist/ && copyfiles -u 1 src/**/*.json dist/", "test": "jest --coverage --maxWorkers=2", "test:watch": "jest --watch", - "build:docker": "docker build . -t app-service", + "predocker": "copyfiles -f ../client/dist/budibase-client.js ../standard-components/manifest.json client", + "build:docker": "yarn run predocker && docker build . -t app-service", "run:docker": "node dist/index.js", "dev:stack:up": "node scripts/dev/manage.js up", "dev:stack:down": "node scripts/dev/manage.js down", diff --git a/packages/server/src/utilities/fileSystem/clientLibrary.js b/packages/server/src/utilities/fileSystem/clientLibrary.js index 6b7e8d837d..0b57bbc3b2 100644 --- a/packages/server/src/utilities/fileSystem/clientLibrary.js +++ b/packages/server/src/utilities/fileSystem/clientLibrary.js @@ -2,6 +2,9 @@ const { join } = require("path") const { ObjectStoreBuckets } = require("../../constants") const fs = require("fs") const { upload, retrieveToTmp, streamUpload } = require("./utilities") +const { resolve } = require("../centralPath") +const env = require("../../environment") +const TOP_LEVEL_PATH = join(__dirname, "..", "..", "..") /** * Client library paths in the object store: @@ -86,13 +89,26 @@ exports.backupClientLibrary = async appId => { * @returns {Promise} */ exports.updateClientLibrary = async appId => { + let manifest, client + + if (false && env.isDev()) { + // Load the symlinked version in dev which is always the newest + manifest = require.resolve("@budibase/standard-components/manifest.json") + client = require.resolve("@budibase/client") + } else { + // Load the bundled version in prod + manifest = resolve(TOP_LEVEL_PATH, "client", "manifest.json") + client = resolve(TOP_LEVEL_PATH, "client", "budibase-client.js") + + console.log(manifest) + console.log(client) + } + // Upload latest component manifest await streamUpload( ObjectStoreBuckets.APPS, join(appId, "manifest.json"), - fs.createReadStream( - require.resolve("@budibase/standard-components/manifest.json") - ), + fs.createReadStream(manifest), { ContentType: "application/json", } @@ -102,7 +118,7 @@ exports.updateClientLibrary = async appId => { await streamUpload( ObjectStoreBuckets.APPS, join(appId, "budibase-client.js"), - fs.createReadStream(require.resolve("@budibase/client")), + fs.createReadStream(client), { ContentType: "application/javascript", } From 60987e3d5cab87426b721d690b8e54ff0ebb59a5 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 9 Jul 2021 12:42:48 +0100 Subject: [PATCH 15/24] Remove leftover code from testing --- packages/server/src/utilities/fileSystem/clientLibrary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/utilities/fileSystem/clientLibrary.js b/packages/server/src/utilities/fileSystem/clientLibrary.js index 0b57bbc3b2..a56e681832 100644 --- a/packages/server/src/utilities/fileSystem/clientLibrary.js +++ b/packages/server/src/utilities/fileSystem/clientLibrary.js @@ -91,7 +91,7 @@ exports.backupClientLibrary = async appId => { exports.updateClientLibrary = async appId => { let manifest, client - if (false && env.isDev()) { + if (env.isDev()) { // Load the symlinked version in dev which is always the newest manifest = require.resolve("@budibase/standard-components/manifest.json") client = require.resolve("@budibase/client") From 8cc67d815c8c853f31ba9acb92bb7916181e3792 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 9 Jul 2021 13:23:49 +0100 Subject: [PATCH 16/24] Reload the client preview whenever client library version changes --- .../app/[application]/design/[assetType]/_layout.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte index 241b0d5200..207daae84a 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte @@ -155,7 +155,9 @@ {/if}
- + {#key $store.version} + + {/key}
{/if}
From 4112049a17f6310d1573f983834319162bcb6aee Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 9 Jul 2021 16:42:09 +0100 Subject: [PATCH 17/24] Remove log statement, batch uploads and remove unecessary conditional --- .../server/src/api/controllers/application.js | 4 +- .../src/utilities/fileSystem/clientLibrary.js | 45 +++++++------------ 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js index 1a1b8d51c3..a2e254461a 100644 --- a/packages/server/src/api/controllers/application.js +++ b/packages/server/src/api/controllers/application.js @@ -313,9 +313,7 @@ const updateAppPackage = async (ctx, appPackage, appId) => { // the locked by property is attached by server but generated from // Redis, shouldn't ever store it - if (newAppPackage.lockedBy) { - delete newAppPackage.lockedBy - } + delete newAppPackage.lockedBy return await db.put(newAppPackage) } diff --git a/packages/server/src/utilities/fileSystem/clientLibrary.js b/packages/server/src/utilities/fileSystem/clientLibrary.js index a56e681832..3f0d31f257 100644 --- a/packages/server/src/utilities/fileSystem/clientLibrary.js +++ b/packages/server/src/utilities/fileSystem/clientLibrary.js @@ -34,10 +34,8 @@ const TOP_LEVEL_PATH = join(__dirname, "..", "..", "..") * @returns {Promise} */ exports.backupClientLibrary = async appId => { - let tmpManifestPath - let tmpClientPath - // Copy existing manifest to tmp + let tmpManifestPath try { // Try to load the manifest from the new file location tmpManifestPath = await retrieveToTmp( @@ -60,26 +58,25 @@ exports.backupClientLibrary = async appId => { } // Copy existing client lib to tmp - tmpClientPath = await retrieveToTmp( + const tmpClientPath = await retrieveToTmp( ObjectStoreBuckets.APPS, join(appId, "budibase-client.js") ) - // Upload manifest as backup - await upload({ + // Upload manifest and client library as backups + const manifestUpload = upload({ bucket: ObjectStoreBuckets.APPS, filename: join(appId, "manifest.json.bak"), path: tmpManifestPath, type: "application/json", }) - - // Upload client library as backup - await upload({ + const clientUpload = upload({ bucket: ObjectStoreBuckets.APPS, filename: join(appId, "budibase-client.js.bak"), path: tmpClientPath, type: "application/javascript", }) + await Promise.all([manifestUpload, clientUpload]) } /** @@ -99,13 +96,10 @@ exports.updateClientLibrary = async appId => { // Load the bundled version in prod manifest = resolve(TOP_LEVEL_PATH, "client", "manifest.json") client = resolve(TOP_LEVEL_PATH, "client", "budibase-client.js") - - console.log(manifest) - console.log(client) } - // Upload latest component manifest - await streamUpload( + // Upload latest manifest and client library + const manifestUpload = streamUpload( ObjectStoreBuckets.APPS, join(appId, "manifest.json"), fs.createReadStream(manifest), @@ -113,9 +107,7 @@ exports.updateClientLibrary = async appId => { ContentType: "application/json", } ) - - // Upload latest component library - await streamUpload( + const clientUpload = streamUpload( ObjectStoreBuckets.APPS, join(appId, "budibase-client.js"), fs.createReadStream(client), @@ -123,6 +115,7 @@ exports.updateClientLibrary = async appId => { ContentType: "application/javascript", } ) + await Promise.all([manifestUpload, clientUpload]) } /** @@ -132,34 +125,30 @@ exports.updateClientLibrary = async appId => { * @returns {Promise} */ exports.revertClientLibrary = async appId => { - let tmpManifestPath - let tmpClientPath - - // Copy backup manifest to tmp - tmpManifestPath = await retrieveToTmp( + // Copy backups manifest to tmp directory + const tmpManifestPath = await retrieveToTmp( ObjectStoreBuckets.APPS, join(appId, "manifest.json.bak") ) // Copy backup client lib to tmp - tmpClientPath = await retrieveToTmp( + const tmpClientPath = await retrieveToTmp( ObjectStoreBuckets.APPS, join(appId, "budibase-client.js.bak") ) - // Upload manifest backup - await upload({ + // Upload backups as new versions + const manifestUpload = upload({ bucket: ObjectStoreBuckets.APPS, filename: join(appId, "manifest.json"), path: tmpManifestPath, type: "application/json", }) - - // Upload client library backup - await upload({ + const clientUpload = upload({ bucket: ObjectStoreBuckets.APPS, filename: join(appId, "budibase-client.js"), path: tmpClientPath, type: "application/javascript", }) + await Promise.all([manifestUpload, clientUpload]) } From 2d451bb3a951fed58b0af39fb9397dcb2c76de68 Mon Sep 17 00:00:00 2001 From: Kyle Harrison Date: Fri, 9 Jul 2021 17:50:01 +0100 Subject: [PATCH 18/24] apply fixes for common spelling mistakes --- hosting/scripts/linux/install-docker.sh | 2 +- packages/bbui/src/Form/Core/Select.svelte | 2 +- packages/builder/CONTRIBUTING.md | 2 +- packages/builder/cypress/setup.js | 2 +- .../FilterEditor/FilterEditor.svelte | 2 +- .../PropertyControls/IconSelect/icons.js | 14 +++++++------- .../users/_components/BasicOnboardingModal.svelte | 2 +- .../server/src/api/controllers/view/viewBuilder.js | 2 +- packages/server/src/utilities/usageQuota.js | 2 +- packages/standard-components/src/helpers.js | 2 +- .../src/processors/preprocessor.js | 2 +- packages/worker/src/utilities/email.js | 2 +- 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/hosting/scripts/linux/install-docker.sh b/hosting/scripts/linux/install-docker.sh index a71809c31f..fe92736d91 100755 --- a/hosting/scripts/linux/install-docker.sh +++ b/hosting/scripts/linux/install-docker.sh @@ -1,6 +1,6 @@ #!/bin/bash echo "**** WARNING - not for production environments ****" -# warning this is a convience script, for production installations install docker +# warning this is a convenience script, for production installations install docker # properly for your environment! curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh diff --git a/packages/bbui/src/Form/Core/Select.svelte b/packages/bbui/src/Form/Core/Select.svelte index 93e59e2420..515bd7397c 100644 --- a/packages/bbui/src/Form/Core/Select.svelte +++ b/packages/bbui/src/Form/Core/Select.svelte @@ -29,7 +29,7 @@ return "" } - // Render the label if the selected option is found, otherwide raw value + // Render the label if the selected option is found, otherwise raw value const index = options.findIndex( (option, idx) => getOptionValue(option, idx) === value ) diff --git a/packages/builder/CONTRIBUTING.md b/packages/builder/CONTRIBUTING.md index 24bd682585..dbefb5a16b 100644 --- a/packages/builder/CONTRIBUTING.md +++ b/packages/builder/CONTRIBUTING.md @@ -9,7 +9,7 @@ Please read this if you are unfamiliar with it. * Please maintain the existing code style. -* Please try to keep your commits small and focussed. +* Please try to keep your commits small and focused. * If the project diverges from your branch, please rebase instead of merging. This makes the commit graph easier to read. diff --git a/packages/builder/cypress/setup.js b/packages/builder/cypress/setup.js index 2c09c4b3c5..4ad8e5287d 100644 --- a/packages/builder/cypress/setup.js +++ b/packages/builder/cypress/setup.js @@ -34,7 +34,7 @@ async function run() { process.exit(-1) } - // dont make this a variable or top level require + // don't make this a variable or top level require // it will cause environment module to be loaded prematurely const server = require("../../server/dist/app") process.env.PORT = WORKER_PORT diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterEditor.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterEditor.svelte index dcda6ac1f1..900ac58971 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterEditor.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterEditor.svelte @@ -48,7 +48,7 @@ Add your first filter column. {:else} Results are filtered to only those which match all of the following - constaints. + constraints. {/if} diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/icons.js b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/icons.js index 8baf58c589..ca57f98180 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/icons.js +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/icons.js @@ -1153,10 +1153,10 @@ export default { space: ["空格"], "page-separator": ["insert", "分页符", "插入"], "code-view": ["代码视图"], - "double-quotes-l": ["left", "quotaion marks", "双引号"], - "double-quotes-r": ["right", "quotaion marks", "双引号"], - "single-quotes-l": ["left", "quotaion marks", "单引号"], - "single-quotes-r": ["right", "quotaion marks", "单引号"], + "double-quotes-l": ["left", "quotation marks", "双引号"], + "double-quotes-r": ["right", "quotation marks", "双引号"], + "single-quotes-l": ["left", "quotation marks", "单引号"], + "single-quotes-r": ["right", "quotation marks", "单引号"], "table-2": ["表格"], subscript: ["角标", "下标", "脚注"], "subscript-2": ["角标", "下标", "脚注"], @@ -1463,7 +1463,7 @@ export default { alipay: ["zhifubao", "支付宝"], amazon: ["亚马逊"], android: ["applications", "安卓", "应用"], - angularjs: ["angular", "programing framework"], + angularjs: ["angular", "programming framework"], "app-store": ["applications", "苹果应用商店"], apple: ["苹果"], baidu: ["du", "claw", "百度", "爪"], @@ -1519,7 +1519,7 @@ export default { playstation: ["ps"], "product-hunt": ["product hunt"], qq: ["penguin", "tencent", "腾讯", "企鹅"], - reactjs: ["react", "programing framework", "facebook"], + reactjs: ["react", "programming framework", "facebook"], reddit: ["reddit"], remixicon: ["remix icon", "图标"], safari: ["safari浏览器"], @@ -1543,7 +1543,7 @@ export default { unsplash: ["photos"], vimeo: ["视频"], visa: ["bank card", "银行卡"], - vuejs: ["vue", "programing framework"], + vuejs: ["vue", "programming framework"], wechat: ["微信"], "wechat-2": ["微信"], "wechat-pay": ["微信支付"], diff --git a/packages/builder/src/pages/builder/portal/manage/users/_components/BasicOnboardingModal.svelte b/packages/builder/src/pages/builder/portal/manage/users/_components/BasicOnboardingModal.svelte index 8ecb274585..9c7b9aa0ea 100644 --- a/packages/builder/src/pages/builder/portal/manage/users/_components/BasicOnboardingModal.svelte +++ b/packages/builder/src/pages/builder/portal/manage/users/_components/BasicOnboardingModal.svelte @@ -20,7 +20,7 @@ if (res.status) { notifications.error(res.message) } else { - notifications.success("Succesfully created user") + notifications.success("Successfully created user") } } diff --git a/packages/server/src/api/controllers/view/viewBuilder.js b/packages/server/src/api/controllers/view/viewBuilder.js index ed1199fa5b..068c6ab7b1 100644 --- a/packages/server/src/api/controllers/view/viewBuilder.js +++ b/packages/server/src/api/controllers/view/viewBuilder.js @@ -108,7 +108,7 @@ function parseEmitExpression(field, groupBy) { * calculation: an optional calculation to be performed over the view data. */ function viewTemplate({ field, tableId, groupBy, filters = [], calculation }) { - // first filter can't have a conjuction + // first filter can't have a conjunction if (filters && filters.length > 0 && filters[0].conjunction) { delete filters[0].conjunction } diff --git a/packages/server/src/utilities/usageQuota.js b/packages/server/src/utilities/usageQuota.js index d042d290d5..bfe71a4093 100644 --- a/packages/server/src/utilities/usageQuota.js +++ b/packages/server/src/utilities/usageQuota.js @@ -85,7 +85,7 @@ exports.update = async (apiKey, property, usage) => { await apiKeyTable.put({ item: keyObj }) return } - // we have infact breached the reset period + // we have in fact breached the reset period else if (keyObj && keyObj.quotaReset <= Date.now()) { // update the quota reset period and reset the values for all properties keyObj.quotaReset = getNewQuotaReset() diff --git a/packages/standard-components/src/helpers.js b/packages/standard-components/src/helpers.js index 07a8081058..4a47d4e538 100644 --- a/packages/standard-components/src/helpers.js +++ b/packages/standard-components/src/helpers.js @@ -22,7 +22,7 @@ export const generateID = (size = 21) => { // It is incorrect to use bytes exceeding the alphabet size. // The following mask reduces the random byte in the 0-255 value // range to the 0-63 value range. Therefore, adding hacks, such - // as empty string fallback or magic numbers, is unneccessary because + // as empty string fallback or magic numbers, is unnecessary because // the bitmask trims bytes down to the alphabet size. let byte = bytes[size] & 63 if (byte < 36) { diff --git a/packages/string-templates/src/processors/preprocessor.js b/packages/string-templates/src/processors/preprocessor.js index ee3a3a9730..6f6537674a 100644 --- a/packages/string-templates/src/processors/preprocessor.js +++ b/packages/string-templates/src/processors/preprocessor.js @@ -28,7 +28,7 @@ module.exports.processors = [ let startBraceIdx = statement.indexOf("[") let lastIdx = 0 while (startBraceIdx !== -1) { - // if the character previous to the literal specifier is alpha-numeric this should happen + // if the character previous to the literal specifier is alphanumeric this should happen if (isAlphaNumeric(statement.charAt(startBraceIdx - 1))) { statement = swapStrings(statement, startBraceIdx + lastIdx, 1, ".[") } diff --git a/packages/worker/src/utilities/email.js b/packages/worker/src/utilities/email.js index 534456fe15..dc13bb948a 100644 --- a/packages/worker/src/utilities/email.js +++ b/packages/worker/src/utilities/email.js @@ -173,7 +173,7 @@ exports.sendEmail = async ( } /** - * Given an SMTP configuration this runs it through nodemailer to see if it is infact functional. + * Given an SMTP configuration this runs it through nodemailer to see if it is in fact functional. * @param {object} config an SMTP configuration - this is based on the nodemailer API. * @return {Promise} returns true if the configuration is valid. */ From 1f5b3b4467edaacc4a312e0847312f688bb0b696 Mon Sep 17 00:00:00 2001 From: Budibase Release Bot <> Date: Fri, 9 Jul 2021 17:29:06 +0000 Subject: [PATCH 19/24] v0.9.73 --- lerna.json | 2 +- packages/auth/package.json | 2 +- packages/bbui/package.json | 2 +- packages/builder/package.json | 8 ++++---- packages/cli/package.json | 2 +- packages/client/package.json | 8 ++++---- packages/server/package.json | 10 +++++----- packages/standard-components/package.json | 4 ++-- packages/string-templates/package.json | 2 +- packages/worker/package.json | 6 +++--- 10 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lerna.json b/lerna.json index 3ececd6c41..f6924bc632 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "0.9.72", + "version": "0.9.73", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/auth/package.json b/packages/auth/package.json index 8f1a9da30c..5429392362 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/auth", - "version": "0.9.72", + "version": "0.9.73", "description": "Authentication middlewares for budibase builder and apps", "main": "src/index.js", "author": "Budibase", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 02bd67f0e6..3250b4ab34 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": "0.9.72", + "version": "0.9.73", "license": "AGPL-3.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", diff --git a/packages/builder/package.json b/packages/builder/package.json index 2a7bd86531..b6aa86c925 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "0.9.72", + "version": "0.9.73", "license": "AGPL-3.0", "private": true, "scripts": { @@ -65,10 +65,10 @@ } }, "dependencies": { - "@budibase/bbui": "^0.9.72", - "@budibase/client": "^0.9.72", + "@budibase/bbui": "^0.9.73", + "@budibase/client": "^0.9.73", "@budibase/colorpicker": "1.1.2", - "@budibase/string-templates": "^0.9.72", + "@budibase/string-templates": "^0.9.73", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/cli/package.json b/packages/cli/package.json index 4550f8ab0b..f08d508ef6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "0.9.72", + "version": "0.9.73", "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 33998632f7..c22a3e807e 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "0.9.72", + "version": "0.9.73", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -18,9 +18,9 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "^0.9.72", - "@budibase/standard-components": "^0.9.72", - "@budibase/string-templates": "^0.9.72", + "@budibase/bbui": "^0.9.73", + "@budibase/standard-components": "^0.9.73", + "@budibase/string-templates": "^0.9.73", "regexparam": "^1.3.0", "shortid": "^2.2.15", "svelte-spa-router": "^3.0.5" diff --git a/packages/server/package.json b/packages/server/package.json index 3be231b1ed..d37fed9b7a 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "0.9.72", + "version": "0.9.73", "description": "Budibase Web Server", "main": "src/index.js", "repository": { @@ -59,9 +59,9 @@ "author": "Budibase", "license": "AGPL-3.0-or-later", "dependencies": { - "@budibase/auth": "^0.9.72", - "@budibase/client": "^0.9.72", - "@budibase/string-templates": "^0.9.72", + "@budibase/auth": "^0.9.73", + "@budibase/client": "^0.9.73", + "@budibase/string-templates": "^0.9.73", "@elastic/elasticsearch": "7.10.0", "@koa/router": "8.0.0", "@sendgrid/mail": "7.1.1", @@ -114,7 +114,7 @@ "devDependencies": { "@babel/core": "^7.14.3", "@babel/preset-env": "^7.14.4", - "@budibase/standard-components": "^0.9.72", + "@budibase/standard-components": "^0.9.73", "@jest/test-sequencer": "^24.8.0", "@types/bull": "^3.15.1", "@types/jest": "^26.0.23", diff --git a/packages/standard-components/package.json b/packages/standard-components/package.json index cd050717b8..b583bb666b 100644 --- a/packages/standard-components/package.json +++ b/packages/standard-components/package.json @@ -29,11 +29,11 @@ "keywords": [ "svelte" ], - "version": "0.9.72", + "version": "0.9.73", "license": "MIT", "gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc", "dependencies": { - "@budibase/bbui": "^0.9.72", + "@budibase/bbui": "^0.9.73", "@spectrum-css/link": "^3.1.3", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index b9b40da67c..34c1843c28 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "0.9.72", + "version": "0.9.73", "description": "Handlebars wrapper for Budibase templating.", "main": "src/index.cjs", "module": "dist/bundle.mjs", diff --git a/packages/worker/package.json b/packages/worker/package.json index 073a03689d..c818b19dd7 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/worker", "email": "hi@budibase.com", - "version": "0.9.72", + "version": "0.9.73", "description": "Budibase background service", "main": "src/index.js", "repository": { @@ -21,8 +21,8 @@ "author": "Budibase", "license": "AGPL-3.0-or-later", "dependencies": { - "@budibase/auth": "^0.9.72", - "@budibase/string-templates": "^0.9.72", + "@budibase/auth": "^0.9.73", + "@budibase/string-templates": "^0.9.73", "@koa/router": "^8.0.0", "aws-sdk": "^2.811.0", "bcryptjs": "^2.4.3", From 7392ad8eb25ef75148b1c74d0903b7ba6c7405a4 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Sat, 10 Jul 2021 11:56:32 +0100 Subject: [PATCH 20/24] Remove padding from empty layouts and add option for full width layout content --- packages/standard-components/manifest.json | 2 +- packages/standard-components/src/Layout.svelte | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/standard-components/manifest.json b/packages/standard-components/manifest.json index ec32a5879d..2410ba56b5 100644 --- a/packages/standard-components/manifest.json +++ b/packages/standard-components/manifest.json @@ -31,7 +31,7 @@ "type": "select", "label": "Width", "key": "width", - "options": ["Small", "Medium", "Large"], + "options": ["Small", "Medium", "Large", "Max"], "defaultValue": "Large" }, { diff --git a/packages/standard-components/src/Layout.svelte b/packages/standard-components/src/Layout.svelte index df0bd19525..24c9709895 100644 --- a/packages/standard-components/src/Layout.svelte +++ b/packages/standard-components/src/Layout.svelte @@ -20,6 +20,7 @@ None: "none", } const widthClasses = { + Max: "max", Large: "l", Medium: "m", Small: "s", @@ -178,6 +179,9 @@ position: relative; padding: 32px; } + .layout--none .main { + padding: 0; + } .size--s { width: 800px; } @@ -187,6 +191,9 @@ .size--l { width: 1400px; } + .size--max { + width: 100%; + } /* Nav components */ .burger { From 184df6c685a7801c6a6fdbdefd20ab9c88db6b9b Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 12 Jul 2021 10:51:30 +0100 Subject: [PATCH 21/24] Fixing some issues discovered with the new SQL connectors were the input type would always be string (causing some SQL types to break) - parsing these before input to attempt to fix this problem - issue referenced in #1943. --- .../scripts/integrations/mysql/init.sql | 3 ++- packages/server/src/integrations/base/sql.ts | 25 ++++++++++++++++--- packages/server/src/integrations/utils.ts | 8 ++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/packages/server/scripts/integrations/mysql/init.sql b/packages/server/scripts/integrations/mysql/init.sql index 8cd120a8a3..efcef00899 100644 --- a/packages/server/scripts/integrations/mysql/init.sql +++ b/packages/server/scripts/integrations/mysql/init.sql @@ -2,6 +2,7 @@ CREATE DATABASE IF NOT EXISTS main; USE main; CREATE TABLE Persons ( PersonID int NOT NULL AUTO_INCREMENT, + CreatedAt datetime, LastName varchar(255), FirstName varchar(255), Address varchar(255), @@ -17,6 +18,6 @@ CREATE TABLE Tasks ( FOREIGN KEY(PersonID) REFERENCES Persons(PersonID) ); -INSERT INTO Persons (FirstName, LastName, Address, City) VALUES ('Mike', 'Hughes', '123 Fake Street', 'Belfast'); +INSERT INTO Persons (FirstName, LastName, Address, City, CreatedAt) VALUES ('Mike', 'Hughes', '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'); diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index e1c065dd26..66dd269412 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -8,9 +8,24 @@ import { Operation, RelationshipsJson, } from "../../definitions/datasource" +import { isIsoDateString } from "../utils" type KnexQuery = Knex.QueryBuilder | Knex +function parseBody(body: any) { + for (let [key, value] of Object.entries(body)) { + if (typeof value !== "string") { + continue + } + if (isIsoDateString(value)) { + body[key] = new Date(value) + } else if (!isNaN(parseFloat(value))) { + body[key] = parseFloat(value) + } + } + return body +} + // right now we only do filters on the specific table being queried function addFilters( tableName: string, @@ -119,11 +134,12 @@ function buildCreate( ): KnexQuery { const { endpoint, body } = json let query: KnexQuery = knex(endpoint.entityId) + const parsedBody = parseBody(body) // mysql can't use returning if (opts.disableReturning) { - return query.insert(body) + return query.insert(parsedBody) } else { - return query.insert(body).returning("*") + return query.insert(parsedBody).returning("*") } } @@ -173,12 +189,13 @@ function buildUpdate( ): KnexQuery { const { endpoint, body, filters } = json let query: KnexQuery = knex(endpoint.entityId) + const parsedBody = parseBody(body) query = addFilters(endpoint.entityId, query, filters) // mysql can't use returning if (opts.disableReturning) { - return query.update(body) + return query.update(parsedBody) } else { - return query.update(body).returning("*") + return query.update(parsedBody).returning("*") } } diff --git a/packages/server/src/integrations/utils.ts b/packages/server/src/integrations/utils.ts index d0af0e99a9..03751bb467 100644 --- a/packages/server/src/integrations/utils.ts +++ b/packages/server/src/integrations/utils.ts @@ -68,3 +68,11 @@ export function isSQL(datasource: Datasource): boolean { const SQL = [SourceNames.POSTGRES, SourceNames.SQL_SERVER, SourceNames.MYSQL] return SQL.indexOf(datasource.source) !== -1 } + +export function isIsoDateString(str: string) { + if (!/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(str)) { + return false + } + let d = new Date(str) + return d.toISOString() === str +} From 7aca56f019b9a781d3d2ae16fb6ad7fefdd78002 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 12 Jul 2021 11:10:11 +0100 Subject: [PATCH 22/24] Adding float type to MySQL. --- packages/server/scripts/integrations/mysql/init.sql | 3 ++- packages/server/src/integrations/mysql.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/server/scripts/integrations/mysql/init.sql b/packages/server/scripts/integrations/mysql/init.sql index efcef00899..4dd75c36d3 100644 --- a/packages/server/scripts/integrations/mysql/init.sql +++ b/packages/server/scripts/integrations/mysql/init.sql @@ -3,6 +3,7 @@ USE main; CREATE TABLE Persons ( PersonID int NOT NULL AUTO_INCREMENT, CreatedAt datetime, + Age float, LastName varchar(255), FirstName varchar(255), Address varchar(255), @@ -18,6 +19,6 @@ CREATE TABLE Tasks ( FOREIGN KEY(PersonID) REFERENCES Persons(PersonID) ); -INSERT INTO Persons (FirstName, LastName, Address, City, CreatedAt) VALUES ('Mike', 'Hughes', '123 Fake Street', 'Belfast', '2021-01-19 03:14:07'); +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'); diff --git a/packages/server/src/integrations/mysql.ts b/packages/server/src/integrations/mysql.ts index 9567fa7054..fab151fc0d 100644 --- a/packages/server/src/integrations/mysql.ts +++ b/packages/server/src/integrations/mysql.ts @@ -29,6 +29,7 @@ module MySQLModule { blob: FieldTypes.LONGFORM, enum: FieldTypes.STRING, varchar: FieldTypes.STRING, + float: FieldTypes.NUMBER, int: FieldTypes.NUMBER, numeric: FieldTypes.NUMBER, bigint: FieldTypes.NUMBER, From 7e5c4be14f33223bd3fa2627290d13b24553c68f Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 13 Jul 2021 17:11:11 +0100 Subject: [PATCH 23/24] fix postgres query array value --- packages/server/src/integrations/base/definitions.ts | 8 +++++--- packages/server/src/integrations/postgres.ts | 2 +- packages/server/src/integrations/tests/postgres.spec.js | 8 ++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/server/src/integrations/base/definitions.ts b/packages/server/src/integrations/base/definitions.ts index 9d5567b6c8..c202a828d0 100644 --- a/packages/server/src/integrations/base/definitions.ts +++ b/packages/server/src/integrations/base/definitions.ts @@ -99,9 +99,11 @@ export interface QueryJson { export interface SqlQuery { sql: string - bindings?: { - [key: string]: any - } + bindings?: + | string[] + | { + [key: string]: any + } } export interface QueryOptions { diff --git a/packages/server/src/integrations/postgres.ts b/packages/server/src/integrations/postgres.ts index 27286ebd02..787bce7e4e 100644 --- a/packages/server/src/integrations/postgres.ts +++ b/packages/server/src/integrations/postgres.ts @@ -92,7 +92,7 @@ module PostgresModule { async function internalQuery(client: any, query: SqlQuery) { try { - return await client.query(query.sql, query.bindings || {}) + return await client.query(query.sql, query.bindings || []) } catch (err) { throw new Error(err) } diff --git a/packages/server/src/integrations/tests/postgres.spec.js b/packages/server/src/integrations/tests/postgres.spec.js index 348fa20b6f..5d0283ec90 100644 --- a/packages/server/src/integrations/tests/postgres.spec.js +++ b/packages/server/src/integrations/tests/postgres.spec.js @@ -20,7 +20,7 @@ describe("Postgres Integration", () => { const response = await config.integration.create({ sql }) - expect(pg.queryMock).toHaveBeenCalledWith(sql, {}) + expect(pg.queryMock).toHaveBeenCalledWith(sql, []) }) it("calls the read method with the correct params", async () => { @@ -28,7 +28,7 @@ describe("Postgres Integration", () => { const response = await config.integration.read({ sql }) - expect(pg.queryMock).toHaveBeenCalledWith(sql, {}) + expect(pg.queryMock).toHaveBeenCalledWith(sql, []) }) it("calls the update method with the correct params", async () => { @@ -36,7 +36,7 @@ describe("Postgres Integration", () => { const response = await config.integration.update({ sql }) - expect(pg.queryMock).toHaveBeenCalledWith(sql, {}) + expect(pg.queryMock).toHaveBeenCalledWith(sql, []) }) it("calls the delete method with the correct params", async () => { @@ -44,7 +44,7 @@ describe("Postgres Integration", () => { await config.integration.delete({ sql }) - expect(pg.queryMock).toHaveBeenCalledWith(sql, {}) + expect(pg.queryMock).toHaveBeenCalledWith(sql, []) }) describe("no rows returned", () => { From 23bb4215c26582fd7acac91aae058a6ee29c4b85 Mon Sep 17 00:00:00 2001 From: Budibase Release Bot <> Date: Tue, 13 Jul 2021 16:53:42 +0000 Subject: [PATCH 24/24] v0.9.74 --- lerna.json | 2 +- packages/auth/package.json | 2 +- packages/bbui/package.json | 2 +- packages/builder/package.json | 8 ++++---- packages/cli/package.json | 2 +- packages/client/package.json | 8 ++++---- packages/server/package.json | 10 +++++----- packages/standard-components/package.json | 4 ++-- packages/string-templates/package.json | 2 +- packages/worker/package.json | 6 +++--- 10 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lerna.json b/lerna.json index f6924bc632..0982cc8bb4 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "0.9.73", + "version": "0.9.74", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/auth/package.json b/packages/auth/package.json index 5429392362..d93a57b47d 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/auth", - "version": "0.9.73", + "version": "0.9.74", "description": "Authentication middlewares for budibase builder and apps", "main": "src/index.js", "author": "Budibase", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 3250b4ab34..5118c1b7cf 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": "0.9.73", + "version": "0.9.74", "license": "AGPL-3.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", diff --git a/packages/builder/package.json b/packages/builder/package.json index b6aa86c925..261db322d7 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "0.9.73", + "version": "0.9.74", "license": "AGPL-3.0", "private": true, "scripts": { @@ -65,10 +65,10 @@ } }, "dependencies": { - "@budibase/bbui": "^0.9.73", - "@budibase/client": "^0.9.73", + "@budibase/bbui": "^0.9.74", + "@budibase/client": "^0.9.74", "@budibase/colorpicker": "1.1.2", - "@budibase/string-templates": "^0.9.73", + "@budibase/string-templates": "^0.9.74", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/cli/package.json b/packages/cli/package.json index f08d508ef6..84ed8b7c91 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "0.9.73", + "version": "0.9.74", "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 c22a3e807e..c9f3935569 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "0.9.73", + "version": "0.9.74", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -18,9 +18,9 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "^0.9.73", - "@budibase/standard-components": "^0.9.73", - "@budibase/string-templates": "^0.9.73", + "@budibase/bbui": "^0.9.74", + "@budibase/standard-components": "^0.9.74", + "@budibase/string-templates": "^0.9.74", "regexparam": "^1.3.0", "shortid": "^2.2.15", "svelte-spa-router": "^3.0.5" diff --git a/packages/server/package.json b/packages/server/package.json index d37fed9b7a..4e225bd108 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "0.9.73", + "version": "0.9.74", "description": "Budibase Web Server", "main": "src/index.js", "repository": { @@ -59,9 +59,9 @@ "author": "Budibase", "license": "AGPL-3.0-or-later", "dependencies": { - "@budibase/auth": "^0.9.73", - "@budibase/client": "^0.9.73", - "@budibase/string-templates": "^0.9.73", + "@budibase/auth": "^0.9.74", + "@budibase/client": "^0.9.74", + "@budibase/string-templates": "^0.9.74", "@elastic/elasticsearch": "7.10.0", "@koa/router": "8.0.0", "@sendgrid/mail": "7.1.1", @@ -114,7 +114,7 @@ "devDependencies": { "@babel/core": "^7.14.3", "@babel/preset-env": "^7.14.4", - "@budibase/standard-components": "^0.9.73", + "@budibase/standard-components": "^0.9.74", "@jest/test-sequencer": "^24.8.0", "@types/bull": "^3.15.1", "@types/jest": "^26.0.23", diff --git a/packages/standard-components/package.json b/packages/standard-components/package.json index b583bb666b..92fb39c914 100644 --- a/packages/standard-components/package.json +++ b/packages/standard-components/package.json @@ -29,11 +29,11 @@ "keywords": [ "svelte" ], - "version": "0.9.73", + "version": "0.9.74", "license": "MIT", "gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc", "dependencies": { - "@budibase/bbui": "^0.9.73", + "@budibase/bbui": "^0.9.74", "@spectrum-css/link": "^3.1.3", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index 34c1843c28..f75a11cf4b 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "0.9.73", + "version": "0.9.74", "description": "Handlebars wrapper for Budibase templating.", "main": "src/index.cjs", "module": "dist/bundle.mjs", diff --git a/packages/worker/package.json b/packages/worker/package.json index c818b19dd7..4d06b614ef 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/worker", "email": "hi@budibase.com", - "version": "0.9.73", + "version": "0.9.74", "description": "Budibase background service", "main": "src/index.js", "repository": { @@ -21,8 +21,8 @@ "author": "Budibase", "license": "AGPL-3.0-or-later", "dependencies": { - "@budibase/auth": "^0.9.73", - "@budibase/string-templates": "^0.9.73", + "@budibase/auth": "^0.9.74", + "@budibase/string-templates": "^0.9.74", "@koa/router": "^8.0.0", "aws-sdk": "^2.811.0", "bcryptjs": "^2.4.3",