diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 2767bbc80d..128a392d6b 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -13,6 +13,7 @@ "@techpass/passport-openidconnect": "^0.3.0", "aws-sdk": "^2.901.0", "bcryptjs": "^2.4.3", + "dotenv": "^16.0.1", "emitter-listener": "^1.1.2", "ioredis": "^4.27.1", "jsonwebtoken": "^8.5.1", diff --git a/packages/backend-core/src/environment.js b/packages/backend-core/src/environment.js index f628e899ad..e0b70d4007 100644 --- a/packages/backend-core/src/environment.js +++ b/packages/backend-core/src/environment.js @@ -10,7 +10,15 @@ function isDev() { return process.env.NODE_ENV !== "production" } +let LOADED = false +if (!LOADED && isDev() && !isTest()) { + require("dotenv").config() + LOADED = true +} + module.exports = { + isTest, + isDev, JWT_SECRET: process.env.JWT_SECRET, COUCH_DB_URL: process.env.COUCH_DB_URL || "http://localhost:4005", COUCH_DB_USERNAME: process.env.COUCH_DB_USER, @@ -41,8 +49,7 @@ module.exports = { GLOBAL_CLOUD_BUCKET_NAME: process.env.GLOBAL_CLOUD_BUCKET_NAME || "prod-budi-tenant-uploads", USE_COUCH: process.env.USE_COUCH || true, - isTest, - isDev, + DISABLE_DEVELOPER_LICENSE: process.env.DISABLE_DEVELOPER_LICENSE, _set(key, value) { process.env[key] = value module.exports[key] = value diff --git a/packages/backend-core/src/index.js b/packages/backend-core/src/index.js index 3868d9bffa..572b61fbeb 100644 --- a/packages/backend-core/src/index.js +++ b/packages/backend-core/src/index.js @@ -19,5 +19,6 @@ module.exports = { env: require("./environment"), accounts: require("./cloud/accounts"), tenancy: require("./tenancy"), + context: require("../context"), featureFlags: require("./featureFlags"), } diff --git a/packages/backend-core/yarn.lock b/packages/backend-core/yarn.lock index 7dfa64810e..80f292140d 100644 --- a/packages/backend-core/yarn.lock +++ b/packages/backend-core/yarn.lock @@ -1485,6 +1485,11 @@ domexception@^2.0.1: dependencies: webidl-conversions "^5.0.0" +dotenv@^16.0.1: + version "16.0.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.1.tgz#8f8f9d94876c35dac989876a5d3a82a267fdce1d" + integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ== + double-ended-queue@2.1.0-0: version "2.1.0-0" resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" diff --git a/packages/builder/cypress/setup.js b/packages/builder/cypress/setup.js index e19c931ed9..d10990573a 100644 --- a/packages/builder/cypress/setup.js +++ b/packages/builder/cypress/setup.js @@ -7,7 +7,6 @@ const tmpdir = path.join(require("os").tmpdir(), ".budibase") const SERVER_PORT = cypressConfig.env.PORT const WORKER_PORT = cypressConfig.env.WORKER_PORT -process.env.BUDIBASE_API_KEY = "6BE826CB-6B30-4AEC-8777-2E90464633DE" process.env.NODE_ENV = "cypress" process.env.ENABLE_ANALYTICS = "false" process.env.JWT_SECRET = cypressConfig.env.JWT_SECRET diff --git a/packages/builder/src/components/usage/Usage.svelte b/packages/builder/src/components/usage/Usage.svelte new file mode 100644 index 0000000000..cd9071785d --- /dev/null +++ b/packages/builder/src/components/usage/Usage.svelte @@ -0,0 +1,56 @@ + + +
+
+ + {#if unlimited} + {usage.used} + {:else} + {usage.used} / {usage.total} + {/if} +
+
+ {#if unlimited} + Unlimited + {:else} + + {/if} +
+
+ + diff --git a/packages/builder/src/pages/builder/portal/_layout.svelte b/packages/builder/src/pages/builder/portal/_layout.svelte index 087a8a0c99..17100987d4 100644 --- a/packages/builder/src/pages/builder/portal/_layout.svelte +++ b/packages/builder/src/pages/builder/portal/_layout.svelte @@ -31,7 +31,20 @@ $: menu = buildMenu($auth.isAdmin) const buildMenu = admin => { - let menu = [{ title: "Apps", href: "/builder/portal/apps" }] + let menu = [ + { + title: "Apps", + href: "/builder/portal/apps", + }, + ] + if (isEnabled(FEATURE_FLAGS.LICENSING)) { + menu = menu.concat([ + { + title: "Usage", + href: "/builder/portal/settings/usage", + }, + ]) + } if (admin) { menu = menu.concat([ { diff --git a/packages/builder/src/pages/builder/portal/manage/_layout.svelte b/packages/builder/src/pages/builder/portal/manage/_layout.svelte index e6c73bc596..b4ffa4910c 100644 --- a/packages/builder/src/pages/builder/portal/manage/_layout.svelte +++ b/packages/builder/src/pages/builder/portal/manage/_layout.svelte @@ -12,7 +12,7 @@ {#if $auth.isAdmin} - + {/if} diff --git a/packages/builder/src/pages/builder/portal/manage/auth/index.svelte b/packages/builder/src/pages/builder/portal/manage/auth/index.svelte index 242b21d945..40ece9d39b 100644 --- a/packages/builder/src/pages/builder/portal/manage/auth/index.svelte +++ b/packages/builder/src/pages/builder/portal/manage/auth/index.svelte @@ -297,7 +297,7 @@ {#if providers.google} - +
@@ -336,7 +336,7 @@ {/if} {#if providers.oidc} - +
diff --git a/packages/builder/src/pages/builder/portal/manage/email/index.svelte b/packages/builder/src/pages/builder/portal/manage/email/index.svelte index a1595072af..3e5b35db41 100644 --- a/packages/builder/src/pages/builder/portal/manage/email/index.svelte +++ b/packages/builder/src/pages/builder/portal/manage/email/index.svelte @@ -132,7 +132,7 @@ values below and click activate. - + {#if smtpConfig} SMTP @@ -186,7 +186,7 @@ Reset
- + Templates diff --git a/packages/builder/src/pages/builder/portal/settings/_layout.svelte b/packages/builder/src/pages/builder/portal/settings/_layout.svelte index f9c2067a94..6e3c76840d 100644 --- a/packages/builder/src/pages/builder/portal/settings/_layout.svelte +++ b/packages/builder/src/pages/builder/portal/settings/_layout.svelte @@ -2,6 +2,6 @@ import { Page } from "@budibase/bbui" - + diff --git a/packages/builder/src/pages/builder/portal/settings/usage.svelte b/packages/builder/src/pages/builder/portal/settings/usage.svelte new file mode 100644 index 0000000000..069c37b555 --- /dev/null +++ b/packages/builder/src/pages/builder/portal/settings/usage.svelte @@ -0,0 +1,139 @@ + + +{#if loaded} + + Usage + Get information about your current usage within Budibase. + {#if $admin.cloud} + {#if $auth.user?.accountPortalAccess} + To upgrade your plan and usage limits visit your Account. + {:else} + Contact your account holder to upgrade your usage limits. + {/if} + {/if} + + + + + + + + YOUR PLAN + {capitalise(license?.plan.type)} + + + USAGE +
+ {#each staticUsage as usage} +
+ +
+ {/each} +
+
+ {#if monthlyUsage.length} + + MONTHLY +
+ {#each monthlyUsage as usage} +
+ +
+ {/each} +
+
+
+ {/if} + +{/if} + + diff --git a/packages/builder/src/stores/portal/index.js b/packages/builder/src/stores/portal/index.js index a5d33b3b15..8810ce6b74 100644 --- a/packages/builder/src/stores/portal/index.js +++ b/packages/builder/src/stores/portal/index.js @@ -6,3 +6,4 @@ export { email } from "./email" export { auth } from "./auth" export { oidc } from "./oidc" export { templates } from "./templates" +export { licensing } from "./licensing" diff --git a/packages/builder/src/stores/portal/licensing.js b/packages/builder/src/stores/portal/licensing.js new file mode 100644 index 0000000000..653dab52ed --- /dev/null +++ b/packages/builder/src/stores/portal/licensing.js @@ -0,0 +1,29 @@ +import { writable } from "svelte/store" +import { API } from "api" + +export const createLicensingStore = () => { + const DEFAULT = { + plans: {}, + } + + const store = writable(DEFAULT) + + const actions = { + getQuotaUsage: async () => { + const quotaUsage = await API.getQuotaUsage() + store.update(state => { + return { + ...state, + quotaUsage, + } + }) + }, + } + + return { + subscribe: store.subscribe, + ...actions, + } +} + +export const licensing = createLicensingStore() diff --git a/packages/frontend-core/src/api/licensing.js b/packages/frontend-core/src/api/licensing.js index a3e5583325..16d65a20d7 100644 --- a/packages/frontend-core/src/api/licensing.js +++ b/packages/frontend-core/src/api/licensing.js @@ -27,4 +27,13 @@ export const buildLicensingEndpoints = API => ({ url: "/api/global/license/refresh", }) }, + + /** + * Retrieve the usage information for the tenant + */ + getQuotaUsage: async () => { + return API.get({ + url: "/api/global/license/usage", + }) + }, }) diff --git a/packages/server/scripts/likeCypress.ts b/packages/server/scripts/likeCypress.ts index 5675966b68..ac32608a32 100644 --- a/packages/server/scripts/likeCypress.ts +++ b/packages/server/scripts/likeCypress.ts @@ -9,7 +9,6 @@ const SERVER_PORT = "4100" const WORKER_PORT = "4200" // @ts-ignore -process.env.BUDIBASE_API_KEY = "6BE826CB-6B30-4AEC-8777-2E90464633DE" process.env.NODE_ENV = "cypress" process.env.ENABLE_ANALYTICS = "false" process.env.JWT_SECRET = "budibase" diff --git a/packages/server/src/environment.js b/packages/server/src/environment.js index 4807ef5493..45b8f68a49 100644 --- a/packages/server/src/environment.js +++ b/packages/server/src/environment.js @@ -39,15 +39,12 @@ module.exports = { COUCH_DB_URL: process.env.COUCH_DB_URL, MINIO_URL: process.env.MINIO_URL, WORKER_URL: process.env.WORKER_URL, - SELF_HOSTED: process.env.SELF_HOSTED, AWS_REGION: process.env.AWS_REGION, - ENABLE_ANALYTICS: process.env.ENABLE_ANALYTICS, MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY, MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY, REDIS_URL: process.env.REDIS_URL, REDIS_PASSWORD: process.env.REDIS_PASSWORD, INTERNAL_API_KEY: process.env.INTERNAL_API_KEY, - MULTI_TENANCY: process.env.MULTI_TENANCY, HTTP_MIGRATIONS: process.env.HTTP_MIGRATIONS, API_REQ_LIMIT_PER_SEC: process.env.API_REQ_LIMIT_PER_SEC, GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID, @@ -57,28 +54,26 @@ module.exports = { JEST_WORKER_ID: process.env.JEST_WORKER_ID, BUDIBASE_ENVIRONMENT: process.env.BUDIBASE_ENVIRONMENT, DISABLE_ACCOUNT_PORTAL: process.env.DISABLE_ACCOUNT_PORTAL, + TEMPLATE_REPOSITORY: process.env.TEMPLATE_REPOSITORY || "app", // minor SALT_ROUNDS: process.env.SALT_ROUNDS, LOGGER: process.env.LOGGER, LOG_LEVEL: process.env.LOG_LEVEL, - AUTOMATION_DIRECTORY: process.env.AUTOMATION_DIRECTORY, - AUTOMATION_BUCKET: process.env.AUTOMATION_BUCKET, AUTOMATION_MAX_ITERATIONS: process.env.AUTOMATION_MAX_ITERATIONS, SENDGRID_API_KEY: process.env.SENDGRID_API_KEY, DYNAMO_ENDPOINT: process.env.DYNAMO_ENDPOINT, POSTHOG_TOKEN: process.env.POSTHOG_TOKEN, QUERY_THREAD_TIMEOUT: parseIntSafe(process.env.QUERY_THREAD_TIMEOUT), - // old - to remove - CLIENT_ID: process.env.CLIENT_ID, - BUDIBASE_DIR: process.env.BUDIBASE_DIR, - DEPLOYMENT_DB_URL: process.env.DEPLOYMENT_DB_URL, - BUDIBASE_API_KEY: process.env.BUDIBASE_API_KEY, - USERID_API_KEY: process.env.USERID_API_KEY, - DEPLOYMENT_CREDENTIALS_URL: process.env.DEPLOYMENT_CREDENTIALS_URL, + SQL_MAX_ROWS: process.env.SQL_MAX_ROWS, + // flags ALLOW_DEV_AUTOMATIONS: process.env.ALLOW_DEV_AUTOMATIONS, DISABLE_THREADING: process.env.DISABLE_THREADING, - SQL_MAX_ROWS: process.env.SQL_MAX_ROWS, - TEMPLATE_REPOSITORY: process.env.TEMPLATE_REPOSITORY || "app", + DISABLE_DEVELOPER_LICENSE: process.env.DISABLE_DEVELOPER_LICENSE, + MULTI_TENANCY: process.env.MULTI_TENANCY, + ENABLE_ANALYTICS: process.env.ENABLE_ANALYTICS, + SELF_HOSTED: process.env.SELF_HOSTED, + // old + CLIENT_ID: process.env.CLIENT_ID, _set(key, value) { process.env[key] = value module.exports[key] = value diff --git a/packages/server/src/utilities/budibaseDir.js b/packages/server/src/utilities/budibaseDir.js index 48ae7eb0e7..dc992aaa8c 100644 --- a/packages/server/src/utilities/budibaseDir.js +++ b/packages/server/src/utilities/budibaseDir.js @@ -1,10 +1,3 @@ -const { join } = require("./centralPath") -const { homedir } = require("os") -const env = require("../environment") const { budibaseTempDir } = require("@budibase/backend-core/objectStore") -module.exports.budibaseAppsDir = function () { - return env.BUDIBASE_DIR || join(homedir(), ".budibase") -} - module.exports.budibaseTempDir = budibaseTempDir diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index 50d5b007a4..8a8cc1f660 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -1014,10 +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.164": - version "1.0.164" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.164.tgz#08c111dcebf5c74159a3c18218c7b3a0716de4f6" - integrity sha512-lpMudezndUD1hHBLfT9LDNKCunj8rQNlaJb30/xggdIUvp718u/jVP54hXF26NYxXOTMZ0EvMwCsIS4AucJ1Mg== +"@budibase/backend-core@1.0.167-alpha.3": + version "1.0.167-alpha.3" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.167-alpha.3.tgz#bb82ba4bbd6aaca47ceb97cb97047f4f615fd9a9" + integrity sha512-sETe50Nid+uuwg0/liEjhy9/o9ygjrYSOJJf1CzuC8xW1ni9wHMMrPx3vsHxYs21aE1+nW1hNgkCUw5kpw7Kjg== dependencies: "@techpass/passport-openidconnect" "^0.3.0" aws-sdk "^2.901.0" @@ -1091,12 +1091,12 @@ svelte-flatpickr "^3.2.3" svelte-portal "^1.0.0" -"@budibase/pro@1.0.164": - version "1.0.164" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.164.tgz#780ae38893d0609c87bf51fe96cc2c35bbdb431a" - integrity sha512-PgF7q2vADPPYzet4Wdma+THWuQPrEnN1+TfRly4l0oS9SUxutog3hYn0TlPmPS0AHgrqG/1v65TcEdC4ucX8TA== +"@budibase/pro@1.0.167-alpha.3": + version "1.0.167-alpha.3" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.167-alpha.3.tgz#22fa274ffbd50e08dfe5ca4bb546f14d68ba02d4" + integrity sha512-y6bQmNxRRChGJUVRu/FEUdkBlYZlGpxMC8xBSd8oj1FDRdTofbL0it2XUEI3P8H5zBM0J33pw6x27dlWnrOItg== dependencies: - "@budibase/backend-core" "1.0.164" + "@budibase/backend-core" "1.0.167-alpha.3" node-fetch "^2.6.1" "@budibase/standard-components@^0.9.139": diff --git a/packages/worker/src/api/controllers/global/license.ts b/packages/worker/src/api/controllers/global/license.ts index 62d6004258..1e5ca9beac 100644 --- a/packages/worker/src/api/controllers/global/license.ts +++ b/packages/worker/src/api/controllers/global/license.ts @@ -25,6 +25,5 @@ export const getInfo = async (ctx: any) => { } export const getQuotaUsage = async (ctx: any) => { - const usage = await quotas.getQuotaUsage() - ctx.body = usage + ctx.body = await quotas.getQuotaUsage() } diff --git a/packages/worker/src/api/controllers/global/self.js b/packages/worker/src/api/controllers/global/self.js index 99346c1298..43ee965d66 100644 --- a/packages/worker/src/api/controllers/global/self.js +++ b/packages/worker/src/api/controllers/global/self.js @@ -75,8 +75,8 @@ const checkCurrentApp = ctx => { const addSessionAttributesToUser = ctx => { ctx.body.account = ctx.user.account ctx.body.license = ctx.user.license - ctx.body.budibaseAccess = ctx.user.budibaseAccess - ctx.body.accountPortalAccess = ctx.user.accountPortalAccess + ctx.body.budibaseAccess = !!ctx.user.budibaseAccess + ctx.body.accountPortalAccess = !!ctx.user.accountPortalAccess ctx.body.csrfToken = ctx.user.csrfToken } diff --git a/packages/worker/src/environment.js b/packages/worker/src/environment.js index c965863a54..125617a7ab 100644 --- a/packages/worker/src/environment.js +++ b/packages/worker/src/environment.js @@ -17,32 +17,38 @@ if (!LOADED && isDev() && !isTest()) { } module.exports = { - NODE_ENV: process.env.NODE_ENV, - SELF_HOSTED: !!parseInt(process.env.SELF_HOSTED), - PORT: process.env.PORT || process.env.WORKER_PORT, - CLUSTER_PORT: process.env.CLUSTER_PORT, + // auth MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY, MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY, - MINIO_URL: process.env.MINIO_URL, - COUCH_DB_URL: process.env.COUCH_DB_URL, - LOG_LEVEL: process.env.LOG_LEVEL, JWT_SECRET: process.env.JWT_SECRET, SALT_ROUNDS: process.env.SALT_ROUNDS, - REDIS_URL: process.env.REDIS_URL, REDIS_PASSWORD: process.env.REDIS_PASSWORD, INTERNAL_API_KEY: process.env.INTERNAL_API_KEY, + COOKIE_DOMAIN: process.env.COOKIE_DOMAIN, + // urls + MINIO_URL: process.env.MINIO_URL, + COUCH_DB_URL: process.env.COUCH_DB_URL, + REDIS_URL: process.env.REDIS_URL, + ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL, + PLATFORM_URL: process.env.PLATFORM_URL, + APPS_URL: process.env.APPS_URL, + // ports + PORT: process.env.PORT || process.env.WORKER_PORT, + CLUSTER_PORT: process.env.CLUSTER_PORT, + // flags + NODE_ENV: process.env.NODE_ENV, + SELF_HOSTED: !!parseInt(process.env.SELF_HOSTED), + LOG_LEVEL: process.env.LOG_LEVEL, MULTI_TENANCY: process.env.MULTI_TENANCY, DISABLE_ACCOUNT_PORTAL: process.env.DISABLE_ACCOUNT_PORTAL, - ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL, SMTP_FALLBACK_ENABLED: process.env.SMTP_FALLBACK_ENABLED, + DISABLE_DEVELOPER_LICENSE: process.env.DISABLE_DEVELOPER_LICENSE, + // smtp SMTP_USER: process.env.SMTP_USER, SMTP_PASSWORD: process.env.SMTP_PASSWORD, SMTP_HOST: process.env.SMTP_HOST, SMTP_PORT: process.env.SMTP_PORT, SMTP_FROM_ADDRESS: process.env.SMTP_FROM_ADDRESS, - PLATFORM_URL: process.env.PLATFORM_URL, - COOKIE_DOMAIN: process.env.COOKIE_DOMAIN, - APPS_URL: process.env.APPS_URL, _set(key, value) { process.env[key] = value module.exports[key] = value diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index 6ec47f0e09..34530c0161 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.164": - version "1.0.164" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.164.tgz#08c111dcebf5c74159a3c18218c7b3a0716de4f6" - integrity sha512-lpMudezndUD1hHBLfT9LDNKCunj8rQNlaJb30/xggdIUvp718u/jVP54hXF26NYxXOTMZ0EvMwCsIS4AucJ1Mg== +"@budibase/backend-core@1.0.167-alpha.3": + version "1.0.167-alpha.3" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.167-alpha.3.tgz#bb82ba4bbd6aaca47ceb97cb97047f4f615fd9a9" + integrity sha512-sETe50Nid+uuwg0/liEjhy9/o9ygjrYSOJJf1CzuC8xW1ni9wHMMrPx3vsHxYs21aE1+nW1hNgkCUw5kpw7Kjg== 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.164": - version "1.0.164" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.164.tgz#780ae38893d0609c87bf51fe96cc2c35bbdb431a" - integrity sha512-PgF7q2vADPPYzet4Wdma+THWuQPrEnN1+TfRly4l0oS9SUxutog3hYn0TlPmPS0AHgrqG/1v65TcEdC4ucX8TA== +"@budibase/pro@1.0.167-alpha.3": + version "1.0.167-alpha.3" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.167-alpha.3.tgz#22fa274ffbd50e08dfe5ca4bb546f14d68ba02d4" + integrity sha512-y6bQmNxRRChGJUVRu/FEUdkBlYZlGpxMC8xBSd8oj1FDRdTofbL0it2XUEI3P8H5zBM0J33pw6x27dlWnrOItg== dependencies: - "@budibase/backend-core" "1.0.164" + "@budibase/backend-core" "1.0.167-alpha.3" node-fetch "^2.6.1" "@cspotcode/source-map-consumer@0.8.0":