diff --git a/packages/account-portal b/packages/account-portal
index c24374879d..048c37ecd9 160000
--- a/packages/account-portal
+++ b/packages/account-portal
@@ -1 +1 @@
-Subproject commit c24374879d2b61516fabc24d7404e7da235be05e
+Subproject commit 048c37ecd921340614bf61a76a774aaa46176569
diff --git a/packages/backend-core/src/events/publishers/ai.ts b/packages/backend-core/src/events/publishers/ai.ts
new file mode 100644
index 0000000000..168ac9f796
--- /dev/null
+++ b/packages/backend-core/src/events/publishers/ai.ts
@@ -0,0 +1,21 @@
+import { publishEvent } from "../events"
+import {
+ Event,
+ AIConfigCreatedEvent,
+ AIConfigUpdatedEvent,
+} from "@budibase/types"
+
+async function AIConfigCreated(timestamp?: string | number) {
+ const properties: AIConfigCreatedEvent = {}
+ await publishEvent(Event.AI_CONFIG_CREATED, properties, timestamp)
+}
+
+async function AIConfigUpdated() {
+ const properties: AIConfigUpdatedEvent = {}
+ await publishEvent(Event.AI_CONFIG_UPDATED, properties)
+}
+
+export default {
+ AIConfigCreated,
+ AIConfigUpdated,
+}
diff --git a/packages/backend-core/src/events/publishers/index.ts b/packages/backend-core/src/events/publishers/index.ts
index 87a34bf3f1..9c92b80499 100644
--- a/packages/backend-core/src/events/publishers/index.ts
+++ b/packages/backend-core/src/events/publishers/index.ts
@@ -4,6 +4,7 @@ export { default as auth } from "./auth"
export { default as automation } from "./automation"
export { default as datasource } from "./datasource"
export { default as email } from "./email"
+export { default as ai } from "./ai"
export { default as license } from "./license"
export { default as layout } from "./layout"
export { default as org } from "./org"
diff --git a/packages/backend-core/src/features/index.ts b/packages/backend-core/src/features/index.ts
index 5951bbc292..5b6ea4ca92 100644
--- a/packages/backend-core/src/features/index.ts
+++ b/packages/backend-core/src/features/index.ts
@@ -269,5 +269,6 @@ export const flags = new FlagSet({
DEFAULT_VALUES: Flag.boolean(env.isDev()),
AUTOMATION_BRANCHING: Flag.boolean(env.isDev()),
SQS: Flag.boolean(env.isDev()),
+ [FeatureFlag.AI_CUSTOM_CONFIGS]: Flag.boolean(env.isDev()),
[FeatureFlag.ENRICHED_RELATIONSHIPS]: Flag.boolean(false),
})
diff --git a/packages/backend-core/tests/core/utilities/structures/licenses.ts b/packages/backend-core/tests/core/utilities/structures/licenses.ts
index bb452f9ad5..b4d209a7ee 100644
--- a/packages/backend-core/tests/core/utilities/structures/licenses.ts
+++ b/packages/backend-core/tests/core/utilities/structures/licenses.ts
@@ -55,6 +55,11 @@ export function quotas(): Quotas {
value: 1,
triggers: [],
},
+ budibaseAICredits: {
+ name: "Budibase AI Credits",
+ value: 1,
+ triggers: [],
+ },
},
static: {
rows: {
@@ -87,6 +92,11 @@ export function quotas(): Quotas {
value: 1,
triggers: [],
},
+ aiCustomConfigs: {
+ name: "Plugins",
+ value: 1,
+ triggers: [],
+ },
},
},
constant: {
diff --git a/packages/backend-core/tests/core/utilities/structures/quotas.ts b/packages/backend-core/tests/core/utilities/structures/quotas.ts
index 8d0b05fe1e..58817e4831 100644
--- a/packages/backend-core/tests/core/utilities/structures/quotas.ts
+++ b/packages/backend-core/tests/core/utilities/structures/quotas.ts
@@ -17,6 +17,7 @@ export const usage = (users: number = 0, creators: number = 0): QuotaUsage => {
automations: 0,
dayPasses: 0,
queries: 0,
+ budibaseAICredits: 0,
triggers: {},
breakdown: {
rowQueries: {
@@ -46,12 +47,14 @@ export const usage = (users: number = 0, creators: number = 0): QuotaUsage => {
automations: 0,
dayPasses: 0,
queries: 0,
+ budibaseAICredits: 0,
triggers: {},
},
current: {
automations: 0,
dayPasses: 0,
queries: 0,
+ budibaseAICredits: 0,
triggers: {},
},
},
@@ -62,6 +65,7 @@ export const usage = (users: number = 0, creators: number = 0): QuotaUsage => {
creators,
userGroups: 0,
rows: 0,
+ aiCustomConfigs: 0,
triggers: {},
},
}
diff --git a/packages/builder/package.json b/packages/builder/package.json
index f44c2ea549..f9e6becbab 100644
--- a/packages/builder/package.json
+++ b/packages/builder/package.json
@@ -93,6 +93,7 @@
"identity-obj-proxy": "^3.0.0",
"jest": "29.7.0",
"jsdom": "^21.1.1",
+ "resize-observer-polyfill": "^1.5.1",
"svelte-jester": "^1.3.2",
"vite": "^4.5.0",
"vite-plugin-static-copy": "^0.17.0",
diff --git a/packages/builder/src/pages/builder/portal/settings/ai/AIConfigTile.svelte b/packages/builder/src/pages/builder/portal/settings/ai/AIConfigTile.svelte
new file mode 100644
index 0000000000..2907919ce7
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/settings/ai/AIConfigTile.svelte
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+ {#if config.name !== "Budibase AI"}
+
+
+ {/if}
+ {#if config.active}
+
Activated
+ {:else if !config.active}
+
Disabled
+ {/if}
+ {#if config.isDefault}
+
Default
+ {/if}
+
+
+
+
diff --git a/packages/builder/src/pages/builder/portal/settings/ai/AISettings.spec.js b/packages/builder/src/pages/builder/portal/settings/ai/AISettings.spec.js
new file mode 100644
index 0000000000..805739957b
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/settings/ai/AISettings.spec.js
@@ -0,0 +1,92 @@
+import { it, expect, describe, vi } from "vitest"
+import AISettings from "./index.svelte"
+import { render } from "@testing-library/svelte"
+import { admin, licensing } from "stores/portal"
+
+vi.spyOn(notifications, "error").mockImplementation(vi.fn)
+vi.spyOn(notifications, "success").mockImplementation(vi.fn)
+
+const Hosting = {
+ Cloud: "cloud",
+ Self: "self",
+}
+
+function setupEnv(hosting, features = {}) {
+ const defaultFeatures = {
+ budibaseAIEnabled: false,
+ customAIConfigsEnabled: false,
+ ...features,
+ }
+ admin.subscribe = vi.fn().mockImplementation(callback => {
+ callback({ cloud: hosting === Hosting.Cloud })
+ return () => {}
+ })
+ licensing.subscribe = vi.fn().mockImplementation(callback => {
+ callback(defaultFeatures)
+ return () => {}
+ })
+}
+
+describe("AISettings", () => {
+ let instance = null
+
+ afterEach(() => {
+ vi.restoreAllMocks()
+ })
+
+ it("that the AISettings is rendered", () => {
+ instance = render(AISettings, {})
+ expect(instance).toBeDefined()
+ })
+
+ describe("Licensing", () => {
+ it("should show the premium label on self host for custom configs", async () => {
+ setupEnv(Hosting.Self)
+ instance = render(AISettings, {})
+ const premiumTag = instance.queryByText("Premium")
+ expect(premiumTag).toBeInTheDocument()
+ })
+
+ it("should show the enterprise label on cloud for custom configs", async () => {
+ setupEnv(Hosting.Cloud)
+ instance = render(AISettings, {})
+ const enterpriseTag = instance.queryByText("Enterprise")
+ expect(enterpriseTag).toBeInTheDocument()
+ })
+
+ it("should show the premium label on cloud when Budibase AI isn't enabled", async () => {
+ setupEnv(Hosting.Cloud)
+ instance = render(AISettings, {})
+ const premiumTag = instance.queryByText("Premium")
+ expect(premiumTag).toBeInTheDocument()
+ })
+
+ it("should not show the add configuration button if the user doesn't have the correct license on cloud", async () => {
+ let addConfigurationButton
+
+ setupEnv(Hosting.Cloud)
+ instance = render(AISettings)
+ addConfigurationButton = instance.queryByText("Add configuration")
+ expect(addConfigurationButton).not.toBeInTheDocument()
+
+ setupEnv(Hosting.Cloud, { customAIConfigsEnabled: true })
+ instance = render(AISettings)
+ addConfigurationButton = instance.queryByText("Add configuration")
+ expect(addConfigurationButton).toBeInTheDocument()
+ })
+
+ it("should not show the add configuration button if the user doesn't have the correct license on self host", async () => {
+ let addConfigurationButton
+
+ setupEnv(Hosting.Self)
+ instance = render(AISettings)
+ addConfigurationButton = instance.queryByText("Add configuration")
+ expect(addConfigurationButton).not.toBeInTheDocument()
+
+ setupEnv(Hosting.Self, { customAIConfigsEnabled: true })
+ instance = render(AISettings, {})
+ addConfigurationButton = instance.queryByText("Add configuration")
+ expect(addConfigurationButton).toBeInTheDocument()
+ })
+ })
+})
diff --git a/packages/builder/src/pages/builder/portal/settings/ai/ConfigModal.svelte b/packages/builder/src/pages/builder/portal/settings/ai/ConfigModal.svelte
new file mode 100644
index 0000000000..d480689028
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/settings/ai/ConfigModal.svelte
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#if config.provider !== Providers.Custom.name}
+
+ {:else}
+
+ {/if}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/builder/src/pages/builder/portal/settings/ai/constants.js b/packages/builder/src/pages/builder/portal/settings/ai/constants.js
new file mode 100644
index 0000000000..deb647f90a
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/settings/ai/constants.js
@@ -0,0 +1,60 @@
+export const Providers = {
+ OpenAI: {
+ name: "OpenAI",
+ models: [
+ { label: "GPT 4o Mini", value: "gpt-4o-mini" },
+ { label: "GPT 4o", value: "gpt-4o" },
+ { label: "GPT 4 Turbo", value: "gpt-4-turbo" },
+ { label: "GPT 4", value: "gpt-4" },
+ { label: "GPT 3.5 Turbo", value: "gpt-3.5-turbo" },
+ ],
+ },
+ Anthropic: {
+ name: "Anthropic",
+ models: [
+ { label: "Claude 3.5 Sonnet", value: "claude-3-5-sonnet-20240620" },
+ { label: "Claude 3 Sonnet", value: "claude-3-sonnet-20240229" },
+ { label: "Claude 3 Opus", value: "claude-3-opus-20240229" },
+ { label: "Claude 3 Haiku", value: "claude-3-haiku-20240307" },
+ ],
+ },
+ TogetherAI: {
+ name: "Together AI",
+ models: [{ label: "Llama 3 8B", value: "meta-llama/Meta-Llama-3-8B" }],
+ },
+ AzureOpenAI: {
+ name: "Azure Open AI",
+ models: [
+ { label: "GPT 4o Mini", value: "gpt-4o-mini" },
+ { label: "GPT 4o", value: "gpt-4o" },
+ { label: "GPT 4 Turbo", value: "gpt-4-turbo" },
+ { label: "GPT 4", value: "gpt-4" },
+ { label: "GPT 3.5 Turbo", value: "gpt-3.5-turbo" },
+ ],
+ },
+ Custom: {
+ name: "Custom",
+ },
+}
+
+export const ConfigMap = {
+ OpenAI: {
+ name: "OpenAI",
+ baseUrl: "https://api.openai.com",
+ },
+ Anthropic: {
+ name: "Anthropic",
+ baseUrl: "https://api.anthropic.com/v1",
+ },
+ TogetherAI: {
+ name: "TogetherAI",
+ baseUrl: "https://api.together.xyz/v1",
+ },
+ AzureOpenAI: {
+ name: "Azure OpenAI",
+ baseUrl: "",
+ },
+ Custom: {
+ baseUrl: "",
+ },
+}
diff --git a/packages/builder/src/pages/builder/portal/settings/ai/index.svelte b/packages/builder/src/pages/builder/portal/settings/ai/index.svelte
new file mode 100644
index 0000000000..2ac1609e7c
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/settings/ai/index.svelte
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
+ AI
+ {#if isCloud && !budibaseAIEnabled}
+
+ Premium
+
+ {/if}
+ Configure your AI settings within this section:
+
+
+
+
+ AI Configurations
+ {#if !isCloud && !customAIConfigsEnabled}
+
+ Premium
+
+ {:else if isCloud && !customAIConfigsEnabled}
+
+ Enterprise
+
+ {:else}
+
+ {/if}
+
+ Use the following interface to select your preferred AI configuration.
+ Select your AI Model:
+ {#if fullAIConfig?.config}
+ {#each Object.keys(fullAIConfig.config) as key}
+ editConfig(key)}
+ deleteHandler={() => deleteConfig(key)}
+ />
+ {/each}
+ {/if}
+
+
+
+
diff --git a/packages/builder/src/pages/builder/portal/settings/ai/logos/Anthropic.svelte b/packages/builder/src/pages/builder/portal/settings/ai/logos/Anthropic.svelte
new file mode 100644
index 0000000000..d16a37ba2b
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/settings/ai/logos/Anthropic.svelte
@@ -0,0 +1,27 @@
+
+
+
diff --git a/packages/builder/src/pages/builder/portal/settings/ai/logos/Budibase.svelte b/packages/builder/src/pages/builder/portal/settings/ai/logos/Budibase.svelte
new file mode 100644
index 0000000000..dc19facb1a
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/settings/ai/logos/Budibase.svelte
@@ -0,0 +1,36 @@
+
+
+
diff --git a/packages/builder/src/pages/builder/portal/settings/ai/logos/OpenAI.svelte b/packages/builder/src/pages/builder/portal/settings/ai/logos/OpenAI.svelte
new file mode 100644
index 0000000000..a049cd537f
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/settings/ai/logos/OpenAI.svelte
@@ -0,0 +1,18 @@
+
+
+
diff --git a/packages/builder/src/pages/builder/portal/settings/ai/logos/TogetherAI.svelte b/packages/builder/src/pages/builder/portal/settings/ai/logos/TogetherAI.svelte
new file mode 100644
index 0000000000..b81450f768
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/settings/ai/logos/TogetherAI.svelte
@@ -0,0 +1,57 @@
+
+
+
diff --git a/packages/builder/src/stores/portal/licensing.js b/packages/builder/src/stores/portal/licensing.js
index 0e44650479..d48377207c 100644
--- a/packages/builder/src/stores/portal/licensing.js
+++ b/packages/builder/src/stores/portal/licensing.js
@@ -22,6 +22,8 @@ export const createLicensingStore = () => {
backupsEnabled: false,
brandingEnabled: false,
scimEnabled: false,
+ budibaseAIEnabled: false,
+ customAIConfigsEnabled: false,
// the currently used quotas from the db
quotaUsage: undefined,
// derived quota metrics for percentages used
@@ -142,6 +144,14 @@ export const createLicensingStore = () => {
Constants.Features.VIEW_READONLY_COLUMNS
)
+ const budibaseAIEnabled = license.features.includes(
+ Constants.Features.BUDIBASE_AI
+ )
+
+ const customAIConfigsEnabled = license.features.includes(
+ Constants.Features.AI_CUSTOM_CONFIGS
+ )
+
store.update(state => {
return {
...state,
@@ -153,6 +163,8 @@ export const createLicensingStore = () => {
groupsEnabled,
backupsEnabled,
brandingEnabled,
+ budibaseAIEnabled,
+ customAIConfigsEnabled,
scimEnabled,
environmentVariablesEnabled,
auditLogsEnabled,
diff --git a/packages/builder/src/stores/portal/menu.js b/packages/builder/src/stores/portal/menu.js
index c7c71d89bc..a1b5450ea4 100644
--- a/packages/builder/src/stores/portal/menu.js
+++ b/packages/builder/src/stores/portal/menu.js
@@ -1,7 +1,9 @@
import { derived } from "svelte/store"
import { admin } from "./admin"
import { auth } from "./auth"
+import { isEnabled } from "helpers/featureFlags"
import { sdk } from "@budibase/shared-core"
+import { FeatureFlag } from "@budibase/types"
export const menu = derived([admin, auth], ([$admin, $auth]) => {
const user = $auth?.user
@@ -62,6 +64,13 @@ export const menu = derived([admin, auth], ([$admin, $auth]) => {
href: "/builder/portal/settings/environment",
},
]
+ if (isEnabled(FeatureFlag.AI_CUSTOM_CONFIGS)) {
+ settingsSubPages.push({
+ title: "AI",
+ href: "/builder/portal/settings/ai",
+ })
+ }
+
if (!cloud) {
settingsSubPages.push({
title: "Version",
@@ -75,7 +84,9 @@ export const menu = derived([admin, auth], ([$admin, $auth]) => {
menu.push({
title: "Settings",
href: "/builder/portal/settings",
- subPages: settingsSubPages,
+ subPages: [...settingsSubPages].sort((a, b) =>
+ a.title.localeCompare(b.title)
+ ),
})
}
diff --git a/packages/builder/vite.config.js b/packages/builder/vite.config.mjs
similarity index 99%
rename from packages/builder/vite.config.js
rename to packages/builder/vite.config.mjs
index 995cd36adb..f5ff388952 100644
--- a/packages/builder/vite.config.js
+++ b/packages/builder/vite.config.mjs
@@ -35,7 +35,7 @@ export default defineConfig(({ mode }) => {
// Copy fonts to an additional path so that svelte's automatic
// prefixing of the base URL path can still resolve assets
copyFonts("builder/fonts"),
- ]
+]
return {
test: {
diff --git a/packages/builder/vitest.setup.js b/packages/builder/vitest.setup.js
index 6581df83e1..0204a1a772 100644
--- a/packages/builder/vitest.setup.js
+++ b/packages/builder/vitest.setup.js
@@ -1,4 +1,7 @@
import { expect } from "vitest"
+import "@testing-library/jest-dom/vitest"
+
+global.ResizeObserver = require("resize-observer-polyfill")
expect.extend({
toBeFunc: received => {
diff --git a/packages/pro b/packages/pro
index a4d1d15d9c..ec1d2bda75 160000
--- a/packages/pro
+++ b/packages/pro
@@ -1 +1 @@
-Subproject commit a4d1d15d9ce6ac3deedb2e42625c90ba32756758
+Subproject commit ec1d2bda756f02c6b4efdee086e4c59b0c2a1b0c
diff --git a/packages/types/src/documents/global/config.ts b/packages/types/src/documents/global/config.ts
index 3fd352aada..8d64b49ee9 100644
--- a/packages/types/src/documents/global/config.ts
+++ b/packages/types/src/documents/global/config.ts
@@ -111,6 +111,22 @@ export interface SCIMInnerConfig {
export interface SCIMConfig extends Config {}
+type AIProvider = "OpenAI" | "Anthropic" | "AzureOpenAI" | "Custom"
+
+export interface AIInnerConfig {
+ [key: string]: {
+ provider: AIProvider
+ isDefault: boolean
+ name: string
+ active: boolean
+ baseUrl?: string
+ apiKey?: string
+ defaultModel?: string
+ }
+}
+
+export interface AIConfig extends Config {}
+
export const isSettingsConfig = (config: Config): config is SettingsConfig =>
config.type === ConfigType.SETTINGS
@@ -126,6 +142,9 @@ export const isOIDCConfig = (config: Config): config is OIDCConfig =>
export const isSCIMConfig = (config: Config): config is SCIMConfig =>
config.type === ConfigType.SCIM
+export const isAIConfig = (config: Config): config is AIConfig =>
+ config.type === ConfigType.AI
+
export enum ConfigType {
SETTINGS = "settings",
ACCOUNT = "account",
@@ -134,4 +153,5 @@ export enum ConfigType {
OIDC = "oidc",
OIDC_LOGOS = "logos_oidc",
SCIM = "scim",
+ AI = "ai",
}
diff --git a/packages/types/src/documents/global/quotas.ts b/packages/types/src/documents/global/quotas.ts
index 4eb1168f7d..4726dabf0d 100644
--- a/packages/types/src/documents/global/quotas.ts
+++ b/packages/types/src/documents/global/quotas.ts
@@ -35,6 +35,7 @@ export interface StaticUsage {
[StaticQuotaName.CREATORS]: number
[StaticQuotaName.USER_GROUPS]: number
[StaticQuotaName.ROWS]: number
+ [StaticQuotaName.AI_CUSTOM_CONFIGS]: number
triggers: {
[key in StaticQuotaName]?: QuotaTriggers
}
@@ -44,6 +45,7 @@ export interface MonthlyUsage {
[MonthlyQuotaName.QUERIES]: number
[MonthlyQuotaName.AUTOMATIONS]: number
[MonthlyQuotaName.DAY_PASSES]: number
+ [MonthlyQuotaName.BUDIBASE_AI_CREDITS]: number
triggers: {
[key in MonthlyQuotaName]?: QuotaTriggers
}
diff --git a/packages/types/src/sdk/events/ai.ts b/packages/types/src/sdk/events/ai.ts
new file mode 100644
index 0000000000..740c59d5f9
--- /dev/null
+++ b/packages/types/src/sdk/events/ai.ts
@@ -0,0 +1,5 @@
+import { BaseEvent } from "./event"
+
+export interface AIConfigCreatedEvent extends BaseEvent {}
+
+export interface AIConfigUpdatedEvent extends BaseEvent {}
diff --git a/packages/types/src/sdk/events/event.ts b/packages/types/src/sdk/events/event.ts
index 05f4fe4be9..242b182dec 100644
--- a/packages/types/src/sdk/events/event.ts
+++ b/packages/types/src/sdk/events/event.ts
@@ -33,6 +33,10 @@ export enum Event {
EMAIL_SMTP_CREATED = "email:smtp:created",
EMAIL_SMTP_UPDATED = "email:smtp:updated",
+ // AI
+ AI_CONFIG_CREATED = "ai:config:created",
+ AI_CONFIG_UPDATED = "ai:config:updated",
+
// AUTH
AUTH_SSO_CREATED = "auth:sso:created",
AUTH_SSO_UPDATED = "auth:sso:updated",
@@ -243,6 +247,10 @@ export const AuditedEventFriendlyName: Record = {
[Event.EMAIL_SMTP_CREATED]: `Email configuration created`,
[Event.EMAIL_SMTP_UPDATED]: `Email configuration updated`,
+ // AI
+ [Event.AI_CONFIG_CREATED]: `AI configuration created`,
+ [Event.AI_CONFIG_UPDATED]: `AI configuration updated`,
+
// AUTH
[Event.AUTH_SSO_CREATED]: `SSO configuration created`,
[Event.AUTH_SSO_UPDATED]: `SSO configuration updated`,
diff --git a/packages/types/src/sdk/events/index.ts b/packages/types/src/sdk/events/index.ts
index 745f84d2a3..043e62faa4 100644
--- a/packages/types/src/sdk/events/index.ts
+++ b/packages/types/src/sdk/events/index.ts
@@ -2,6 +2,7 @@ export * from "./app"
export * from "./auth"
export * from "./automation"
export * from "./email"
+export * from "./ai"
export * from "./datasource"
export * from "./event"
export * from "./layout"
diff --git a/packages/types/src/sdk/featureFlag.ts b/packages/types/src/sdk/featureFlag.ts
index 3d96b63c64..f87772233d 100644
--- a/packages/types/src/sdk/featureFlag.ts
+++ b/packages/types/src/sdk/featureFlag.ts
@@ -1,6 +1,7 @@
export enum FeatureFlag {
PER_CREATOR_PER_USER_PRICE = "PER_CREATOR_PER_USER_PRICE",
PER_CREATOR_PER_USER_PRICE_ALERT = "PER_CREATOR_PER_USER_PRICE_ALERT",
+ AI_CUSTOM_CONFIGS = "AI_CUSTOM_CONFIGS",
ENRICHED_RELATIONSHIPS = "ENRICHED_RELATIONSHIPS",
}
diff --git a/packages/types/src/sdk/licensing/feature.ts b/packages/types/src/sdk/licensing/feature.ts
index 0d8db8258e..9d09f1d14f 100644
--- a/packages/types/src/sdk/licensing/feature.ts
+++ b/packages/types/src/sdk/licensing/feature.ts
@@ -15,6 +15,8 @@ export enum Feature {
EXPANDED_PUBLIC_API = "expandedPublicApi",
VIEW_PERMISSIONS = "viewPermissions",
VIEW_READONLY_COLUMNS = "viewReadonlyColumns",
+ BUDIBASE_AI = "budibaseAI",
+ AI_CUSTOM_CONFIGS = "aiCustomConfigs",
}
export type PlanFeatures = { [key in PlanType]: Feature[] | undefined }
diff --git a/packages/types/src/sdk/licensing/quota.ts b/packages/types/src/sdk/licensing/quota.ts
index 85700f167b..75fc18e8e6 100644
--- a/packages/types/src/sdk/licensing/quota.ts
+++ b/packages/types/src/sdk/licensing/quota.ts
@@ -17,12 +17,14 @@ export enum StaticQuotaName {
CREATORS = "creators",
USER_GROUPS = "userGroups",
PLUGINS = "plugins",
+ AI_CUSTOM_CONFIGS = "aiCustomConfigs",
}
export enum MonthlyQuotaName {
QUERIES = "queries",
AUTOMATIONS = "automations",
DAY_PASSES = "dayPasses",
+ BUDIBASE_AI_CREDITS = "budibaseAICredits",
}
export enum ConstantQuotaName {
@@ -62,6 +64,7 @@ export type MonthlyQuotas = {
[MonthlyQuotaName.QUERIES]: Quota
[MonthlyQuotaName.AUTOMATIONS]: Quota
[MonthlyQuotaName.DAY_PASSES]: Quota
+ [MonthlyQuotaName.BUDIBASE_AI_CREDITS]: Quota
}
export type StaticQuotas = {
@@ -71,6 +74,7 @@ export type StaticQuotas = {
[StaticQuotaName.CREATORS]: Quota
[StaticQuotaName.USER_GROUPS]: Quota
[StaticQuotaName.PLUGINS]: Quota
+ [StaticQuotaName.AI_CUSTOM_CONFIGS]: Quota
}
export type ConstantQuotas = {
diff --git a/packages/worker/src/api/controllers/global/configs.ts b/packages/worker/src/api/controllers/global/configs.ts
index a44b173869..70b2279f6c 100644
--- a/packages/worker/src/api/controllers/global/configs.ts
+++ b/packages/worker/src/api/controllers/global/configs.ts
@@ -29,6 +29,10 @@ import {
SSOConfigType,
UserCtx,
OIDCLogosConfig,
+ AIConfig,
+ PASSWORD_REPLACEMENT,
+ isAIConfig,
+ AIInnerConfig,
} from "@budibase/types"
import * as pro from "@budibase/pro"
@@ -38,6 +42,11 @@ const getEventFns = async (config: Config, existing?: Config) => {
if (!existing) {
if (isSMTPConfig(config)) {
fns.push(events.email.SMTPCreated)
+ } else if (isAIConfig(config)) {
+ fns.push(() => events.ai.AIConfigCreated)
+ fns.push(() =>
+ pro.quotas.updateCustomAIConfigCount(Object.keys(config.config).length)
+ )
} else if (isGoogleConfig(config)) {
fns.push(() => events.auth.SSOCreated(ConfigType.GOOGLE))
if (config.config.activated) {
@@ -74,6 +83,11 @@ const getEventFns = async (config: Config, existing?: Config) => {
} else {
if (isSMTPConfig(config)) {
fns.push(events.email.SMTPUpdated)
+ } else if (isAIConfig(config)) {
+ fns.push(() => events.ai.AIConfigUpdated)
+ fns.push(() =>
+ pro.quotas.updateCustomAIConfigCount(Object.keys(config.config).length)
+ )
} else if (isGoogleConfig(config)) {
fns.push(() => events.auth.SSOUpdated(ConfigType.GOOGLE))
if (!existing.config.activated && config.config.activated) {
@@ -122,7 +136,6 @@ const getEventFns = async (config: Config, existing?: Config) => {
}
}
}
-
return fns
}
@@ -197,6 +210,18 @@ async function verifyOIDCConfig(config: OIDCConfigs) {
await verifySSOConfig(ConfigType.OIDC, config.configs[0])
}
+export async function verifyAIConfig(
+ configToSave: AIInnerConfig,
+ existingConfig: AIConfig
+) {
+ // ensure that the redacted API keys are not overwritten in the DB
+ for (const uuid in existingConfig.config) {
+ if (configToSave[uuid]?.apiKey === PASSWORD_REPLACEMENT) {
+ configToSave[uuid].apiKey = existingConfig.config[uuid].apiKey
+ }
+ }
+}
+
export async function save(ctx: UserCtx) {
const body = ctx.request.body
const type = body.type
@@ -224,6 +249,11 @@ export async function save(ctx: UserCtx) {
case ConfigType.OIDC:
await verifyOIDCConfig(config)
break
+ case ConfigType.AI:
+ if (existingConfig) {
+ await verifyAIConfig(config, existingConfig)
+ }
+ break
}
} catch (err: any) {
ctx.throw(400, err)
@@ -304,6 +334,32 @@ function enrichOIDCLogos(oidcLogos: OIDCLogosConfig) {
)
}
+async function enrichAIConfig(aiConfig: AIConfig) {
+ // Strip out the API Keys from the response so they don't show in the UI
+ for (const key in aiConfig.config) {
+ if (aiConfig.config[key].apiKey) {
+ aiConfig.config[key].apiKey = PASSWORD_REPLACEMENT
+ }
+ }
+
+ // Return the Budibase AI data source as part of the response if licensing allows
+ const budibaseAIEnabled = await pro.features.isBudibaseAIEnabled()
+ const defaultConfigExists = Object.keys(aiConfig.config).some(
+ key => aiConfig.config[key].isDefault
+ )
+ if (budibaseAIEnabled) {
+ aiConfig.config["budibase_ai"] = {
+ provider: "OpenAI",
+ active: true,
+ isDefault: !defaultConfigExists,
+ defaultModel: env.BUDIBASE_AI_DEFAULT_MODEL || "",
+ name: "Budibase AI",
+ }
+ }
+
+ return aiConfig
+}
+
export async function find(ctx: UserCtx) {
try {
// Find the config with the most granular scope based on context
@@ -314,6 +370,10 @@ export async function find(ctx: UserCtx) {
if (type === ConfigType.OIDC_LOGOS) {
enrichOIDCLogos(scopedConfig)
}
+
+ if (type === ConfigType.AI) {
+ await enrichAIConfig(scopedConfig)
+ }
ctx.body = scopedConfig
} else {
// don't throw an error, there simply is nothing to return
diff --git a/packages/worker/src/api/controllers/global/tests/configs.spec.ts b/packages/worker/src/api/controllers/global/tests/configs.spec.ts
new file mode 100644
index 0000000000..3ff6a5298c
--- /dev/null
+++ b/packages/worker/src/api/controllers/global/tests/configs.spec.ts
@@ -0,0 +1,106 @@
+import * as pro from "@budibase/pro"
+import { verifyAIConfig } from "../configs"
+import { TestConfiguration, structures } from "../../../../tests"
+import { AIInnerConfig } from "@budibase/types"
+
+describe("Global configs controller", () => {
+ const config = new TestConfiguration()
+
+ beforeAll(async () => {
+ await config.beforeAll()
+ })
+
+ afterAll(async () => {
+ await config.afterAll()
+ })
+
+ afterEach(() => {
+ jest.resetAllMocks()
+ })
+
+ it("Should strip secrets when pulling AI config", async () => {
+ const data = structures.configs.ai()
+ await config.api.configs.saveConfig(data)
+ const response = await config.api.configs.getAIConfig()
+ expect(response.body.config).toEqual({
+ ai: {
+ active: true,
+ apiKey: "--secret-value--",
+ baseUrl: "https://api.example.com",
+ defaultModel: "gpt4",
+ isDefault: false,
+ name: "Test",
+ provider: "OpenAI",
+ },
+ })
+ })
+
+ it("Should return the default BB AI config when the feature is turned on", async () => {
+ jest
+ .spyOn(pro.features, "isBudibaseAIEnabled")
+ .mockImplementation(() => Promise.resolve(true))
+ const data = structures.configs.ai()
+ await config.api.configs.saveConfig(data)
+ const response = await config.api.configs.getAIConfig()
+
+ expect(response.body.config).toEqual({
+ budibase_ai: {
+ provider: "OpenAI",
+ active: true,
+ isDefault: true,
+ name: "Budibase AI",
+ defaultModel: "",
+ },
+ ai: {
+ active: true,
+ apiKey: "--secret-value--",
+ baseUrl: "https://api.example.com",
+ defaultModel: "gpt4",
+ isDefault: false,
+ name: "Test",
+ provider: "OpenAI",
+ },
+ })
+ })
+
+ it("Should not not return the default Budibase AI config when on self host", async () => {
+ jest
+ .spyOn(pro.features, "isBudibaseAIEnabled")
+ .mockImplementation(() => Promise.resolve(false))
+ const data = structures.configs.ai()
+ await config.api.configs.saveConfig(data)
+ const response = await config.api.configs.getAIConfig()
+
+ expect(response.body.config).toEqual({
+ ai: {
+ active: true,
+ apiKey: "--secret-value--",
+ baseUrl: "https://api.example.com",
+ defaultModel: "gpt4",
+ isDefault: false,
+ name: "Test",
+ provider: "OpenAI",
+ },
+ })
+ })
+
+ it("Should not update existing secrets when updating an existing AI Config", async () => {
+ const data = structures.configs.ai()
+ await config.api.configs.saveConfig(data)
+
+ const newConfig: AIInnerConfig = {
+ ai: {
+ provider: "OpenAI",
+ isDefault: true,
+ apiKey: "--secret-value--",
+ name: "MyConfig",
+ active: true,
+ defaultModel: "gpt4",
+ },
+ }
+
+ await verifyAIConfig(newConfig, data)
+ // should be unchanged
+ expect(newConfig.ai.apiKey).toEqual("myapikey")
+ })
+})
diff --git a/packages/worker/src/api/routes/global/configs.ts b/packages/worker/src/api/routes/global/configs.ts
index fcab2b58e0..471005c2aa 100644
--- a/packages/worker/src/api/routes/global/configs.ts
+++ b/packages/worker/src/api/routes/global/configs.ts
@@ -65,6 +65,22 @@ function scimValidation() {
}).unknown(true)
}
+function aiValidation() {
+ // prettier-ignore
+ return Joi.object().pattern(
+ Joi.string(),
+ Joi.object({
+ provider: Joi.string().required(),
+ isDefault: Joi.boolean().required(),
+ name: Joi.string().required(),
+ active: Joi.boolean().required(),
+ baseUrl: Joi.string().optional().allow("", null),
+ apiKey: Joi.string().required(),
+ defaultModel: Joi.string().optional(),
+ }).required()
+ )
+}
+
function buildConfigSaveValidation() {
// prettier-ignore
return auth.joiValidator.body(Joi.object({
@@ -82,7 +98,8 @@ function buildConfigSaveValidation() {
{ is: ConfigType.ACCOUNT, then: Joi.object().unknown(true) },
{ is: ConfigType.GOOGLE, then: googleValidation() },
{ is: ConfigType.OIDC, then: oidcValidation() },
- { is: ConfigType.SCIM, then: scimValidation() }
+ { is: ConfigType.SCIM, then: scimValidation() },
+ { is: ConfigType.AI, then: aiValidation() }
],
}),
}).required().unknown(true),
diff --git a/packages/worker/src/environment.ts b/packages/worker/src/environment.ts
index ed618f7c71..3a9efd70ce 100644
--- a/packages/worker/src/environment.ts
+++ b/packages/worker/src/environment.ts
@@ -70,6 +70,9 @@ const environment = {
PASSPORT_OIDCAUTH_FAILURE_REDIRECT:
process.env.PASSPORT_OIDCAUTH_FAILURE_REDIRECT || "/error",
+ // Budibase AI
+ BUDIBASE_AI_API_KEY: process.env.BUDIBASE_AI_API_KEY,
+ BUDIBASE_AI_DEFAULT_MODEL: process.env.BUDIBASE_AI_DEFAULT_MODEL,
_set(key: any, value: any) {
process.env[key] = value
// @ts-ignore
diff --git a/packages/worker/src/tests/api/configs.ts b/packages/worker/src/tests/api/configs.ts
index 86fe0830ca..e0c1c806af 100644
--- a/packages/worker/src/tests/api/configs.ts
+++ b/packages/worker/src/tests/api/configs.ts
@@ -22,6 +22,14 @@ export class ConfigAPI extends TestAPI {
.expect("Content-Type", /json/)
}
+ getAIConfig = () => {
+ return this.request
+ .get(`/api/global/configs/ai`)
+ .set(this.config.defaultHeaders())
+ .expect(200)
+ .expect("Content-Type", /json/)
+ }
+
saveConfig = (data: any) => {
return this.request
.post(`/api/global/configs`)
diff --git a/packages/worker/src/tests/structures/configs.ts b/packages/worker/src/tests/structures/configs.ts
index bac94a4154..5aa073408c 100644
--- a/packages/worker/src/tests/structures/configs.ts
+++ b/packages/worker/src/tests/structures/configs.ts
@@ -5,6 +5,7 @@ import {
SMTPConfig,
GoogleConfig,
OIDCConfig,
+ AIConfig,
} from "@budibase/types"
export function oidc(conf?: any): OIDCConfig {
@@ -81,3 +82,20 @@ export function settings(conf?: any): SettingsConfig {
},
}
}
+
+export function ai(): AIConfig {
+ return {
+ type: ConfigType.AI,
+ config: {
+ ai: {
+ provider: "OpenAI",
+ isDefault: false,
+ name: "Test",
+ active: true,
+ defaultModel: "gpt4",
+ apiKey: "myapikey",
+ baseUrl: "https://api.example.com",
+ },
+ },
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index 655d7d78fc..146fa74d5b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8,9 +8,9 @@
integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
"@adobe/css-tools@^4.3.2":
- version "4.3.3"
- resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.3.tgz#90749bde8b89cd41764224f5aac29cd4138f75ff"
- integrity sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.0.tgz#728c484f4e10df03d5a3acd0d8adcbbebff8ad63"
+ integrity sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==
"@adobe/spectrum-css-workflow-icons@1.2.1":
version "1.2.1"
@@ -1995,14 +1995,14 @@
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
-"@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
+"@babel/runtime@^7.10.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.8.4":
version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12"
integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==
dependencies:
regenerator-runtime "^0.14.0"
-"@babel/runtime@^7.13.10":
+"@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.9.2":
version "7.25.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.6.tgz#9afc3289f7184d8d7f98b099884c26317b9264d2"
integrity sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==
@@ -2053,7 +2053,7 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
-"@budibase/backend-core@2.29.24":
+"@budibase/backend-core@2.31.8":
version "0.0.0"
dependencies:
"@budibase/nano" "10.1.5"
@@ -2134,16 +2134,17 @@
through2 "^2.0.0"
"@budibase/pro@npm:@budibase/pro@latest":
- version "2.29.24"
- resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.29.24.tgz#2dbd4c6c0f757aab7e17c413c6d6e4520086f9ac"
- integrity sha512-m1v24UD6O21Vbrfsuo5kC5oeg7FzjWO2w8TQMw1VvPKmdIqqclaKDPTPytxwllTMkapMDRNzM5cQzqnQ3yHf6A==
+ version "2.31.8"
+ resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.31.8.tgz#92b27f99f815f5d20bf58bfae916760b14a036da"
+ integrity sha512-nmNKVoMdUVqEIq6xqoBq0gVBCLkoPMszmn0Zu0SJ/Dc2SpsXhPz9S3n9xXfAA+FHUg9LgUAS+eKPCKPWZXtDHQ==
dependencies:
- "@budibase/backend-core" "2.29.24"
- "@budibase/shared-core" "2.29.24"
- "@budibase/string-templates" "2.29.24"
- "@budibase/types" "2.29.24"
+ "@budibase/backend-core" "2.31.8"
+ "@budibase/shared-core" "2.31.8"
+ "@budibase/string-templates" "2.31.8"
+ "@budibase/types" "2.31.8"
"@koa/router" "8.0.8"
bull "4.10.1"
+ dd-trace "5.2.0"
joi "17.6.0"
jsonwebtoken "9.0.2"
lru-cache "^7.14.1"
@@ -2152,13 +2153,13 @@
scim-patch "^0.8.1"
scim2-parse-filter "^0.2.8"
-"@budibase/shared-core@2.29.24":
+"@budibase/shared-core@2.31.8":
version "0.0.0"
dependencies:
"@budibase/types" "0.0.0"
cron-validate "1.4.5"
-"@budibase/string-templates@2.29.24":
+"@budibase/string-templates@2.31.8":
version "0.0.0"
dependencies:
"@budibase/handlebars-helpers" "^0.13.2"
@@ -2166,7 +2167,7 @@
handlebars "^4.7.8"
lodash.clonedeep "^4.5.0"
-"@budibase/types@2.29.24":
+"@budibase/types@2.31.8":
version "0.0.0"
dependencies:
scim-patch "^0.8.1"
@@ -5338,9 +5339,9 @@
redent "^3.0.0"
"@testing-library/svelte@^4.1.0":
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/@testing-library/svelte/-/svelte-4.1.0.tgz#de6fa34d13d99505e68134ef2acfbafdc03ed39a"
- integrity sha512-MJqe7x9WowkiAVdk9mvazEC2ktFZdmK2OqFVoO557PC37aBemQ4ozqdK3yrG34Zg9kuln3qgTVeLSh08e69AMw==
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/@testing-library/svelte/-/svelte-4.2.3.tgz#bd0fd3dde5c63012da95d58ee640c0b44fd27a04"
+ integrity sha512-8vM2+JSPc6wZWkO9ICPmHvzacjy8jBw+iVjmNs+0VsPV3AO3v4P8qCLWTaQ9nYW/e+IR1BCy3MM3Uqg21dlBkw==
dependencies:
"@testing-library/dom" "^9.3.1"
@@ -5412,9 +5413,9 @@
"@types/readdir-glob" "*"
"@types/aria-query@^5.0.1":
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.1.tgz#3286741fb8f1e1580ac28784add4c7a1d49bdfbc"
- integrity sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708"
+ integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==
"@types/babel__core@^7.1.14":
version "7.20.0"
@@ -5485,9 +5486,9 @@
"@types/chai" "*"
"@types/chai@*", "@types/chai@^4.3.4":
- version "4.3.16"
- resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.16.tgz#b1572967f0b8b60bf3f87fe1d854a5604ea70c82"
- integrity sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==
+ version "4.3.19"
+ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.19.tgz#14519f437361d41e84102ed3fbc922ddace3e228"
+ integrity sha512-2hHHvQBVE2FiSK4eN0Br6snX9MtolHaTo/batnLjlGRhoQzlCL61iVpxoqO7SfFyOw+P/pwv+0zNHzKoGWz9Cw==
"@types/chance@1.1.3":
version "1.1.3"
@@ -6922,16 +6923,16 @@ acorn@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
-acorn@^8.1.0, acorn@^8.10.0, acorn@^8.11.0, acorn@^8.11.3, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0:
- version "8.12.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c"
- integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==
-
-acorn@^8.12.0, acorn@^8.12.1:
+acorn@^8.1.0, acorn@^8.11.3, acorn@^8.12.0, acorn@^8.12.1, acorn@^8.8.1:
version "8.12.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248"
integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==
+acorn@^8.10.0, acorn@^8.11.0, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.8.2, acorn@^8.9.0:
+ version "8.12.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c"
+ integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==
+
add-stream@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa"
@@ -7259,7 +7260,7 @@ aria-query@^5.0.0, aria-query@^5.3.0:
dependencies:
dequal "^2.0.3"
-array-buffer-byte-length@^1.0.1:
+array-buffer-byte-length@^1.0.0, array-buffer-byte-length@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f"
integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==
@@ -8306,9 +8307,9 @@ caseless@~0.12.0:
integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==
chai@^4.3.7:
- version "4.4.1"
- resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1"
- integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8"
+ integrity sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==
dependencies:
assertion-error "^1.1.0"
check-error "^1.0.3"
@@ -8316,7 +8317,7 @@ chai@^4.3.7:
get-func-name "^2.0.2"
loupe "^2.3.6"
pathval "^1.1.1"
- type-detect "^4.0.8"
+ type-detect "^4.1.0"
chai@^5.1.1:
version "5.1.1"
@@ -9625,9 +9626,9 @@ dedent@^1.0.0:
integrity sha512-7glNLfvdsMzZm3FpRY1CHuI2lbYDR+71YmrhmTZjYFD5pfT0ACgnGRdrrC9Mk2uICnzkcdelCx5at787UDGOvg==
deep-eql@^4.1.3:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d"
- integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.4.tgz#d0d3912865911bb8fac5afb4e3acfa6a28dc72b7"
+ integrity sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==
dependencies:
type-detect "^4.0.0"
@@ -9637,15 +9638,16 @@ deep-eql@^5.0.1:
integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==
deep-equal@^2.0.5:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.0.tgz#5caeace9c781028b9ff459f33b779346637c43e6"
- integrity sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1"
+ integrity sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==
dependencies:
- call-bind "^1.0.2"
- es-get-iterator "^1.1.2"
- get-intrinsic "^1.1.3"
+ array-buffer-byte-length "^1.0.0"
+ call-bind "^1.0.5"
+ es-get-iterator "^1.1.3"
+ get-intrinsic "^1.2.2"
is-arguments "^1.1.1"
- is-array-buffer "^3.0.1"
+ is-array-buffer "^3.0.2"
is-date-object "^1.0.5"
is-regex "^1.1.4"
is-shared-array-buffer "^1.0.2"
@@ -9653,11 +9655,11 @@ deep-equal@^2.0.5:
object-is "^1.1.5"
object-keys "^1.1.1"
object.assign "^4.1.4"
- regexp.prototype.flags "^1.4.3"
+ regexp.prototype.flags "^1.5.1"
side-channel "^1.0.4"
which-boxed-primitive "^1.0.2"
which-collection "^1.0.1"
- which-typed-array "^1.1.9"
+ which-typed-array "^1.1.13"
deep-equal@~1.0.1:
version "1.0.1"
@@ -10619,7 +10621,7 @@ es-errors@^1.2.1, es-errors@^1.3.0:
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
-es-get-iterator@^1.1.2:
+es-get-iterator@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6"
integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==
@@ -11936,7 +11938,7 @@ get-func-name@^2.0.1, get-func-name@^2.0.2:
resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41"
integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==
-get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4:
+get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
@@ -13211,7 +13213,7 @@ is-arguments@^1.1.1:
call-bind "^1.0.2"
has-tostringtag "^1.0.0"
-is-array-buffer@^3.0.1, is-array-buffer@^3.0.4:
+is-array-buffer@^3.0.2, is-array-buffer@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98"
integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==
@@ -13402,10 +13404,10 @@ is-lambda@^1.0.1:
resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==
-is-map@^2.0.1, is-map@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127"
- integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==
+is-map@^2.0.2, is-map@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e"
+ integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==
is-module@^1.0.0:
version "1.0.0"
@@ -13552,10 +13554,10 @@ is-self-closing@^1.0.1:
dependencies:
self-closing-tags "^1.0.1"
-is-set@^2.0.1, is-set@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec"
- integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==
+is-set@^2.0.2, is-set@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d"
+ integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==
is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3:
version "1.0.3"
@@ -13653,10 +13655,10 @@ is-utf8@^0.2.0:
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==
-is-weakmap@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2"
- integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==
+is-weakmap@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd"
+ integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==
is-weakref@^1.0.2:
version "1.0.2"
@@ -13665,13 +13667,13 @@ is-weakref@^1.0.2:
dependencies:
call-bind "^1.0.2"
-is-weakset@^2.0.1:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d"
- integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==
+is-weakset@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007"
+ integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==
dependencies:
- call-bind "^1.0.2"
- get-intrinsic "^1.1.1"
+ call-bind "^1.0.7"
+ get-intrinsic "^1.2.4"
is-whitespace@^0.3.0:
version "0.3.0"
@@ -14395,9 +14397,9 @@ jsdom@^16.0.1:
xml-name-validator "^3.0.0"
jsdom@^21.1.1:
- version "21.1.1"
- resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-21.1.1.tgz#ab796361e3f6c01bcfaeda1fea3c06197ac9d8ae"
- integrity sha512-Jjgdmw48RKcdAIQyUD1UdBh2ecH7VqwaXPN3ehoZN6MqgVbMn+lRm1aAT1AsdJRAJpwfa4IpwgzySn61h2qu3w==
+ version "21.1.2"
+ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-21.1.2.tgz#6433f751b8718248d646af1cdf6662dc8a1ca7f9"
+ integrity sha512-sCpFmK2jv+1sjff4u7fzft+pUh2KSUbUrEHYHyfSIbGTIcmnjyp83qg6qLwdJ/I3LpTXx33ACxeRL7Lsyc6lGQ==
dependencies:
abab "^2.0.6"
acorn "^8.8.2"
@@ -14412,7 +14414,7 @@ jsdom@^21.1.1:
http-proxy-agent "^5.0.0"
https-proxy-agent "^5.0.1"
is-potential-custom-element-name "^1.0.1"
- nwsapi "^2.2.2"
+ nwsapi "^2.2.4"
parse5 "^7.1.2"
rrweb-cssom "^0.6.0"
saxes "^6.0.0"
@@ -16191,7 +16193,7 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-mlly@^1.1.0, mlly@^1.7.0:
+mlly@^1.1.0, mlly@^1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.1.tgz#e0336429bb0731b6a8e887b438cbdae522c8f32f"
integrity sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==
@@ -16849,11 +16851,16 @@ nunjucks@^3.2.3:
asap "^2.0.3"
commander "^5.1.0"
-nwsapi@^2.2.0, nwsapi@^2.2.2:
+nwsapi@^2.2.0:
version "2.2.4"
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.4.tgz#fd59d5e904e8e1f03c25a7d5a15cfa16c714a1e5"
integrity sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==
+nwsapi@^2.2.4:
+ version "2.2.12"
+ resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.12.tgz#fb6af5c0ec35b27b4581eb3bbad34ec9e5c696f8"
+ integrity sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==
+
nx-cloud@16.0.5:
version "16.0.5"
resolved "https://registry.yarnpkg.com/nx-cloud/-/nx-cloud-16.0.5.tgz#fa0b0185d254405ec47fcbcdbbd8b12ff1add096"
@@ -16954,12 +16961,12 @@ object-inspect@^1.13.1:
integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
object-is@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
- integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07"
+ integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==
dependencies:
- call-bind "^1.0.2"
- define-properties "^1.1.3"
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
object-keys@^1.1.1:
version "1.1.1"
@@ -18024,12 +18031,12 @@ pkg-dir@^4.2.0:
find-up "^4.0.0"
pkg-types@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.1.1.tgz#07b626880749beb607b0c817af63aac1845a73f2"
- integrity sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.2.0.tgz#d0268e894e93acff11a6279de147e83354ebd42d"
+ integrity sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==
dependencies:
confbox "^0.1.7"
- mlly "^1.7.0"
+ mlly "^1.7.1"
pathe "^1.1.2"
pkginfo@0.4.x:
@@ -19396,7 +19403,7 @@ regexp-tree@~0.1.1:
resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd"
integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==
-regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.2:
+regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334"
integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==
@@ -19520,6 +19527,11 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
+resize-observer-polyfill@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
+ integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
+
resolve-alpn@^1.0.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
@@ -20743,16 +20755,7 @@ string-similarity@^4.0.4:
resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b"
integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==
-"string-width-cjs@npm:string-width@^4.2.0":
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
- integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.1"
-
-"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -20843,7 +20846,7 @@ stringify-object@^3.2.1:
is-obj "^1.0.1"
is-regexp "^1.0.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -20857,13 +20860,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
dependencies:
ansi-regex "^4.1.0"
-strip-ansi@^6.0.0, strip-ansi@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
- integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
- dependencies:
- ansi-regex "^5.0.1"
-
strip-ansi@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2"
@@ -21523,12 +21519,7 @@ tiny-queue@^0.2.0:
resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046"
integrity sha512-EijGsv7kzd9I9g0ByCl6h42BWNGUZrlCSejfrb3AKeHC33SGbASu1VDf5O3rRiiUOhAC9CHdZxFPbZu0HmR70A==
-tinybench@^2.3.1:
- version "2.8.0"
- resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.8.0.tgz#30e19ae3a27508ee18273ffed9ac7018949acd7b"
- integrity sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==
-
-tinybench@^2.8.0:
+tinybench@^2.3.1, tinybench@^2.8.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b"
integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==
@@ -21873,11 +21864,16 @@ type-check@~0.3.2:
dependencies:
prelude-ls "~1.1.2"
-type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.8:
+type-detect@4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
+type-detect@^4.0.0, type-detect@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c"
+ integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==
+
type-fest@^0.13.1:
version "0.13.1"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
@@ -22042,9 +22038,9 @@ typo-js@*:
integrity sha512-C7pYBQK17EjSg8tVNY91KHdUt5Nf6FMJ+c3js076quPmBML57PmNMzAcIq/2kf/hSYtFABNDIYNYlJRl5BJhGw==
ufo@^1.5.3:
- version "1.5.3"
- resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.3.tgz#3325bd3c977b6c6cd3160bf4ff52989adc9d3344"
- integrity sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.4.tgz#16d6949674ca0c9e0fbbae1fa20a71d7b1ded754"
+ integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==
uglify-js@^3.1.4:
version "3.17.4"
@@ -22703,21 +22699,21 @@ which-boxed-primitive@^1.0.2:
is-symbol "^1.0.3"
which-collection@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906"
- integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0"
+ integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==
dependencies:
- is-map "^2.0.1"
- is-set "^2.0.1"
- is-weakmap "^2.0.1"
- is-weakset "^2.0.1"
+ is-map "^2.0.3"
+ is-set "^2.0.3"
+ is-weakmap "^2.0.2"
+ is-weakset "^2.0.3"
which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==
-which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9:
+which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15:
version "1.1.15"
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d"
integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==
@@ -22749,15 +22745,7 @@ which@^3.0.0:
dependencies:
isexe "^2.0.0"
-why-is-node-running@^2.2.2:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.2.2.tgz#4185b2b4699117819e7154594271e7e344c9973e"
- integrity sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==
- dependencies:
- siginfo "^2.0.0"
- stackback "0.0.2"
-
-why-is-node-running@^2.3.0:
+why-is-node-running@^2.2.2, why-is-node-running@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04"
integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==
@@ -22832,7 +22820,7 @@ worker-farm@1.7.0:
dependencies:
errno "~0.1.7"
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -22850,15 +22838,6 @@ wrap-ansi@^5.1.0:
string-width "^3.0.0"
strip-ansi "^5.0.0"
-wrap-ansi@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
- integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
- dependencies:
- ansi-styles "^4.0.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
-
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
@@ -22941,7 +22920,12 @@ ws@^7.4.6:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9"
integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==
-ws@^8.13.0, ws@~8.17.1:
+ws@^8.13.0:
+ version "8.18.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
+ integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
+
+ws@~8.17.1:
version "8.17.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b"
integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==
@@ -23172,9 +23156,9 @@ yocto-queue@^0.1.0:
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
yocto-queue@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251"
- integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110"
+ integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==
yup@0.32.9:
version "0.32.9"