diff --git a/lerna.json b/lerna.json
index 99d61cf6dc..4b2ef30117 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,5 +1,5 @@
{
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"npmClient": "yarn",
"packages": [
"packages/backend-core",
diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json
index 1296f45c54..fe23105596 100644
--- a/packages/backend-core/package.json
+++ b/packages/backend-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/backend-core",
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"description": "Budibase backend core libraries used in server and worker",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
@@ -22,7 +22,7 @@
"dependencies": {
"@budibase/nano": "10.1.2",
"@budibase/pouchdb-replication-stream": "1.2.10",
- "@budibase/types": "2.5.6-alpha.28",
+ "@budibase/types": "2.5.6-alpha.42",
"@shopify/jest-koa-mocks": "5.0.1",
"@techpass/passport-openidconnect": "0.3.2",
"aws-cloudfront-sign": "2.2.0",
@@ -45,6 +45,8 @@
"passport-jwt": "4.0.0",
"passport-local": "1.0.0",
"passport-oauth2-refresh": "^2.1.0",
+ "pino": "8.11.0",
+ "pino-http": "8.3.3",
"posthog-node": "1.3.0",
"pouchdb": "7.3.0",
"pouchdb-find": "7.2.2",
@@ -78,7 +80,6 @@
"jest-serial-runner": "^1.2.1",
"koa": "2.13.4",
"nodemon": "2.0.16",
- "pino": "7.11.0",
"pino-pretty": "10.0.0",
"pouchdb-adapter-memory": "7.2.2",
"timekeeper": "2.2.0",
diff --git a/packages/backend-core/src/events/publishers/license.ts b/packages/backend-core/src/events/publishers/license.ts
index aff3286c87..d1ff4d7609 100644
--- a/packages/backend-core/src/events/publishers/license.ts
+++ b/packages/backend-core/src/events/publishers/license.ts
@@ -3,7 +3,6 @@ import {
Event,
LicenseActivatedEvent,
LicensePlanChangedEvent,
- LicenseTierChangedEvent,
PlanType,
Account,
LicensePortalOpenedEvent,
@@ -11,22 +10,22 @@ import {
LicenseCheckoutOpenedEvent,
LicensePaymentFailedEvent,
LicensePaymentRecoveredEvent,
+ PriceDuration,
} from "@budibase/types"
-async function tierChanged(account: Account, from: number, to: number) {
- const properties: LicenseTierChangedEvent = {
- accountId: account.accountId,
- to,
- from,
- }
- await publishEvent(Event.LICENSE_TIER_CHANGED, properties)
-}
-
-async function planChanged(account: Account, from: PlanType, to: PlanType) {
+async function planChanged(
+ account: Account,
+ from: PlanType,
+ to: PlanType,
+ quantity: number | undefined,
+ duration: PriceDuration | undefined
+) {
const properties: LicensePlanChangedEvent = {
accountId: account.accountId,
to,
from,
+ quantity,
+ duration,
}
await publishEvent(Event.LICENSE_PLAN_CHANGED, properties)
}
@@ -74,7 +73,6 @@ async function paymentRecovered(account: Account) {
}
export default {
- tierChanged,
planChanged,
activated,
checkoutOpened,
diff --git a/packages/backend-core/tests/core/utilities/mocks/events.ts b/packages/backend-core/tests/core/utilities/mocks/events.ts
index dacf7dcce8..81de1f8175 100644
--- a/packages/backend-core/tests/core/utilities/mocks/events.ts
+++ b/packages/backend-core/tests/core/utilities/mocks/events.ts
@@ -123,7 +123,6 @@ beforeAll(async () => {
jest.spyOn(events.plugin, "imported")
jest.spyOn(events.plugin, "deleted")
- jest.spyOn(events.license, "tierChanged")
jest.spyOn(events.license, "planChanged")
jest.spyOn(events.license, "activated")
jest.spyOn(events.license, "checkoutOpened")
diff --git a/packages/backend-core/tests/core/utilities/structures/licenses.ts b/packages/backend-core/tests/core/utilities/structures/licenses.ts
index 24b120451e..810f31cf4f 100644
--- a/packages/backend-core/tests/core/utilities/structures/licenses.ts
+++ b/packages/backend-core/tests/core/utilities/structures/licenses.ts
@@ -7,16 +7,29 @@ import {
PlanType,
PriceDuration,
PurchasedPlan,
+ PurchasedPrice,
Quotas,
Subscription,
} from "@budibase/types"
+export function price(): PurchasedPrice {
+ return {
+ amount: 10000,
+ amountMonthly: 10000,
+ currency: "usd",
+ duration: PriceDuration.MONTHLY,
+ priceId: "price_123",
+ dayPasses: undefined,
+ isPerUser: true,
+ }
+}
+
export const plan = (type: PlanType = PlanType.FREE): PurchasedPlan => {
return {
type,
usesInvoicing: false,
- minUsers: 1,
model: PlanModel.PER_USER,
+ price: price(),
}
}
diff --git a/packages/bbui/package.json b/packages/bbui/package.json
index b46e5c3b7d..ff82bbc2c4 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": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"license": "MPL-2.0",
"svelte": "src/index.js",
"module": "dist/bbui.es.js",
@@ -38,8 +38,8 @@
],
"dependencies": {
"@adobe/spectrum-css-workflow-icons": "1.2.1",
- "@budibase/shared-core": "2.5.6-alpha.28",
- "@budibase/string-templates": "2.5.6-alpha.28",
+ "@budibase/shared-core": "2.5.6-alpha.42",
+ "@budibase/string-templates": "2.5.6-alpha.42",
"@spectrum-css/accordion": "3.0.24",
"@spectrum-css/actionbutton": "1.0.1",
"@spectrum-css/actiongroup": "1.0.1",
diff --git a/packages/builder/package.json b/packages/builder/package.json
index 4009a401e7..0015174bcf 100644
--- a/packages/builder/package.json
+++ b/packages/builder/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/builder",
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"license": "GPL-3.0",
"private": true,
"scripts": {
@@ -58,11 +58,10 @@
}
},
"dependencies": {
- "@budibase/bbui": "2.5.6-alpha.28",
- "@budibase/client": "2.5.6-alpha.28",
- "@budibase/frontend-core": "2.5.6-alpha.28",
- "@budibase/shared-core": "2.5.6-alpha.28",
- "@budibase/string-templates": "2.5.6-alpha.28",
+ "@budibase/bbui": "2.5.6-alpha.42",
+ "@budibase/frontend-core": "2.5.6-alpha.42",
+ "@budibase/shared-core": "2.5.6-alpha.42",
+ "@budibase/string-templates": "2.5.6-alpha.42",
"@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/free-brands-svg-icons": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1",
diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js
index 3fc0eb769e..e264dc099b 100644
--- a/packages/builder/src/builderStore/store/frontend.js
+++ b/packages/builder/src/builderStore/store/frontend.js
@@ -134,6 +134,7 @@ export const getFrontendStore = () => {
previousTopNavPath: {},
version: application.version,
revertableVersion: application.revertableVersion,
+ upgradableVersion: application.upgradableVersion,
navigation: application.navigation || {},
usedPlugins: application.usedPlugins || [],
}))
diff --git a/packages/builder/src/components/deploy/VersionModal.svelte b/packages/builder/src/components/deploy/VersionModal.svelte
index f357cc7820..75acc974ce 100644
--- a/packages/builder/src/components/deploy/VersionModal.svelte
+++ b/packages/builder/src/components/deploy/VersionModal.svelte
@@ -9,7 +9,6 @@
} from "@budibase/bbui"
import { store } from "builderStore"
import { API } from "api"
- import clientPackage from "@budibase/client/package.json"
export function show() {
updateModal.show()
@@ -25,9 +24,9 @@
$: appId = $store.appId
$: updateAvailable =
- clientPackage.version &&
+ $store.upgradableVersion &&
$store.version &&
- clientPackage.version !== $store.version
+ $store.upgradableVersion !== $store.version
$: revertAvailable = $store.revertableVersion != null
const refreshAppPackage = async () => {
@@ -46,7 +45,7 @@
// Don't wait for the async refresh, since this causes modal flashing
refreshAppPackage()
notifications.success(
- `App updated successfully to version ${clientPackage.version}`
+ `App updated successfully to version ${$store.upgradableVersion}`
)
} catch (err) {
notifications.error(`Error updating app: ${err}`)
@@ -91,7 +90,7 @@
{#if updateAvailable}
This app is currently using version {$store.version} , but version
- {clientPackage.version} is available. Updates can contain new features,
+ {$store.upgradableVersion} is available. Updates can contain new features,
performance improvements and bug fixes.
{:else}
diff --git a/packages/builder/src/components/usage/Usage.svelte b/packages/builder/src/components/usage/Usage.svelte
index 6e81abfe63..23d8ddc2f3 100644
--- a/packages/builder/src/components/usage/Usage.svelte
+++ b/packages/builder/src/components/usage/Usage.svelte
@@ -27,7 +27,7 @@
onMount(() => {
unlimited = isUnlimited()
percentage = getPercentage()
- if (warnWhenFull && percentage === 100) {
+ if (warnWhenFull && percentage >= 100) {
showWarning = true
}
})
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte
index 8e6ac603e7..bfc2f94f43 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutSettingsPanel.svelte
@@ -35,7 +35,7 @@
}
-
+
Custom layouts are being deprecated. They will be removed in a future
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte
index dbd23c462f..614e1eed80 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationInfoPanel.svelte
@@ -9,7 +9,7 @@
}
-
+
{#if $selectedScreen.layoutId}
{#if $selectedScreen.layoutId}
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeInfoPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeInfoPanel.svelte
index 9593f0bff5..c3325852c8 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeInfoPanel.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/theme/_components/ThemeInfoPanel.svelte
@@ -3,7 +3,7 @@
import { Body, Layout } from "@budibase/bbui"
-
+
Your theme is set across all the screens within your app.
diff --git a/packages/builder/src/pages/builder/portal/account/usage.svelte b/packages/builder/src/pages/builder/portal/account/usage.svelte
index 80e42d52a8..8dc02c6c80 100644
--- a/packages/builder/src/pages/builder/portal/account/usage.svelte
+++ b/packages/builder/src/pages/builder/portal/account/usage.svelte
@@ -43,12 +43,18 @@
}
$: quotaUsage = $licensing.quotaUsage
+
$: license = $auth.user?.license
+ $: plan = license?.plan
+ $: usesInvoicing = plan?.usesInvoicing
+
$: accountPortalAccess = $auth?.user?.accountPortalAccess
$: quotaReset = quotaUsage?.quotaReset
$: canManagePlan =
($admin.cloud && accountPortalAccess) || (!$admin.cloud && $auth.isAdmin)
+ $: showButton = !usesInvoicing && accountPortalAccess
+
const setMonthlyUsage = () => {
monthlyUsage = []
if (quotaUsage.monthly) {
@@ -121,7 +127,7 @@
const setTextRows = () => {
textRows = []
- if (cancelAt) {
+ if (cancelAt && !usesInvoicing) {
textRows.push({ message: "Subscription has been cancelled" })
textRows.push({
message: `${getDaysRemaining(cancelAt)} days remaining`,
@@ -213,7 +219,7 @@
description="YOUR CURRENT PLAN"
title={planTitle()}
{primaryActionText}
- primaryAction={accountPortalAccess ? goToAccountPortal : undefined}
+ primaryAction={showButton ? goToAccountPortal : undefined}
{textRows}
>
@@ -224,33 +230,23 @@
{/each}
+
+ Monthly limits
+
+
+
+ Resets in {daysRemainingInMonth} days
+
+
+
+
+
+ {#each monthlyUsage as usage}
+
+ {/each}
+
-
- {#if monthlyUsage.length}
-
-
-
- Monthly limits
-
-
-
- Resets in {daysRemainingInMonth} days
-
-
-
-
-
- {#each monthlyUsage as usage}
-
- {/each}
-
-
-
- {/if}
diff --git a/packages/builder/src/pages/builder/portal/overview/[appId]/backups/index.svelte b/packages/builder/src/pages/builder/portal/overview/[appId]/backups/index.svelte
index 4ff9ea386a..77d76c9609 100644
--- a/packages/builder/src/pages/builder/portal/overview/[appId]/backups/index.svelte
+++ b/packages/builder/src/pages/builder/portal/overview/[appId]/backups/index.svelte
@@ -176,7 +176,7 @@
Backups
{#if !$licensing.backupsEnabled}
- Pro plan
+ Premium
{/if}
diff --git a/packages/builder/src/pages/builder/portal/overview/[appId]/overview.svelte b/packages/builder/src/pages/builder/portal/overview/[appId]/overview.svelte
index 2d2b6775fb..c049a610b6 100644
--- a/packages/builder/src/pages/builder/portal/overview/[appId]/overview.svelte
+++ b/packages/builder/src/pages/builder/portal/overview/[appId]/overview.svelte
@@ -13,7 +13,6 @@
notifications,
} from "@budibase/bbui"
import { store } from "builderStore"
- import clientPackage from "@budibase/client/package.json"
import { processStringSync } from "@budibase/string-templates"
import { users, auth, apps, groups, overview } from "stores/portal"
import { fetchData } from "@budibase/frontend-core"
@@ -40,7 +39,7 @@
},
},
})
- $: updateAvailable = clientPackage.version !== $store.version
+ $: updateAvailable = $store.upgradableVersion !== $store.version
$: isPublished = app?.status === AppStatus.DEPLOYED
$: appEditorId = !app?.updatedBy ? $auth.user._id : app?.updatedBy
$: appEditorText = appEditor?.firstName || appEditor?.email
@@ -172,8 +171,8 @@
{$store.version}
{#if updateAvailable}
- New version {clientPackage.version} is available
- -
+ New version {$store.upgradableVersion} is
+ available -
{
$goto("./version")
diff --git a/packages/builder/src/pages/builder/portal/overview/[appId]/version.svelte b/packages/builder/src/pages/builder/portal/overview/[appId]/version.svelte
index 676d0b4f59..723e32984d 100644
--- a/packages/builder/src/pages/builder/portal/overview/[appId]/version.svelte
+++ b/packages/builder/src/pages/builder/portal/overview/[appId]/version.svelte
@@ -1,12 +1,11 @@
@@ -18,7 +17,7 @@
{#if updateAvailable}
The app is currently using version {$store.version}
- but version {clientPackage.version} is available.
+ but version {$store.upgradableVersion} is available.
Updates can contain new features, performance improvements and bug fixes.
diff --git a/packages/builder/src/pages/builder/portal/settings/auth/index.svelte b/packages/builder/src/pages/builder/portal/settings/auth/index.svelte
index 60f84049a3..38f5e0788b 100644
--- a/packages/builder/src/pages/builder/portal/settings/auth/index.svelte
+++ b/packages/builder/src/pages/builder/portal/settings/auth/index.svelte
@@ -378,7 +378,7 @@
{#if !$licensing.enforceableSSO}
- Enterprise plan
+ Enterprise
{/if}
diff --git a/packages/builder/src/pages/builder/portal/settings/branding.svelte b/packages/builder/src/pages/builder/portal/settings/branding.svelte
index 2184280e89..ae22d310a1 100644
--- a/packages/builder/src/pages/builder/portal/settings/branding.svelte
+++ b/packages/builder/src/pages/builder/portal/settings/branding.svelte
@@ -213,7 +213,7 @@
{/if}
{#if isCloud && !brandingEnabled}
- Pro
+ Premium
{/if}
diff --git a/packages/builder/src/pages/builder/portal/users/groups/index.svelte b/packages/builder/src/pages/builder/portal/users/groups/index.svelte
index 1a0bad7b11..6abc63811f 100644
--- a/packages/builder/src/pages/builder/portal/users/groups/index.svelte
+++ b/packages/builder/src/pages/builder/portal/users/groups/index.svelte
@@ -94,7 +94,7 @@
Groups
{#if !$licensing.groupsEnabled}
- Pro plan
+ Business
{/if}
diff --git a/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte b/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte
index be0023ec21..b35c6c998f 100644
--- a/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte
+++ b/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte
@@ -25,7 +25,7 @@
$: invalidEmails = []
$: userCount = $licensing.userCount + userEmails.length
- $: willExceed = userCount > $licensing.userLimit
+ $: willExceed = licensing.willExceedUserLimit(userCount)
$: importDisabled =
!userEmails.length || !validEmails(userEmails) || !usersRole || willExceed
diff --git a/packages/builder/src/stores/portal/users.js b/packages/builder/src/stores/portal/users.js
index d223239f67..898d47c0e2 100644
--- a/packages/builder/src/stores/portal/users.js
+++ b/packages/builder/src/stores/portal/users.js
@@ -114,11 +114,13 @@ export function createUsersStore() {
const getUserRole = ({ admin, builder }) =>
admin?.global ? "admin" : builder?.global ? "developer" : "appUser"
- const refreshUsage = fn => async args => {
- const response = await fn(args)
- await licensing.setQuotaUsage()
- return response
- }
+ const refreshUsage =
+ fn =>
+ async (...args) => {
+ const response = await fn(...args)
+ await licensing.setQuotaUsage()
+ return response
+ }
return {
subscribe,
@@ -133,7 +135,7 @@ export function createUsersStore() {
updateInvite,
getUserCountByApp,
// any operation that adds or deletes users
- acceptInvite: refreshUsage(acceptInvite),
+ acceptInvite,
create: refreshUsage(create),
save: refreshUsage(save),
bulkDelete: refreshUsage(bulkDelete),
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 321c9b6a35..87f8885baa 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/cli",
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "dist/index.js",
"bin": {
@@ -29,9 +29,9 @@
"outputPath": "build"
},
"dependencies": {
- "@budibase/backend-core": "2.5.6-alpha.28",
- "@budibase/string-templates": "2.5.6-alpha.28",
- "@budibase/types": "2.5.6-alpha.28",
+ "@budibase/backend-core": "2.5.6-alpha.42",
+ "@budibase/string-templates": "2.5.6-alpha.42",
+ "@budibase/types": "2.5.6-alpha.42",
"axios": "0.21.2",
"chalk": "4.1.0",
"cli-progress": "3.11.2",
diff --git a/packages/client/manifest.json b/packages/client/manifest.json
index 84ffca314c..71637723c1 100644
--- a/packages/client/manifest.json
+++ b/packages/client/manifest.json
@@ -5225,36 +5225,5 @@
"type": "schema",
"suffix": "repeater"
}
- },
- "spreadsheet": {
- "name": "Spreadsheet",
- "icon": "ViewGrid",
- "settings": [
- {
- "key": "table",
- "type": "table",
- "label": "Table"
- },
- {
- "type": "filter",
- "label": "Filtering",
- "key": "filter"
- },
- {
- "type": "field/sortable",
- "label": "Sort Column",
- "key": "sortColumn"
- },
- {
- "type": "select",
- "label": "Sort Order",
- "key": "sortOrder",
- "options": [
- "Ascending",
- "Descending"
- ],
- "defaultValue": "Ascending"
- }
- ]
}
}
diff --git a/packages/client/package.json b/packages/client/package.json
index b953eee349..7ff0ddae9c 100644
--- a/packages/client/package.json
+++ b/packages/client/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/client",
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"license": "MPL-2.0",
"module": "dist/budibase-client.js",
"main": "dist/budibase-client.js",
@@ -19,11 +19,11 @@
"dev:builder": "rollup -cw"
},
"dependencies": {
- "@budibase/bbui": "2.5.6-alpha.28",
- "@budibase/frontend-core": "2.5.6-alpha.28",
- "@budibase/shared-core": "2.5.6-alpha.28",
- "@budibase/string-templates": "2.5.6-alpha.28",
- "@budibase/types": "2.5.6-alpha.28",
+ "@budibase/bbui": "2.5.6-alpha.42",
+ "@budibase/frontend-core": "2.5.6-alpha.42",
+ "@budibase/shared-core": "2.5.6-alpha.42",
+ "@budibase/string-templates": "2.5.6-alpha.42",
+ "@budibase/types": "2.5.6-alpha.42",
"@spectrum-css/button": "^3.0.3",
"@spectrum-css/card": "^3.0.3",
"@spectrum-css/divider": "^1.0.3",
diff --git a/packages/frontend-core/package.json b/packages/frontend-core/package.json
index ff830b0cb5..c0b60cb091 100644
--- a/packages/frontend-core/package.json
+++ b/packages/frontend-core/package.json
@@ -1,13 +1,13 @@
{
"name": "@budibase/frontend-core",
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"description": "Budibase frontend core libraries used in builder and client",
"author": "Budibase",
"license": "MPL-2.0",
"svelte": "src/index.js",
"dependencies": {
- "@budibase/bbui": "2.5.6-alpha.28",
- "@budibase/shared-core": "2.5.6-alpha.28",
+ "@budibase/bbui": "2.5.6-alpha.42",
+ "@budibase/shared-core": "2.5.6-alpha.42",
"dayjs": "^1.11.7",
"lodash": "^4.17.21",
"socket.io-client": "^4.6.1",
diff --git a/packages/frontend-core/src/components/grid/cells/DataCell.svelte b/packages/frontend-core/src/components/grid/cells/DataCell.svelte
index 5a2e02340f..0aa0cd54f4 100644
--- a/packages/frontend-core/src/components/grid/cells/DataCell.svelte
+++ b/packages/frontend-core/src/components/grid/cells/DataCell.svelte
@@ -19,6 +19,7 @@
export let updateValue = rows.actions.updateValue
export let invertX = false
export let invertY = false
+ export let contentLines = 1
const emptyError = writable(null)
@@ -84,5 +85,7 @@
{readonly}
{invertY}
{invertX}
+ {contentLines}
/>
+
diff --git a/packages/frontend-core/src/components/grid/cells/GridCell.svelte b/packages/frontend-core/src/components/grid/cells/GridCell.svelte
index dfc53f6f0c..6589c18d07 100644
--- a/packages/frontend-core/src/components/grid/cells/GridCell.svelte
+++ b/packages/frontend-core/src/components/grid/cells/GridCell.svelte
@@ -117,6 +117,9 @@
.cell.error {
--cell-color: var(--spectrum-global-color-red-500);
}
+ .cell.readonly {
+ --cell-color: var(--spectrum-global-color-gray-600);
+ }
.cell:not(.focused) {
user-select: none;
}
diff --git a/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte b/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte
index 165711c51f..72b0ad0ff1 100644
--- a/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte
+++ b/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte
@@ -37,6 +37,8 @@
$: sortedBy = column.name === $sort.column
$: canMoveLeft = orderable && idx > 0
$: canMoveRight = orderable && idx < $renderedColumns.length - 1
+ $: ascendingLabel = column.schema?.type === "number" ? "low-high" : "A-Z"
+ $: descendingLabel = column.schema?.type === "number" ? "high-low" : "Z-A"
const editColumn = () => {
dispatch("edit-column", column.schema)
@@ -179,14 +181,14 @@
on:click={sortAscending}
disabled={column.name === $sort.column && $sort.order === "ascending"}
>
- Sort A-Z
+ Sort {ascendingLabel}
- Sort Z-A
+ Sort {descendingLabel}
Move left
diff --git a/packages/frontend-core/src/components/grid/cells/LongFormCell.svelte b/packages/frontend-core/src/components/grid/cells/LongFormCell.svelte
index 00e12dc6a3..886d4ef8b0 100644
--- a/packages/frontend-core/src/components/grid/cells/LongFormCell.svelte
+++ b/packages/frontend-core/src/components/grid/cells/LongFormCell.svelte
@@ -1,5 +1,6 @@
-
+
diff --git a/packages/frontend-core/src/components/grid/cells/OptionsCell.svelte b/packages/frontend-core/src/components/grid/cells/OptionsCell.svelte
index f3b6b9b59d..9399617eb7 100644
--- a/packages/frontend-core/src/components/grid/cells/OptionsCell.svelte
+++ b/packages/frontend-core/src/components/grid/cells/OptionsCell.svelte
@@ -1,5 +1,5 @@
+
+
+ {#each parsedKeys as key}
+
+ {key}
+
+ {/each}
+
+
+
diff --git a/packages/frontend-core/src/components/grid/layout/NewRow.svelte b/packages/frontend-core/src/components/grid/layout/NewRow.svelte
index 54fef78301..71c390c946 100644
--- a/packages/frontend-core/src/components/grid/layout/NewRow.svelte
+++ b/packages/frontend-core/src/components/grid/layout/NewRow.svelte
@@ -7,6 +7,7 @@
import { GutterWidth } from "../lib/constants"
import { NewRowID } from "../lib/constants"
import GutterCell from "../cells/GutterCell.svelte"
+ import KeyboardShortcut from "./KeyboardShortcut.svelte"
const {
hoveredRowId,
@@ -27,13 +28,14 @@
columnHorizontalInversionIndex,
} = getContext("grid")
+ let visible = false
let isAdding = false
let newRow = {}
let offset = 0
$: firstColumn = $stickyColumn || $renderedColumns[0]
$: width = GutterWidth + ($stickyColumn?.width || 0)
- $: $tableId, (isAdding = false)
+ $: $tableId, (visible = false)
$: invertY = shouldInvertY(offset, $rowVerticalInversionIndex, $renderedRows)
const shouldInvertY = (offset, inversionIndex, rows) => {
@@ -45,7 +47,8 @@
const addRow = async () => {
// Blur the active cell and tick to let final value updates propagate
- $focusedCellAPI?.blur()
+ isAdding = true
+ $focusedCellId = null
await tick()
// Create row
@@ -60,17 +63,19 @@
$focusedCellId = `${savedRow._id}-${firstColumn.name}`
}
}
+ isAdding = false
}
const clear = () => {
isAdding = false
+ visible = false
$focusedCellId = null
$hoveredRowId = null
document.removeEventListener("keydown", handleKeyPress)
}
const startAdding = async () => {
- if (isAdding) {
+ if (visible) {
return
}
@@ -95,7 +100,7 @@
// Update state and select initial cell
newRow = {}
- isAdding = true
+ visible = true
$hoveredRowId = NewRowID
if (firstColumn) {
$focusedCellId = `${NewRowID}-${firstColumn.name}`
@@ -115,7 +120,7 @@
}
const handleKeyPress = e => {
- if (!isAdding) {
+ if (!visible) {
return
}
if (e.key === "Escape") {
@@ -137,7 +142,7 @@
-{#if isAdding}
+{#if visible}
0}
@@ -148,6 +153,9 @@
+ {#if isAdding}
+
+ {/if}
{#if $stickyColumn}
{@const cellId = `${NewRowID}-${$stickyColumn.name}`}
@@ -161,7 +169,14 @@
{updateValue}
rowIdx={0}
{invertY}
- />
+ >
+ {#if $stickyColumn?.schema?.autocolumn}
+
Can't edit auto column
+ {/if}
+ {#if isAdding}
+
+ {/if}
+
{/if}
@@ -181,15 +196,32 @@
rowIdx={0}
invertX={columnIdx >= $columnHorizontalInversionIndex}
{invertY}
- />
+ >
+ {#if column?.schema?.autocolumn}
+
Can't edit auto column
+ {/if}
+ {#if isAdding}
+
+ {/if}
+
{/key}
{/each}
{/if}
@@ -240,6 +272,14 @@
top: calc(var(--row-height) + var(--offset) + 24px);
left: var(--gutter-width);
}
+ .button-with-keys {
+ display: flex;
+ gap: 6px;
+ align-items: center;
+ }
+ .button-with-keys :global(> div) {
+ padding-top: 2px;
+ }
/* Sticky column styles */
.sticky-column {
@@ -262,4 +302,33 @@
width: 0;
display: flex;
}
+
+ /* Readonly cell overlay */
+ .readonly-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: var(--row-height);
+ width: 100%;
+ padding: var(--cell-padding);
+ font-style: italic;
+ color: var(--spectrum-global-color-gray-600);
+ z-index: 1;
+ user-select: none;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+
+ /* Overlay while row is being added */
+ .loading-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: var(--row-height);
+ width: 100%;
+ z-index: 1;
+ background: var(--spectrum-global-color-gray-400);
+ opacity: 0.25;
+ }
diff --git a/packages/frontend-core/src/components/grid/layout/StickyColumn.svelte b/packages/frontend-core/src/components/grid/layout/StickyColumn.svelte
index 6f10c30695..6301112110 100644
--- a/packages/frontend-core/src/components/grid/layout/StickyColumn.svelte
+++ b/packages/frontend-core/src/components/grid/layout/StickyColumn.svelte
@@ -7,6 +7,7 @@
import HeaderCell from "../cells/HeaderCell.svelte"
import { GutterWidth, BlankRowID } from "../lib/constants"
import GutterCell from "../cells/GutterCell.svelte"
+ import KeyboardShortcut from "./KeyboardShortcut.svelte"
const {
rows,
@@ -21,6 +22,7 @@
focusedRow,
scrollLeft,
dispatch,
+ contentLines,
} = getContext("grid")
$: rowCount = $rows.length
@@ -85,6 +87,7 @@
selectedUser={$selectedCellMap[cellId]}
width={$stickyColumn.width}
column={$stickyColumn}
+ contentLines={$contentLines}
/>
{/if}
@@ -103,7 +106,9 @@
+ >
+
+
{/if}
{/if}
diff --git a/packages/frontend-core/src/components/grid/overlays/KeyboardManager.svelte b/packages/frontend-core/src/components/grid/overlays/KeyboardManager.svelte
index e0e842dc16..f0f56118d9 100644
--- a/packages/frontend-core/src/components/grid/overlays/KeyboardManager.svelte
+++ b/packages/frontend-core/src/components/grid/overlays/KeyboardManager.svelte
@@ -15,8 +15,22 @@
selectedRows,
} = getContext("grid")
+ const ignoredOriginSelectors = [
+ ".spectrum-Modal",
+ "#builder-side-panel-container",
+ ]
+
// Global key listener which intercepts all key events
const handleKeyDown = e => {
+ // Avoid processing events sourced from certain origins
+ if (e.target?.closest) {
+ for (let selector of ignoredOriginSelectors) {
+ if (e.target.closest(selector)) {
+ return
+ }
+ }
+ }
+
// If nothing selected avoid processing further key presses
if (!$focusedCellId) {
if (e.key === "Tab" || e.key?.startsWith("Arrow")) {
@@ -60,11 +74,6 @@
return
}
}
-
- // Avoid processing events sourced from modals
- if (e.target?.closest?.(".spectrum-Modal")) {
- return
- }
e.preventDefault()
// Handle the key ourselves
diff --git a/packages/sdk/package.json b/packages/sdk/package.json
index a8dff3da10..13cc20f9e9 100644
--- a/packages/sdk/package.json
+++ b/packages/sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/sdk",
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"description": "Budibase Public API SDK",
"author": "Budibase",
"license": "MPL-2.0",
diff --git a/packages/server/package.json b/packages/server/package.json
index 1cd28f6829..cc8a8208dc 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -1,7 +1,7 @@
{
"name": "@budibase/server",
"email": "hi@budibase.com",
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"description": "Budibase Web Server",
"main": "src/index.ts",
"repository": {
@@ -45,12 +45,12 @@
"license": "GPL-3.0",
"dependencies": {
"@apidevtools/swagger-parser": "10.0.3",
- "@budibase/backend-core": "2.5.6-alpha.28",
- "@budibase/client": "2.5.6-alpha.28",
- "@budibase/pro": "2.5.6-alpha.28",
- "@budibase/shared-core": "2.5.6-alpha.28",
- "@budibase/string-templates": "2.5.6-alpha.28",
- "@budibase/types": "2.5.6-alpha.28",
+ "@budibase/backend-core": "2.5.6-alpha.42",
+ "@budibase/client": "2.5.6-alpha.42",
+ "@budibase/pro": "2.5.6-alpha.42",
+ "@budibase/shared-core": "2.5.6-alpha.42",
+ "@budibase/string-templates": "2.5.6-alpha.42",
+ "@budibase/types": "2.5.6-alpha.42",
"@bull-board/api": "3.7.0",
"@bull-board/koa": "3.9.4",
"@elastic/elasticsearch": "7.10.0",
diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts
index ec68ca4c72..ff0dbe015b 100644
--- a/packages/server/src/api/controllers/application.ts
+++ b/packages/server/src/api/controllers/application.ts
@@ -223,7 +223,7 @@ export async function fetchAppPackage(ctx: UserCtx) {
)
ctx.body = {
- application,
+ application: { ...application, upgradableVersion: envCore.VERSION },
screens,
layouts,
clientLibPath,
diff --git a/packages/server/src/api/controllers/datasource.ts b/packages/server/src/api/controllers/datasource.ts
index 3d41cd89af..b61b168980 100644
--- a/packages/server/src/api/controllers/datasource.ts
+++ b/packages/server/src/api/controllers/datasource.ts
@@ -12,7 +12,15 @@ import { getIntegration } from "../../integrations"
import { getDatasourceAndQuery } from "./row/utils"
import { invalidateDynamicVariables } from "../../threads/utils"
import { db as dbCore, context, events } from "@budibase/backend-core"
-import { UserCtx, Datasource, Row } from "@budibase/types"
+import {
+ UserCtx,
+ Datasource,
+ Row,
+ CreateDatasourceResponse,
+ UpdateDatasourceResponse,
+ UpdateDatasourceRequest,
+ CreateDatasourceRequest,
+} from "@budibase/types"
import sdk from "../../sdk"
export async function fetch(ctx: UserCtx) {
@@ -146,7 +154,7 @@ async function invalidateVariables(
await invalidateDynamicVariables(toInvalidate)
}
-export async function update(ctx: UserCtx) {
+export async function update(ctx: UserCtx) {
const db = context.getAppDB()
const datasourceId = ctx.params.datasourceId
let datasource = await sdk.datasources.get(datasourceId)
@@ -187,15 +195,17 @@ export async function update(ctx: UserCtx) {
}
}
-export async function save(ctx: UserCtx) {
+export async function save(
+ ctx: UserCtx
+) {
const db = context.getAppDB()
const plus = ctx.request.body.datasource.plus
const fetchSchema = ctx.request.body.fetchSchema
const datasource = {
_id: generateDatasourceID({ plus }),
- type: plus ? DocumentType.DATASOURCE_PLUS : DocumentType.DATASOURCE,
...ctx.request.body.datasource,
+ type: plus ? DocumentType.DATASOURCE_PLUS : DocumentType.DATASOURCE,
}
let schemaError = null
@@ -218,7 +228,7 @@ export async function save(ctx: UserCtx) {
}
}
- const response: any = {
+ const response: CreateDatasourceResponse = {
datasource: await sdk.datasources.removeSecretSingle(datasource),
}
if (schemaError) {
diff --git a/packages/server/src/db/utils.ts b/packages/server/src/db/utils.ts
index 50341e4abc..e08392c3a1 100644
--- a/packages/server/src/db/utils.ts
+++ b/packages/server/src/db/utils.ts
@@ -27,6 +27,7 @@ export const isProdAppID = dbCore.isProdAppID
export const USER_METDATA_PREFIX = `${DocumentType.ROW}${SEPARATOR}${dbCore.InternalTable.USER_METADATA}${SEPARATOR}`
export const LINK_USER_METADATA_PREFIX = `${DocumentType.LINK}${SEPARATOR}${dbCore.InternalTable.USER_METADATA}${SEPARATOR}`
export const TABLE_ROW_PREFIX = `${DocumentType.ROW}${SEPARATOR}${DocumentType.TABLE}`
+export const AUTOMATION_LOG_PREFIX = `${DocumentType.AUTOMATION_LOG}${SEPARATOR}`
export const ViewName = dbCore.ViewName
export const InternalTables = dbCore.InternalTable
export const UNICODE_MAX = dbCore.UNICODE_MAX
diff --git a/packages/server/src/integration-test/postgres.spec.ts b/packages/server/src/integration-test/postgres.spec.ts
index 36285e2831..78075b4e54 100644
--- a/packages/server/src/integration-test/postgres.spec.ts
+++ b/packages/server/src/integration-test/postgres.spec.ts
@@ -349,7 +349,7 @@ describe("row api - postgres", () => {
},
plus: true,
source: "POSTGRES",
- type: "datasource",
+ type: "datasource_plus",
_id: expect.any(String),
_rev: expect.any(String),
createdAt: expect.any(String),
diff --git a/packages/server/src/sdk/app/backups/exports.ts b/packages/server/src/sdk/app/backups/exports.ts
index 27a907fceb..57342e7462 100644
--- a/packages/server/src/sdk/app/backups/exports.ts
+++ b/packages/server/src/sdk/app/backups/exports.ts
@@ -3,6 +3,7 @@ import { budibaseTempDir } from "../../../utilities/budibaseDir"
import { streamFile, createTempFolder } from "../../../utilities/fileSystem"
import { ObjectStoreBuckets } from "../../../constants"
import {
+ AUTOMATION_LOG_PREFIX,
LINK_USER_METADATA_PREFIX,
TABLE_ROW_PREFIX,
USER_METDATA_PREFIX,
@@ -20,11 +21,15 @@ const uuid = require("uuid/v4")
const tar = require("tar")
const MemoryStream = require("memorystream")
-type ExportOpts = {
+interface DBDumpOpts {
filter?: any
exportPath?: string
+}
+
+interface ExportOpts extends DBDumpOpts {
tar?: boolean
excludeRows?: boolean
+ excludeLogs?: boolean
}
function tarFilesToTmp(tmpDir: string, files: string[]) {
@@ -49,7 +54,7 @@ function tarFilesToTmp(tmpDir: string, files: string[]) {
* a filter function or the name of the export.
* @return {*} either a readable stream or a string
*/
-export async function exportDB(dbName: string, opts: ExportOpts = {}) {
+export async function exportDB(dbName: string, opts: DBDumpOpts = {}) {
const exportOpts = {
filter: opts?.filter,
batch_size: 1000,
@@ -76,11 +81,14 @@ export async function exportDB(dbName: string, opts: ExportOpts = {}) {
})
}
-function defineFilter(excludeRows?: boolean) {
+function defineFilter(excludeRows?: boolean, excludeLogs?: boolean) {
const ids = [USER_METDATA_PREFIX, LINK_USER_METADATA_PREFIX]
if (excludeRows) {
ids.push(TABLE_ROW_PREFIX)
}
+ if (excludeLogs) {
+ ids.push(AUTOMATION_LOG_PREFIX)
+ }
return (doc: any) =>
!ids.map(key => doc._id.includes(key)).reduce((prev, curr) => prev || curr)
}
@@ -130,8 +138,7 @@ export async function exportApp(appId: string, config?: ExportOpts) {
// enforce an export of app DB to the tmp path
const dbPath = join(tmpPath, DB_EXPORT_FILE)
await exportDB(appId, {
- ...config,
- filter: defineFilter(config?.excludeRows),
+ filter: defineFilter(config?.excludeRows, config?.excludeLogs),
exportPath: dbPath,
})
// if tar requested, return where the tarball is
@@ -155,6 +162,10 @@ export async function exportApp(appId: string, config?: ExportOpts) {
* @returns {*} a readable stream of the backup which is written in real time
*/
export async function streamExportApp(appId: string, excludeRows: boolean) {
- const tmpPath = await exportApp(appId, { excludeRows, tar: true })
+ const tmpPath = await exportApp(appId, {
+ excludeRows,
+ excludeLogs: true,
+ tar: true,
+ })
return streamFile(tmpPath)
}
diff --git a/packages/shared-core/package.json b/packages/shared-core/package.json
index 2d9ab33701..4ea3deea5f 100644
--- a/packages/shared-core/package.json
+++ b/packages/shared-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/shared-core",
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"description": "Shared data utils",
"main": "dist/cjs/src/index.js",
"types": "dist/mjs/src/index.d.ts",
@@ -20,7 +20,7 @@
"dev:builder": "yarn prebuild && concurrently \"tsc -p tsconfig.build.json --watch\" \"tsc -p tsconfig-cjs.build.json --watch\""
},
"dependencies": {
- "@budibase/types": "2.5.6-alpha.28"
+ "@budibase/types": "2.5.6-alpha.42"
},
"devDependencies": {
"concurrently": "^7.6.0",
diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json
index d9b9adcfbd..e1397182dc 100644
--- a/packages/string-templates/package.json
+++ b/packages/string-templates/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/string-templates",
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs",
"module": "dist/bundle.mjs",
diff --git a/packages/types/package.json b/packages/types/package.json
index 76ebca7e05..3068068d4c 100644
--- a/packages/types/package.json
+++ b/packages/types/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/types",
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"description": "Budibase types",
"main": "dist/cjs/index.js",
"types": "dist/mjs/index.d.ts",
diff --git a/packages/types/src/api/account/license.ts b/packages/types/src/api/account/license.ts
index 2ea564ea39..a867358559 100644
--- a/packages/types/src/api/account/license.ts
+++ b/packages/types/src/api/account/license.ts
@@ -1,4 +1,5 @@
-import { QuotaUsage } from "../../documents"
+import { LicenseOverrides, QuotaUsage } from "../../documents"
+import { PlanType } from "../../sdk"
export interface GetLicenseRequest {
// All fields should be optional to cater for
@@ -20,3 +21,8 @@ export interface QuotaTriggeredRequest {
export interface LicenseActivateRequest {
installVersion?: string
}
+
+export interface UpdateLicenseRequest {
+ planType?: PlanType
+ overrides?: LicenseOverrides
+}
diff --git a/packages/types/src/api/web/app/datasource.ts b/packages/types/src/api/web/app/datasource.ts
new file mode 100644
index 0000000000..d54259eab5
--- /dev/null
+++ b/packages/types/src/api/web/app/datasource.ts
@@ -0,0 +1,19 @@
+import { Datasource } from "../../../documents"
+
+export interface CreateDatasourceResponse {
+ datasource: Datasource
+ error?: any
+}
+
+export interface UpdateDatasourceResponse {
+ datasource: Datasource
+}
+
+export interface CreateDatasourceRequest {
+ datasource: Datasource
+ fetchSchema?: boolean
+}
+
+export interface UpdateDatasourceRequest extends Datasource {
+ datasource: Datasource
+}
diff --git a/packages/types/src/api/web/app/index.ts b/packages/types/src/api/web/app/index.ts
index 1d73755cb6..9be15ecfe3 100644
--- a/packages/types/src/api/web/app/index.ts
+++ b/packages/types/src/api/web/app/index.ts
@@ -1 +1,2 @@
export * from "./backup"
+export * from "./datasource"
diff --git a/packages/types/src/documents/account/account.ts b/packages/types/src/documents/account/account.ts
index 24d6606916..dad8abed30 100644
--- a/packages/types/src/documents/account/account.ts
+++ b/packages/types/src/documents/account/account.ts
@@ -1,4 +1,5 @@
import { Feature, Hosting, License, PlanType, Quotas } from "../../sdk"
+import { DeepPartial } from "../../shared"
import { QuotaUsage } from "../global"
export interface CreateAccount {
@@ -25,7 +26,7 @@ export const isCreatePasswordAccount = (
export interface LicenseOverrides {
features?: Feature[]
- quotas?: Quotas
+ quotas?: DeepPartial
}
export interface Account extends CreateAccount {
@@ -38,6 +39,7 @@ export interface Account extends CreateAccount {
// licensing
tier: string // deprecated
planType?: PlanType
+ /** @deprecated */
planTier?: number
license?: License
installId?: string
@@ -46,6 +48,7 @@ export interface Account extends CreateAccount {
stripeCustomerId?: string
licenseKey?: string
licenseKeyActivatedAt?: number
+ licenseRequestedAt?: number
licenseOverrides?: LicenseOverrides
quotaUsage?: QuotaUsage
}
diff --git a/packages/types/src/documents/app/query.ts b/packages/types/src/documents/app/query.ts
index 72b6c288a5..31a3a3ba09 100644
--- a/packages/types/src/documents/app/query.ts
+++ b/packages/types/src/documents/app/query.ts
@@ -42,3 +42,10 @@ export interface PaginationValues {
page: string | number | null
limit: number | null
}
+
+export interface PreviewQueryRequest extends Omit {
+ parameters: {}
+ flags?: {
+ urlName?: boolean
+ }
+}
diff --git a/packages/types/src/sdk/events/event.ts b/packages/types/src/sdk/events/event.ts
index c4990f869b..0d0b166253 100644
--- a/packages/types/src/sdk/events/event.ts
+++ b/packages/types/src/sdk/events/event.ts
@@ -138,7 +138,6 @@ export enum Event {
// LICENSE
LICENSE_PLAN_CHANGED = "license:plan:changed",
- LICENSE_TIER_CHANGED = "license:tier:changed",
LICENSE_ACTIVATED = "license:activated",
LICENSE_PAYMENT_FAILED = "license:payment:failed",
LICENSE_PAYMENT_RECOVERED = "license:payment:recovered",
@@ -328,7 +327,6 @@ export const AuditedEventFriendlyName: Record = {
// LICENSE - NOT AUDITED
[Event.LICENSE_PLAN_CHANGED]: undefined,
- [Event.LICENSE_TIER_CHANGED]: undefined,
[Event.LICENSE_ACTIVATED]: undefined,
[Event.LICENSE_PAYMENT_FAILED]: undefined,
[Event.LICENSE_PAYMENT_RECOVERED]: undefined,
diff --git a/packages/types/src/sdk/events/license.ts b/packages/types/src/sdk/events/license.ts
index a12fc6bbb5..b92c556cc8 100644
--- a/packages/types/src/sdk/events/license.ts
+++ b/packages/types/src/sdk/events/license.ts
@@ -1,15 +1,15 @@
-import { PlanType } from "../licensing"
-
-export interface LicenseTierChangedEvent {
- accountId: string
- from: number
- to: number
-}
+import { PlanType, PriceDuration } from "../licensing"
export interface LicensePlanChangedEvent {
accountId: string
from: PlanType
to: PlanType
+ // may not be on historical events
+ // free plans won't have a duration
+ duration: PriceDuration | undefined
+ // may not be on historical events
+ // free plans won't have a quantity
+ quantity: number | undefined
}
export interface LicenseActivatedEvent {
diff --git a/packages/types/src/sdk/licensing/plan.ts b/packages/types/src/sdk/licensing/plan.ts
index 360d7d08e5..3e214a01ff 100644
--- a/packages/types/src/sdk/licensing/plan.ts
+++ b/packages/types/src/sdk/licensing/plan.ts
@@ -17,7 +17,6 @@ export enum PriceDuration {
export interface AvailablePlan {
type: PlanType
maxUsers: number
- minUsers: number
prices: AvailablePrice[]
}
@@ -38,7 +37,6 @@ export interface PurchasedPlan {
type: PlanType
model: PlanModel
usesInvoicing: boolean
- minUsers: number
price?: PurchasedPrice
}
diff --git a/packages/types/src/sdk/licensing/quota.ts b/packages/types/src/sdk/licensing/quota.ts
index ea51f7a490..73afa1ed05 100644
--- a/packages/types/src/sdk/licensing/quota.ts
+++ b/packages/types/src/sdk/licensing/quota.ts
@@ -55,12 +55,6 @@ export const isConstantQuota = (
return quotaType === QuotaType.CONSTANT
}
-export interface Minimums {
- users: number
-}
-
-export type PlanMinimums = { [key in PlanType]: Minimums }
-
export type PlanQuotas = { [key in PlanType]: Quotas | undefined }
export type MonthlyQuotas = {
diff --git a/packages/types/src/shared/index.ts b/packages/types/src/shared/index.ts
new file mode 100644
index 0000000000..f8f5c5cc25
--- /dev/null
+++ b/packages/types/src/shared/index.ts
@@ -0,0 +1 @@
+export * from "./typeUtils"
diff --git a/packages/types/src/shared/typeUtils.ts b/packages/types/src/shared/typeUtils.ts
new file mode 100644
index 0000000000..71fadfc7aa
--- /dev/null
+++ b/packages/types/src/shared/typeUtils.ts
@@ -0,0 +1,3 @@
+export type DeepPartial = {
+ [P in keyof T]?: T[P] extends object ? DeepPartial : T[P]
+}
diff --git a/packages/worker/package.json b/packages/worker/package.json
index 9a4411222a..ae9358f084 100644
--- a/packages/worker/package.json
+++ b/packages/worker/package.json
@@ -1,7 +1,7 @@
{
"name": "@budibase/worker",
"email": "hi@budibase.com",
- "version": "2.5.6-alpha.28",
+ "version": "2.5.6-alpha.42",
"description": "Budibase background service",
"main": "src/index.ts",
"repository": {
@@ -37,10 +37,10 @@
"author": "Budibase",
"license": "GPL-3.0",
"dependencies": {
- "@budibase/backend-core": "2.5.6-alpha.28",
- "@budibase/pro": "2.5.6-alpha.28",
- "@budibase/string-templates": "2.5.6-alpha.28",
- "@budibase/types": "2.5.6-alpha.28",
+ "@budibase/backend-core": "2.5.6-alpha.42",
+ "@budibase/pro": "2.5.6-alpha.42",
+ "@budibase/string-templates": "2.5.6-alpha.42",
+ "@budibase/types": "2.5.6-alpha.42",
"@koa/router": "8.0.8",
"@sentry/node": "6.17.7",
"@techpass/passport-openidconnect": "0.3.2",
diff --git a/packages/worker/src/api/controllers/global/users.ts b/packages/worker/src/api/controllers/global/users.ts
index 8db2d29691..d9ebc87517 100644
--- a/packages/worker/src/api/controllers/global/users.ts
+++ b/packages/worker/src/api/controllers/global/users.ts
@@ -424,7 +424,9 @@ export const inviteAccept = async (
if (err.code === ErrorCode.USAGE_LIMIT_EXCEEDED) {
// explicitly re-throw limit exceeded errors
ctx.throw(400, err)
+ return
}
+ console.warn("Error inviting user", err)
ctx.throw(400, "Unable to create new user, invitation invalid.")
}
}
diff --git a/packages/worker/src/api/controllers/system/accounts.ts b/packages/worker/src/api/controllers/system/accounts.ts
index 10b809c0b5..7e6d1b51b8 100644
--- a/packages/worker/src/api/controllers/system/accounts.ts
+++ b/packages/worker/src/api/controllers/system/accounts.ts
@@ -1,7 +1,7 @@
-import { Account, AccountMetadata } from "@budibase/types"
+import { Account, AccountMetadata, Ctx } from "@budibase/types"
import * as accounts from "../../../sdk/accounts"
-export const save = async (ctx: any) => {
+export const save = async (ctx: Ctx) => {
const account = ctx.request.body as Account
let metadata: AccountMetadata = {
_id: accounts.metadata.formatAccountMetadataId(account.accountId),
diff --git a/packages/worker/src/constants/templates/core.hbs b/packages/worker/src/constants/templates/core.hbs
index b7f9658d8c..0b8b8cbde7 100644
--- a/packages/worker/src/constants/templates/core.hbs
+++ b/packages/worker/src/constants/templates/core.hbs
@@ -16,7 +16,8 @@
cellspacing="0"
>
{
diff --git a/qa-core/src/account-api/api/AccountInternalAPIClient.ts b/qa-core/src/account-api/api/AccountInternalAPIClient.ts
index 7438059a8c..df58ab0ce3 100644
--- a/qa-core/src/account-api/api/AccountInternalAPIClient.ts
+++ b/qa-core/src/account-api/api/AccountInternalAPIClient.ts
@@ -8,6 +8,7 @@ interface ApiOptions {
method?: APIMethod
body?: object
headers?: HeadersInit | undefined
+ internal?: boolean
}
export default class AccountInternalAPIClient {
@@ -18,6 +19,9 @@ export default class AccountInternalAPIClient {
if (!env.ACCOUNT_PORTAL_URL) {
throw new Error("Must set ACCOUNT_PORTAL_URL env var")
}
+ if (!env.ACCOUNT_PORTAL_API_KEY) {
+ throw new Error("Must set ACCOUNT_PORTAL_API_KEY env var")
+ }
this.host = `${env.ACCOUNT_PORTAL_URL}`
this.state = state
}
@@ -39,6 +43,13 @@ export default class AccountInternalAPIClient {
credentials: "include",
}
+ if (options.internal) {
+ requestOptions.headers = {
+ ...requestOptions.headers,
+ ...{ "x-budibase-api-key": env.ACCOUNT_PORTAL_API_KEY },
+ }
+ }
+
// @ts-ignore
const response = await fetch(`${this.host}${url}`, requestOptions)
@@ -50,15 +61,20 @@ export default class AccountInternalAPIClient {
body = await response.text()
}
- const message = `${method} ${url} - ${response.status}
- Response body: ${JSON.stringify(body)}
- Request body: ${requestOptions.body}`
+ const data = {
+ request: requestOptions.body,
+ response: body,
+ }
+ const message = `${method} ${url} - ${response.status}`
if (response.status > 499) {
- console.error(message)
+ console.error(message, data)
} else if (response.status >= 400) {
- console.warn(message)
+ console.warn(message, data)
+ } else {
+ console.debug(message, data)
}
+
return [response, body]
}
diff --git a/qa-core/src/account-api/api/apis/LicenseAPI.ts b/qa-core/src/account-api/api/apis/LicenseAPI.ts
index 080c22a4ff..f726eb5682 100644
--- a/qa-core/src/account-api/api/apis/LicenseAPI.ts
+++ b/qa-core/src/account-api/api/apis/LicenseAPI.ts
@@ -1,4 +1,6 @@
import AccountInternalAPIClient from "../AccountInternalAPIClient"
+import { Account, UpdateLicenseRequest } from "@budibase/types"
+import { Response } from "node-fetch"
export default class LicenseAPI {
client: AccountInternalAPIClient
@@ -6,4 +8,18 @@ export default class LicenseAPI {
constructor(client: AccountInternalAPIClient) {
this.client = client
}
+
+ async updateLicense(
+ accountId: string,
+ body: UpdateLicenseRequest
+ ): Promise<[Response, Account]> {
+ const [response, json] = await this.client.put(
+ `/api/accounts/${accountId}/license`,
+ {
+ body,
+ internal: true,
+ }
+ )
+ return [response, json]
+ }
}
diff --git a/qa-core/src/environment.ts b/qa-core/src/environment.ts
index 9377461a24..0257b10831 100644
--- a/qa-core/src/environment.ts
+++ b/qa-core/src/environment.ts
@@ -11,8 +11,23 @@ if (!LOADED) {
const env = {
BUDIBASE_URL: process.env.BUDIBASE_URL,
ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL,
+ ACCOUNT_PORTAL_API_KEY: process.env.ACCOUNT_PORTAL_API_KEY,
BB_ADMIN_USER_EMAIL: process.env.BB_ADMIN_USER_EMAIL,
BB_ADMIN_USER_PASSWORD: process.env.BB_ADMIN_USER_PASSWORD,
+ POSTGRES_HOST: process.env.POSTGRES_HOST,
+ POSTGRES_PORT: process.env.POSTGRES_PORT,
+ POSTGRES_DB: process.env.POSTGRES_DB,
+ POSTGRES_USER: process.env.POSTGRES_USER,
+ POSTGRES_PASSWORD: process.env.POSTGRES_PASSWORD,
+ MONGODB_CONNECTION_STRING: process.env.MONGODB_CONNECTION_STRING,
+ MONGODB_DB: process.env.MONGODB_DB,
+ REST_API_BASE_URL: process.env.REST_API_BASE_URL,
+ REST_API_KEY: process.env.REST_API_KEY,
+ MARIADB_HOST: process.env.MARIADB_HOST,
+ MARIADB_PORT: process.env.MARIADB_PORT,
+ MARIADB_DB: process.env.MARIADB_DB,
+ MARIADB_USER: process.env.MARIADB_USER,
+ MARIADB_PASSWORD: process.env.MARIADB_PASSWORD,
}
export = env
diff --git a/qa-core/src/internal-api/api/BudibaseInternalAPI.ts b/qa-core/src/internal-api/api/BudibaseInternalAPI.ts
index 5bb6b72ef0..316775b1b9 100644
--- a/qa-core/src/internal-api/api/BudibaseInternalAPI.ts
+++ b/qa-core/src/internal-api/api/BudibaseInternalAPI.ts
@@ -7,6 +7,10 @@ import ScreenAPI from "./apis/ScreenAPI"
import SelfAPI from "./apis/SelfAPI"
import TableAPI from "./apis/TableAPI"
import UserAPI from "./apis/UserAPI"
+import DatasourcesAPI from "./apis/DatasourcesAPI"
+import IntegrationsAPI from "./apis/IntegrationsAPI"
+import QueriesAPI from "./apis/QueriesAPI"
+import PermissionsAPI from "./apis/PermissionsAPI"
import BudibaseInternalAPIClient from "./BudibaseInternalAPIClient"
import { State } from "../../types"
@@ -22,6 +26,10 @@ export default class BudibaseInternalAPI {
self: SelfAPI
tables: TableAPI
users: UserAPI
+ datasources: DatasourcesAPI
+ integrations: IntegrationsAPI
+ queries: QueriesAPI
+ permissions: PermissionsAPI
constructor(state: State) {
this.client = new BudibaseInternalAPIClient(state)
@@ -35,5 +43,9 @@ export default class BudibaseInternalAPI {
this.self = new SelfAPI(this.client)
this.tables = new TableAPI(this.client)
this.users = new UserAPI(this.client)
+ this.datasources = new DatasourcesAPI(this.client)
+ this.integrations = new IntegrationsAPI(this.client)
+ this.queries = new QueriesAPI(this.client)
+ this.permissions = new PermissionsAPI(this.client)
}
}
diff --git a/qa-core/src/internal-api/api/BudibaseInternalAPIClient.ts b/qa-core/src/internal-api/api/BudibaseInternalAPIClient.ts
index ab6c5f065e..a6921a75b2 100644
--- a/qa-core/src/internal-api/api/BudibaseInternalAPIClient.ts
+++ b/qa-core/src/internal-api/api/BudibaseInternalAPIClient.ts
@@ -18,7 +18,6 @@ class BudibaseInternalAPIClient {
if (!env.BUDIBASE_URL) {
throw new Error("Must set BUDIBASE_URL env var")
}
- this.host = `${env.ACCOUNT_PORTAL_URL}/api`
this.host = `${env.BUDIBASE_URL}/api`
this.state = state
}
@@ -53,14 +52,18 @@ class BudibaseInternalAPIClient {
body = await response.text()
}
- const message = `${method} ${url} - ${response.status}
- Response body: ${JSON.stringify(body)}
- Request body: ${requestOptions.body}`
+ const data = {
+ request: requestOptions.body,
+ response: body,
+ }
+ const message = `${method} ${url} - ${response.status}`
if (response.status > 499) {
- console.error(message)
+ console.error(message, data)
} else if (response.status >= 400) {
- console.warn(message)
+ console.warn(message, data)
+ } else {
+ console.debug(message, data)
}
return [response, body]
diff --git a/qa-core/src/internal-api/api/apis/DatasourcesAPI.ts b/qa-core/src/internal-api/api/apis/DatasourcesAPI.ts
new file mode 100644
index 0000000000..f29bb9d6bc
--- /dev/null
+++ b/qa-core/src/internal-api/api/apis/DatasourcesAPI.ts
@@ -0,0 +1,95 @@
+import { Response } from "node-fetch"
+import {
+ Datasource,
+ CreateDatasourceResponse,
+ UpdateDatasourceResponse,
+} from "@budibase/types"
+import BudibaseInternalAPIClient from "../BudibaseInternalAPIClient"
+
+export default class DatasourcesAPI {
+ client: BudibaseInternalAPIClient
+
+ constructor(client: BudibaseInternalAPIClient) {
+ this.client = client
+ }
+
+ async getIntegrations(): Promise<[Response, any]> {
+ const [response, json] = await this.client.get(`/integrations`)
+ expect(response).toHaveStatusCode(200)
+ const integrationsCount = Object.keys(json).length
+ expect(integrationsCount).toBe(16)
+ return [response, json]
+ }
+
+ async getAll(): Promise<[Response, Datasource[]]> {
+ const [response, json] = await this.client.get(`/datasources`)
+ expect(response).toHaveStatusCode(200)
+ expect(json.length).toBeGreaterThan(0)
+ return [response, json]
+ }
+
+ async getTable(dataSourceId: string): Promise<[Response, Datasource]> {
+ const [response, json] = await this.client.get(
+ `/datasources/${dataSourceId}`
+ )
+ expect(response).toHaveStatusCode(200)
+ expect(json._id).toEqual(dataSourceId)
+ return [response, json]
+ }
+
+ async add(body: any): Promise<[Response, CreateDatasourceResponse]> {
+ const [response, json] = await this.client.post(`/datasources`, { body })
+ expect(response).toHaveStatusCode(200)
+ expect(json.datasource._id).toBeDefined()
+ expect(json.datasource._rev).toBeDefined()
+
+ return [response, json]
+ }
+
+ async update(body: any): Promise<[Response, UpdateDatasourceResponse]> {
+ const [response, json] = await this.client.put(`/datasources/${body._id}`, {
+ body,
+ })
+ expect(response).toHaveStatusCode(200)
+ expect(json.datasource._id).toBeDefined()
+ expect(json.datasource._rev).toBeDefined()
+
+ return [response, json]
+ }
+
+ async previewQuery(body: any): Promise<[Response, any]> {
+ const [response, json] = await this.client.post(`/queries/preview`, {
+ body,
+ })
+ expect(response).toHaveStatusCode(200)
+ return [response, json]
+ }
+
+ async saveQuery(body: any): Promise<[Response, any]> {
+ const [response, json] = await this.client.post(`/queries`, {
+ body,
+ })
+ expect(response).toHaveStatusCode(200)
+ return [response, json]
+ }
+
+ async getQuery(queryId: string): Promise<[Response, any]> {
+ const [response, json] = await this.client.get(`/queries/${queryId}`)
+ expect(response).toHaveStatusCode(200)
+ return [response, json]
+ }
+
+ async getQueryPermissions(queryId: string): Promise<[Response, any]> {
+ const [response, json] = await this.client.get(`/permissions/${queryId}`)
+ expect(response).toHaveStatusCode(200)
+ return [response, json]
+ }
+
+ async delete(dataSourceId: string, revId: string): Promise {
+ const [response, json] = await this.client.del(
+ `/datasources/${dataSourceId}/${revId}`
+ )
+ expect(response).toHaveStatusCode(200)
+ return response
+ }
+}
diff --git a/qa-core/src/internal-api/api/apis/IntegrationsAPI.ts b/qa-core/src/internal-api/api/apis/IntegrationsAPI.ts
new file mode 100644
index 0000000000..2478823bfa
--- /dev/null
+++ b/qa-core/src/internal-api/api/apis/IntegrationsAPI.ts
@@ -0,0 +1,18 @@
+import { Response } from "node-fetch"
+import BudibaseInternalAPIClient from "../BudibaseInternalAPIClient"
+
+export default class IntegrationsAPI {
+ client: BudibaseInternalAPIClient
+
+ constructor(client: BudibaseInternalAPIClient) {
+ this.client = client
+ }
+
+ async getAll(): Promise<[Response, any]> {
+ const [response, json] = await this.client.get(`/integrations`)
+ expect(response).toHaveStatusCode(200)
+ const integrationsCount = Object.keys(json).length
+ expect(integrationsCount).toBeGreaterThan(0)
+ return [response, json]
+ }
+}
diff --git a/qa-core/src/internal-api/api/apis/PermissionsAPI.ts b/qa-core/src/internal-api/api/apis/PermissionsAPI.ts
new file mode 100644
index 0000000000..e78ef7560d
--- /dev/null
+++ b/qa-core/src/internal-api/api/apis/PermissionsAPI.ts
@@ -0,0 +1,16 @@
+import { Response } from "node-fetch"
+import BudibaseInternalAPIClient from "../BudibaseInternalAPIClient"
+
+export default class PermissionsAPI {
+ client: BudibaseInternalAPIClient
+
+ constructor(client: BudibaseInternalAPIClient) {
+ this.client = client
+ }
+
+ async getAll(id: string): Promise<[Response, any]> {
+ const [response, json] = await this.client.get(`/permissions/${id}`)
+ expect(response).toHaveStatusCode(200)
+ return [response, json]
+ }
+}
diff --git a/qa-core/src/internal-api/api/apis/QueriesAPI.ts b/qa-core/src/internal-api/api/apis/QueriesAPI.ts
new file mode 100644
index 0000000000..5c8ac9883e
--- /dev/null
+++ b/qa-core/src/internal-api/api/apis/QueriesAPI.ts
@@ -0,0 +1,33 @@
+import { Response } from "node-fetch"
+import BudibaseInternalAPIClient from "../BudibaseInternalAPIClient"
+import { PreviewQueryRequest, Query } from "@budibase/types"
+
+export default class DatasourcesAPI {
+ client: BudibaseInternalAPIClient
+
+ constructor(client: BudibaseInternalAPIClient) {
+ this.client = client
+ }
+
+ async preview(body: PreviewQueryRequest): Promise<[Response, any]> {
+ const [response, json] = await this.client.post(`/queries/preview`, {
+ body,
+ })
+ expect(response).toHaveStatusCode(200)
+ return [response, json]
+ }
+
+ async save(body: Query): Promise<[Response, any]> {
+ const [response, json] = await this.client.post(`/queries`, {
+ body,
+ })
+ expect(response).toHaveStatusCode(200)
+ return [response, json]
+ }
+
+ async get(queryId: string): Promise<[Response, any]> {
+ const [response, json] = await this.client.get(`/queries/${queryId}`)
+ expect(response).toHaveStatusCode(200)
+ return [response, json]
+ }
+}
diff --git a/qa-core/src/internal-api/fixtures/datasources.ts b/qa-core/src/internal-api/fixtures/datasources.ts
new file mode 100644
index 0000000000..dcf6af824a
--- /dev/null
+++ b/qa-core/src/internal-api/fixtures/datasources.ts
@@ -0,0 +1,71 @@
+// Add information about the data source to the fixtures file from 1password
+export const mongoDB = () => {
+ return {
+ datasource: {
+ name: "MongoDB",
+ source: "MONGODB",
+ type: "datasource",
+ config: {
+ connectionString: process.env.MONGODB_CONNECTION_STRING,
+ db: process.env.MONGODB_DB,
+ },
+ },
+
+ fetchSchema: false,
+ }
+}
+
+export const postgresSQL = () => {
+ return {
+ datasource: {
+ name: "PostgresSQL",
+ plus: true,
+ source: "POSTGRES",
+ type: "datasource",
+ config: {
+ database: process.env.POSTGRES_DB,
+ host: process.env.POSTGRES_HOST,
+ password: process.env.POSTGRES_PASSWORD,
+ port: process.env.POSTGRES_PORT,
+ schema: "public",
+ user: process.env.POSTGRES_USER,
+ },
+ },
+ fetchSchema: true,
+ }
+}
+export const mariaDB = () => {
+ return {
+ datasource: {
+ name: "MariaDB",
+ plus: true,
+ source: "MYSQL",
+ type: "datasource",
+ config: {
+ database: process.env.MARIADB_DB,
+ host: process.env.MARIADB_HOST,
+ password: process.env.MARIADB_PASSWORD,
+ port: process.env.MARIADB_PORT,
+ schema: "public",
+ user: process.env.MARIADB_USER,
+ },
+ },
+ fetchSchema: true,
+ }
+}
+
+export const restAPI = () => {
+ return {
+ datasource: {
+ name: "RestAPI",
+ source: "REST",
+ type: "datasource",
+ config: {
+ defaultHeaders: {},
+ rejectUnauthorized: true,
+ url: process.env.REST_API_BASE_URL,
+ },
+ },
+ fetchSchema: false,
+ }
+}
diff --git a/qa-core/src/internal-api/fixtures/index.ts b/qa-core/src/internal-api/fixtures/index.ts
index d97c5f76b7..38291052b8 100644
--- a/qa-core/src/internal-api/fixtures/index.ts
+++ b/qa-core/src/internal-api/fixtures/index.ts
@@ -4,3 +4,5 @@ export * as rows from "./rows"
export * as screens from "./screens"
export * as tables from "./tables"
export * as users from "./users"
+export * as datasources from "./datasources"
+export * as queries from "./queries"
diff --git a/qa-core/src/internal-api/fixtures/queries.ts b/qa-core/src/internal-api/fixtures/queries.ts
new file mode 100644
index 0000000000..83839a0b41
--- /dev/null
+++ b/qa-core/src/internal-api/fixtures/queries.ts
@@ -0,0 +1,123 @@
+import { PreviewQueryRequest } from "@budibase/types"
+
+const query = (datasourceId: string, fields: any): any => {
+ return {
+ datasourceId: datasourceId,
+ fields: fields,
+ name: "Query 1",
+ parameters: {},
+ queryVerb: "read",
+ schema: {},
+ transformer: "return data",
+ }
+}
+
+export const mariaDB = (datasourceId: string): PreviewQueryRequest => {
+ const fields = {
+ sql: "SELECT * FROM employees LIMIT 10;",
+ }
+ return query(datasourceId, fields)
+}
+
+export const mongoDB = (datasourceId: string): PreviewQueryRequest => {
+ const fields = {
+ extra: {
+ collection: "movies",
+ actionType: "find",
+ },
+ json: "",
+ }
+ return query(datasourceId, fields)
+}
+
+export const postgres = (datasourceId: string): PreviewQueryRequest => {
+ const fields = {
+ sql: "SELECT * FROM customers;",
+ }
+ return query(datasourceId, fields)
+}
+
+export const expectedSchemaFields = {
+ mariaDB: {
+ birth_date: "string",
+ emp_no: "number",
+ first_name: "string",
+ gender: "string",
+ hire_date: "string",
+ last_name: "string",
+ },
+ mongoDB: {
+ directors: "array",
+ genres: "array",
+ image: "string",
+ plot: "string",
+ rank: "number",
+ rating: "number",
+ release_date: "string",
+ running_time_secs: "number",
+ title: "string",
+ year: "number",
+ _id: "json",
+ },
+ postgres: {
+ address: "string",
+ city: "string",
+ company_name: "string",
+ contact_name: "string",
+ contact_title: "string",
+ country: "string",
+ customer_id: "string",
+ fax: "string",
+ phone: "string",
+ postal_code: "string",
+ region: "string",
+ },
+ restAPI: {
+ abilities: "array",
+ base_experience: "number",
+ forms: "array",
+ game_indices: "array",
+ height: "number",
+ held_items: "array",
+ id: "number",
+ is_default: "string",
+ location_area_encounters: "string",
+ moves: "array",
+ name: "string",
+ order: "number",
+ past_types: "array",
+ species: "json",
+ sprites: "json",
+ stats: "array",
+ types: "array",
+ weight: "number",
+ },
+}
+
+const request = (datasourceId: string, fields: any, flags: any): any => {
+ return {
+ datasourceId: datasourceId,
+ fields: fields,
+ flags: flags,
+ name: "Query 1",
+ parameters: {},
+ queryVerb: "read",
+ schema: {},
+ transformer: "return data",
+ }
+}
+export const restAPI = (datasourceId: string): PreviewQueryRequest => {
+ const fields = {
+ authConfigId: null,
+ bodyType: "none",
+ disabledHeaders: {},
+ headers: {},
+ pagination: {},
+ path: `${process.env.REST_API_BASE_URL}/pokemon/ditto`,
+ queryString: "",
+ }
+ const flags = {
+ urlName: true,
+ }
+ return request(datasourceId, fields, flags)
+}
diff --git a/qa-core/src/internal-api/tests/dataSources/example.spec.ts b/qa-core/src/internal-api/tests/dataSources/example.spec.ts
deleted file mode 100644
index 0b8bc38a45..0000000000
--- a/qa-core/src/internal-api/tests/dataSources/example.spec.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import TestConfiguration from "../../config/TestConfiguration"
-import * as fixtures from "../../fixtures"
-
-describe("Internal API - Data Sources", () => {
- const config = new TestConfiguration()
-
- beforeAll(async () => {
- await config.beforeAll()
- })
-
- afterAll(async () => {
- await config.afterAll()
- })
-
- it("Create an app with a data source", async () => {
- // Create app
- await config.createApp()
-
- // Create Screen
- const roleArray = ["BASIC", "POWER", "ADMIN", "PUBLIC"]
- for (let role in roleArray) {
- const [response, screen] = await config.api.screens.create(
- fixtures.screens.generateScreen(roleArray[role])
- )
- }
- })
-})
diff --git a/qa-core/src/internal-api/tests/dataSources/mariaDB.spec.ts b/qa-core/src/internal-api/tests/dataSources/mariaDB.spec.ts
new file mode 100644
index 0000000000..44c2c03c8b
--- /dev/null
+++ b/qa-core/src/internal-api/tests/dataSources/mariaDB.spec.ts
@@ -0,0 +1,69 @@
+import TestConfiguration from "../../config/TestConfiguration"
+import * as fixtures from "../../fixtures"
+import { Query } from "@budibase/types"
+
+describe("Internal API - Data Sources: MariaDB", () => {
+ const config = new TestConfiguration()
+
+ beforeAll(async () => {
+ await config.beforeAll()
+ })
+
+ afterAll(async () => {
+ await config.afterAll()
+ })
+
+ it("Create an app with a data source - MariaDB", async () => {
+ // Create app
+ await config.createApp()
+
+ // Get all integrations
+ await config.api.integrations.getAll()
+
+ // Add data source
+ const [dataSourceResponse, dataSourceJson] =
+ await config.api.datasources.add(fixtures.datasources.mariaDB())
+
+ // Update data source
+ const newDataSourceInfo = {
+ ...dataSourceJson.datasource,
+ name: "MariaDB2",
+ }
+ const [updatedDataSourceResponse, updatedDataSourceJson] =
+ await config.api.datasources.update(newDataSourceInfo)
+
+ // Query data source
+ const [queryResponse, queryJson] = await config.api.queries.preview(
+ fixtures.queries.mariaDB(updatedDataSourceJson.datasource._id!)
+ )
+
+ expect(queryJson.rows.length).toEqual(10)
+ expect(queryJson.schemaFields).toEqual(
+ fixtures.queries.expectedSchemaFields.mariaDB
+ )
+
+ // Save query
+ const datasourcetoSave: Query = {
+ ...fixtures.queries.mariaDB(updatedDataSourceJson.datasource._id!),
+ parameters: [],
+ }
+
+ const [saveQueryResponse, saveQueryJson] = await config.api.queries.save(
+ datasourcetoSave
+ )
+ // Get Query
+ const [getQueryResponse, getQueryJson] = await config.api.queries.get(
+ saveQueryJson._id
+ )
+
+ // Get Query permissions
+ const [getQueryPermissionsResponse, getQueryPermissionsJson] =
+ await config.api.permissions.getAll(saveQueryJson._id!)
+
+ // Delete data source
+ const deleteResponse = await config.api.datasources.delete(
+ updatedDataSourceJson.datasource._id!,
+ updatedDataSourceJson.datasource._rev!
+ )
+ })
+})
diff --git a/qa-core/src/internal-api/tests/dataSources/mongoDB.spec.ts b/qa-core/src/internal-api/tests/dataSources/mongoDB.spec.ts
new file mode 100644
index 0000000000..ed5178b57c
--- /dev/null
+++ b/qa-core/src/internal-api/tests/dataSources/mongoDB.spec.ts
@@ -0,0 +1,69 @@
+import TestConfiguration from "../../config/TestConfiguration"
+import * as fixtures from "../../fixtures"
+import { Query } from "@budibase/types"
+
+describe("Internal API - Data Sources: MongoDB", () => {
+ const config = new TestConfiguration()
+
+ beforeAll(async () => {
+ await config.beforeAll()
+ })
+
+ afterAll(async () => {
+ await config.afterAll()
+ })
+
+ it("Create an app with a data source - MongoDB", async () => {
+ // Create app
+ await config.createApp()
+
+ // Get all integrations
+ await config.api.integrations.getAll()
+
+ // Add data source
+ const [dataSourceResponse, dataSourceJson] =
+ await config.api.datasources.add(fixtures.datasources.mongoDB())
+
+ // Update data source
+ const newDataSourceInfo = {
+ ...dataSourceJson.datasource,
+ name: "MongoDB2",
+ }
+ const [updatedDataSourceResponse, updatedDataSourceJson] =
+ await config.api.datasources.update(newDataSourceInfo)
+
+ // Query data source
+ const [queryResponse, queryJson] = await config.api.queries.preview(
+ fixtures.queries.mongoDB(updatedDataSourceJson.datasource._id!)
+ )
+
+ expect(queryJson.rows.length).toBeGreaterThan(10)
+ expect(queryJson.schemaFields).toEqual(
+ fixtures.queries.expectedSchemaFields.mongoDB
+ )
+
+ // Save query
+ const datasourcetoSave: Query = {
+ ...fixtures.queries.mongoDB(updatedDataSourceJson.datasource._id!),
+ parameters: [],
+ }
+
+ const [saveQueryResponse, saveQueryJson] = await config.api.queries.save(
+ datasourcetoSave
+ )
+ // Get Query
+ const [getQueryResponse, getQueryJson] = await config.api.queries.get(
+ saveQueryJson._id
+ )
+
+ // Get Query permissions
+ const [getQueryPermissionsResponse, getQueryPermissionsJson] =
+ await config.api.permissions.getAll(saveQueryJson._id!)
+
+ // Delete data source
+ const deleteResponse = await config.api.datasources.delete(
+ updatedDataSourceJson.datasource._id!,
+ updatedDataSourceJson.datasource._rev!
+ )
+ })
+})
diff --git a/qa-core/src/internal-api/tests/dataSources/postgresSQL.spec.ts b/qa-core/src/internal-api/tests/dataSources/postgresSQL.spec.ts
new file mode 100644
index 0000000000..bc8d86b862
--- /dev/null
+++ b/qa-core/src/internal-api/tests/dataSources/postgresSQL.spec.ts
@@ -0,0 +1,69 @@
+import TestConfiguration from "../../config/TestConfiguration"
+import * as fixtures from "../../fixtures"
+import { Query } from "@budibase/types"
+
+describe("Internal API - Data Sources: PostgresSQL", () => {
+ const config = new TestConfiguration()
+
+ beforeAll(async () => {
+ await config.beforeAll()
+ })
+
+ afterAll(async () => {
+ await config.afterAll()
+ })
+
+ it("Create an app with a data source - PostgresSQL", async () => {
+ // Create app
+ await config.createApp()
+
+ // Get all integrations
+ await config.api.integrations.getAll()
+
+ // Add data source
+ const [dataSourceResponse, dataSourceJson] =
+ await config.api.datasources.add(fixtures.datasources.postgresSQL())
+
+ // Update data source
+ const newDataSourceInfo = {
+ ...dataSourceJson.datasource,
+ name: "PostgresSQL2",
+ }
+ const [updatedDataSourceResponse, updatedDataSourceJson] =
+ await config.api.datasources.update(newDataSourceInfo)
+
+ // Query data source
+ const [queryResponse, queryJson] = await config.api.queries.preview(
+ fixtures.queries.postgres(updatedDataSourceJson.datasource._id!)
+ )
+
+ expect(queryJson.rows.length).toEqual(91)
+ expect(queryJson.schemaFields).toEqual(
+ fixtures.queries.expectedSchemaFields.postgres
+ )
+
+ // Save query
+ const datasourcetoSave: Query = {
+ ...fixtures.queries.postgres(updatedDataSourceJson.datasource._id!),
+ parameters: [],
+ }
+
+ const [saveQueryResponse, saveQueryJson] = await config.api.queries.save(
+ datasourcetoSave
+ )
+ // Get Query
+ const [getQueryResponse, getQueryJson] = await config.api.queries.get(
+ saveQueryJson._id!
+ )
+
+ // Get Query permissions
+ const [getQueryPermissionsResponse, getQueryPermissionsJson] =
+ await config.api.permissions.getAll(saveQueryJson._id!)
+
+ // Delete data source
+ const deleteResponse = await config.api.datasources.delete(
+ updatedDataSourceJson.datasource._id!,
+ updatedDataSourceJson.datasource._rev!
+ )
+ })
+})
diff --git a/qa-core/src/internal-api/tests/dataSources/restAPI.spec.ts b/qa-core/src/internal-api/tests/dataSources/restAPI.spec.ts
new file mode 100644
index 0000000000..d7b75db514
--- /dev/null
+++ b/qa-core/src/internal-api/tests/dataSources/restAPI.spec.ts
@@ -0,0 +1,69 @@
+import TestConfiguration from "../../config/TestConfiguration"
+import * as fixtures from "../../fixtures"
+import { Query } from "@budibase/types"
+
+describe("Internal API - Data Sources: REST API", () => {
+ const config = new TestConfiguration()
+
+ beforeAll(async () => {
+ await config.beforeAll()
+ })
+
+ afterAll(async () => {
+ await config.afterAll()
+ })
+
+ it("Create an app with a data source - REST API", async () => {
+ // Create app
+ await config.createApp()
+
+ // Get all integrations
+ await config.api.integrations.getAll()
+
+ // Add data source
+ const [dataSourceResponse, dataSourceJson] =
+ await config.api.datasources.add(fixtures.datasources.restAPI())
+
+ // Update data source
+ const newDataSourceInfo = {
+ ...dataSourceJson.datasource,
+ name: "RestAPI - Updated",
+ }
+ const [updatedDataSourceResponse, updatedDataSourceJson] =
+ await config.api.datasources.update(newDataSourceInfo)
+
+ // Query data source
+ const [queryResponse, queryJson] = await config.api.queries.preview(
+ fixtures.queries.restAPI(updatedDataSourceJson.datasource._id!)
+ )
+
+ expect(queryJson.rows.length).toEqual(1)
+ expect(queryJson.schemaFields).toEqual(
+ fixtures.queries.expectedSchemaFields.restAPI
+ )
+
+ // Save query
+ const datasourcetoSave: Query = {
+ ...fixtures.queries.postgres(updatedDataSourceJson.datasource._id!),
+ parameters: [],
+ }
+
+ const [saveQueryResponse, saveQueryJson] = await config.api.queries.save(
+ datasourcetoSave
+ )
+ // Get Query
+ const [getQueryResponse, getQueryJson] = await config.api.queries.get(
+ saveQueryJson._id!
+ )
+
+ // Get Query permissions
+ const [getQueryPermissionsResponse, getQueryPermissionsJson] =
+ await config.api.permissions.getAll(saveQueryJson._id!)
+
+ // Delete data source
+ const deleteResponse = await config.api.datasources.delete(
+ updatedDataSourceJson.datasource._id!,
+ updatedDataSourceJson.datasource._rev!
+ )
+ })
+})
diff --git a/qa-core/src/jest/globalSetup.ts b/qa-core/src/jest/globalSetup.ts
index a25c483173..e222e7c043 100644
--- a/qa-core/src/jest/globalSetup.ts
+++ b/qa-core/src/jest/globalSetup.ts
@@ -1,8 +1,8 @@
+import { DEFAULT_TENANT_ID, logging } from "@budibase/backend-core"
import { AccountInternalAPI } from "../account-api"
import * as fixtures from "../internal-api/fixtures"
import { BudibaseInternalAPI } from "../internal-api"
-import { DEFAULT_TENANT_ID, logging } from "@budibase/backend-core"
-import { CreateAccountRequest } from "@budibase/types"
+import { CreateAccountRequest, Feature } from "@budibase/types"
import env from "../environment"
import { APIRequestOpts } from "../types"
@@ -22,10 +22,35 @@ async function createAccount() {
const account = fixtures.accounts.generateAccount()
await accountsApi.accounts.validateEmail(account.email, API_OPTS)
await accountsApi.accounts.validateTenantId(account.tenantId, API_OPTS)
- await accountsApi.accounts.create(account, API_OPTS)
+ const [res, newAccount] = await accountsApi.accounts.create(account, API_OPTS)
+ await updateLicense(newAccount.accountId)
return account
}
+const UNLIMITED = { value: -1 }
+
+async function updateLicense(accountId: string) {
+ await accountsApi.licenses.updateLicense(accountId, {
+ overrides: {
+ // add all features
+ features: Object.values(Feature),
+ quotas: {
+ usage: {
+ monthly: {
+ automations: UNLIMITED,
+ },
+ static: {
+ rows: UNLIMITED,
+ users: UNLIMITED,
+ userGroups: UNLIMITED,
+ plugins: UNLIMITED,
+ },
+ },
+ },
+ },
+ })
+}
+
async function loginAsAdmin() {
const username = env.BB_ADMIN_USER_EMAIL!
const password = env.BB_ADMIN_USER_PASSWORD!
diff --git a/qa-core/src/jest/jestSetup.ts b/qa-core/src/jest/jestSetup.ts
index 7f0aeddaa3..5c86d5fd24 100644
--- a/qa-core/src/jest/jestSetup.ts
+++ b/qa-core/src/jest/jestSetup.ts
@@ -1 +1,4 @@
+import { logging } from "@budibase/backend-core"
+logging.LOG_CONTEXT = false
+
jest.setTimeout(60000)
diff --git a/qa-core/src/public-api/api/BudibasePublicAPIClient.ts b/qa-core/src/public-api/api/BudibasePublicAPIClient.ts
index d5fd6b9ef4..f4fe978812 100644
--- a/qa-core/src/public-api/api/BudibasePublicAPIClient.ts
+++ b/qa-core/src/public-api/api/BudibasePublicAPIClient.ts
@@ -51,14 +51,18 @@ class BudibasePublicAPIClient {
body = await response.text()
}
- const message = `${method} ${url} - ${response.status}
- Response body: ${JSON.stringify(body)}
- Request body: ${requestOptions.body}`
+ const data = {
+ request: requestOptions.body,
+ response: body,
+ }
+ const message = `${method} ${url} - ${response.status}`
if (response.status > 499) {
- console.error(message)
+ console.error(message, data)
} else if (response.status >= 400) {
- console.warn(message)
+ console.warn(message, data)
+ } else {
+ console.debug(message, data)
}
return [response, body]
diff --git a/qa-core/src/shared/BudibaseTestConfiguration.ts b/qa-core/src/shared/BudibaseTestConfiguration.ts
index 6adc1bf5c4..12a0f16138 100644
--- a/qa-core/src/shared/BudibaseTestConfiguration.ts
+++ b/qa-core/src/shared/BudibaseTestConfiguration.ts
@@ -3,9 +3,6 @@ import { AccountInternalAPI } from "../account-api"
import { CreateAppRequest, State } from "../types"
import * as fixtures from "../internal-api/fixtures"
-// TEMP
-import setup from "../jest/globalSetup"
-
export default class BudibaseTestConfiguration {
// apis
internalApi: BudibaseInternalAPI
@@ -23,11 +20,6 @@ export default class BudibaseTestConfiguration {
// LIFECYCLE
async beforeAll() {
- // TEMP - move back to single tenant when we integrate licensing with
- // the test run - need to use multiple tenants in cloud to get around
- // app limit restrictions
- await setup()
-
// @ts-ignore
this.state.tenantId = global.qa.tenantId
// @ts-ignore
diff --git a/qa-core/src/types/index.ts b/qa-core/src/types/index.ts
index bc75da46f8..6c3740200c 100644
--- a/qa-core/src/types/index.ts
+++ b/qa-core/src/types/index.ts
@@ -8,6 +8,7 @@ export * from "./responseMessage"
export * from "./routing"
export * from "./state"
export * from "./unpublishAppResponse"
+export * from "./addedDatasource"
// re-export public api types
export * from "@budibase/server/api/controllers/public/mapping/types"
diff --git a/yarn.lock b/yarn.lock
index ed87f491f1..91c6f6b135 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1386,6 +1386,45 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
+"@budibase/backend-core@2.5.6-alpha.26":
+ version "2.5.6-alpha.26"
+ resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.5.6-alpha.26.tgz#72029afe5a85402fa996e92b84ad56cb8c6bde45"
+ integrity sha512-ktP2SWwLjaDzJYLnadU1BcZlrfQkvhRb3T+v1SEciTBWi0vF7MUa7k5OW0EKwECpGA3VA576sbI7FgGu7m7Sxw==
+ dependencies:
+ "@budibase/nano" "10.1.2"
+ "@budibase/pouchdb-replication-stream" "1.2.10"
+ "@budibase/types" "2.5.6-alpha.26"
+ "@shopify/jest-koa-mocks" "5.0.1"
+ "@techpass/passport-openidconnect" "0.3.2"
+ aws-cloudfront-sign "2.2.0"
+ aws-sdk "2.1030.0"
+ bcrypt "5.0.1"
+ bcryptjs "2.4.3"
+ bull "4.10.1"
+ correlation-id "4.0.0"
+ dotenv "16.0.1"
+ emitter-listener "1.1.2"
+ ioredis "4.28.0"
+ joi "17.6.0"
+ jsonwebtoken "9.0.0"
+ koa-passport "4.1.4"
+ koa-pino-logger "4.0.0"
+ lodash "4.17.21"
+ lodash.isarguments "3.1.0"
+ node-fetch "2.6.7"
+ passport-google-oauth "2.0.0"
+ passport-jwt "4.0.0"
+ passport-local "1.0.0"
+ passport-oauth2-refresh "^2.1.0"
+ posthog-node "1.3.0"
+ pouchdb "7.3.0"
+ pouchdb-find "7.2.2"
+ redlock "4.2.0"
+ sanitize-s3-objectkey "0.0.1"
+ semver "7.3.7"
+ tar-fs "2.1.1"
+ uuid "8.3.2"
+
"@budibase/bbui@^0.9.139":
version "0.9.190"
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.190.tgz#e1ec400ac90f556bfbc80fc23a04506f1585ea81"
@@ -1486,15 +1525,15 @@
pouchdb-promise "^6.0.4"
through2 "^2.0.0"
-"@budibase/pro@2.5.6-alpha.28":
- version "2.5.6-alpha.28"
- resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.5.6-alpha.28.tgz#54af46014c08c570ffd4f347cc56c1b9e1226304"
- integrity sha512-12ZGhTXoZRCmVbxHcOO78aOuAml7S3/NGy063c3ZQUyPJoAi3O+rokj0yDb0t7TAgs06gkiiFUumMhWn35Jaxw==
+"@budibase/pro@2.5.6-alpha.42":
+ version "2.5.6-alpha.42"
+ resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.5.6-alpha.42.tgz#15ec86d9918b7d58e3236240afda31309f3162ae"
+ integrity sha512-aes19IVAEGqf0YPLJMnOKHv99AR6LO8jMpPVCbSZcZODS3byxh9kC2+sWH1mAd781zymyN79HnwGrVJNOdV8jw==
dependencies:
- "@budibase/backend-core" "2.5.6-alpha.28"
+ "@budibase/backend-core" "2.5.6-alpha.42"
"@budibase/shared-core" "2.4.44-alpha.1"
"@budibase/string-templates" "2.4.44-alpha.1"
- "@budibase/types" "2.5.6-alpha.28"
+ "@budibase/types" "2.5.6-alpha.42"
"@koa/router" "8.0.8"
bull "4.10.1"
joi "17.6.0"
@@ -1547,6 +1586,13 @@
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.44-alpha.1.tgz#1679657aa180d9c59afa1dffa611bff0638bd933"
integrity sha512-Sq+8HfM75EBMoOvKYFwELdlxmVN6wNZMofDjT/2G+9aF+Zfe5Tzw69C+unmdBgcGGjGCHEYWSz4mF0v8FPAGbg==
+"@budibase/types@2.5.6-alpha.26":
+ version "2.5.6-alpha.26"
+ resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.5.6-alpha.26.tgz#09ac8f1e4f4dfd5e7e109839cd9db36d5c563dc4"
+ integrity sha512-C1eHWj4tRwsQb2dJbMdukxRFVqiyzRBhwIMuCSIdJg763sbn9TXTqWTBbljyG7ppH+Dwge+py9KtiFP2MpMCfQ==
+ dependencies:
+ scim-patch "^0.7.0"
+
"@bull-board/api@3.7.0":
version "3.7.0"
resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-3.7.0.tgz#231f687187c0cb34e0b97f463917b6aaeb4ef6af"
@@ -3007,7 +3053,7 @@
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
-"@jridgewell/sourcemap-codec@^1.4.10":
+"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13":
version "1.4.15"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
@@ -3717,7 +3763,7 @@
dependencies:
slash "^3.0.0"
-"@rollup/plugin-commonjs@^16.0.0":
+"@rollup/plugin-commonjs@16.0.0", "@rollup/plugin-commonjs@^16.0.0":
version "16.0.0"
resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz#169004d56cd0f0a1d0f35915d31a036b0efe281f"
integrity sha512-LuNyypCP3msCGVQJ7ki8PqYdpjfEkE/xtFa5DqlF+7IBD0JsfMZ87C58heSwIMint58sAUZbt3ITqOmdQv/dXw==
@@ -3800,6 +3846,22 @@
"@rollup/pluginutils" "^3.1.0"
magic-string "^0.25.7"
+"@rollup/plugin-replace@^5.0.2":
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-5.0.2.tgz#45f53501b16311feded2485e98419acb8448c61d"
+ integrity sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==
+ dependencies:
+ "@rollup/pluginutils" "^5.0.1"
+ magic-string "^0.27.0"
+
+"@rollup/plugin-typescript@8.3.0":
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-8.3.0.tgz#bc1077fa5897b980fc27e376c4e377882c63e68b"
+ integrity sha512-I5FpSvLbtAdwJ+naznv+B4sjXZUcIvLLceYpITAn7wAP8W0wqc5noLdGIp9HGVntNhRWXctwPYrSSFQxtl0FPA==
+ dependencies:
+ "@rollup/pluginutils" "^3.1.0"
+ resolve "^1.17.0"
+
"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
@@ -11129,7 +11191,7 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
-fast-redact@^3.0.0:
+fast-redact@^3.0.0, fast-redact@^3.1.1:
version "3.1.2"
resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa"
integrity sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==
@@ -11698,7 +11760,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
-fsevents@^2.1.2, fsevents@^2.3.2, fsevents@~2.3.2:
+fsevents@^2.1.2, fsevents@^2.3.2, fsevents@~2.3.1, fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@@ -16688,6 +16750,13 @@ magic-string@^0.26.2:
dependencies:
sourcemap-codec "^1.4.8"
+magic-string@^0.27.0:
+ version "0.27.0"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3"
+ integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==
+ dependencies:
+ "@jridgewell/sourcemap-codec" "^1.4.13"
+
make-dir@3.1.0, make-dir@^3.0.0, make-dir@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
@@ -19203,7 +19272,7 @@ pinkie@^2.0.0:
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==
-pino-abstract-transport@^1.0.0:
+pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3"
integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==
@@ -19219,6 +19288,16 @@ pino-abstract-transport@v0.5.0:
duplexify "^4.1.2"
split2 "^4.0.0"
+pino-http@8.3.3:
+ version "8.3.3"
+ resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-8.3.3.tgz#2b140e734bfc6babe0df272a43bb8f36f2b525c0"
+ integrity sha512-p4umsNIXXVu95HD2C8wie/vXH7db5iGRpc+yj1/ZQ3sRtTQLXNjoS6Be5+eI+rQbqCRxen/7k/KSN+qiZubGDw==
+ dependencies:
+ get-caller-file "^2.0.5"
+ pino "^8.0.0"
+ pino-std-serializers "^6.0.0"
+ process-warning "^2.0.0"
+
pino-http@^6.5.0:
version "6.6.0"
resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-6.6.0.tgz#d0a1deacada8c93327fdaa48f5bdc94bc43d3407"
@@ -19264,7 +19343,42 @@ pino-std-serializers@^5.0.0:
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-5.6.0.tgz#31b141155d6520967c5ec72944d08fb45c490fd3"
integrity sha512-VdUXCw8gO+xhir7sFuoYSjTnzB+TMDGxhAC/ph3YS3sdHnXNdsK0wMtADNUltfeGkn2KDxEM21fnjF3RwXyC8A==
-pino@7.11.0, pino@^7.5.0:
+pino-std-serializers@^6.0.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.2.0.tgz#169048c0df3f61352fce56aeb7fb962f1b66ab43"
+ integrity sha512-IWgSzUL8X1w4BIWTwErRgtV8PyOGOOi60uqv0oKuS/fOA8Nco/OeI6lBuc4dyP8MMfdFwyHqTMcBIA7nDiqEqA==
+
+pino@8.11.0, pino@^8.0.0:
+ version "8.11.0"
+ resolved "https://registry.yarnpkg.com/pino/-/pino-8.11.0.tgz#2a91f454106b13e708a66c74ebc1c2ab7ab38498"
+ integrity sha512-Z2eKSvlrl2rH8p5eveNUnTdd4AjJk8tAsLkHYZQKGHP4WTh2Gi1cOSOs3eWPqaj+niS3gj4UkoreoaWgF3ZWYg==
+ dependencies:
+ atomic-sleep "^1.0.0"
+ fast-redact "^3.1.1"
+ on-exit-leak-free "^2.1.0"
+ pino-abstract-transport v1.0.0
+ pino-std-serializers "^6.0.0"
+ process-warning "^2.0.0"
+ quick-format-unescaped "^4.0.3"
+ real-require "^0.2.0"
+ safe-stable-stringify "^2.3.1"
+ sonic-boom "^3.1.0"
+ thread-stream "^2.0.0"
+
+pino@^6.11.2:
+ version "6.14.0"
+ resolved "https://registry.yarnpkg.com/pino/-/pino-6.14.0.tgz#b745ea87a99a6c4c9b374e4f29ca7910d4c69f78"
+ integrity sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==
+ dependencies:
+ fast-redact "^3.0.0"
+ fast-safe-stringify "^2.0.8"
+ flatstr "^1.0.12"
+ pino-std-serializers "^3.1.0"
+ process-warning "^1.0.0"
+ quick-format-unescaped "^4.0.3"
+ sonic-boom "^1.0.2"
+
+pino@^7.5.0:
version "7.11.0"
resolved "https://registry.yarnpkg.com/pino/-/pino-7.11.0.tgz#0f0ea5c4683dc91388081d44bff10c83125066f6"
integrity sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==
@@ -19281,19 +19395,6 @@ pino@7.11.0, pino@^7.5.0:
sonic-boom "^2.2.1"
thread-stream "^0.15.1"
-pino@^6.11.2:
- version "6.14.0"
- resolved "https://registry.yarnpkg.com/pino/-/pino-6.14.0.tgz#b745ea87a99a6c4c9b374e4f29ca7910d4c69f78"
- integrity sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==
- dependencies:
- fast-redact "^3.0.0"
- fast-safe-stringify "^2.0.8"
- flatstr "^1.0.12"
- pino-std-serializers "^3.1.0"
- process-warning "^1.0.0"
- quick-format-unescaped "^4.0.3"
- sonic-boom "^1.0.2"
-
pirates@^4.0.1, pirates@^4.0.4:
version "4.0.5"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b"
@@ -20169,6 +20270,11 @@ process-warning@^1.0.0:
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616"
integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==
+process-warning@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.2.0.tgz#008ec76b579820a8e5c35d81960525ca64feb626"
+ integrity sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==
+
process@^0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
@@ -20772,6 +20878,11 @@ real-require@^0.1.0:
resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381"
integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==
+real-require@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78"
+ integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==
+
recast@^0.10.1:
version "0.10.43"
resolved "https://registry.yarnpkg.com/recast/-/recast-0.10.43.tgz#b95d50f6d60761a5f6252e15d80678168491ce7f"
@@ -21417,6 +21528,13 @@ rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.5.0, rollup-pluginutils@^2.6.0,
dependencies:
estree-walker "^0.6.1"
+rollup@2.45.2:
+ version "2.45.2"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.45.2.tgz#8fb85917c9f35605720e92328f3ccbfba6f78b48"
+ integrity sha512-kRRU7wXzFHUzBIv0GfoFFIN3m9oteY4uAsKllIpQDId5cfnkWF2J130l+27dzDju0E6MScKiV0ZM5Bw8m4blYQ==
+ optionalDependencies:
+ fsevents "~2.3.1"
+
rollup@^2.36.2, rollup@^2.44.0, rollup@^2.45.2, rollup@^2.79.1:
version "2.79.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7"
@@ -22151,7 +22269,7 @@ sonic-boom@^2.2.1:
dependencies:
atomic-sleep "^1.0.0"
-sonic-boom@^3.0.0:
+sonic-boom@^3.0.0, sonic-boom@^3.1.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.3.0.tgz#cffab6dafee3b2bcb88d08d589394198bee1838c"
integrity sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==
@@ -23323,6 +23441,13 @@ thread-stream@^0.15.1:
dependencies:
real-require "^0.1.0"
+thread-stream@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.3.0.tgz#4fc07fb39eff32ae7bad803cb7dd9598349fed33"
+ integrity sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==
+ dependencies:
+ real-require "^0.2.0"
+
throat@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b"
@@ -23379,7 +23504,7 @@ timed-out@^4.0.1:
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==
-timekeeper@2.2.0:
+timekeeper@2.2.0, timekeeper@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.2.0.tgz#9645731fce9e3280a18614a57a9d1b72af3ca368"
integrity sha512-W3AmPTJWZkRwu+iSNxPIsLZ2ByADsOLbbLxe46UJyWj3mlYLlwucKiq+/dPm0l9wTzqoF3/2PH0AGFCebjq23A==