diff --git a/charts/budibase/templates/app-service-deployment.yaml b/charts/budibase/templates/app-service-deployment.yaml index b417fbd765..2b099d01f5 100644 --- a/charts/budibase/templates/app-service-deployment.yaml +++ b/charts/budibase/templates/app-service-deployment.yaml @@ -65,7 +65,10 @@ spec: - name: ENABLE_ANALYTICS value: {{ .Values.globals.enableAnalytics | quote }} - name: API_ENCRYPTION_KEY - value: {{ .Values.globals.apiEncryptionKey | quote }} + valueFrom: + secretKeyRef: + name: {{ template "budibase.fullname" . }} + key: apiEncryptionKey - name: HTTP_LOGGING value: {{ .Values.services.apps.httpLogging | quote }} - name: INTERNAL_API_KEY @@ -161,7 +164,10 @@ spec: - name: TENANT_FEATURE_FLAGS value: {{ .Values.globals.tenantFeatureFlags | quote }} - name: ENCRYPTION_KEY - value: {{ .Values.globals.bbEncryptionKey | quote }} + valueFrom: + secretKeyRef: + name: {{ template "budibase.fullname" . }} + key: bbEncryptionKey {{ if .Values.globals.bbAdminUserEmail }} - name: BB_ADMIN_USER_EMAIL value: {{ .Values.globals.bbAdminUserEmail | quote }} @@ -217,7 +223,7 @@ spec: name: {{ .secretName }} key: {{ .secretKey | quote }} {{- end}} - image: budibase/apps:{{ .Values.globals.appVersion | default .Chart.AppVersion }} + image: {{ .Values.globals.dockerRegistry }}budibase/apps:{{ .Values.globals.appVersion | default .Chart.AppVersion }} imagePullPolicy: Always {{- if .Values.services.apps.startupProbe }} {{- with .Values.services.apps.startupProbe }} diff --git a/charts/budibase/templates/automation-worker-service-deployment.yaml b/charts/budibase/templates/automation-worker-service-deployment.yaml index 38a384626e..71089bd7ee 100644 --- a/charts/budibase/templates/automation-worker-service-deployment.yaml +++ b/charts/budibase/templates/automation-worker-service-deployment.yaml @@ -58,7 +58,10 @@ spec: - name: ENABLE_ANALYTICS value: {{ .Values.globals.enableAnalytics | quote }} - name: API_ENCRYPTION_KEY - value: {{ .Values.globals.apiEncryptionKey | quote }} + valueFrom: + secretKeyRef: + name: {{ template "budibase.fullname" . }} + key: apiEncryptionKey - name: HTTP_LOGGING value: {{ .Values.services.automationWorkers.httpLogging | quote }} - name: INTERNAL_API_KEY @@ -154,7 +157,10 @@ spec: - name: TENANT_FEATURE_FLAGS value: {{ .Values.globals.tenantFeatureFlags | quote }} - name: ENCRYPTION_KEY - value: {{ .Values.globals.bbEncryptionKey | quote }} + valueFrom: + secretKeyRef: + name: {{ template "budibase.fullname" . }} + key: bbEncryptionKey {{ if .Values.globals.bbAdminUserEmail }} - name: BB_ADMIN_USER_EMAIL value: {{ .Values.globals.bbAdminUserEmail | quote }} @@ -209,7 +215,7 @@ spec: key: {{ .secretKey | quote }} {{- end}} - image: budibase/apps:{{ .Values.globals.appVersion | default .Chart.AppVersion }} + image: {{ .Values.globals.dockerRegistry }}budibase/apps:{{ .Values.globals.appVersion | default .Chart.AppVersion }} imagePullPolicy: Always {{- if .Values.services.automationWorkers.startupProbe }} {{- with .Values.services.automationWorkers.startupProbe }} diff --git a/charts/budibase/templates/minio-service-deployment.yaml b/charts/budibase/templates/minio-service-deployment.yaml index 901ead2b46..9ad2642e8d 100644 --- a/charts/budibase/templates/minio-service-deployment.yaml +++ b/charts/budibase/templates/minio-service-deployment.yaml @@ -35,7 +35,7 @@ spec: name: {{ template "budibase.fullname" . }} key: objectStoreSecret - image: minio/minio + image: {{ .Values.globals.dockerRegistry }}minio/minio imagePullPolicy: "" livenessProbe: httpGet: diff --git a/charts/budibase/templates/proxy-service-deployment.yaml b/charts/budibase/templates/proxy-service-deployment.yaml index d5ea696431..8ef7056fa4 100644 --- a/charts/budibase/templates/proxy-service-deployment.yaml +++ b/charts/budibase/templates/proxy-service-deployment.yaml @@ -32,7 +32,7 @@ spec: {{ end }} spec: containers: - - image: budibase/proxy:{{ .Values.globals.appVersion | default .Chart.AppVersion }} + - image: {{ .Values.globals.dockerRegistry }}budibase/proxy:{{ .Values.globals.appVersion | default .Chart.AppVersion }} imagePullPolicy: Always name: proxy-service {{- if .Values.services.proxy.startupProbe }} diff --git a/charts/budibase/templates/redis-service-deployment.yaml b/charts/budibase/templates/redis-service-deployment.yaml index 9ad12e0167..22950df41a 100644 --- a/charts/budibase/templates/redis-service-deployment.yaml +++ b/charts/budibase/templates/redis-service-deployment.yaml @@ -22,7 +22,7 @@ spec: - redis-server - --requirepass - {{ .Values.services.redis.password }} - image: {{ .Values.services.redis.image }} + image: {{ .Values.globals.dockerRegistry }}{{ .Values.services.redis.image }} imagePullPolicy: "" name: redis-service ports: diff --git a/charts/budibase/templates/secrets.yaml b/charts/budibase/templates/secrets.yaml index 263934187e..a44d2c0d9b 100644 --- a/charts/budibase/templates/secrets.yaml +++ b/charts/budibase/templates/secrets.yaml @@ -16,10 +16,14 @@ data: jwtSecret: {{ index $existingSecret.data "jwtSecret" }} objectStoreAccess: {{ index $existingSecret.data "objectStoreAccess" }} objectStoreSecret: {{ index $existingSecret.data "objectStoreSecret" }} + bbEncryptionKey: {{ index $existingSecret.data "bbEncryptionKey" }} + apiEncryptionKey: {{ index $existingSecret.data "apiEncryptionKey" }} {{- else }} internalApiKey: {{ template "budibase.defaultsecret" .Values.globals.internalApiKey }} jwtSecret: {{ template "budibase.defaultsecret" .Values.globals.jwtSecret }} objectStoreAccess: {{ template "budibase.defaultsecret" .Values.services.objectStore.accessKey }} objectStoreSecret: {{ template "budibase.defaultsecret" .Values.services.objectStore.secretKey }} + bbEncryptionKey: {{ template "budibase.defaultsecret" .Values.globals.bbEncryptionKey }} + apiEncryptionKey: {{ template "budibase.defaultsecret" .Values.globals.apiEncryptionKey }} {{- end }} {{- end }} diff --git a/charts/budibase/templates/worker-service-deployment.yaml b/charts/budibase/templates/worker-service-deployment.yaml index b07c7f02a7..dcab33fa58 100644 --- a/charts/budibase/templates/worker-service-deployment.yaml +++ b/charts/budibase/templates/worker-service-deployment.yaml @@ -65,7 +65,10 @@ spec: {{ end }} {{ end }} - name: API_ENCRYPTION_KEY - value: {{ .Values.globals.apiEncryptionKey | quote }} + valueFrom: + secretKeyRef: + name: {{ template "budibase.fullname" . }} + key: apiEncryptionKey - name: HTTP_LOGGING value: {{ .Values.services.worker.httpLogging | quote }} - name: INTERNAL_API_KEY @@ -167,7 +170,10 @@ spec: - name: TENANT_FEATURE_FLAGS value: {{ .Values.globals.tenantFeatureFlags | quote }} - name: ENCRYPTION_KEY - value: {{ .Values.globals.bbEncryptionKey | quote }} + valueFrom: + secretKeyRef: + name: {{ template "budibase.fullname" . }} + key: bbEncryptionKey {{ if .Values.globals.datadogApmEnabled }} - name: DD_LOGS_INJECTION value: {{ .Values.globals.datadogApmEnabled | quote }} @@ -203,7 +209,7 @@ spec: name: {{ .secretName }} key: {{ .secretKey | quote }} {{- end}} - image: budibase/worker:{{ .Values.globals.appVersion | default .Chart.AppVersion }} + image: {{ .Values.globals.dockerRegistry }}budibase/worker:{{ .Values.globals.appVersion | default .Chart.AppVersion }} imagePullPolicy: Always {{- if .Values.services.worker.startupProbe }} {{- with .Values.services.worker.startupProbe }} diff --git a/hosting/single/runner.sh b/hosting/single/runner.sh index 89c5540370..95464dd031 100644 --- a/hosting/single/runner.sh +++ b/hosting/single/runner.sh @@ -44,8 +44,7 @@ fi # randomise any unset environment variables for ENV_VAR in "${ENV_VARS[@]}" do - temp=$(eval "echo \$$ENV_VAR") - if [[ -z "${temp}" ]]; then + if [[ -z "${!ENV_VAR}" ]]; then eval "export $ENV_VAR=$(uuidgen | sed -e 's/-//g')" fi done diff --git a/lerna.json b/lerna.json index 070d726a42..00a472c483 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "2.30.3", + "version": "2.31.2", "npmClient": "yarn", "packages": [ "packages/*", diff --git a/packages/backend-core/src/db/tests/index.spec.ts b/packages/backend-core/src/db/tests/index.spec.ts index d61b0b7655..cbad64a6a6 100644 --- a/packages/backend-core/src/db/tests/index.spec.ts +++ b/packages/backend-core/src/db/tests/index.spec.ts @@ -1,4 +1,4 @@ -import { context } from "../.." +import { doInTenant } from "../../context" import { structures } from "../../../tests" import { getDB } from "../db" @@ -18,7 +18,7 @@ describe("db", () => { }) it("uses the custom put function", async () => { - await context.doInTenant("foo", async () => { + await doInTenant("foo", async () => { const db = getDB(structures.db.id()) let doc: Doc = { _id: "test" } await db.put(doc) diff --git a/packages/backend-core/src/features/index.ts b/packages/backend-core/src/features/index.ts index d1d757d8a9..a8d6f0d0ef 100644 --- a/packages/backend-core/src/features/index.ts +++ b/packages/backend-core/src/features/index.ts @@ -159,8 +159,9 @@ export class FlagSet, T extends { [key: string]: V }> { specificallySetFalse.add(feature) } + // ignore unknown flags if (!this.isFlagName(feature)) { - throw new Error(`Feature: ${feature} is not an allowed option`) + continue } if (typeof flagValues[feature] !== "boolean") { @@ -169,7 +170,7 @@ export class FlagSet, T extends { [key: string]: V }> { // @ts-expect-error - TS does not like you writing into a generic type, // but we know that it's okay in this case because it's just an object. - flagValues[feature] = value + flagValues[feature as keyof FlagValues] = value tags[`flags.${feature}.source`] = "environment" } } diff --git a/packages/backend-core/src/features/tests/features.spec.ts b/packages/backend-core/src/features/tests/features.spec.ts index 55f668f288..d092585cc6 100644 --- a/packages/backend-core/src/features/tests/features.spec.ts +++ b/packages/backend-core/src/features/tests/features.spec.ts @@ -67,9 +67,9 @@ describe("feature flags", () => { expected: flags.defaults(), }, { - it: "should fail when an environment flag is not recognised", + it: "should ignore unknown feature flags", environmentFlags: "default:TEST_BOOLEAN,default:FOO", - errorMessage: "Feature: FOO is not an allowed option", + expected: { TEST_BOOLEAN: true }, }, { it: "should be able to read boolean flags from PostHog", diff --git a/packages/backend-core/src/sql/sql.ts b/packages/backend-core/src/sql/sql.ts index ebae09e156..6a8518ea7b 100644 --- a/packages/backend-core/src/sql/sql.ts +++ b/packages/backend-core/src/sql/sql.ts @@ -36,6 +36,7 @@ import { } from "@budibase/types" import environment from "../environment" import { dataFilters, helpers } from "@budibase/shared-core" +import { cloneDeep } from "lodash" type QueryFunction = (query: SqlQuery | SqlQuery[], operation: Operation) => any @@ -268,6 +269,7 @@ class InternalBuilder { } private parseFilters(filters: SearchFilters): SearchFilters { + filters = cloneDeep(filters) for (const op of Object.values(BasicOperator)) { const filter = filters[op] if (!filter) { @@ -337,7 +339,7 @@ class InternalBuilder { if (!filters) { return query } - filters = this.parseFilters(filters) + filters = this.parseFilters({ ...filters }) const aliases = this.query.tableAliases // if all or specified in filters, then everything is an or const allOr = filters.allOr @@ -371,10 +373,11 @@ class InternalBuilder { ), castedTypeValue.values ) - } else if (!opts?.relationship && !isRelationshipField) { + } else if (!isRelationshipField) { const alias = getTableAlias(tableName) fn(alias ? `${alias}.${updatedKey}` : updatedKey, value) - } else if (opts?.relationship && isRelationshipField) { + } + if (opts?.relationship && isRelationshipField) { const [filterTableName, property] = updatedKey.split(".") const alias = getTableAlias(filterTableName) fn(alias ? `${alias}.${property}` : property, value) @@ -465,18 +468,20 @@ class InternalBuilder { if (filters.$and) { const { $and } = filters - query = query.where(x => { - for (const condition of $and.conditions) { - x = this.addFilters(x, condition, opts) - } - }) + for (const condition of $and.conditions) { + query = query.where(b => { + this.addFilters(b, condition, opts) + }) + } } if (filters.$or) { const { $or } = filters - query = query.where(x => { + query = query.where(b => { for (const condition of $or.conditions) { - x = this.addFilters(x, { ...condition, allOr: true }, opts) + b.orWhere(c => + this.addFilters(c, { ...condition, allOr: true }, opts) + ) } }) } diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 1b3510cf3b..0830f8ab6f 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -72,6 +72,7 @@ "@spectrum-css/switch": "1.0.2", "@spectrum-css/table": "3.0.1", "@spectrum-css/tabs": "3.2.12", + "@spectrum-css/tag": "3.0.0", "@spectrum-css/tags": "3.0.2", "@spectrum-css/textfield": "3.0.1", "@spectrum-css/toast": "3.0.1", diff --git a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte index 76891a4cf5..6c4865b539 100644 --- a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte +++ b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte @@ -1065,7 +1065,12 @@ value={inputData[key]} /> {:else if value.customType === "code"} - + { + // Push any pending changes when the window closes + onChange({ [key]: inputData[key] }) + }} + >
{ // need to pass without the value inside - onChange({ [key]: e.detail }) inputData[key] = e.detail }} completions={stepCompletions} diff --git a/packages/builder/src/components/automation/SetupPanel/CodeEditorModal.svelte b/packages/builder/src/components/automation/SetupPanel/CodeEditorModal.svelte index ce61af2b8c..92ced5dcc7 100644 --- a/packages/builder/src/components/automation/SetupPanel/CodeEditorModal.svelte +++ b/packages/builder/src/components/automation/SetupPanel/CodeEditorModal.svelte @@ -11,7 +11,7 @@ } - + { if (!event.detail.startsWith("/")) { - screenUrl = "/" + event.detail + route = "/" + event.detail } touched = true - screenUrl = sanitizeUrl(screenUrl) - if (routeExists(screenUrl)) { + route = sanitizeUrl(route) + if (routeExists(route)) { error = "This URL is already taken for this access role" } else { error = null @@ -33,19 +33,19 @@ } const routeExists = url => { - if (!screenRole) { + if (!role) { return false } return get(screenStore).screens.some( screen => screen.routing.route.toLowerCase() === url.toLowerCase() && - screen.routing.roleId === screenRole + screen.routing.roleId === role ) } const confirmScreenDetails = async () => { await onConfirm({ - screenUrl, + route, }) } @@ -58,13 +58,13 @@ onConfirm={confirmScreenDetails} {onCancel} cancelText={"Back"} - disabled={!screenUrl || error || !touched} + disabled={!route || error || !touched} >
modal.confirm()}>
diff --git a/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceCategory.svelte b/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceCategory.svelte index fa6f477ed9..f6d7cfc2c3 100644 --- a/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceCategory.svelte +++ b/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceCategory.svelte @@ -29,7 +29,7 @@ on:click={() => onSelect(data)} > - {data.datasource?.name ? `${data.datasource.name} - ` : ""}{data.label} + {data.datasourceName ? `${data.datasourceName} - ` : ""}{data.label} ({ - label: m.name, - tableId: m._id, - type: "table", - datasource: $datasources.list.find( - ds => ds._id === m.sourceId || m.datasourceId - ), - })) + $: tables = $tablesStore.list.map(table => + format.table(table, $datasources.list) + ) $: viewsV1 = $viewsStore.list.map(view => ({ ...view, label: view.name, type: "view", })) - $: viewsV2 = $viewsV2Store.list.map(view => ({ - ...view, - label: view.name, - type: "viewV2", - })) + $: viewsV2 = $viewsV2Store.list.map(format.viewV2) $: views = [...(viewsV1 || []), ...(viewsV2 || [])] $: queries = $queriesStore.list .filter(q => showAllQueries || q.queryVerb === "read" || q.readable) diff --git a/packages/builder/src/components/design/settings/controls/TableSelect.svelte b/packages/builder/src/components/design/settings/controls/TableSelect.svelte index 7b73d0a7cf..545110a8cc 100644 --- a/packages/builder/src/components/design/settings/controls/TableSelect.svelte +++ b/packages/builder/src/components/design/settings/controls/TableSelect.svelte @@ -2,24 +2,14 @@ import { Select } from "@budibase/bbui" import { createEventDispatcher, onMount } from "svelte" import { tables as tablesStore, viewsV2 } from "stores/builder" + import { tableSelect as format } from "helpers/data/format" export let value const dispatch = createEventDispatcher() - $: tables = $tablesStore.list.map(table => ({ - type: "table", - label: table.name, - tableId: table._id, - resourceId: table._id, - })) - $: views = $viewsV2.list.map(view => ({ - type: "viewV2", - id: view.id, - label: view.name, - tableId: view.tableId, - resourceId: view.id, - })) + $: tables = $tablesStore.list.map(format.table) + $: views = $viewsV2.list.map(format.viewV2) $: options = [...(tables || []), ...(views || [])] const onChange = e => { diff --git a/packages/builder/src/helpers/data/format.js b/packages/builder/src/helpers/data/format.js new file mode 100644 index 0000000000..5b9714008b --- /dev/null +++ b/packages/builder/src/helpers/data/format.js @@ -0,0 +1,33 @@ +export const datasourceSelect = { + table: (table, datasources) => { + const sourceId = table.sourceId || table.datasourceId + const datasource = datasources.find(ds => ds._id === sourceId) + return { + label: table.name, + tableId: table._id, + type: "table", + datasourceName: datasource?.name, + } + }, + viewV2: view => ({ + ...view, + label: view.name, + type: "viewV2", + }), +} + +export const tableSelect = { + table: table => ({ + type: "table", + label: table.name, + tableId: table._id, + resourceId: table._id, + }), + viewV2: view => ({ + type: "viewV2", + id: view.id, + label: view.name, + tableId: view.tableId, + resourceId: view.id, + }), +} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte index 54241ea1cc..d5a696c6bf 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte @@ -1,5 +1,4 @@ diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte index cecfdba858..62fe593602 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte @@ -14,11 +14,90 @@ import sanitizeUrl from "helpers/sanitizeUrl" import ButtonActionEditor from "components/design/settings/controls/ButtonActionEditor/ButtonActionEditor.svelte" import { getBindableProperties } from "dataBinding" + import BarButtonList from "components/design/settings/controls/BarButtonList.svelte" $: bindings = getBindableProperties($selectedScreen, null) + $: screenSettings = getScreenSettings($selectedScreen) let errors = {} + const getScreenSettings = screen => { + let settings = [ + { + key: "routing.homeScreen", + control: Checkbox, + props: { + text: "Set as home screen", + }, + }, + { + key: "routing.route", + label: "Route", + control: Input, + parser: val => { + if (!val.startsWith("/")) { + val = "/" + val + } + return sanitizeUrl(val) + }, + validate: route => { + const existingRoute = screen.routing.route + if (route !== existingRoute && routeTaken(route)) { + return "That URL is already in use for this role" + } + return null + }, + }, + { + key: "routing.roleId", + label: "Access", + control: RoleSelect, + validate: role => { + const existingRole = screen.routing.roleId + if (role !== existingRole && roleTaken(role)) { + return "That role is already in use for this URL" + } + return null + }, + }, + { + key: "onLoad", + label: "On screen load", + control: ButtonActionEditor, + }, + { + key: "width", + label: "Width", + control: Select, + props: { + options: ["Extra small", "Small", "Medium", "Large", "Max"], + placeholder: "Default", + disabled: !!screen.layoutId, + }, + }, + { + key: "props.layout", + label: "Layout", + defaultValue: "flex", + control: BarButtonList, + props: { + options: [ + { + barIcon: "ModernGridView", + value: "flex", + }, + { + barIcon: "ViewGrid", + value: "grid", + }, + ], + }, + }, + ] + + return settings + } + const routeTaken = url => { const roleId = get(selectedScreen).routing.roleId || "BASIC" return get(screenStore).screens.some( @@ -71,61 +150,6 @@ } } - $: screenSettings = [ - { - key: "routing.homeScreen", - control: Checkbox, - props: { - text: "Set as home screen", - }, - }, - { - key: "routing.route", - label: "Route", - control: Input, - parser: val => { - if (!val.startsWith("/")) { - val = "/" + val - } - return sanitizeUrl(val) - }, - validate: route => { - const existingRoute = get(selectedScreen).routing.route - if (route !== existingRoute && routeTaken(route)) { - return "That URL is already in use for this role" - } - return null - }, - }, - { - key: "routing.roleId", - label: "Access", - control: RoleSelect, - validate: role => { - const existingRole = get(selectedScreen).routing.roleId - if (role !== existingRole && roleTaken(role)) { - return "That role is already in use for this URL" - } - return null - }, - }, - { - key: "onLoad", - label: "On screen load", - control: ButtonActionEditor, - }, - { - key: "width", - label: "Width", - control: Select, - props: { - options: ["Extra small", "Small", "Medium", "Large", "Max"], - placeholder: "Default", - disabled: !!$selectedScreen.layoutId, - }, - }, - ] - const removeCustomLayout = async () => { return screenStore.removeCustomLayout(get(selectedScreen)) } @@ -149,6 +173,7 @@ value={Helpers.deepGet($selectedScreen, setting.key)} onChange={val => setScreenSetting(setting, val)} props={{ ...setting.props, error: errors[setting.key] }} + defaultValue={setting.defaultValue} {bindings} /> {/each} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte index 8a544eac86..405b8b0c21 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/index.svelte @@ -33,7 +33,7 @@ {/each}
- + {#if activeTab === "theme"} {:else} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte index 0ce9e096f2..055ecd88e0 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte @@ -144,7 +144,12 @@ const rootComponent = get(selectedScreen).props const component = findComponent(rootComponent, data.id) componentStore.copy(component) - await componentStore.paste(component) + await componentStore.paste( + component, + data.mode, + null, + data.selectComponent + ) } else if (type === "preview-loaded") { // Wait for this event to show the client library if intelligent // loading is supported @@ -246,13 +251,13 @@ -
+
{#if loading} -
+
+
diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/FormTypeModal.svelte b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/FormTypeModal.svelte deleted file mode 100644 index b7108fd9aa..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/FormTypeModal.svelte +++ /dev/null @@ -1,115 +0,0 @@ - - - - onConfirm(type)} - {onCancel} - disabled={!type} - size="L" - > - - - -
(type = "Create")} - > -
-
- Create a new row - - For capturing and storing new data from your users - -
- {#if type === "Create"} - - - - {/if} -
-
-
(type = "Update")} - > -
-
- Update an existing row - For viewing and updating existing data -
- {#if type === "Update"} - - - - {/if} -
-
-
(type = "View")} - > -
-
- View an existing row - For a read only view of your data -
- {#if type === "View"} - - - - {/if} -
-
-
-
-
- - diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/TableOrViewOption.svelte b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/TableOrViewOption.svelte index b0b9f3dfc1..47a4a834ff 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/TableOrViewOption.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/TableOrViewOption.svelte @@ -1,49 +1,14 @@
-
- - {tableOrView.name} -
- -
- -
- read - -
-
- -
- write - -
-
-
+ + {tableOrView.name}
diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/TypeModal.svelte b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/TypeModal.svelte new file mode 100644 index 0000000000..045e3000e7 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/TypeModal.svelte @@ -0,0 +1,82 @@ + + + onConfirm(selectedType)} + {onCancel} + disabled={!selectedType} + size="L" +> + + + + {#each types as type} +
(selectedType = type.id)} + > +
+ {type.img.alt} +
+
+ {type.title} + {type.description} +
+
+ {/each} +
+
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/formTypes.js b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/formTypes.js new file mode 100644 index 0000000000..c1e0d93f5a --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/formTypes.js @@ -0,0 +1,35 @@ +import formView from "./images/formView.svg" +import formUpdate from "./images/formUpdate.svg" +import formCreate from "./images/formCreate.svg" + +const tableTypes = [ + { + id: "create", + img: { + alt: "A form containing new data", + src: formCreate, + }, + title: "Create a new row", + description: "For capturing and storing new data from your users", + }, + { + id: "update", + img: { + alt: "A form containing edited data", + src: formUpdate, + }, + title: "Update an existing row", + description: "For viewing and updating existing data", + }, + { + id: "view", + img: { + alt: "A form containing read-only data", + src: formView, + }, + title: "View an existing row", + description: "For a read only view of your data", + }, +] + +export default tableTypes diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/blank.png b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/blank.png deleted file mode 100644 index 4867cc8dc3..0000000000 Binary files a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/blank.png and /dev/null differ diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/blank.svg b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/blank.svg new file mode 100644 index 0000000000..6a225a3271 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/blank.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/form.png b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/form.png deleted file mode 100644 index cb9b57d23b..0000000000 Binary files a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/form.png and /dev/null differ diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/formCreate.svg b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/formCreate.svg new file mode 100644 index 0000000000..d8d0220142 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/formCreate.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/formUpdate.svg b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/formUpdate.svg new file mode 100644 index 0000000000..674dbb12cc --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/formUpdate.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/formView.svg b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/formView.svg new file mode 100644 index 0000000000..0b65846b16 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/formView.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/grid.png b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/grid.png deleted file mode 100644 index c3efa30a67..0000000000 Binary files a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/grid.png and /dev/null differ diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/table.png b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/table.png deleted file mode 100644 index 0bfda10bbe..0000000000 Binary files a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/table.png and /dev/null differ diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableDetails.png b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableDetails.png deleted file mode 100644 index f67495f3aa..0000000000 Binary files a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableDetails.png and /dev/null differ diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableInline.png b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableInline.png deleted file mode 100644 index 905294a9ae..0000000000 Binary files a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableInline.png and /dev/null differ diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableInline.svg b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableInline.svg new file mode 100644 index 0000000000..d2d2fb8134 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableInline.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableModal.svg b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableModal.svg new file mode 100644 index 0000000000..a638c0eec8 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableModal.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableNewScreen.svg b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableNewScreen.svg new file mode 100644 index 0000000000..462ddfc4a2 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableNewScreen.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableSidePanel.svg b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableSidePanel.svg new file mode 100644 index 0000000000..c590f1ab70 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/images/tableSidePanel.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/index.svelte b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/index.svelte index ef07b277ef..3101ce41ea 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/_components/NewScreen/index.svelte @@ -1,10 +1,9 @@ -{#if url} -
-
- -
+
+
+
-{:else if $builderStore.inBuilder} -
- -
-{/if} +
diff --git a/packages/client/src/components/app/ButtonGroup.svelte b/packages/client/src/components/app/ButtonGroup.svelte index 2cf6b3db7d..b3523cdd21 100644 --- a/packages/client/src/components/app/ButtonGroup.svelte +++ b/packages/client/src/components/app/ButtonGroup.svelte @@ -19,6 +19,11 @@ gap, wrap: true, }} + styles={{ + normal: { + height: "100%", + }, + }} > {#each buttons as { text, type, quiet, disabled, onClick, size, icon, gap }} - import { getContext } from "svelte" - - const component = getContext("component") - const { styleable, builderStore } = getContext("sdk") - - export let cols = 12 - export let rows = 12 - - // Deliberately non-reactive as we want this fixed whenever the grid renders - const defaultColSpan = Math.ceil((cols + 1) / 2) - const defaultRowSpan = Math.ceil((rows + 1) / 2) - - $: coords = generateCoords(rows, cols) - - const generateCoords = (rows, cols) => { - let grid = [] - for (let row = 0; row < rows; row++) { - for (let col = 0; col < cols; col++) { - grid.push({ row, col }) - } - } - return grid - } - - -
- {#if $builderStore.inBuilder} -
- {#each coords as _} -
- {/each} -
- {/if} - -
- - diff --git a/packages/client/src/components/app/GridBlock.svelte b/packages/client/src/components/app/GridBlock.svelte index e86f163dba..30a35b0713 100644 --- a/packages/client/src/components/app/GridBlock.svelte +++ b/packages/client/src/components/app/GridBlock.svelte @@ -198,7 +198,7 @@ overflow: hidden; height: 410px; } - div.in-builder :global(*) { - pointer-events: none; + div.in-builder :global(> *) { + pointer-events: none !important; } diff --git a/packages/client/src/components/app/Layout.svelte b/packages/client/src/components/app/Layout.svelte index af74e14aa0..04dbb9efda 100644 --- a/packages/client/src/components/app/Layout.svelte +++ b/packages/client/src/components/app/Layout.svelte @@ -36,7 +36,6 @@ export let logoLinkUrl export let openLogoLinkInNewTab export let textAlign - export let embedded = false const NavigationClasses = { @@ -339,6 +338,7 @@ />
+ diff --git a/packages/client/src/components/app/container/Container.svelte b/packages/client/src/components/app/container/Container.svelte new file mode 100644 index 0000000000..9cfe74cf35 --- /dev/null +++ b/packages/client/src/components/app/container/Container.svelte @@ -0,0 +1,12 @@ + + + + + diff --git a/packages/client/src/components/app/Container.svelte b/packages/client/src/components/app/container/FlexContainer.svelte similarity index 94% rename from packages/client/src/components/app/Container.svelte rename to packages/client/src/components/app/container/FlexContainer.svelte index f11636b339..34368dcc8c 100644 --- a/packages/client/src/components/app/Container.svelte +++ b/packages/client/src/components/app/container/FlexContainer.svelte @@ -12,7 +12,7 @@ export let wrap export let onClick - $: directionClass = direction ? `valid-container direction-${direction}` : "" + $: directionClass = direction ? `flex-container direction-${direction}` : "" $: hAlignClass = hAlign ? `hAlign-${hAlign}` : "" $: vAlignClass = vAlign ? `vAlign-${vAlign}` : "" $: sizeClass = size ? `size-${size}` : "" @@ -39,11 +39,11 @@
diff --git a/packages/client/src/components/app/index.js b/packages/client/src/components/app/index.js index 6d9df6e588..63cdb95ac1 100644 --- a/packages/client/src/components/app/index.js +++ b/packages/client/src/components/app/index.js @@ -13,7 +13,7 @@ import "@spectrum-css/page/dist/index-vars.css" export { default as Placeholder } from "./Placeholder.svelte" // User facing components -export { default as container } from "./Container.svelte" +export { default as container } from "./container/Container.svelte" export { default as section } from "./Section.svelte" export { default as dataprovider } from "./DataProvider.svelte" export { default as divider } from "./Divider.svelte" @@ -35,7 +35,6 @@ export { default as spectrumcard } from "./SpectrumCard.svelte" export { default as tag } from "./Tag.svelte" export { default as markdownviewer } from "./MarkdownViewer.svelte" export { default as embeddedmap } from "./embedded-map/EmbeddedMap.svelte" -export { default as grid } from "./Grid.svelte" export { default as sidepanel } from "./SidePanel.svelte" export { default as modal } from "./Modal.svelte" export { default as gridblock } from "./GridBlock.svelte" diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 767efc9e3a..bdd538748b 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -13,6 +13,7 @@ import { Utils } from "@budibase/frontend-core" import { findComponentById } from "utils/components.js" import { DNDPlaceholderID } from "constants" + import { isGridEvent } from "utils/grid" const ThrottleRate = 130 @@ -25,15 +26,6 @@ // Local flag for whether we are awaiting an async drop event let dropping = false - // Util to check if a DND event originates from a grid (or inside a grid). - // This is important as we do not handle grid DND in this handler. - const isGridEvent = e => { - return e.target - ?.closest?.(".component") - ?.parentNode?.closest?.(".component") - ?.childNodes[0]?.classList.contains("grid") - } - // Util to get the inner DOM node by a component ID const getDOMNode = id => { return document.getElementsByClassName(`${id}-dom`)[0] @@ -267,7 +259,7 @@ // Check if we're adding a new component rather than moving one if (source.newComponentType) { dropping = true - await builderStore.actions.dropNewComponent( + builderStore.actions.dropNewComponent( source.newComponentType, drop.parent, drop.index diff --git a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte index 0be7faff1b..0ad4280e07 100644 --- a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte +++ b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte @@ -1,7 +1,7 @@ diff --git a/packages/client/src/components/preview/GridStylesButton.svelte b/packages/client/src/components/preview/GridStylesButton.svelte new file mode 100644 index 0000000000..430a0659ec --- /dev/null +++ b/packages/client/src/components/preview/GridStylesButton.svelte @@ -0,0 +1,42 @@ + + + + +
{ + builderStore.actions.updateStyles({ [style]: value }, componentId) + }} +> + +
+ + diff --git a/packages/client/src/components/preview/Indicator.svelte b/packages/client/src/components/preview/Indicator.svelte index 0480ea91ce..dce7945b29 100644 --- a/packages/client/src/components/preview/Indicator.svelte +++ b/packages/client/src/components/preview/Indicator.svelte @@ -1,5 +1,6 @@ diff --git a/packages/client/src/components/preview/SettingsBar.svelte b/packages/client/src/components/preview/SettingsBar.svelte index c5109c6bca..ec861ab5b4 100644 --- a/packages/client/src/components/preview/SettingsBar.svelte +++ b/packages/client/src/components/preview/SettingsBar.svelte @@ -1,117 +1,180 @@ {#if showBar}
+ {#if showGridStyles} + + + + +
+ + + + +
+ {/if} {#each settings as setting, idx} {#if setting.type === "select"} {#if setting.barStyle === "buttons"} @@ -141,6 +273,7 @@ value={option.value} icon={option.barIcon} title={option.barTitle || option.label} + {component} /> {/each} {:else} @@ -148,6 +281,7 @@ prop={setting.key} options={setting.options} label={setting.label} + {component} /> {/if} {:else if setting.type === "boolean"} @@ -156,9 +290,10 @@ icon={setting.barIcon} title={setting.barTitle || setting.label} bool + {component} /> {:else if setting.type === "color"} - + {/if} {#if setting.barSeparator !== false && (settings.length != idx + 1 || !isRoot)}
diff --git a/packages/client/src/components/preview/SettingsButton.svelte b/packages/client/src/components/preview/SettingsButton.svelte index 36009da821..a93ffb77af 100644 --- a/packages/client/src/components/preview/SettingsButton.svelte +++ b/packages/client/src/components/preview/SettingsButton.svelte @@ -1,17 +1,19 @@ @@ -19,7 +21,6 @@
{ if (prop) { @@ -49,7 +50,4 @@ background-color: rgba(13, 102, 208, 0.1); color: var(--spectrum-global-color-blue-600); } - .rotate { - transform: rotate(90deg); - } diff --git a/packages/client/src/components/preview/SettingsColorPicker.svelte b/packages/client/src/components/preview/SettingsColorPicker.svelte index b078d048d2..a292d7d838 100644 --- a/packages/client/src/components/preview/SettingsColorPicker.svelte +++ b/packages/client/src/components/preview/SettingsColorPicker.svelte @@ -1,10 +1,11 @@
diff --git a/packages/client/src/components/preview/SettingsPicker.svelte b/packages/client/src/components/preview/SettingsPicker.svelte index 8b83729fde..3900d065e8 100644 --- a/packages/client/src/components/preview/SettingsPicker.svelte +++ b/packages/client/src/components/preview/SettingsPicker.svelte @@ -1,12 +1,13 @@
diff --git a/packages/client/src/constants.js b/packages/client/src/constants.js index d3f1ab8be9..f7e3e86d40 100644 --- a/packages/client/src/constants.js +++ b/packages/client/src/constants.js @@ -15,3 +15,6 @@ export const ActionTypes = { export const DNDPlaceholderID = "dnd-placeholder" export const ScreenslotType = "screenslot" +export const GridRowHeight = 24 +export const GridColumns = 12 +export const GridSpacing = 4 diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index 5440fc3a79..faa37eddca 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -41,13 +41,20 @@ const createBuilderStore = () => { eventStore.actions.dispatchEvent("update-prop", { prop, value }) }, updateStyles: async (styles, id) => { - await eventStore.actions.dispatchEvent("update-styles", { styles, id }) + await eventStore.actions.dispatchEvent("update-styles", { + styles, + id, + }) }, keyDown: (key, ctrlKey) => { eventStore.actions.dispatchEvent("key-down", { key, ctrlKey }) }, - duplicateComponent: id => { - eventStore.actions.dispatchEvent("duplicate-component", { id }) + duplicateComponent: (id, mode = "below", selectComponent = true) => { + eventStore.actions.dispatchEvent("duplicate-component", { + id, + mode, + selectComponent, + }) }, deleteComponent: id => { eventStore.actions.dispatchEvent("delete-component", { id }) diff --git a/packages/client/src/stores/components.js b/packages/client/src/stores/components.js index b7f7d98197..d4afa6c7f1 100644 --- a/packages/client/src/stores/components.js +++ b/packages/client/src/stores/components.js @@ -142,9 +142,6 @@ const createComponentStore = () => { } const getComponentInstance = id => { - if (!id) { - return null - } return derived(store, $store => $store.mountedComponents[id]) } diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js index 9cb0d536de..3c5ece0a6c 100644 --- a/packages/client/src/stores/screens.js +++ b/packages/client/src/stores/screens.js @@ -129,29 +129,30 @@ const createScreenStore = () => { // If we don't have a legacy custom layout, build a layout structure // from the screen navigation settings if (!activeLayout) { - let navigationSettings = { + let layoutSettings = { navigation: "None", pageWidth: activeScreen?.width || "Large", + embedded: $appStore.embedded, } if (activeScreen?.showNavigation) { - navigationSettings = { - ...navigationSettings, + layoutSettings = { + ...layoutSettings, ...($builderStore.navigation || $appStore.application?.navigation), } // Default navigation to top - if (!navigationSettings.navigation) { - navigationSettings.navigation = "Top" + if (!layoutSettings.navigation) { + layoutSettings.navigation = "Top" } // Default title to app name - if (!navigationSettings.title && !navigationSettings.hideTitle) { - navigationSettings.title = $appStore.application?.name + if (!layoutSettings.title && !layoutSettings.hideTitle) { + layoutSettings.title = $appStore.application?.name } // Default to the org logo - if (!navigationSettings.logoUrl) { - navigationSettings.logoUrl = $orgStore?.logoUrl + if (!layoutSettings.logoUrl) { + layoutSettings.logoUrl = $orgStore?.logoUrl } } activeLayout = { @@ -173,8 +174,7 @@ const createScreenStore = () => { }, }, ], - ...navigationSettings, - embedded: $appStore.embedded, + ...layoutSettings, }, } } diff --git a/packages/client/src/utils/domDebounce.js b/packages/client/src/utils/domDebounce.js deleted file mode 100644 index b15d2698b4..0000000000 --- a/packages/client/src/utils/domDebounce.js +++ /dev/null @@ -1,14 +0,0 @@ -export const domDebounce = (callback, extractParams = x => x) => { - let active = false - let lastParams - return (...params) => { - lastParams = extractParams(...params) - if (!active) { - active = true - requestAnimationFrame(() => { - callback(lastParams) - active = false - }) - } - } -} diff --git a/packages/client/src/utils/grid.js b/packages/client/src/utils/grid.js new file mode 100644 index 0000000000..1727b904ca --- /dev/null +++ b/packages/client/src/utils/grid.js @@ -0,0 +1,183 @@ +import { GridSpacing, GridRowHeight } from "constants" +import { builderStore } from "stores" +import { buildStyleString } from "utils/styleable.js" + +/** + * We use CSS variables on components to control positioning and layout of + * components inside grids. + * --grid-[mobile/desktop]-[row/col]-[start-end]: for positioning + * --grid-[mobile/desktop]-[h/v]-align: for layout of inner components within + * the components grid bounds + * + * Component definitions define their default layout preference via the + * `grid.hAlign` and `grid.vAlign` keys in the manifest. + * + * We also apply grid-[mobile/desktop]-grow CSS classes to component wrapper + * DOM nodes to use later in selectors, to control the sizing of children. + */ + +// Enum representing the different CSS variables we use for grid metadata +export const GridParams = { + HAlign: "h-align", + VAlign: "v-align", + ColStart: "col-start", + ColEnd: "col-end", + RowStart: "row-start", + RowEnd: "row-end", +} + +// Classes used in selectors inside grid containers to control child styles +export const GridClasses = { + DesktopFill: "grid-desktop-grow", + MobileFill: "grid-mobile-grow", +} + +// Enum for device preview type, included in grid CSS variables +export const Devices = { + Desktop: "desktop", + Mobile: "mobile", +} + +export const GridDragModes = { + Resize: "resize", + Move: "move", +} + +// Builds a CSS variable name for a certain piece of grid metadata +export const getGridVar = (device, param) => `--grid-${device}-${param}` + +// Determines whether a JS event originated from immediately within a grid +export const isGridEvent = e => { + return ( + e.target.dataset?.indicator === "true" || + e.target + .closest?.(".component") + ?.parentNode.closest(".component") + ?.childNodes[0]?.classList?.contains("grid") + ) +} + +// Svelte action to apply required class names and styles to our component +// wrappers +export const gridLayout = (node, metadata) => { + let selectComponent + + // Applies the required listeners, CSS and classes to a component DOM node + const applyMetadata = metadata => { + const { + id, + styles, + interactive, + errored, + definition, + draggable, + insideGrid, + ignoresLayout, + } = metadata + if (!insideGrid) { + return + } + + // If this component ignores layout, flag it as such so that we can avoid + // selecting it later + if (ignoresLayout) { + node.classList.add("ignores-layout") + return + } + + // Callback to select the component when clicking on the wrapper + selectComponent = e => { + e.stopPropagation() + builderStore.actions.selectComponent(id) + } + + // Determine default width and height of component + let width = errored ? 500 : definition?.size?.width || 200 + let height = errored ? 60 : definition?.size?.height || 200 + width += 2 * GridSpacing + height += 2 * GridSpacing + let vars = { + "--default-width": width, + "--default-height": height, + } + + // Generate defaults for all grid params + const defaults = { + [GridParams.HAlign]: definition?.grid?.hAlign || "stretch", + [GridParams.VAlign]: definition?.grid?.vAlign || "center", + [GridParams.ColStart]: 1, + [GridParams.ColEnd]: + "round(up, calc((var(--grid-spacing) * 2 + var(--default-width)) / var(--col-size) + 1))", + [GridParams.RowStart]: 1, + [GridParams.RowEnd]: Math.max(2, Math.ceil(height / GridRowHeight) + 1), + } + + // Specify values for all grid params for all devices, and strip these CSS + // variables from the styles being applied to the inner component, as we + // want to apply these to the wrapper instead + for (let param of Object.values(GridParams)) { + let dVar = getGridVar(Devices.Desktop, param) + let mVar = getGridVar(Devices.Mobile, param) + vars[dVar] = styles[dVar] ?? styles[mVar] ?? defaults[param] + vars[mVar] = styles[mVar] ?? styles[dVar] ?? defaults[param] + } + + // Apply some overrides depending on component state + if (errored) { + vars[getGridVar(Devices.Desktop, GridParams.HAlign)] = "stretch" + vars[getGridVar(Devices.Mobile, GridParams.HAlign)] = "stretch" + vars[getGridVar(Devices.Desktop, GridParams.VAlign)] = "stretch" + vars[getGridVar(Devices.Mobile, GridParams.VAlign)] = "stretch" + } + + // Apply some metadata to data attributes to speed up lookups + const addDataTag = (tagName, device, param) => { + const val = `${vars[getGridVar(device, param)]}` + if (node.dataset[tagName] !== val) { + node.dataset[tagName] = val + } + } + addDataTag("gridDesktopRowEnd", Devices.Desktop, GridParams.RowEnd) + addDataTag("gridMobileRowEnd", Devices.Mobile, GridParams.RowEnd) + addDataTag("gridDesktopHAlign", Devices.Desktop, GridParams.HAlign) + addDataTag("gridMobileHAlign", Devices.Mobile, GridParams.HAlign) + addDataTag("gridDesktopVAlign", Devices.Desktop, GridParams.VAlign) + addDataTag("gridMobileVAlign", Devices.Mobile, GridParams.VAlign) + if (node.dataset.insideGrid !== true) { + node.dataset.insideGrid = true + } + + // Apply all CSS variables to the wrapper + node.style = buildStyleString(vars) + + // Add a listener to select this node on click + if (interactive) { + node.addEventListener("click", selectComponent, false) + } + + // Add draggable attribute + node.setAttribute("draggable", !!draggable) + } + + // Removes the previously set up listeners + const removeListeners = () => { + // By checking if this is defined we can avoid trying to remove event + // listeners on every component + if (selectComponent) { + node.removeEventListener("click", selectComponent, false) + selectComponent = null + } + } + + applyMetadata(metadata) + + return { + update(newMetadata) { + removeListeners() + applyMetadata(newMetadata) + }, + destroy() { + removeListeners() + }, + } +} diff --git a/packages/client/src/utils/styleable.js b/packages/client/src/utils/styleable.js index 3fccae0be5..0f484a9ab9 100644 --- a/packages/client/src/utils/styleable.js +++ b/packages/client/src/utils/styleable.js @@ -3,13 +3,13 @@ import { builderStore } from "stores" /** * Helper to build a CSS string from a style object. */ -const buildStyleString = (styleObject, customStyles) => { +export const buildStyleString = (styleObject, customStyles) => { let str = "" - Object.entries(styleObject || {}).forEach(([style, value]) => { - if (style && value != null) { - str += `${style}: ${value}; ` + for (let key of Object.keys(styleObject || {})) { + if (styleObject[key] != null) { + str += `${key}:${styleObject[key]};` } - }) + } return str + (customStyles || "") } diff --git a/packages/frontend-core/src/components/ClientAppSkeleton.svelte b/packages/frontend-core/src/components/ClientAppSkeleton.svelte index a1c90d2db7..f867fccddb 100644 --- a/packages/frontend-core/src/components/ClientAppSkeleton.svelte +++ b/packages/frontend-core/src/components/ClientAppSkeleton.svelte @@ -58,7 +58,6 @@ height: 100%; display: flex; flex-direction: column; - border-radius: 4px; overflow: hidden; background-color: var(--spectrum-global-color-gray-200); } diff --git a/packages/frontend-core/src/components/grid/controls/ColumnsSettingButton.svelte b/packages/frontend-core/src/components/grid/controls/ColumnsSettingButton.svelte index f3a7678cf2..8c66d9ecfc 100644 --- a/packages/frontend-core/src/components/grid/controls/ColumnsSettingButton.svelte +++ b/packages/frontend-core/src/components/grid/controls/ColumnsSettingButton.svelte @@ -1,95 +1,17 @@
@@ -106,51 +28,5 @@
-
-
- {#each displayColumns as column} -
- -
- {column.label} -
-
- toggleColumn(column, e.detail)} - value={columnToPermissionOptions(column)} - options={column.options} - /> - {/each} -
-
+
- - diff --git a/packages/frontend-core/src/components/grid/controls/ColumnsSettingContent.svelte b/packages/frontend-core/src/components/grid/controls/ColumnsSettingContent.svelte new file mode 100644 index 0000000000..4f0e4424d4 --- /dev/null +++ b/packages/frontend-core/src/components/grid/controls/ColumnsSettingContent.svelte @@ -0,0 +1,134 @@ + + +
+
+ {#each displayColumns as column} +
+ +
+ {column.label} +
+
+ toggleColumn(column, e.detail)} + value={columnToPermissionOptions(column)} + options={column.options} + /> + {/each} +
+
+ + diff --git a/packages/frontend-core/src/utils/index.js b/packages/frontend-core/src/utils/index.js index 9eb7206012..5f21e7db99 100644 --- a/packages/frontend-core/src/utils/index.js +++ b/packages/frontend-core/src/utils/index.js @@ -9,3 +9,4 @@ export { memo, derivedMemo } from "./memo" export { createWebsocket } from "./websocket" export * from "./download" export * from "./theme" +export * from "./settings" diff --git a/packages/frontend-core/src/utils/memo.js b/packages/frontend-core/src/utils/memo.js index ba0e3f3490..8192be6790 100644 --- a/packages/frontend-core/src/utils/memo.js +++ b/packages/frontend-core/src/utils/memo.js @@ -4,32 +4,23 @@ import { writable, get, derived } from "svelte/store" // subscribed children will only fire when a new value is actually set export const memo = initialValue => { const store = writable(initialValue) + let currentJSON = JSON.stringify(initialValue) - const tryUpdateValue = (newValue, currentValue) => { - // Sanity check for primitive equality - if (currentValue === newValue) { - return - } - - // Otherwise deep compare via JSON stringify - const currentString = JSON.stringify(currentValue) - const newString = JSON.stringify(newValue) - if (currentString !== newString) { + const tryUpdateValue = newValue => { + const newJSON = JSON.stringify(newValue) + if (newJSON !== currentJSON) { store.set(newValue) + currentJSON = newJSON } } return { subscribe: store.subscribe, - set: newValue => { - const currentValue = get(store) - tryUpdateValue(newValue, currentValue) - }, + set: tryUpdateValue, update: updateFn => { - const currentValue = get(store) - let mutableCurrentValue = JSON.parse(JSON.stringify(currentValue)) + let mutableCurrentValue = JSON.parse(currentJSON) const newValue = updateFn(mutableCurrentValue) - tryUpdateValue(newValue, currentValue) + tryUpdateValue(newValue) }, } } diff --git a/packages/frontend-core/src/utils/settings.js b/packages/frontend-core/src/utils/settings.js new file mode 100644 index 0000000000..0e312c70e6 --- /dev/null +++ b/packages/frontend-core/src/utils/settings.js @@ -0,0 +1,43 @@ +import { helpers } from "@budibase/shared-core" + +// Util to check if a setting can be rendered for a certain instance, based on +// the "dependsOn" metadata in the manifest +export const shouldDisplaySetting = (instance, setting) => { + let dependsOn = setting.dependsOn + if (dependsOn && !Array.isArray(dependsOn)) { + dependsOn = [dependsOn] + } + if (!dependsOn?.length) { + return true + } + + // Ensure all conditions are met + return dependsOn.every(condition => { + let dependantSetting = condition + let dependantValues = null + let invert = !!condition.invert + if (typeof condition === "object") { + dependantSetting = condition.setting + dependantValues = condition.value + } + if (!dependantSetting) { + return false + } + + // Ensure values is an array + if (!Array.isArray(dependantValues)) { + dependantValues = [dependantValues] + } + + // If inverting, we want to ensure that we don't have any matches. + // If not inverting, we want to ensure that we do have any matches. + const currentVal = helpers.deepGet(instance, dependantSetting) + const anyMatches = dependantValues.some(dependantVal => { + if (dependantVal == null) { + return currentVal != null && currentVal !== false && currentVal !== "" + } + return dependantVal === currentVal + }) + return anyMatches !== invert + }) +} diff --git a/packages/frontend-core/src/utils/utils.js b/packages/frontend-core/src/utils/utils.js index b8cfa5ad37..3e8cdcc781 100644 --- a/packages/frontend-core/src/utils/utils.js +++ b/packages/frontend-core/src/utils/utils.js @@ -155,6 +155,7 @@ export const buildFormBlockButtonConfig = props => { providerId: formId, tableId: resourceId, notificationOverride, + confirm: null, }, }, { diff --git a/packages/pro b/packages/pro index 4889395fa3..0d2728a881 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 4889395fa35035a74ed098e323c15a4057b31b64 +Subproject commit 0d2728a88123138ea109e0827a4fdf849015e2d5 diff --git a/packages/server/src/api/controllers/row/ExternalRequest.ts b/packages/server/src/api/controllers/row/ExternalRequest.ts index 5ee2d0fe2b..ac2d1e8c39 100644 --- a/packages/server/src/api/controllers/row/ExternalRequest.ts +++ b/packages/server/src/api/controllers/row/ExternalRequest.ts @@ -45,6 +45,7 @@ import { db as dbCore } from "@budibase/backend-core" import sdk from "../../../sdk" import env from "../../../environment" import { makeExternalQuery } from "../../../integrations/base/query" +import { dataFilters } from "@budibase/shared-core" export interface ManyRelationship { tableId?: string @@ -195,29 +196,33 @@ export class ExternalRequest { if (filters) { // need to map over the filters and make sure the _id field isn't present let prefix = 1 - for (const [operatorType, operator] of Object.entries(filters)) { - const isArrayOp = sdk.rows.utils.isArrayFilter(operatorType) - for (const field of Object.keys(operator || {})) { - if (dbCore.removeKeyNumbering(field) === "_id") { - if (primary) { - const parts = breakRowIdField(operator[field]) - if (primary.length > 1 && isArrayOp) { - operator[InternalSearchFilterOperator.COMPLEX_ID_OPERATOR] = { - id: primary, - values: parts[0], + const checkFilters = (innerFilters: SearchFilters): SearchFilters => { + for (const [operatorType, operator] of Object.entries(innerFilters)) { + const isArrayOp = sdk.rows.utils.isArrayFilter(operatorType) + for (const field of Object.keys(operator || {})) { + if (dbCore.removeKeyNumbering(field) === "_id") { + if (primary) { + const parts = breakRowIdField(operator[field]) + if (primary.length > 1 && isArrayOp) { + operator[InternalSearchFilterOperator.COMPLEX_ID_OPERATOR] = { + id: primary, + values: parts[0], + } + } else { + for (let field of primary) { + operator[`${prefix}:${field}`] = parts.shift() + } + prefix++ } - } else { - for (let field of primary) { - operator[`${prefix}:${field}`] = parts.shift() - } - prefix++ } + // make sure this field doesn't exist on any filter + delete operator[field] } - // make sure this field doesn't exist on any filter - delete operator[field] } } + return dataFilters.recurseLogicalOperators(innerFilters, checkFilters) } + checkFilters(filters) } // there is no id, just use the user provided filters if (!idCopy || !table) { diff --git a/packages/server/src/api/controllers/row/utils/sqlUtils.ts b/packages/server/src/api/controllers/row/utils/sqlUtils.ts index 32124fa79d..a24ec17c26 100644 --- a/packages/server/src/api/controllers/row/utils/sqlUtils.ts +++ b/packages/server/src/api/controllers/row/utils/sqlUtils.ts @@ -151,7 +151,10 @@ export function buildExternalRelationships( return relationships } -export function buildInternalRelationships(table: Table): RelationshipsJson[] { +export function buildInternalRelationships( + table: Table, + allTables: Table[] +): RelationshipsJson[] { const relationships: RelationshipsJson[] = [] const links = Object.values(table.schema).filter( column => column.type === FieldType.LINK @@ -164,6 +167,10 @@ export function buildInternalRelationships(table: Table): RelationshipsJson[] { const linkTableId = link.tableId! const junctionTableId = generateJunctionTableID(tableId, linkTableId) const isFirstTable = tableId > linkTableId + // skip relationships with missing table definitions + if (!allTables.find(table => table._id === linkTableId)) { + continue + } relationships.push({ through: junctionTableId, column: link.name, @@ -192,10 +199,10 @@ export function buildSqlFieldList( function extractRealFields(table: Table, existing: string[] = []) { return Object.entries(table.schema) .filter( - column => - column[1].type !== FieldType.LINK && - column[1].type !== FieldType.FORMULA && - !existing.find((field: string) => field === column[0]) + ([columnName, column]) => + column.type !== FieldType.LINK && + column.type !== FieldType.FORMULA && + !existing.find((field: string) => field === columnName) ) .map(column => `${table.name}.${column[0]}`) } diff --git a/packages/server/src/api/controllers/row/views.ts b/packages/server/src/api/controllers/row/views.ts index be051677b5..e9b6b0d8e5 100644 --- a/packages/server/src/api/controllers/row/views.ts +++ b/packages/server/src/api/controllers/row/views.ts @@ -38,7 +38,6 @@ export async function searchView( let query = dataFilters.buildQuery(view.query || []) if (body.query) { // Delete extraneous search params that cannot be overridden - delete body.query.allOr delete body.query.onEmptyFilter if ( @@ -60,13 +59,12 @@ export async function searchView( } }) }) - } else { + } else query = { $and: { conditions: [query, body.query], }, } - } } await context.ensureSnippetContext(true) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index 9351976d66..95e714fbd6 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -1664,7 +1664,7 @@ describe.each([ isInternal && describe("attachments and signatures", () => { const coreAttachmentEnrichment = async ( - schema: any, + schema: TableSchema, field: string, attachmentCfg: string | string[] ) => { @@ -1691,7 +1691,7 @@ describe.each([ await withEnv({ SELF_HOSTED: "true" }, async () => { return context.doInAppContext(config.getAppId(), async () => { - const enriched: Row[] = await outputProcessing(table, [row]) + const enriched: Row[] = await outputProcessing(testTable, [row]) const [targetRow] = enriched const attachmentEntries = Array.isArray(targetRow[field]) ? targetRow[field] diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index 9675cc7271..7ac6840be1 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -2761,6 +2761,57 @@ describe.each([ }) }) + isSql && + describe("primaryDisplay", () => { + beforeAll(async () => { + let toRelateTable = await createTable({ + name: { + name: "name", + type: FieldType.STRING, + }, + }) + table = await config.api.table.save( + tableForDatasource(datasource, { + schema: { + name: { + name: "name", + type: FieldType.STRING, + }, + link: { + name: "link", + type: FieldType.LINK, + relationshipType: RelationshipType.MANY_TO_ONE, + tableId: toRelateTable._id!, + fieldName: "link", + }, + }, + }) + ) + toRelateTable = await config.api.table.get(toRelateTable._id!) + await config.api.table.save({ + ...toRelateTable, + primaryDisplay: "link", + }) + const relatedRows = await Promise.all([ + config.api.row.save(toRelateTable._id!, { name: "test" }), + ]) + await Promise.all([ + config.api.row.save(table._id!, { + name: "test", + link: relatedRows.map(row => row._id), + }), + ]) + }) + + it("should be able to query, primary display on related table shouldn't be used", async () => { + // this test makes sure that if a relationship has been specified as the primary display on a table + // it is ignored and another column is used instead + await expectQuery({}).toContain([ + { name: "test", link: [{ primaryDisplay: "test" }] }, + ]) + }) + }) + !isLucene && describe("$and", () => { beforeAll(async () => { diff --git a/packages/server/src/api/routes/tests/viewV2.spec.ts b/packages/server/src/api/routes/tests/viewV2.spec.ts index 4abd0f9b4c..079d85c684 100644 --- a/packages/server/src/api/routes/tests/viewV2.spec.ts +++ b/packages/server/src/api/routes/tests/viewV2.spec.ts @@ -30,6 +30,7 @@ import { withEnv as withCoreEnv, setEnv as setCoreEnv, } from "@budibase/backend-core" +import sdk from "../../../sdk" describe.each([ ["lucene", undefined], @@ -119,6 +120,7 @@ describe.each([ }) beforeEach(() => { + jest.clearAllMocks() mocks.licenses.useCloudFree() }) @@ -1489,83 +1491,189 @@ describe.each([ ) }) - isLucene && - it("in lucene, cannot override a view filter", async () => { - await config.api.row.save(table._id!, { - one: "foo", - two: "bar", - }) - const two = await config.api.row.save(table._id!, { - one: "foo2", - two: "bar2", - }) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - query: [ - { - operator: BasicOperator.EQUAL, - field: "two", - value: "bar2", - }, - ], - schema: { - id: { visible: true }, - one: { visible: false }, - two: { visible: true }, - }, - }) - - const response = await config.api.viewV2.search(view.id, { - query: { - equal: { - two: "bar", - }, - }, - }) - expect(response.rows).toHaveLength(1) - expect(response.rows).toEqual([ - expect.objectContaining({ _id: two._id }), - ]) + it("can query on top of the view filters", async () => { + await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + await config.api.row.save(table._id!, { + one: "foo2", + two: "bar2", + }) + const three = await config.api.row.save(table._id!, { + one: "foo3", + two: "bar3", }) - !isLucene && - it("can filter a view without a view filter", async () => { - const one = await config.api.row.save(table._id!, { - one: "foo", - two: "bar", - }) - await config.api.row.save(table._id!, { - one: "foo2", - two: "bar2", - }) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - id: { visible: true }, - one: { visible: false }, - two: { visible: true }, + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + query: [ + { + operator: BasicOperator.NOT_EQUAL, + field: "one", + value: "foo2", }, - }) + ], + schema: { + id: { visible: true }, + one: { visible: true }, + two: { visible: true }, + }, + }) - const response = await config.api.viewV2.search(view.id, { - query: { - equal: { - two: "bar", - }, + const response = await config.api.viewV2.search(view.id, { + query: { + [BasicOperator.EQUAL]: { + two: "bar3", }, - }) - expect(response.rows).toHaveLength(1) - expect(response.rows).toEqual([ + [BasicOperator.NOT_EMPTY]: { + two: null, + }, + }, + }) + expect(response.rows).toHaveLength(1) + expect(response.rows).toEqual( + expect.arrayContaining([expect.objectContaining({ _id: three._id })]) + ) + }) + + it("can query on top of the view filters (using or filters)", async () => { + const one = await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + await config.api.row.save(table._id!, { + one: "foo2", + two: "bar2", + }) + const three = await config.api.row.save(table._id!, { + one: "foo3", + two: "bar3", + }) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + query: [ + { + operator: BasicOperator.NOT_EQUAL, + field: "two", + value: "bar2", + }, + ], + schema: { + id: { visible: true }, + one: { visible: false }, + two: { visible: true }, + }, + }) + + const response = await config.api.viewV2.search(view.id, { + query: { + allOr: true, + [BasicOperator.NOT_EQUAL]: { + two: "bar", + }, + [BasicOperator.NOT_EMPTY]: { + two: null, + }, + }, + }) + expect(response.rows).toHaveLength(2) + expect(response.rows).toEqual( + expect.arrayContaining([ expect.objectContaining({ _id: one._id }), + expect.objectContaining({ _id: three._id }), ]) - }) + ) + }) + + isLucene && + it.each([true, false])( + "in lucene, cannot override a view filter", + async allOr => { + await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + const two = await config.api.row.save(table._id!, { + one: "foo2", + two: "bar2", + }) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + query: [ + { + operator: BasicOperator.EQUAL, + field: "two", + value: "bar2", + }, + ], + schema: { + id: { visible: true }, + one: { visible: false }, + two: { visible: true }, + }, + }) + + const response = await config.api.viewV2.search(view.id, { + query: { + allOr, + equal: { + two: "bar", + }, + }, + }) + expect(response.rows).toHaveLength(1) + expect(response.rows).toEqual([ + expect.objectContaining({ _id: two._id }), + ]) + } + ) !isLucene && - it("cannot bypass a view filter", async () => { + it.each([true, false])( + "can filter a view without a view filter", + async allOr => { + const one = await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + await config.api.row.save(table._id!, { + one: "foo2", + two: "bar2", + }) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + schema: { + id: { visible: true }, + one: { visible: false }, + two: { visible: true }, + }, + }) + + const response = await config.api.viewV2.search(view.id, { + query: { + allOr, + equal: { + two: "bar", + }, + }, + }) + expect(response.rows).toHaveLength(1) + expect(response.rows).toEqual([ + expect.objectContaining({ _id: one._id }), + ]) + } + ) + + !isLucene && + it.each([true, false])("cannot bypass a view filter", async allOr => { await config.api.row.save(table._id!, { one: "foo", two: "bar", @@ -1594,6 +1702,7 @@ describe.each([ const response = await config.api.viewV2.search(view.id, { query: { + allOr, equal: { two: "bar", }, @@ -1601,6 +1710,28 @@ describe.each([ }) expect(response.rows).toHaveLength(0) }) + + it("queries the row api passing the view fields only", async () => { + const searchSpy = jest.spyOn(sdk.rows, "search") + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + schema: { + id: { visible: true }, + one: { visible: false }, + }, + }) + + await config.api.viewV2.search(view.id, { query: {} }) + expect(searchSpy).toHaveBeenCalledTimes(1) + + expect(searchSpy).toHaveBeenCalledWith( + expect.objectContaining({ + fields: ["id"], + }) + ) + }) }) describe("permissions", () => { diff --git a/packages/server/src/automations/steps/branch.ts b/packages/server/src/automations/steps/branch.ts new file mode 100644 index 0000000000..56396488cb --- /dev/null +++ b/packages/server/src/automations/steps/branch.ts @@ -0,0 +1,51 @@ +import { + AutomationActionStepId, + AutomationCustomIOType, + AutomationIOType, + AutomationStepDefinition, + AutomationStepType, +} from "@budibase/types" + +export const definition: AutomationStepDefinition = { + name: "Branch", + icon: "Branch3", + tagline: "Branch from this step", + description: "Branching", + stepId: AutomationActionStepId.BRANCH, + internal: true, + features: {}, + inputs: {}, + schema: { + inputs: { + properties: { + branches: { + properties: { + name: { + type: AutomationIOType.STRING, + }, + condition: { + customType: AutomationCustomIOType.FILTERS, + }, + }, + }, + children: { + type: AutomationIOType.ARRAY, + }, + }, + required: ["conditions"], + }, + outputs: { + properties: { + branchName: { + type: AutomationIOType.STRING, + }, + result: { + type: AutomationIOType.BOOLEAN, + description: "Whether the condition was met", + }, + }, + required: ["output"], + }, + }, + type: AutomationStepType.LOGIC, +} diff --git a/packages/server/src/automations/tests/scenarios/scenarios.spec.ts b/packages/server/src/automations/tests/scenarios/scenarios.spec.ts index 7df902d61c..c0c30e46e4 100644 --- a/packages/server/src/automations/tests/scenarios/scenarios.spec.ts +++ b/packages/server/src/automations/tests/scenarios/scenarios.spec.ts @@ -7,7 +7,7 @@ import { ServerLogStepOutputs, FieldType, } from "@budibase/types" -import { createAutomationBuilder } from "../utilities/AutomationBuilder" +import { createAutomationBuilder } from "../utilities/AutomationTestBuilder" import { DatabaseName } from "../../../integrations/tests/utils" describe("Automation Scenarios", () => { @@ -23,6 +23,43 @@ describe("Automation Scenarios", () => { afterAll(setup.afterAll) + // eslint-disable-next-line jest/no-commented-out-tests + // describe("Branching automations", () => { + // eslint-disable-next-line jest/no-commented-out-tests + // it("should run an automation with a trigger, loop, and create row step", async () => { + // const builder = createAutomationBuilder({ + // name: "Test Trigger with Loop and Create Row", + // }) + + // builder + // .serverLog({ text: "Starting automation" }) + // .branch({ + // topLevelBranch1: { + // steps: stepBuilder => + // stepBuilder.serverLog({ text: "Branch 1" }).branch({ + // branch1: { + // steps: stepBuilder => + // stepBuilder.serverLog({ text: "Branch 1.1" }), + // condition: { notEmpty: { column: 10 } }, + // }, + // branch2: { + // steps: stepBuilder => + // stepBuilder.serverLog({ text: "Branch 1.2" }), + // condition: { fuzzy: { column: "sadsd" } }, + // }, + // }), + // condition: { equal: { column: 10 } }, + // }, + // topLevelBranch2: { + // steps: stepBuilder => stepBuilder.serverLog({ text: "Branch 2" }), + // condition: { equal: { column: 20 } }, + // }, + // }) + // .run() + // }) + + // }) + describe("Loop automations", () => { it("should run an automation with a trigger, loop, and create row step", async () => { const builder = createAutomationBuilder({ diff --git a/packages/server/src/automations/tests/utilities/AutomationBuilder.ts b/packages/server/src/automations/tests/utilities/AutomationTestBuilder.ts similarity index 69% rename from packages/server/src/automations/tests/utilities/AutomationBuilder.ts rename to packages/server/src/automations/tests/utilities/AutomationTestBuilder.ts index b3a9d57d06..16cab73b75 100644 --- a/packages/server/src/automations/tests/utilities/AutomationBuilder.ts +++ b/packages/server/src/automations/tests/utilities/AutomationTestBuilder.ts @@ -30,10 +30,13 @@ import { AutomationStepInputs, AutomationTriggerInputs, ServerLogStepInputs, + BranchStepInputs, + SearchFilters, + Branch, } from "@budibase/types" -import {} from "../../steps/loop" import TestConfiguration from "../../../tests/utilities/TestConfiguration" import * as setup from "../utilities" +import { definition } from "../../../automations/steps/branch" type TriggerOutputs = | RowCreatedTriggerOutputs @@ -43,69 +46,56 @@ type TriggerOutputs = | CronTriggerOutputs | undefined -class AutomationBuilder { - private automationConfig: Automation = { - name: "", - definition: { - steps: [], - trigger: {} as AutomationTrigger, - }, - type: "automation", - appId: setup.getConfig().getAppId(), - } - private config: TestConfiguration = setup.getConfig() - private triggerOutputs: TriggerOutputs - private triggerSet: boolean = false +type StepBuilderFunction = (stepBuilder: StepBuilder) => void - constructor(options: { name?: string } = {}) { - this.automationConfig.name = options.name || `Test Automation ${uuidv4()}` +type BranchConfig = { + [key: string]: { + steps: StepBuilderFunction + condition: SearchFilters + } +} + +class BaseStepBuilder { + protected steps: AutomationStep[] = [] + + protected step( + stepId: TStep, + stepSchema: Omit, + inputs: AutomationStepInputs + ): this { + this.steps.push({ + ...stepSchema, + inputs: inputs as any, + id: uuidv4(), + stepId, + }) + return this } - // TRIGGERS - rowSaved(inputs: RowCreatedTriggerInputs, outputs: RowCreatedTriggerOutputs) { - this.triggerOutputs = outputs - return this.trigger( - TRIGGER_DEFINITIONS.ROW_SAVED, - AutomationTriggerStepId.ROW_SAVED, - inputs, - outputs - ) - } + protected addBranchStep(branchConfig: BranchConfig): void { + const branchStepInputs: BranchStepInputs = { + branches: [] as Branch[], + children: {}, + } - rowUpdated( - inputs: RowUpdatedTriggerInputs, - outputs: RowUpdatedTriggerOutputs - ) { - this.triggerOutputs = outputs - return this.trigger( - TRIGGER_DEFINITIONS.ROW_UPDATED, - AutomationTriggerStepId.ROW_UPDATED, - inputs, - outputs - ) - } + Object.entries(branchConfig).forEach(([key, branch]) => { + const stepBuilder = new StepBuilder() + branch.steps(stepBuilder) - rowDeleted( - inputs: RowDeletedTriggerInputs, - outputs: RowDeletedTriggerOutputs - ) { - this.triggerOutputs = outputs - return this.trigger( - TRIGGER_DEFINITIONS.ROW_DELETED, - AutomationTriggerStepId.ROW_DELETED, - inputs, - outputs - ) - } + branchStepInputs.branches.push({ + name: key, + condition: branch.condition, + }) + branchStepInputs.children![key] = stepBuilder.build() + }) - appAction(outputs: AppActionTriggerOutputs, inputs?: AppActionTriggerInputs) { - this.triggerOutputs = outputs - return this.trigger( - TRIGGER_DEFINITIONS.APP, - AutomationTriggerStepId.APP, - inputs, - outputs - ) + const branchStep: AutomationStep = { + ...definition, + id: uuidv4(), + stepId: AutomationActionStepId.BRANCH, + inputs: branchStepInputs, + } + this.steps.push(branchStep) } // STEPS @@ -171,6 +161,84 @@ class AutomationBuilder { input ) } +} +class StepBuilder extends BaseStepBuilder { + build(): AutomationStep[] { + return this.steps + } + + branch(branchConfig: BranchConfig): this { + this.addBranchStep(branchConfig) + return this + } +} + +class AutomationBuilder extends BaseStepBuilder { + private automationConfig: Automation + private config: TestConfiguration + private triggerOutputs: any + private triggerSet: boolean = false + + constructor(options: { name?: string } = {}) { + super() + this.automationConfig = { + name: options.name || `Test Automation ${uuidv4()}`, + definition: { + steps: [], + trigger: {} as AutomationTrigger, + }, + type: "automation", + appId: setup.getConfig().getAppId(), + } + this.config = setup.getConfig() + } + + // TRIGGERS + rowSaved(inputs: RowCreatedTriggerInputs, outputs: RowCreatedTriggerOutputs) { + this.triggerOutputs = outputs + return this.trigger( + TRIGGER_DEFINITIONS.ROW_SAVED, + AutomationTriggerStepId.ROW_SAVED, + inputs, + outputs + ) + } + + rowUpdated( + inputs: RowUpdatedTriggerInputs, + outputs: RowUpdatedTriggerOutputs + ) { + this.triggerOutputs = outputs + return this.trigger( + TRIGGER_DEFINITIONS.ROW_UPDATED, + AutomationTriggerStepId.ROW_UPDATED, + inputs, + outputs + ) + } + + rowDeleted( + inputs: RowDeletedTriggerInputs, + outputs: RowDeletedTriggerOutputs + ) { + this.triggerOutputs = outputs + return this.trigger( + TRIGGER_DEFINITIONS.ROW_DELETED, + AutomationTriggerStepId.ROW_DELETED, + inputs, + outputs + ) + } + + appAction(outputs: AppActionTriggerOutputs, inputs?: AppActionTriggerInputs) { + this.triggerOutputs = outputs + return this.trigger( + TRIGGER_DEFINITIONS.APP, + AutomationTriggerStepId.APP, + inputs, + outputs + ) + } private trigger( triggerSchema: AutomationTriggerDefinition, @@ -181,7 +249,6 @@ class AutomationBuilder { if (this.triggerSet) { throw new Error("Only one trigger can be set for an automation.") } - this.automationConfig.definition.trigger = { ...triggerSchema, stepId, @@ -194,21 +261,20 @@ class AutomationBuilder { return this } - private step( - stepId: TStep, - stepSchema: Omit, - inputs: AutomationStepInputs - ): this { - this.automationConfig.definition.steps.push({ - ...stepSchema, - inputs: inputs as any, - id: uuidv4(), - stepId, - }) - return this + branch(branchConfig: BranchConfig): { + run: () => Promise + } { + this.addBranchStep(branchConfig) + return { + run: () => this.run(), + } } async run() { + if (!Object.keys(this.automationConfig.definition.trigger).length) { + throw new Error("Please add a trigger to this automation test") + } + this.automationConfig.definition.steps = this.steps const automation = await this.config.createAutomation(this.automationConfig) const results = await testAutomation( this.config, @@ -218,7 +284,9 @@ class AutomationBuilder { return this.processResults(results) } - private processResults(results: { body: AutomationResults }) { + private processResults(results: { + body: AutomationResults + }): AutomationResults { results.body.steps.shift() return { trigger: results.body.trigger, diff --git a/packages/server/src/db/linkedRows/index.ts b/packages/server/src/db/linkedRows/index.ts index 87f980600a..2da7e212b9 100644 --- a/packages/server/src/db/linkedRows/index.ts +++ b/packages/server/src/db/linkedRows/index.ts @@ -1,10 +1,10 @@ import LinkController from "./LinkController" import { getLinkDocuments, - getUniqueByProp, - getRelatedTableForField, - getLinkedTableIDs, getLinkedTable, + getLinkedTableIDs, + getRelatedTableForField, + getUniqueByProp, } from "./linkUtils" import flatten from "lodash/flatten" import { USER_METDATA_PREFIX } from "../utils" @@ -13,16 +13,25 @@ import { getGlobalUsersFromMetadata } from "../../utilities/global" import { processFormulas } from "../../utilities/rowProcessor" import { context } from "@budibase/backend-core" import { - Table, - Row, - LinkDocumentValue, - FieldType, ContextUser, + FieldType, + LinkDocumentValue, + Row, + Table, } from "@budibase/types" import sdk from "../../sdk" export { IncludeDocs, getLinkDocuments, createLinkView } from "./linkUtils" +const INVALID_DISPLAY_COLUMN_TYPE = [ + FieldType.LINK, + FieldType.ATTACHMENTS, + FieldType.ATTACHMENT_SINGLE, + FieldType.SIGNATURE_SINGLE, + FieldType.BB_REFERENCE, + FieldType.BB_REFERENCE_SINGLE, +] + /** * This functionality makes sure that when rows with links are created, updated or deleted they are processed * correctly - making sure that no stale links are left around and that all links have been made successfully. @@ -206,6 +215,31 @@ export async function attachFullLinkedDocs( return rows } +/** + * Finds a valid value for the primary display, avoiding columns which break things + * like relationships (can be circular). + * @param row The row to lift a value from for the primary display. + * @param table The related table to attempt to work out the primary display column from. + */ +function getPrimaryDisplayValue(row: Row, table?: Table) { + const primaryDisplay = table?.primaryDisplay + let invalid = true + if (primaryDisplay) { + const primaryDisplaySchema = table?.schema[primaryDisplay] + invalid = INVALID_DISPLAY_COLUMN_TYPE.includes(primaryDisplaySchema.type) + } + if (invalid || !primaryDisplay) { + const validKey = Object.keys(table?.schema || {}).find( + key => + table?.schema[key].type && + !INVALID_DISPLAY_COLUMN_TYPE.includes(table?.schema[key].type) + ) + return validKey ? row[validKey] : undefined + } else { + return row[primaryDisplay] + } +} + /** * This function will take the given enriched rows and squash the links to only contain the primary display field. * @param table The table from which the rows originated. @@ -232,9 +266,7 @@ export async function squashLinksToPrimaryDisplay( const linkTblId = link.tableId || getRelatedTableForField(table, column) const linkedTable = await getLinkedTable(linkTblId!, linkedTables) const obj: any = { _id: link._id } - if (linkedTable?.primaryDisplay && link[linkedTable.primaryDisplay]) { - obj.primaryDisplay = link[linkedTable.primaryDisplay] - } + obj.primaryDisplay = getPrimaryDisplayValue(link, linkedTable) newLinks.push(obj) } row[column] = newLinks diff --git a/packages/server/src/integrations/tests/sql.spec.ts b/packages/server/src/integrations/tests/sql.spec.ts index c4b2a69f7d..a6e63c434d 100644 --- a/packages/server/src/integrations/tests/sql.spec.ts +++ b/packages/server/src/integrations/tests/sql.spec.ts @@ -194,8 +194,8 @@ describe("SQL query builder", () => { }) ) expect(query).toEqual({ - bindings: ["john%", limit, 5000], - sql: `select * from (select * from (select * from (select * from "test" where LOWER("test"."name") LIKE :1 order by "test"."id" asc) where rownum <= :2) "test" order by "test"."id" asc) where rownum <= :3`, + bindings: ["john%", limit, "john%", 5000], + sql: `select * from (select * from (select * from (select * from "test" where LOWER("test"."name") LIKE :1 order by "test"."id" asc) where rownum <= :2) "test" where LOWER("test"."name") LIKE :3 order by "test"."id" asc) where rownum <= :4`, }) query = new Sql(SqlClient.ORACLE, limit)._query( @@ -208,9 +208,10 @@ describe("SQL query builder", () => { }, }) ) + const filterSet = [`%20%`, `%25%`, `%"john"%`, `%"mary"%`] expect(query).toEqual({ - bindings: ["%20%", "%25%", `%"john"%`, `%"mary"%`, limit, 5000], - sql: `select * from (select * from (select * from (select * from "test" where COALESCE(LOWER("test"."age"), '') LIKE :1 AND COALESCE(LOWER("test"."age"), '') LIKE :2 and COALESCE(LOWER("test"."name"), '') LIKE :3 AND COALESCE(LOWER("test"."name"), '') LIKE :4 order by "test"."id" asc) where rownum <= :5) "test" order by "test"."id" asc) where rownum <= :6`, + bindings: [...filterSet, limit, ...filterSet, 5000], + sql: `select * from (select * from (select * from (select * from "test" where COALESCE(LOWER("test"."age"), '') LIKE :1 AND COALESCE(LOWER("test"."age"), '') LIKE :2 and COALESCE(LOWER("test"."name"), '') LIKE :3 AND COALESCE(LOWER("test"."name"), '') LIKE :4 order by "test"."id" asc) where rownum <= :5) "test" where COALESCE(LOWER("test"."age"), '') LIKE :6 AND COALESCE(LOWER("test"."age"), '') LIKE :7 and COALESCE(LOWER("test"."name"), '') LIKE :8 AND COALESCE(LOWER("test"."name"), '') LIKE :9 order by "test"."id" asc) where rownum <= :10`, }) query = new Sql(SqlClient.ORACLE, limit)._query( @@ -223,8 +224,8 @@ describe("SQL query builder", () => { }) ) expect(query).toEqual({ - bindings: [`%jo%`, limit, 5000], - sql: `select * from (select * from (select * from (select * from "test" where LOWER("test"."name") LIKE :1 order by "test"."id" asc) where rownum <= :2) "test" order by "test"."id" asc) where rownum <= :3`, + bindings: [`%jo%`, limit, `%jo%`, 5000], + sql: `select * from (select * from (select * from (select * from "test" where LOWER("test"."name") LIKE :1 order by "test"."id" asc) where rownum <= :2) "test" where LOWER("test"."name") LIKE :3 order by "test"."id" asc) where rownum <= :4`, }) }) @@ -241,8 +242,8 @@ describe("SQL query builder", () => { ) expect(query).toEqual({ - bindings: ["John", limit, 5000], - sql: `select * from (select * from (select * from (select * from "test" where (to_char("test"."name") IS NOT NULL AND to_char("test"."name") = :1) order by "test"."id" asc) where rownum <= :2) "test" order by "test"."id" asc) where rownum <= :3`, + bindings: ["John", limit, "John", 5000], + sql: `select * from (select * from (select * from (select * from "test" where (to_char("test"."name") IS NOT NULL AND to_char("test"."name") = :1) order by "test"."id" asc) where rownum <= :2) "test" where (to_char("test"."name") IS NOT NULL AND to_char("test"."name") = :3) order by "test"."id" asc) where rownum <= :4`, }) }) @@ -259,8 +260,8 @@ describe("SQL query builder", () => { ) expect(query).toEqual({ - bindings: ["John", limit, 5000], - sql: `select * from (select * from (select * from (select * from "test" where (to_char("test"."name") IS NOT NULL AND to_char("test"."name") != :1) OR to_char("test"."name") IS NULL order by "test"."id" asc) where rownum <= :2) "test" order by "test"."id" asc) where rownum <= :3`, + bindings: ["John", limit, "John", 5000], + sql: `select * from (select * from (select * from (select * from "test" where (to_char("test"."name") IS NOT NULL AND to_char("test"."name") != :1) OR to_char("test"."name") IS NULL order by "test"."id" asc) where rownum <= :2) "test" where (to_char("test"."name") IS NOT NULL AND to_char("test"."name") != :3) OR to_char("test"."name") IS NULL order by "test"."id" asc) where rownum <= :4`, }) }) }) diff --git a/packages/server/src/integrations/tests/sqlAlias.spec.ts b/packages/server/src/integrations/tests/sqlAlias.spec.ts index 0b433896bf..6f34f4eb89 100644 --- a/packages/server/src/integrations/tests/sqlAlias.spec.ts +++ b/packages/server/src/integrations/tests/sqlAlias.spec.ts @@ -97,13 +97,14 @@ describe("Captures of real examples", () => { const filters = queryJson.filters?.oneOf?.taskid as number[] let query = new Sql(SqlClient.POSTGRES, limit)._query(queryJson) expect(query).toEqual({ - bindings: [...filters, limit, limit], - sql: multiline(`select "a"."executorid" as "a.executorid", "a"."taskname" as "a.taskname", - "a"."taskid" as "a.taskid", "a"."completed" as "a.completed", "a"."qaid" as "a.qaid", - "b"."productname" as "b.productname", "b"."productid" as "b.productid" - from (select * from "tasks" as "a" where "a"."taskid" in ($1, $2) order by "a"."taskid" asc limit $3) as "a" - left join "products_tasks" as "c" on "a"."taskid" = "c"."taskid" - left join "products" as "b" on "b"."productid" = "c"."productid" order by "a"."taskid" asc limit $4`), + bindings: [...filters, limit, ...filters, limit], + sql: multiline( + `select "a"."executorid" as "a.executorid", "a"."taskname" as "a.taskname", "a"."taskid" as "a.taskid", + "a"."completed" as "a.completed", "a"."qaid" as "a.qaid", "b"."productname" as "b.productname", "b"."productid" as "b.productid" + from (select * from "tasks" as "a" where "a"."taskid" in ($1, $2) order by "a"."taskid" asc limit $3) as "a" + left join "products_tasks" as "c" on "a"."taskid" = "c"."taskid" left join "products" as "b" on "b"."productid" = "c"."productid" + where "a"."taskid" in ($4, $5) order by "a"."taskid" asc limit $6` + ), }) }) @@ -123,6 +124,7 @@ describe("Captures of real examples", () => { rangeValue.low, rangeValue.high, equalValue, + true, limit, ], sql: expect.stringContaining( @@ -186,8 +188,9 @@ describe("Captures of real examples", () => { }, queryJson) expect(returningQuery).toEqual({ sql: multiline(`select top (@p0) * from (select top (@p1) * from [people] where CASE WHEN [people].[name] = @p2 - THEN 1 ELSE 0 END = 1 and CASE WHEN [people].[age] = @p3 THEN 1 ELSE 0 END = 1 order by [people].[name] asc) as [people]`), - bindings: [5000, 1, "Test", 22], + THEN 1 ELSE 0 END = 1 and CASE WHEN [people].[age] = @p3 THEN 1 ELSE 0 END = 1 order by [people].[name] asc) as [people] + where CASE WHEN [people].[name] = @p4 THEN 1 ELSE 0 END = 1 and CASE WHEN [people].[age] = @p5 THEN 1 ELSE 0 END = 1`), + bindings: [5000, 1, "Test", 22, "Test", 22], }) }) }) diff --git a/packages/server/src/sdk/app/rows/queryUtils.ts b/packages/server/src/sdk/app/rows/queryUtils.ts new file mode 100644 index 0000000000..65f400a1d9 --- /dev/null +++ b/packages/server/src/sdk/app/rows/queryUtils.ts @@ -0,0 +1,116 @@ +import { db } from "@budibase/backend-core" +import { + FieldType, + isLogicalSearchOperator, + SearchFilters, + Table, +} from "@budibase/types" +import { cloneDeep } from "lodash/fp" +import sdk from "../../../sdk" + +export const removeInvalidFilters = ( + filters: SearchFilters, + validFields: string[] +) => { + const result = cloneDeep(filters) + + validFields = validFields.map(f => f.toLowerCase()) + for (const filterKey of Object.keys(result) as (keyof SearchFilters)[]) { + const filter = result[filterKey] + if (!filter || typeof filter !== "object") { + continue + } + if (isLogicalSearchOperator(filterKey)) { + const resultingConditions: SearchFilters[] = [] + for (const condition of filter.conditions) { + const resultingCondition = removeInvalidFilters(condition, validFields) + if (Object.keys(resultingCondition).length) { + resultingConditions.push(resultingCondition) + } + } + if (resultingConditions.length) { + filter.conditions = resultingConditions + } else { + delete result[filterKey] + } + continue + } + + for (const columnKey of Object.keys(filter)) { + const possibleKeys = [columnKey, db.removeKeyNumbering(columnKey)].map( + c => c.toLowerCase() + ) + if (!validFields.some(f => possibleKeys.includes(f.toLowerCase()))) { + delete filter[columnKey as keyof typeof filter] + } + } + if (!Object.keys(filter).length) { + delete result[filterKey] + } + } + + return result +} + +export const getQueryableFields = async ( + fields: string[], + table: Table +): Promise => { + const extractTableFields = async ( + table: Table, + allowedFields: string[], + fromTables: string[], + opts?: { noRelationships?: boolean } + ): Promise => { + const result = [] + for (const field of Object.keys(table.schema).filter( + f => allowedFields.includes(f) && table.schema[f].visible !== false + )) { + const subSchema = table.schema[field] + const isRelationship = subSchema.type === FieldType.LINK + // avoid relationship loops + if ( + isRelationship && + (opts?.noRelationships || fromTables.includes(subSchema.tableId)) + ) { + continue + } + if (isRelationship) { + try { + const relatedTable = await sdk.tables.getTable(subSchema.tableId) + const relatedFields = await extractTableFields( + relatedTable, + Object.keys(relatedTable.schema), + [...fromTables, subSchema.tableId], + // don't let it recurse back and forth between relationships + { noRelationships: true } + ) + + result.push( + ...relatedFields.flatMap(f => [ + `${subSchema.name}.${f}`, + // should be able to filter by relationship using table name + `${relatedTable.name}.${f}`, + ]) + ) + } catch (err: any) { + // if related table is removed, ignore + if (err.status !== 404) { + throw err + } + } + } else { + result.push(field) + } + } + return result + } + + const result = [ + "_id", // Querying by _id is always allowed, even if it's never part of the schema + ] + + result.push(...(await extractTableFields(table, fields, [table._id!]))) + + return result +} diff --git a/packages/server/src/sdk/app/rows/search.ts b/packages/server/src/sdk/app/rows/search.ts index f199a4f6e1..eac807ffa2 100644 --- a/packages/server/src/sdk/app/rows/search.ts +++ b/packages/server/src/sdk/app/rows/search.ts @@ -14,6 +14,7 @@ import sdk from "../../index" import { searchInputMapping } from "./search/utils" import { features } from "@budibase/backend-core" import tracer from "dd-trace" +import { getQueryableFields, removeInvalidFilters } from "./queryUtils" export { isValidFilter } from "../../../integrations/utils" @@ -73,6 +74,18 @@ export async function search( const table = await sdk.tables.getTable(options.tableId) options = searchInputMapping(table, options) + if (options.query) { + const tableFields = Object.keys(table.schema).filter( + f => table.schema[f].visible !== false + ) + + const queriableFields = await getQueryableFields( + options.fields?.filter(f => tableFields.includes(f)) ?? tableFields, + table + ) + options.query = removeInvalidFilters(options.query, queriableFields) + } + let result: SearchResponse if (isExternalTable) { span?.addTags({ searchType: "external" }) diff --git a/packages/server/src/sdk/app/rows/search/filters.ts b/packages/server/src/sdk/app/rows/search/filters.ts index ccce0ab86a..4049fc5352 100644 --- a/packages/server/src/sdk/app/rows/search/filters.ts +++ b/packages/server/src/sdk/app/rows/search/filters.ts @@ -5,6 +5,7 @@ import { Table, } from "@budibase/types" import { isPlainObject } from "lodash" +import { dataFilters } from "@budibase/shared-core" export function getRelationshipColumns(table: Table): { name: string @@ -58,5 +59,7 @@ export function updateFilterKeys( } } } - return filters + return dataFilters.recurseLogicalOperators(filters, (f: SearchFilters) => { + return updateFilterKeys(f, updates) + }) } diff --git a/packages/server/src/sdk/app/rows/search/internal/sqs.ts b/packages/server/src/sdk/app/rows/search/internal/sqs.ts index 4bfa8f8fa5..6736ff6abf 100644 --- a/packages/server/src/sdk/app/rows/search/internal/sqs.ts +++ b/packages/server/src/sdk/app/rows/search/internal/sqs.ts @@ -297,7 +297,7 @@ export async function search( throw new Error("Unable to find table") } - const relationships = buildInternalRelationships(table) + const relationships = buildInternalRelationships(table, allTables) const searchFilters: SearchFilters = { ...cleanupFilters(query, table, allTables), diff --git a/packages/server/src/sdk/app/rows/search/tests/search.spec.ts b/packages/server/src/sdk/app/rows/search/tests/search.spec.ts index 8603be2fe8..558725c1ed 100644 --- a/packages/server/src/sdk/app/rows/search/tests/search.spec.ts +++ b/packages/server/src/sdk/app/rows/search/tests/search.spec.ts @@ -1,4 +1,11 @@ -import { Datasource, FieldType, Row, Table } from "@budibase/types" +import { + AutoColumnFieldMetadata, + AutoFieldSubType, + Datasource, + FieldType, + NumberFieldMetadata, + Table, +} from "@budibase/types" import TestConfiguration from "../../../../../tests/utilities/TestConfiguration" import { search } from "../../../../../sdk/app/rows/search" @@ -32,7 +39,6 @@ describe.each([ let envCleanup: (() => void) | undefined let datasource: Datasource | undefined let table: Table - let rows: Row[] beforeAll(async () => { await withCoreEnv({ TENANT_FEATURE_FLAGS: isSqs ? "*:SQS" : "" }, () => @@ -50,16 +56,28 @@ describe.each([ datasource: await dsProvider, }) } + }) + + beforeEach(async () => { + const idFieldSchema: NumberFieldMetadata | AutoColumnFieldMetadata = + isInternal + ? { + name: "id", + type: FieldType.AUTO, + subtype: AutoFieldSubType.AUTO_ID, + autocolumn: true, + } + : { + name: "id", + type: FieldType.NUMBER, + autocolumn: true, + } table = await config.api.table.save( tableForDatasource(datasource, { primary: ["id"], schema: { - id: { - name: "id", - type: FieldType.NUMBER, - autocolumn: true, - }, + id: idFieldSchema, name: { name: "name", type: FieldType.STRING, @@ -80,16 +98,13 @@ describe.each([ }) ) - rows = [] for (let i = 0; i < 10; i++) { - rows.push( - await config.api.row.save(table._id!, { - name: generator.first(), - surname: generator.last(), - age: generator.age(), - address: generator.address(), - }) - ) + await config.api.row.save(table._id!, { + name: generator.first(), + surname: generator.last(), + age: generator.age(), + address: generator.address(), + }) } }) @@ -137,4 +152,100 @@ describe.each([ ) }) }) + + it("does not allow accessing hidden fields", async () => { + await config.doInContext(config.appId, async () => { + await config.api.table.save({ + ...table, + schema: { + ...table.schema, + name: { + ...table.schema.name, + visible: true, + }, + age: { + ...table.schema.age, + visible: false, + }, + }, + }) + const result = await search({ + tableId: table._id!, + query: {}, + }) + expect(result.rows).toHaveLength(10) + for (const row of result.rows) { + const keys = Object.keys(row) + expect(keys).toContain("name") + expect(keys).toContain("surname") + expect(keys).toContain("address") + expect(keys).not.toContain("age") + } + }) + }) + + it("does not allow accessing hidden fields even if requested", async () => { + await config.doInContext(config.appId, async () => { + await config.api.table.save({ + ...table, + schema: { + ...table.schema, + name: { + ...table.schema.name, + visible: true, + }, + age: { + ...table.schema.age, + visible: false, + }, + }, + }) + const result = await search({ + tableId: table._id!, + query: {}, + fields: ["name", "age"], + }) + expect(result.rows).toHaveLength(10) + for (const row of result.rows) { + const keys = Object.keys(row) + expect(keys).toContain("name") + expect(keys).not.toContain("age") + expect(keys).not.toContain("surname") + expect(keys).not.toContain("address") + } + }) + }) + + !isLucene && + it.each([ + [["id", "name", "age"], 3], + [["name", "age"], 10], + ])( + "cannot query by non search fields (fields: %s)", + async (queryFields, expectedRows) => { + await config.doInContext(config.appId, async () => { + const { rows } = await search({ + tableId: table._id!, + query: { + $or: { + conditions: [ + { + $and: { + conditions: [ + { range: { id: { low: 2, high: 4 } } }, + { range: { id: { low: 3, high: 5 } } }, + ], + }, + }, + { equal: { id: 7 } }, + ], + }, + }, + fields: queryFields, + }) + + expect(rows).toHaveLength(expectedRows) + }) + } + ) }) diff --git a/packages/server/src/sdk/app/rows/sqlAlias.ts b/packages/server/src/sdk/app/rows/sqlAlias.ts index 664e64057b..535709791d 100644 --- a/packages/server/src/sdk/app/rows/sqlAlias.ts +++ b/packages/server/src/sdk/app/rows/sqlAlias.ts @@ -12,6 +12,7 @@ import { getSQLClient } from "./utils" import { cloneDeep } from "lodash" import datasources from "../datasources" import { BudibaseInternalDB } from "../../../db/utils" +import { dataFilters } from "@budibase/shared-core" type PerformQueryFunction = ( datasource: Datasource, @@ -199,16 +200,20 @@ export default class AliasTables { ) } if (json.filters) { - for (let [filterKey, filter] of Object.entries(json.filters)) { - if (typeof filter !== "object") { - continue + const aliasFilters = (filters: SearchFilters): SearchFilters => { + for (let [filterKey, filter] of Object.entries(filters)) { + if (typeof filter !== "object") { + continue + } + const aliasedFilters: typeof filter = {} + for (let key of Object.keys(filter)) { + aliasedFilters[this.aliasField(key)] = filter[key] + } + filters[filterKey as keyof SearchFilters] = aliasedFilters } - const aliasedFilters: typeof filter = {} - for (let key of Object.keys(filter)) { - aliasedFilters[this.aliasField(key)] = filter[key] - } - json.filters[filterKey as keyof SearchFilters] = aliasedFilters + return dataFilters.recurseLogicalOperators(filters, aliasFilters) } + json.filters = aliasFilters(json.filters) } if (json.meta?.table) { this.getAlias(json.meta.table.name) diff --git a/packages/server/src/sdk/app/rows/tests/queryUtils.spec.ts b/packages/server/src/sdk/app/rows/tests/queryUtils.spec.ts new file mode 100644 index 0000000000..aabc359484 --- /dev/null +++ b/packages/server/src/sdk/app/rows/tests/queryUtils.spec.ts @@ -0,0 +1,505 @@ +import { + FieldType, + RelationshipType, + SearchFilters, + Table, +} from "@budibase/types" +import { getQueryableFields, removeInvalidFilters } from "../queryUtils" +import { structures } from "../../../../api/routes/tests/utilities" +import TestConfiguration from "../../../../tests/utilities/TestConfiguration" + +describe("query utils", () => { + describe("removeInvalidFilters", () => { + const fullFilters: SearchFilters = { + equal: { one: "foo" }, + $or: { + conditions: [ + { + equal: { one: "foo2", two: "bar" }, + notEmpty: { one: null }, + $and: { + conditions: [ + { + equal: { three: "baz" }, + notEmpty: { forth: null }, + }, + ], + }, + }, + ], + }, + $and: { + conditions: [{ equal: { one: "foo2" }, notEmpty: { one: null } }], + }, + } + + it("can filter empty queries", () => { + const filters: SearchFilters = {} + const result = removeInvalidFilters(filters, []) + expect(result).toEqual({}) + }) + + it("does not trim any valid field", () => { + const result = removeInvalidFilters(fullFilters, [ + "one", + "two", + "three", + "forth", + ]) + expect(result).toEqual(fullFilters) + }) + + it("trims invalid field", () => { + const result = removeInvalidFilters(fullFilters, [ + "one", + "three", + "forth", + ]) + expect(result).toEqual({ + equal: { one: "foo" }, + $or: { + conditions: [ + { + equal: { one: "foo2" }, + notEmpty: { one: null }, + $and: { + conditions: [ + { + equal: { three: "baz" }, + notEmpty: { forth: null }, + }, + ], + }, + }, + ], + }, + $and: { + conditions: [{ equal: { one: "foo2" }, notEmpty: { one: null } }], + }, + }) + }) + + it("trims invalid field keeping a valid fields", () => { + const result = removeInvalidFilters(fullFilters, ["three", "forth"]) + const expected: SearchFilters = { + $or: { + conditions: [ + { + $and: { + conditions: [ + { + equal: { three: "baz" }, + notEmpty: { forth: null }, + }, + ], + }, + }, + ], + }, + } + expect(result).toEqual(expected) + }) + + it("keeps filter key numering", () => { + const prefixedFilters: SearchFilters = { + equal: { "1:one": "foo" }, + $or: { + conditions: [ + { + equal: { "2:one": "foo2", "3:two": "bar" }, + notEmpty: { "4:one": null }, + $and: { + conditions: [ + { + equal: { "5:three": "baz", two: "bar2" }, + notEmpty: { forth: null }, + }, + ], + }, + }, + ], + }, + $and: { + conditions: [{ equal: { "6:one": "foo2" }, notEmpty: { one: null } }], + }, + } + + const result = removeInvalidFilters(prefixedFilters, [ + "one", + "three", + "forth", + ]) + expect(result).toEqual({ + equal: { "1:one": "foo" }, + $or: { + conditions: [ + { + equal: { "2:one": "foo2" }, + notEmpty: { "4:one": null }, + $and: { + conditions: [ + { + equal: { "5:three": "baz" }, + notEmpty: { forth: null }, + }, + ], + }, + }, + ], + }, + $and: { + conditions: [{ equal: { "6:one": "foo2" }, notEmpty: { one: null } }], + }, + }) + }) + + it("handles relationship filters", () => { + const prefixedFilters: SearchFilters = { + $or: { + conditions: [ + { equal: { "1:other.one": "foo" } }, + { + equal: { + "2:other.one": "foo2", + "3:other.two": "bar", + "4:other.three": "baz", + }, + }, + { equal: { "another.three": "baz2" } }, + ], + }, + } + + const result = removeInvalidFilters(prefixedFilters, [ + "other.one", + "other.two", + "another.three", + ]) + expect(result).toEqual({ + $or: { + conditions: [ + { equal: { "1:other.one": "foo" } }, + { equal: { "2:other.one": "foo2", "3:other.two": "bar" } }, + { equal: { "another.three": "baz2" } }, + ], + }, + }) + }) + }) + + describe("getQueryableFields", () => { + const config = new TestConfiguration() + + beforeAll(async () => { + await config.init() + }) + + it("returns table schema fields and _id", async () => { + const table: Table = await config.api.table.save({ + ...structures.basicTable(), + schema: { + name: { name: "name", type: FieldType.STRING }, + age: { name: "age", type: FieldType.NUMBER }, + }, + }) + + const result = await getQueryableFields(Object.keys(table.schema), table) + expect(result).toEqual(["_id", "name", "age"]) + }) + + it("excludes hidden fields", async () => { + const table: Table = await config.api.table.save({ + ...structures.basicTable(), + schema: { + name: { name: "name", type: FieldType.STRING }, + age: { name: "age", type: FieldType.NUMBER, visible: false }, + }, + }) + + const result = await getQueryableFields(Object.keys(table.schema), table) + expect(result).toEqual(["_id", "name"]) + }) + + it("includes relationship fields", async () => { + const aux: Table = await config.api.table.save({ + ...structures.basicTable(), + name: "auxTable", + schema: { + title: { name: "title", type: FieldType.STRING }, + name: { name: "name", type: FieldType.STRING }, + }, + }) + + const table: Table = await config.api.table.save({ + ...structures.basicTable(), + schema: { + name: { name: "name", type: FieldType.STRING }, + aux: { + name: "aux", + type: FieldType.LINK, + tableId: aux._id!, + relationshipType: RelationshipType.ONE_TO_MANY, + fieldName: "table", + }, + }, + }) + + const result = await config.doInContext(config.appId, () => { + return getQueryableFields(Object.keys(table.schema), table) + }) + expect(result).toEqual([ + "_id", + "name", + "aux.title", + "auxTable.title", + "aux.name", + "auxTable.name", + ]) + }) + + it("excludes hidden relationship fields", async () => { + const aux: Table = await config.api.table.save({ + ...structures.basicTable(), + name: "auxTable", + schema: { + title: { name: "title", type: FieldType.STRING, visible: false }, + name: { name: "name", type: FieldType.STRING, visible: true }, + }, + }) + + const table: Table = await config.api.table.save({ + ...structures.basicTable(), + schema: { + name: { name: "name", type: FieldType.STRING }, + aux: { + name: "aux", + type: FieldType.LINK, + tableId: aux._id!, + relationshipType: RelationshipType.ONE_TO_MANY, + fieldName: "table", + }, + }, + }) + + const result = await config.doInContext(config.appId, () => { + return getQueryableFields(Object.keys(table.schema), table) + }) + expect(result).toEqual(["_id", "name", "aux.name", "auxTable.name"]) + }) + + it("excludes all relationship fields if hidden", async () => { + const aux: Table = await config.api.table.save({ + ...structures.basicTable(), + name: "auxTable", + schema: { + title: { name: "title", type: FieldType.STRING, visible: false }, + name: { name: "name", type: FieldType.STRING, visible: true }, + }, + }) + + const table: Table = await config.api.table.save({ + ...structures.basicTable(), + schema: { + name: { name: "name", type: FieldType.STRING }, + aux: { + name: "aux", + type: FieldType.LINK, + tableId: aux._id!, + relationshipType: RelationshipType.ONE_TO_MANY, + fieldName: "table", + visible: false, + }, + }, + }) + + const result = await config.doInContext(config.appId, () => { + return getQueryableFields(Object.keys(table.schema), table) + }) + expect(result).toEqual(["_id", "name"]) + }) + + describe("nested relationship", () => { + describe("one-to-many", () => { + let table: Table, aux1: Table, aux2: Table + + beforeAll(async () => { + const { _id: aux1Id } = await config.api.table.save({ + ...structures.basicTable(), + name: "aux1Table", + schema: { + name: { name: "name", type: FieldType.STRING }, + }, + }) + const { _id: aux2Id } = await config.api.table.save({ + ...structures.basicTable(), + name: "aux2Table", + schema: { + title: { name: "title", type: FieldType.STRING }, + aux1_1: { + name: "aux1_1", + type: FieldType.LINK, + tableId: aux1Id!, + relationshipType: RelationshipType.ONE_TO_MANY, + fieldName: "aux2_1", + }, + aux1_2: { + name: "aux1_2", + type: FieldType.LINK, + tableId: aux1Id!, + relationshipType: RelationshipType.ONE_TO_MANY, + fieldName: "aux2_2", + }, + }, + }) + + const { _id: tableId } = await config.api.table.save({ + ...structures.basicTable(), + schema: { + name: { name: "name", type: FieldType.STRING }, + aux1: { + name: "aux1", + type: FieldType.LINK, + tableId: aux1Id!, + relationshipType: RelationshipType.ONE_TO_MANY, + fieldName: "table", + }, + aux2: { + name: "aux2", + type: FieldType.LINK, + tableId: aux2Id!, + relationshipType: RelationshipType.ONE_TO_MANY, + fieldName: "table", + }, + }, + }) + + // We need to refech them to get the updated foreign keys + aux1 = await config.api.table.get(aux1Id!) + aux2 = await config.api.table.get(aux2Id!) + table = await config.api.table.get(tableId!) + }) + + it("includes nested relationship fields from main table", async () => { + const result = await config.doInContext(config.appId, () => { + return getQueryableFields(Object.keys(table.schema), table) + }) + expect(result).toEqual([ + "_id", + "name", + // aux1 primitive props + "aux1.name", + "aux1Table.name", + + // aux2 primitive props + "aux2.title", + "aux2Table.title", + ]) + }) + + it("includes nested relationship fields from aux 1 table", async () => { + const result = await config.doInContext(config.appId, () => { + return getQueryableFields(Object.keys(aux1.schema), aux1) + }) + expect(result).toEqual([ + "_id", + "name", + + // aux2_1 primitive props + "aux2_1.title", + "aux2Table.title", + + // aux2_2 primitive props + "aux2_2.title", + "aux2Table.title", + + // table primitive props + "table.name", + "TestTable.name", + ]) + }) + + it("includes nested relationship fields from aux 2 table", async () => { + const result = await config.doInContext(config.appId, () => { + return getQueryableFields(Object.keys(aux2.schema), aux2) + }) + expect(result).toEqual([ + "_id", + "title", + + // aux1_1 primitive props + "aux1_1.name", + "aux1Table.name", + + // aux1_2 primitive props + "aux1_2.name", + "aux1Table.name", + + // table primitive props + "table.name", + "TestTable.name", + ]) + }) + }) + + describe("many-to-many", () => { + let table: Table, aux: Table + + beforeAll(async () => { + const { _id: auxId } = await config.api.table.save({ + ...structures.basicTable(), + name: "auxTable", + schema: { + title: { name: "title", type: FieldType.STRING }, + }, + }) + + const { _id: tableId } = await config.api.table.save({ + ...structures.basicTable(), + schema: { + name: { name: "name", type: FieldType.STRING }, + aux: { + name: "aux", + type: FieldType.LINK, + tableId: auxId!, + relationshipType: RelationshipType.MANY_TO_MANY, + fieldName: "table", + }, + }, + }) + + // We need to refech them to get the updated foreign keys + aux = await config.api.table.get(auxId!) + table = await config.api.table.get(tableId!) + }) + + it("includes nested relationship fields from main table", async () => { + const result = await config.doInContext(config.appId, () => { + return getQueryableFields(Object.keys(table.schema), table) + }) + expect(result).toEqual([ + "_id", + "name", + + // deep 1 aux primitive props + "aux.title", + "auxTable.title", + ]) + }) + + it("includes nested relationship fields from aux table", async () => { + const result = await config.doInContext(config.appId, () => { + return getQueryableFields(Object.keys(aux.schema), aux) + }) + expect(result).toEqual([ + "_id", + "title", + + // deep 1 dependency primitive props + "table.name", + "TestTable.name", + ]) + }) + }) + }) + }) +}) diff --git a/packages/server/src/utilities/rowProcessor/index.ts b/packages/server/src/utilities/rowProcessor/index.ts index 62a3b2dd74..4b2fd83882 100644 --- a/packages/server/src/utilities/rowProcessor/index.ts +++ b/packages/server/src/utilities/rowProcessor/index.ts @@ -26,8 +26,13 @@ import { processOutputBBReferences, } from "./bbReferenceProcessor" import { isExternalTableID } from "../../integrations/utils" -import { helpers } from "@budibase/shared-core" +import { + helpers, + PROTECTED_EXTERNAL_COLUMNS, + PROTECTED_INTERNAL_COLUMNS, +} from "@budibase/shared-core" import { processString } from "@budibase/string-templates" +import { isUserMetadataTable } from "../../api/controllers/row/utils" export * from "./utils" export * from "./attachments" @@ -53,9 +58,9 @@ export async function processAutoColumn( row: Row, opts?: AutoColumnProcessingOpts ) { - let noUser = !userId - let isUserTable = table._id === InternalTables.USER_METADATA - let now = new Date().toISOString() + const noUser = !userId + const isUserTable = table._id === InternalTables.USER_METADATA + const now = new Date().toISOString() // if a row doesn't have a revision then it doesn't exist yet const creating = !row._rev // check its not user table, or whether any of the processing options have been disabled @@ -111,7 +116,7 @@ async function processDefaultValues(table: Table, row: Row) { ctx.user = user } - for (let [key, schema] of Object.entries(table.schema)) { + for (const [key, schema] of Object.entries(table.schema)) { if ("default" in schema && schema.default != null && row[key] == null) { const processed = await processString(schema.default, ctx) @@ -165,10 +170,10 @@ export async function inputProcessing( row: Row, opts?: AutoColumnProcessingOpts ) { - let clonedRow = cloneDeep(row) + const clonedRow = cloneDeep(row) const dontCleanseKeys = ["type", "_id", "_rev", "tableId"] - for (let [key, value] of Object.entries(clonedRow)) { + for (const [key, value] of Object.entries(clonedRow)) { const field = table.schema[key] // cleanse fields that aren't in the schema if (!field) { @@ -268,13 +273,13 @@ export async function outputProcessing( } // process complex types: attachments, bb references... - for (let [property, column] of Object.entries(table.schema)) { + for (const [property, column] of Object.entries(table.schema)) { if ( column.type === FieldType.ATTACHMENTS || column.type === FieldType.ATTACHMENT_SINGLE || column.type === FieldType.SIGNATURE_SINGLE ) { - for (let row of enriched) { + for (const row of enriched) { if (row[property] == null) { continue } @@ -299,7 +304,7 @@ export async function outputProcessing( !opts.skipBBReferences && column.type == FieldType.BB_REFERENCE ) { - for (let row of enriched) { + for (const row of enriched) { row[property] = await processOutputBBReferences( row[property], column.subtype @@ -309,14 +314,14 @@ export async function outputProcessing( !opts.skipBBReferences && column.type == FieldType.BB_REFERENCE_SINGLE ) { - for (let row of enriched) { + for (const row of enriched) { row[property] = await processOutputBBReference( row[property], column.subtype ) } } else if (column.type === FieldType.DATETIME && column.timeOnly) { - for (let row of enriched) { + for (const row of enriched) { if (row[property] instanceof Date) { const hours = row[property].getUTCHours().toString().padStart(2, "0") const minutes = row[property] @@ -343,14 +348,36 @@ export async function outputProcessing( )) as Row[] } // remove null properties to match internal API - if (isExternalTableID(table._id!)) { - for (let row of enriched) { - for (let key of Object.keys(row)) { + const isExternal = isExternalTableID(table._id!) + if (isExternal) { + for (const row of enriched) { + for (const key of Object.keys(row)) { if (row[key] === null) { delete row[key] } } } } + + if (!isUserMetadataTable(table._id!)) { + const protectedColumns = isExternal + ? PROTECTED_EXTERNAL_COLUMNS + : PROTECTED_INTERNAL_COLUMNS + + const tableFields = Object.keys(table.schema).filter( + f => table.schema[f].visible !== false + ) + const fields = [...tableFields, ...protectedColumns].map(f => + f.toLowerCase() + ) + for (const row of enriched) { + for (const key of Object.keys(row)) { + if (!fields.includes(key.toLowerCase())) { + delete row[key] + } + } + } + } + return (wasArray ? enriched : enriched[0]) as T } diff --git a/packages/shared-core/src/filters.ts b/packages/shared-core/src/filters.ts index 2dd485a8a0..fa0b5c92ed 100644 --- a/packages/shared-core/src/filters.ts +++ b/packages/shared-core/src/filters.ts @@ -113,6 +113,20 @@ export const NoEmptyFilterStrings = [ OperatorOptions.In.value, ] as (keyof SearchQueryFields)[] +export function recurseLogicalOperators( + filters: SearchFilters, + fn: (f: SearchFilters) => SearchFilters +) { + for (const logical of Object.values(LogicalOperator)) { + if (filters[logical]) { + filters[logical]!.conditions = filters[logical]!.conditions.map( + condition => fn(condition) + ) + } + } + return filters +} + /** * Removes any fields that contain empty strings that would cause inconsistent * behaviour with how backend tables are filtered (no value means no filter). @@ -145,6 +159,7 @@ export const cleanupQuery = (query: SearchFilters) => { } } } + query = recurseLogicalOperators(query, cleanupQuery) return query } @@ -410,6 +425,7 @@ export function fixupFilterArrays(filters: SearchFilters) { } } } + recurseLogicalOperators(filters, fixupFilterArrays) return filters } diff --git a/packages/types/src/documents/app/automation/StepInputsOutputs.ts b/packages/types/src/documents/app/automation/StepInputsOutputs.ts index e62a6e3f08..983a67daf5 100644 --- a/packages/types/src/documents/app/automation/StepInputsOutputs.ts +++ b/packages/types/src/documents/app/automation/StepInputsOutputs.ts @@ -111,10 +111,15 @@ export type LoopStepOutputs = { } export type BranchStepInputs = { - conditions: SearchFilters + branches: Branch[] children?: Record } +export type Branch = { + name: string + condition: SearchFilters +} + export type MakeIntegrationInputs = { url: string body: any diff --git a/yarn.lock b/yarn.lock index c22d22c723..713a1845b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,6 +25,14 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@ampproject/remapping@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + "@apidevtools/json-schema-ref-parser@^9.0.6": version "9.1.2" resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz#8ff5386b365d4c9faa7c8b566ff16a46a577d9b8" @@ -2632,11 +2640,25 @@ dependencies: eslint-visitor-keys "^3.3.0" +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.11.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" + integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== + "@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": version "4.10.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== +"@eslint/config-array@^0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.17.1.tgz#d9b8b8b6b946f47388f32bedfd3adf29ca8f8910" + integrity sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA== + dependencies: + "@eslint/object-schema" "^2.1.4" + debug "^4.3.1" + minimatch "^3.1.2" + "@eslint/eslintrc@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" @@ -2652,11 +2674,36 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@eslint/eslintrc@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6" + integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + "@eslint/js@8.57.0": version "8.57.0" resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== +"@eslint/js@9.9.0", "@eslint/js@^9.7.0": + version "9.9.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.9.0.tgz#d8437adda50b3ed4401964517b64b4f59b0e2638" + integrity sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug== + +"@eslint/object-schema@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.4.tgz#9e69f8bb4031e11df79e03db09f9dbbae1740843" + integrity sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ== + "@fontsource/source-sans-pro@^5.0.3": version "5.0.3" resolved "https://registry.yarnpkg.com/@fontsource/source-sans-pro/-/source-sans-pro-5.0.3.tgz#7d6e84a8169ba12fa5e6ce70757aa2ca7e74d855" @@ -2816,6 +2863,11 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@humanwhocodes/retry@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.0.tgz#6d86b8cb322660f03d3f0aa94b99bdd8e172d570" + integrity sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew== + "@hutson/parse-repository-url@^3.0.0": version "3.0.2" resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340" @@ -4156,160 +4208,160 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27" integrity sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ== -"@rollup/rollup-android-arm-eabi@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.1.tgz#7746deb85e4a8fb54fbfda8ac5c102692f102476" - integrity sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww== +"@rollup/rollup-android-arm-eabi@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.0.tgz#d941173f82f9b041c61b0dc1a2a91dcd06e4b31e" + integrity sha512-WTWD8PfoSAJ+qL87lE7votj3syLavxunWhzCnx3XFxFiI/BA/r3X7MUM8dVrH8rb2r4AiO8jJsr3ZjdaftmnfA== "@rollup/rollup-android-arm64@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz#97255ef6384c5f73f4800c0de91f5f6518e21203" integrity sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA== -"@rollup/rollup-android-arm64@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.1.tgz#93de4d867709d3313794723b5afd91e1e174f906" - integrity sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A== +"@rollup/rollup-android-arm64@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.0.tgz#7e7157c8543215245ceffc445134d9e843ba51c0" + integrity sha512-a1sR2zSK1B4eYkiZu17ZUZhmUQcKjk2/j9Me2IDjk1GHW7LB5Z35LEzj9iJch6gtUfsnvZs1ZNyDW2oZSThrkA== "@rollup/rollup-darwin-arm64@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz#b6dd74e117510dfe94541646067b0545b42ff096" integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w== -"@rollup/rollup-darwin-arm64@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.1.tgz#e41e6a81673260ab196e0f59462b9940a6ac03cd" - integrity sha512-8o6eqeFZzVLia2hKPUZk4jdE3zW7LCcZr+MD18tXkgBBid3lssGVAYuox8x6YHoEPDdDa9ixTaStcmx88lio5Q== +"@rollup/rollup-darwin-arm64@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.0.tgz#f0a18a4fc8dc6eb1e94a51fa2adb22876f477947" + integrity sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA== "@rollup/rollup-darwin-x64@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz#e07d76de1cec987673e7f3d48ccb8e106d42c05c" integrity sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA== -"@rollup/rollup-darwin-x64@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.1.tgz#2b0a0aef6e8c5317d494cfc9076d7a16b099bdcb" - integrity sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA== +"@rollup/rollup-darwin-x64@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.0.tgz#34b7867613e5cc42d2b85ddc0424228cc33b43f0" + integrity sha512-7doS8br0xAkg48SKE2QNtMSFPFUlRdw9+votl27MvT46vo44ATBmdZdGysOevNELmZlfd+NEa0UYOA8f01WSrg== "@rollup/rollup-linux-arm-gnueabihf@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz#9f1a6d218b560c9d75185af4b8bb42f9f24736b8" integrity sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA== -"@rollup/rollup-linux-arm-gnueabihf@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.1.tgz#e22319deb5367384ef315e66bc6de80d2bf2b3ae" - integrity sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q== +"@rollup/rollup-linux-arm-gnueabihf@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.0.tgz#422b19ff9ae02b05d3395183d1d43b38c7c8be0b" + integrity sha512-pWJsfQjNWNGsoCq53KjMtwdJDmh/6NubwQcz52aEwLEuvx08bzcy6tOUuawAOncPnxz/3siRtd8hiQ32G1y8VA== "@rollup/rollup-linux-arm-musleabihf@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz#53618b92e6ffb642c7b620e6e528446511330549" integrity sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A== -"@rollup/rollup-linux-arm-musleabihf@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.1.tgz#d5dd68f5d7ae21b345a5c87208c94e5c813f54b8" - integrity sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw== +"@rollup/rollup-linux-arm-musleabihf@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.0.tgz#568aa29195ef6fc57ec6ed3f518923764406a8ee" + integrity sha512-efRIANsz3UHZrnZXuEvxS9LoCOWMGD1rweciD6uJQIx2myN3a8Im1FafZBzh7zk1RJ6oKcR16dU3UPldaKd83w== "@rollup/rollup-linux-arm64-gnu@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz#99a7ba5e719d4f053761a698f7b52291cefba577" integrity sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw== -"@rollup/rollup-linux-arm64-gnu@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.1.tgz#1703d3a418d33f8f025acaf93f39ca1efcd5b645" - integrity sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw== +"@rollup/rollup-linux-arm64-gnu@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.0.tgz#22309c8bcba9a73114f69165c72bc94b2fbec085" + integrity sha512-ZrPhydkTVhyeGTW94WJ8pnl1uroqVHM3j3hjdquwAcWnmivjAwOYjTEAuEDeJvGX7xv3Z9GAvrBkEzCgHq9U1w== "@rollup/rollup-linux-arm64-musl@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz#f53db99a45d9bc00ce94db8a35efa7c3c144a58c" integrity sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ== -"@rollup/rollup-linux-arm64-musl@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.1.tgz#3f59c2c6e60f75ce8b1090bd841c555e3bb01f0e" - integrity sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw== +"@rollup/rollup-linux-arm64-musl@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.0.tgz#c93c388af6d33f082894b8a60839d7265b2b9bc5" + integrity sha512-cfaupqd+UEFeURmqNP2eEvXqgbSox/LHOyN9/d2pSdV8xTrjdg3NgOFJCtc1vQ/jEke1qD0IejbBfxleBPHnPw== "@rollup/rollup-linux-powerpc64le-gnu@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz#cbb0837408fe081ce3435cf3730e090febafc9bf" integrity sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA== -"@rollup/rollup-linux-powerpc64le-gnu@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.1.tgz#3f99a0921596a6f539121a312df29af52a205f15" - integrity sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ== +"@rollup/rollup-linux-powerpc64le-gnu@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.0.tgz#493c5e19e395cf3c6bd860c7139c8a903dea72b4" + integrity sha512-ZKPan1/RvAhrUylwBXC9t7B2hXdpb/ufeu22pG2psV7RN8roOfGurEghw1ySmX/CmDDHNTDDjY3lo9hRlgtaHg== "@rollup/rollup-linux-riscv64-gnu@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz#8ed09c1d1262ada4c38d791a28ae0fea28b80cc9" integrity sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg== -"@rollup/rollup-linux-riscv64-gnu@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.1.tgz#c08fb3e629d50d2eac31329347cfc559a1cf81d1" - integrity sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A== +"@rollup/rollup-linux-riscv64-gnu@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.0.tgz#a2eab4346fbe5909165ce99adb935ba30c9fb444" + integrity sha512-H1eRaCwd5E8eS8leiS+o/NqMdljkcb1d6r2h4fKSsCXQilLKArq6WS7XBLDu80Yz+nMqHVFDquwcVrQmGr28rg== "@rollup/rollup-linux-s390x-gnu@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz#938138d3c8e0c96f022252a28441dcfb17afd7ec" integrity sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg== -"@rollup/rollup-linux-s390x-gnu@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.1.tgz#173722cd745779d730d4b24d21386185e0e12de8" - integrity sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q== +"@rollup/rollup-linux-s390x-gnu@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.0.tgz#0bc49a79db4345d78d757bb1b05e73a1b42fa5c3" + integrity sha512-zJ4hA+3b5tu8u7L58CCSI0A9N1vkfwPhWd/puGXwtZlsB5bTkwDNW/+JCU84+3QYmKpLi+XvHdmrlwUwDA6kqw== "@rollup/rollup-linux-x64-gnu@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz#1a7481137a54740bee1ded4ae5752450f155d942" integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w== -"@rollup/rollup-linux-x64-gnu@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.1.tgz#0af2b6541ab0f4954d2c4f96bcdc7947420dd28c" - integrity sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q== +"@rollup/rollup-linux-x64-gnu@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.0.tgz#4fd36a6a41f3406d8693321b13d4f9b7658dd4b9" + integrity sha512-e2hrvElFIh6kW/UNBQK/kzqMNY5mO+67YtEh9OA65RM5IJXYTWiXjX6fjIiPaqOkBthYF1EqgiZ6OXKcQsM0hg== "@rollup/rollup-linux-x64-musl@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz#f1186afc601ac4f4fc25fac4ca15ecbee3a1874d" integrity sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg== -"@rollup/rollup-linux-x64-musl@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.1.tgz#f973f9552744764b221128f7c3629222216ace69" - integrity sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q== +"@rollup/rollup-linux-x64-musl@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.0.tgz#10ebb13bd4469cbad1a5d9b073bd27ec8a886200" + integrity sha512-1vvmgDdUSebVGXWX2lIcgRebqfQSff0hMEkLJyakQ9JQUbLDkEaMsPTLOmyccyC6IJ/l3FZuJbmrBw/u0A0uCQ== "@rollup/rollup-win32-arm64-msvc@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz#ed6603e93636a96203c6915be4117245c1bd2daf" integrity sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA== -"@rollup/rollup-win32-arm64-msvc@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.1.tgz#21ac5ed84d914bc31821fec3dd909f7257cfb17b" - integrity sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA== +"@rollup/rollup-win32-arm64-msvc@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.0.tgz#2fef1a90f1402258ef915ae5a94cc91a5a1d5bfc" + integrity sha512-s5oFkZ/hFcrlAyBTONFY1TWndfyre1wOMwU+6KCpm/iatybvrRgmZVM+vCFwxmC5ZhdlgfE0N4XorsDpi7/4XQ== "@rollup/rollup-win32-ia32-msvc@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz#14e0b404b1c25ebe6157a15edb9c46959ba74c54" integrity sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg== -"@rollup/rollup-win32-ia32-msvc@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.1.tgz#0cfe740063b35dcd5a62c4e243226631a846ce11" - integrity sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ== +"@rollup/rollup-win32-ia32-msvc@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.0.tgz#a18ad47a95c5f264defb60acdd8c27569f816fc1" + integrity sha512-G9+TEqRnAA6nbpqyUqgTiopmnfgnMkR3kMukFBDsiyy23LZvUCpiUwjTRx6ezYCjJODXrh52rBR9oXvm+Fp5wg== "@rollup/rollup-win32-x64-msvc@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz#5d694d345ce36b6ecf657349e03eb87297e68da4" integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g== -"@rollup/rollup-win32-x64-msvc@4.19.1": - version "4.19.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.1.tgz#5f2c40d3f1b53ede80fb4e6964f840c0f8936832" - integrity sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg== +"@rollup/rollup-win32-x64-msvc@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.0.tgz#20c09cf44dcb082140cc7f439dd679fe4bba3375" + integrity sha512-2jsCDZwtQvRhejHLfZ1JY6w6kEuEtfF9nzYsZxzSlNVKDX+DpsDJ+Rbjkm74nvg2rdx0gwBS+IMdvwJuq3S9pQ== "@roxi/routify@2.18.0": version "2.18.0" @@ -4363,6 +4415,14 @@ koa "^2.13.4" node-mocks-http "^1.11.0" +"@shopify/jest-koa-mocks@5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@shopify/jest-koa-mocks/-/jest-koa-mocks-5.3.0.tgz#0b9b6ce01a7ef945df7272aa08cda559c11b39f5" + integrity sha512-Yy9uS298/aWhT/bjfhUAcFRaq7pq7j0ybaI6U/vWQ5IcdWD3E73iqptkw+FNC+Z9cdV9QT8osFd0r0frFNb9Nw== + dependencies: + koa "^2.13.4" + node-mocks-http "^1.11.0" + "@sideway/address@^4.1.3", "@sideway/address@^4.1.5": version "4.1.5" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" @@ -5067,6 +5127,11 @@ resolved "https://registry.yarnpkg.com/@spectrum-css/tabs/-/tabs-3.2.12.tgz#9b08f23d5aa881b3441af7757800c7173e5685ff" integrity sha512-rPFUW9SSW4+3/UJ3UrtY2/l3sQvlqB1fqxHLPDjgykvbfrnMejcCTNV4ZrFNHXpE/6+kGnk+yVViSPtWGwJzkA== +"@spectrum-css/tag@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@spectrum-css/tag/-/tag-3.0.0.tgz#b2e335dc526713b83f3e995e8d1d4fc84a3fc4df" + integrity sha512-a9z7ZTAWPonkWRNY5kxVaO6bxu9de3qUZWJ9Bl1YBlwWc8Fy1L7XqT4Wq3pW+4sktUbUUqqPYPIXK9xEFDofEw== + "@spectrum-css/tags@3.0.2": version "3.0.2" resolved "https://registry.yarnpkg.com/@spectrum-css/tags/-/tags-3.0.2.tgz#5bf35fb79c97cd9344de485bd4626ad5b9f07757" @@ -5498,6 +5563,21 @@ "@types/docker-modem" "*" "@types/node" "*" +"@types/eslint@*": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.0.tgz#51d4fe4d0316da9e9f2c80884f2c20ed5fb022ff" + integrity sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/eslint__js@^8.42.3": + version "8.42.3" + resolved "https://registry.yarnpkg.com/@types/eslint__js/-/eslint__js-8.42.3.tgz#d1fa13e5c1be63a10b4e3afe992779f81c1179a0" + integrity sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw== + dependencies: + "@types/eslint" "*" + "@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.0", "@types/estree@^1.0.1": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" @@ -5595,7 +5675,7 @@ expect "^29.0.0" pretty-format "^29.0.0" -"@types/json-schema@^7.0.12", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -5646,6 +5726,14 @@ dependencies: "@types/koa" "*" +"@types/koa-session@^6.4.5": + version "6.4.5" + resolved "https://registry.yarnpkg.com/@types/koa-session/-/koa-session-6.4.5.tgz#ac10bac507f4bb722fa6c55c33607b5c8769f779" + integrity sha512-Vc6+fslnPuMH2v9y80WYeo39UMo8mweuNNthKCwYU2ZE6l5vnRrzRU3BRvexKwsoI5sxsRl5CxDsBlLI8kY/XA== + dependencies: + "@types/cookies" "*" + "@types/koa" "*" + "@types/koa-static@^4.0.2": version "4.0.4" resolved "https://registry.yarnpkg.com/@types/koa-static/-/koa-static-4.0.4.tgz#ce6f2a5d14cc7ef19f9bf6ee8e4f3eadfcc77323" @@ -5791,11 +5879,11 @@ integrity sha512-7GgtHCs/QZrBrDzgIJnQtuSvhFSwhyYSI2uafSwZoNt1iOGhEN5fwNrQMjtONyHm9+/LoA4453jH0CMYcr06Pg== "@types/node@>=8.1.0": - version "22.0.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.0.0.tgz#04862a2a71e62264426083abe1e27e87cac05a30" - integrity sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw== + version "22.4.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.4.2.tgz#55fefb1c3dba2ecd7eb76738c6b80da75760523f" + integrity sha512-nAvM3Ey230/XzxtyDcJ+VjvlzpzoHwLsF7JaDRfoI0ytO0mVheerNmM45CtA0yOILXwXXxOrcUWH3wltX+7PSw== dependencies: - undici-types "~6.11.1" + undici-types "~6.19.2" "@types/node@^18.11.18": version "18.19.10" @@ -6288,6 +6376,21 @@ dependencies: "@types/yargs-parser" "*" +"@typescript-eslint/eslint-plugin@7.18.0", "@typescript-eslint/eslint-plugin@^7.16.1": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz#b16d3cf3ee76bf572fdf511e79c248bdec619ea3" + integrity sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "7.18.0" + "@typescript-eslint/type-utils" "7.18.0" + "@typescript-eslint/utils" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^1.3.0" + "@typescript-eslint/eslint-plugin@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.3.1.tgz#0d8f38a6c8a1802139e62184ee7a68ed024f30a1" @@ -6316,6 +6419,17 @@ "@typescript-eslint/visitor-keys" "6.9.0" debug "^4.3.4" +"@typescript-eslint/parser@7.18.0", "@typescript-eslint/parser@^7.16.1": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.18.0.tgz#83928d0f1b7f4afa974098c64b5ce6f9051f96a0" + integrity sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg== + dependencies: + "@typescript-eslint/scope-manager" "7.18.0" + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/typescript-estree" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" + debug "^4.3.4" + "@typescript-eslint/parser@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.3.1.tgz#c4ba7dc2744318a5e4506596cbc3a0086255c526" @@ -6343,6 +6457,14 @@ "@typescript-eslint/types" "6.9.0" "@typescript-eslint/visitor-keys" "6.9.0" +"@typescript-eslint/scope-manager@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz#c928e7a9fc2c0b3ed92ab3112c614d6bd9951c83" + integrity sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA== + dependencies: + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" + "@typescript-eslint/scope-manager@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz#73fd0cb4211a7be23e49e5b6efec8820caa6ec36" @@ -6351,6 +6473,16 @@ "@typescript-eslint/types" "7.3.1" "@typescript-eslint/visitor-keys" "7.3.1" +"@typescript-eslint/type-utils@7.18.0", "@typescript-eslint/type-utils@^7.2.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz#2165ffaee00b1fbbdd2d40aa85232dab6998f53b" + integrity sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA== + dependencies: + "@typescript-eslint/typescript-estree" "7.18.0" + "@typescript-eslint/utils" "7.18.0" + debug "^4.3.4" + ts-api-utils "^1.3.0" + "@typescript-eslint/type-utils@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.3.1.tgz#cbf90d3d7e788466aa8a5c0ab3f46103f098aa0d" @@ -6376,6 +6508,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.9.0.tgz#86a0cbe7ac46c0761429f928467ff3d92f841098" integrity sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw== +"@typescript-eslint/types@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.18.0.tgz#b90a57ccdea71797ffffa0321e744f379ec838c9" + integrity sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ== + "@typescript-eslint/types@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.3.1.tgz#ae104de8efa4227a462c0874d856602c5994413c" @@ -6407,6 +6544,20 @@ semver "^7.5.4" ts-api-utils "^1.0.1" +"@typescript-eslint/typescript-estree@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz#b5868d486c51ce8f312309ba79bdb9f331b37931" + integrity sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA== + dependencies: + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + "@typescript-eslint/typescript-estree@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz#598848195fad34c7aa73f548bd00a4d4e5f5e2bb" @@ -6434,6 +6585,16 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/utils@7.18.0", "@typescript-eslint/utils@^7.3.1": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.18.0.tgz#bca01cde77f95fc6a8d5b0dbcbfb3d6ca4be451f" + integrity sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "7.18.0" + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/typescript-estree" "7.18.0" + "@typescript-eslint/utils@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.3.1.tgz#fc28fd508ccf89495012561b7c02a6fdad162460" @@ -6485,6 +6646,14 @@ "@typescript-eslint/types" "6.9.0" eslint-visitor-keys "^3.4.1" +"@typescript-eslint/visitor-keys@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz#0564629b6124d67607378d0f0332a0495b25e7d7" + integrity sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg== + dependencies: + "@typescript-eslint/types" "7.18.0" + eslint-visitor-keys "^3.4.3" + "@typescript-eslint/visitor-keys@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz#6ddef14a3ce2a79690f01176f5305c34d7b93d8c" @@ -6507,14 +6676,22 @@ "@vitest/utils" "0.29.8" chai "^4.3.7" -"@vitest/expect@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.6.0.tgz#0b3ba0914f738508464983f4d811bc122b51fb30" - integrity sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ== +"@vitest/expect@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.0.5.tgz#f3745a6a2c18acbea4d39f5935e913f40d26fa86" + integrity sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA== dependencies: - "@vitest/spy" "1.6.0" - "@vitest/utils" "1.6.0" - chai "^4.3.10" + "@vitest/spy" "2.0.5" + "@vitest/utils" "2.0.5" + chai "^5.1.1" + tinyrainbow "^1.2.0" + +"@vitest/pretty-format@2.0.5", "@vitest/pretty-format@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.0.5.tgz#91d2e6d3a7235c742e1a6cc50e7786e2f2979b1e" + integrity sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ== + dependencies: + tinyrainbow "^1.2.0" "@vitest/runner@0.29.8": version "0.29.8" @@ -6525,23 +6702,22 @@ p-limit "^4.0.0" pathe "^1.1.0" -"@vitest/runner@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.6.0.tgz#a6de49a96cb33b0e3ba0d9064a3e8d6ce2f08825" - integrity sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg== +"@vitest/runner@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.0.5.tgz#89197e712bb93513537d6876995a4843392b2a84" + integrity sha512-TfRfZa6Bkk9ky4tW0z20WKXFEwwvWhRY+84CnSEtq4+3ZvDlJyY32oNTJtM7AW9ihW90tX/1Q78cb6FjoAs+ig== dependencies: - "@vitest/utils" "1.6.0" - p-limit "^5.0.0" - pathe "^1.1.1" + "@vitest/utils" "2.0.5" + pathe "^1.1.2" -"@vitest/snapshot@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.6.0.tgz#deb7e4498a5299c1198136f56e6e0f692e6af470" - integrity sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ== +"@vitest/snapshot@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.0.5.tgz#a2346bc5013b73c44670c277c430e0334690a162" + integrity sha512-SgCPUeDFLaM0mIUHfaArq8fD2WbaXG/zVXjRupthYfYGzc8ztbFbu6dUNOblBG7XLMR1kEhS/DNnfCZ2IhdDew== dependencies: - magic-string "^0.30.5" - pathe "^1.1.1" - pretty-format "^29.7.0" + "@vitest/pretty-format" "2.0.5" + magic-string "^0.30.10" + pathe "^1.1.2" "@vitest/spy@0.29.8": version "0.29.8" @@ -6550,12 +6726,12 @@ dependencies: tinyspy "^1.0.2" -"@vitest/spy@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-1.6.0.tgz#362cbd42ccdb03f1613798fde99799649516906d" - integrity sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw== +"@vitest/spy@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.0.5.tgz#590fc07df84a78b8e9dd976ec2090920084a2b9f" + integrity sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA== dependencies: - tinyspy "^2.2.0" + tinyspy "^3.0.0" "@vitest/utils@0.29.8": version "0.29.8" @@ -6567,15 +6743,15 @@ loupe "^2.3.6" pretty-format "^27.5.1" -"@vitest/utils@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-1.6.0.tgz#5c5675ca7d6f546a7b4337de9ae882e6c57896a1" - integrity sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw== +"@vitest/utils@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.0.5.tgz#6f8307a4b6bc6ceb9270007f73c67c915944e926" + integrity sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ== dependencies: - diff-sequences "^29.6.3" + "@vitest/pretty-format" "2.0.5" estree-walker "^3.0.3" - loupe "^2.3.7" - pretty-format "^29.7.0" + loupe "^3.1.1" + tinyrainbow "^1.2.0" "@yarnpkg/lockfile@^1.1.0": version "1.1.0" @@ -6707,39 +6883,34 @@ acorn-import-assertions@^1.9.0: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== -acorn-jsx-walk@2.0.0: +acorn-jsx-walk@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/acorn-jsx-walk/-/acorn-jsx-walk-2.0.0.tgz#a5ed648264e68282d7c2aead80216bfdf232573a" integrity sha512-uuo6iJj4D4ygkdzd6jPtcxs8vZgDX9YFIkqczGImoypX2fQ4dVImmu3UzA4ynixCIMTrEOWW+95M2HuBaCEOVA== -acorn-jsx@5.3.2, acorn-jsx@^5.3.2: +acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn-loose@8.4.0: +acorn-loose@^8.4.0: version "8.4.0" resolved "https://registry.yarnpkg.com/acorn-loose/-/acorn-loose-8.4.0.tgz#26d3e219756d1e180d006f5bcc8d261a28530f55" integrity sha512-M0EUka6rb+QC4l9Z3T0nJEzNOO7JcoJlYMrBlyBCiFSXRyxjLKayd4TbQs2FDRWQU1h9FR7QVNHt+PEaoNL5rQ== dependencies: acorn "^8.11.0" -acorn-walk@8.3.3, acorn-walk@^8.0.2, acorn-walk@^8.1.1, acorn-walk@^8.2.0, acorn-walk@^8.3.2: - version "8.3.3" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" - integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== - dependencies: - acorn "^8.11.0" - acorn-walk@^7.1.1: version "7.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn@8.12.1: - version "8.12.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" - integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== +acorn-walk@^8.0.2, acorn-walk@^8.1.1, acorn-walk@^8.2.0, acorn-walk@^8.3.3: + version "8.3.3" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" + integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== + dependencies: + acorn "^8.11.0" acorn@^5.2.1, acorn@^5.7.3: version "5.7.4" @@ -6756,6 +6927,11 @@ acorn@^8.1.0, acorn@^8.10.0, acorn@^8.11.0, acorn@^8.11.3, acorn@^8.2.4, acorn@^ 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: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" @@ -6808,16 +6984,6 @@ ajv-formats@^2.0.2: dependencies: ajv "^8.0.0" -ajv@8.17.1: - version "8.17.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" - integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== - dependencies: - fast-deep-equal "^3.1.3" - fast-uri "^3.0.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -6838,6 +7004,16 @@ ajv@^8.0.0, ajv@^8.1.0, ajv@^8.4.0: require-from-string "^2.0.2" uri-js "^4.2.2" +ajv@^8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -7232,6 +7408,11 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + ast-module-types@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-2.7.1.tgz#3f7989ef8dfa1fdb82dfe0ab02bdfc7c77a57dd3" @@ -8124,19 +8305,6 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -chai@^4.3.10: - 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" - deep-eql "^4.1.3" - get-func-name "^2.0.2" - loupe "^2.3.6" - pathval "^1.1.1" - type-detect "^4.1.0" - chai@^4.3.7: version "4.4.1" resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1" @@ -8150,6 +8318,17 @@ chai@^4.3.7: pathval "^1.1.1" type-detect "^4.0.8" +chai@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.1.tgz#f035d9792a22b481ead1c65908d14bb62ec1c82c" + integrity sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA== + dependencies: + assertion-error "^2.0.1" + check-error "^2.1.1" + deep-eql "^5.0.1" + loupe "^3.1.0" + pathval "^2.0.0" + chalk@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" @@ -8215,6 +8394,11 @@ check-error@^1.0.3: dependencies: get-func-name "^2.0.2" +check-error@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" + integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== + chokidar@3.5.3, chokidar@^3.5.2, chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -8511,11 +8695,6 @@ combos@^0.2.0: resolved "https://registry.yarnpkg.com/combos/-/combos-0.2.0.tgz#dc31c5a899b42293d55fe19c064d3e6e207ba4f7" integrity sha512-Z6YfvgiTCERWJTj3wQiXamFhssdvz1n4ok447rS330lw3uL72WAx8IvrLU7xiE71uyb5WF8JEP+BWB5KhOoGeg== -commander@12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" - integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== - commander@6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" @@ -8531,6 +8710,11 @@ commander@^11.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== +commander@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + commander@^2.16.0, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, commander@^2.5.0, commander@^2.7.1, commander@^2.8.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -9261,9 +9445,9 @@ dayjs@^1.10.8: integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg== dayjs@^1.8.15: - version "1.11.12" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.12.tgz#5245226cc7f40a15bf52e0b99fd2a04669ccac1d" - integrity sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg== + version "1.11.13" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== dc-polyfill@^0.1.2: version "0.1.3" @@ -9328,6 +9512,13 @@ debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.5: + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== + dependencies: + ms "2.1.2" + debuglog@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -9440,6 +9631,11 @@ deep-eql@^4.1.3: dependencies: type-detect "^4.0.0" +deep-eql@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" + 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" @@ -9478,6 +9674,11 @@ deep-is@^0.1.3, deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +deepmerge-ts@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz#c55206cc4c7be2ded89b9c816cf3608884525d7a" + integrity sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw== + deepmerge@^4.2.2: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" @@ -9584,32 +9785,32 @@ depd@^1.1.0, depd@~1.1.2: integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== dependency-cruiser@^16.3.7: - version "16.3.10" - resolved "https://registry.yarnpkg.com/dependency-cruiser/-/dependency-cruiser-16.3.10.tgz#fe26a50d5e10a4496bc2b70d027fca6ded48814f" - integrity sha512-WkCnibHBfvaiaQ+S46LZ6h4AR6oj42Vsf5/0Vgtrwdwn7ZekMJdZ/ALoTwNp/RaGlKW+MbV/fhSZOvmhAWVWzQ== + version "16.4.0" + resolved "https://registry.yarnpkg.com/dependency-cruiser/-/dependency-cruiser-16.4.0.tgz#a1b7d452acddf05045ae4f7942a2e9337aedad35" + integrity sha512-la/NnD23m6esCox8KMiZ/pcmtec6G/r7LgnJvkBepcErdzlGaxWnyaxtpoYB3fgODrU/7E2u81/nX5FNu5zfyw== dependencies: - acorn "8.12.1" - acorn-jsx "5.3.2" - acorn-jsx-walk "2.0.0" - acorn-loose "8.4.0" - acorn-walk "8.3.3" - ajv "8.17.1" - commander "12.1.0" - enhanced-resolve "5.17.1" - ignore "5.3.1" + acorn "^8.12.1" + acorn-jsx "^5.3.2" + acorn-jsx-walk "^2.0.0" + acorn-loose "^8.4.0" + acorn-walk "^8.3.3" + ajv "^8.17.1" + commander "^12.1.0" + enhanced-resolve "^5.17.1" + ignore "^5.3.2" interpret "^3.1.1" - is-installed-globally "1.0.0" - json5 "2.2.3" - memoize "10.0.0" - picocolors "1.0.1" - picomatch "4.0.2" - prompts "2.4.2" + is-installed-globally "^1.0.0" + json5 "^2.2.3" + memoize "^10.0.0" + picocolors "^1.0.1" + picomatch "^4.0.2" + prompts "^2.4.2" rechoir "^0.8.0" - safe-regex "2.1.1" + safe-regex "^2.1.1" semver "^7.6.3" - teamcity-service-messages "0.1.14" - tsconfig-paths-webpack-plugin "4.1.0" - watskeburt "4.1.0" + teamcity-service-messages "^0.1.14" + tsconfig-paths-webpack-plugin "^4.1.0" + watskeburt "^4.1.0" dependency-tree@^9.0.0: version "9.0.0" @@ -10162,23 +10363,10 @@ electron-to-chromium@^1.4.284: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.317.tgz#9a3d38a1a37f26a417d3d95dafe198ff11ed072b" integrity sha512-JhCRm9v30FMNzQSsjl4kXaygU+qHBD0Yh7mKxyjmF0V8VwYVB6qpBRX28GyAucrM9wDCpSUctT6FpMUQxbyKuA== -elliptic@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - -elliptic@^6.5.5: - version "6.5.5" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.5.tgz#c715e09f78b6923977610d4c2346d6ce22e6dded" - integrity sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw== +elliptic@^6.5.3, elliptic@^6.5.5: + version "6.5.7" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" + integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -10281,7 +10469,7 @@ engine.io@~6.5.2: engine.io-parser "~5.2.1" ws "~8.17.1" -enhanced-resolve@5.17.1, enhanced-resolve@^5.7.0: +enhanced-resolve@^5.17.1, enhanced-resolve@^5.7.0: version "5.17.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== @@ -10635,6 +10823,18 @@ eslint-module-utils@^2.8.0: dependencies: debug "^3.2.7" +eslint-plugin-functional@^6.6.3: + version "6.6.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-functional/-/eslint-plugin-functional-6.6.3.tgz#85b895afb91835c5ffa2eb97f473fd4182aa5228" + integrity sha512-sVbbvNvwX3HVkXAykKyoNLv57r4DPF7f1sy+/8j4YtzLYVQPGljMUWv3T6Kd4lwnnjmcKuj0EkIbS+knL6P5jw== + dependencies: + "@typescript-eslint/utils" "^7.3.1" + deepmerge-ts "^5.1.0" + escape-string-regexp "^4.0.0" + is-immutable-type "^4.0.0" + semver "^7.6.0" + ts-api-utils "^1.3.0" + eslint-plugin-import@^2.26.0, eslint-plugin-import@^2.29.0: version "2.29.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" @@ -10704,6 +10904,14 @@ eslint-scope@^7.0.0, eslint-scope@^7.2.2: esrecurse "^4.3.0" estraverse "^5.2.0" +eslint-scope@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.2.tgz#5cbb33d4384c9136083a71190d548158fe128f94" + integrity sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" @@ -10714,6 +10922,11 @@ eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== +eslint-visitor-keys@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" + integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== + eslint@^8.52.0, eslint@^8.56.0: version "8.57.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" @@ -10758,11 +10971,60 @@ eslint@^8.52.0, eslint@^8.56.0: strip-ansi "^6.0.1" text-table "^0.2.0" +eslint@^9.7.0: + version "9.9.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.9.0.tgz#8d214e69ae4debeca7ae97daebbefe462072d975" + integrity sha512-JfiKJrbx0506OEerjK2Y1QlldtBxkAlLxT5OEcRF8uaQ86noDe2k31Vw9rnSWv+MXZHj7OOUV/dA0AhdLFcyvA== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.11.0" + "@eslint/config-array" "^0.17.1" + "@eslint/eslintrc" "^3.1.0" + "@eslint/js" "9.9.0" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.3.0" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.0.2" + eslint-visitor-keys "^4.0.0" + espree "^10.1.0" + esquery "^1.5.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + esm@^3.2.25: version "3.2.25" resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== +espree@^10.0.1, espree@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.1.0.tgz#8788dae611574c0f070691f522e4116c5a11fc56" + integrity sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA== + dependencies: + acorn "^8.12.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.0.0" + espree@^9.0.0, espree@^9.6.0, espree@^9.6.1: version "9.6.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" @@ -10799,6 +11061,13 @@ esquery@^1.4.2: dependencies: estraverse "^5.1.0" +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" @@ -11190,6 +11459,13 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + file-type@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-11.1.0.tgz#93780f3fed98b599755d846b99a1617a2ad063b8" @@ -11324,6 +11600,14 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + flat@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" @@ -11334,6 +11618,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + flatten@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" @@ -11984,6 +12273,11 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + globalthis@^1.0.1, globalthis@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" @@ -12549,6 +12843,11 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +husky@^9.1.4: + version "9.1.5" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.5.tgz#2b6edede53ee1adbbd3a3da490628a23f5243b83" + integrity sha512-rowAVRUBfI0b4+niA4SJMhfQwc107VLkBUgEYYAOQAbqDCnra1nYh83hF/MDmhYs9t9n1E3DuKOrs2LYNC+0Ag== + ical-generator@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ical-generator/-/ical-generator-4.1.0.tgz#2a336c951864c5583a2aa715d16f2edcdfd2d90b" @@ -12621,16 +12920,16 @@ ignore-walk@^6.0.0: dependencies: minimatch "^7.4.2" -ignore@5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== - ignore@^5.0.4, ignore@^5.2.0, ignore@^5.2.4: version "5.3.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== +ignore@^5.3.1, ignore@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + image-q@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/image-q/-/image-q-4.0.0.tgz#31e075be7bae3c1f42a85c469b4732c358981776" @@ -13068,13 +13367,14 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-installed-globally@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-1.0.0.tgz#08952c43758c33d815692392f7f8437b9e436d5a" - integrity sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ== +is-immutable-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-immutable-type/-/is-immutable-type-4.0.0.tgz#d62ad1ff411eef8dfa3a87222960ec3b645db1a1" + integrity sha512-gyFBCXv+NikTs8/PGZhgjbMmFZQ5jvHGZIsVu6+/9Bk4K7imlWBIDN7hTr9fNioGzFg71I4YM3z8f0aKXarTAw== dependencies: - global-directory "^4.0.1" - is-path-inside "^4.0.0" + "@typescript-eslint/type-utils" "^7.2.0" + ts-api-utils "^1.3.0" + ts-declaration-location "^1.0.0" is-installed-globally@^0.4.0: version "0.4.0" @@ -13084,6 +13384,14 @@ is-installed-globally@^0.4.0: global-dirs "^3.0.0" is-path-inside "^3.0.2" +is-installed-globally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-1.0.0.tgz#08952c43758c33d815692392f7f8437b9e436d5a" + integrity sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ== + dependencies: + global-directory "^4.0.1" + is-path-inside "^4.0.0" + is-interactive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" @@ -14028,11 +14336,6 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.0.tgz#0f893996d6f3ed46df7f0a3b12a03f5fd84223c1" - integrity sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ== - js-yaml@4.1.0, js-yaml@^4.0.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -14200,11 +14503,6 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json5@2.2.3, json5@^2.2.1, json5@^2.2.2, json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -14212,6 +14510,11 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" +json5@^2.2.1, json5@^2.2.2, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + jsonc-parser@3.2.0, jsonc-parser@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" @@ -14333,7 +14636,7 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" -keyv@^4.0.0: +keyv@^4.0.0, keyv@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== @@ -15000,14 +15303,6 @@ local-pkg@^0.4.2: resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.4.3.tgz#0ff361ab3ae7f1c19113d9bb97b98b905dbc4963" integrity sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g== -local-pkg@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c" - integrity sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg== - dependencies: - mlly "^1.4.2" - pkg-types "^1.0.3" - locate-character@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-character/-/locate-character-3.0.0.tgz#0305c5b8744f61028ef5d01f444009e00779f974" @@ -15240,13 +15535,20 @@ lossless-json@^4.0.1: resolved "https://registry.yarnpkg.com/lossless-json/-/lossless-json-4.0.1.tgz#d45229e3abb213a0235812780ca894ea8c5b2c6b" integrity sha512-l0L+ppmgPDnb+JGxNLndPtJZGNf6+ZmVaQzoxQm3u6TXmhdnsA+YtdVR8DjzZd/em58686CQhOFDPewfJ4l7MA== -loupe@^2.3.6, loupe@^2.3.7: +loupe@^2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== dependencies: get-func-name "^2.0.1" +loupe@^3.1.0, loupe@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.1.tgz#71d038d59007d890e3247c5db97c1ec5a92edc54" + integrity sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw== + dependencies: + get-func-name "^2.0.1" + lowercase-keys@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" @@ -15364,6 +15666,13 @@ magic-string@^0.26.7: dependencies: sourcemap-codec "^1.4.8" +magic-string@^0.30.10: + version "0.30.11" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954" + integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + magic-string@^0.30.3, magic-string@^0.30.4: version "0.30.10" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e" @@ -15371,13 +15680,6 @@ magic-string@^0.30.3, magic-string@^0.30.4: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" -magic-string@^0.30.5: - version "0.30.11" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954" - integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A== - dependencies: - "@jridgewell/sourcemap-codec" "^1.5.0" - make-dir@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" @@ -15557,7 +15859,7 @@ memdown@^5.1.0: ltgt "~2.2.0" safe-buffer "~5.2.0" -memoize@10.0.0: +memoize@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/memoize/-/memoize-10.0.0.tgz#43fa66b2022363c7c50cf5dfab732a808a3d7147" integrity sha512-H6cBLgsi6vMWOcCpvVCdFFnl3kerEXbrYh9q+lY6VXvQSmM6CkmV08VOwT+WE2tzIEqRPFfAq3fm4v/UIW6mSA== @@ -15735,6 +16037,13 @@ minimatch@9.0.3: dependencies: brace-expansion "^2.0.1" +minimatch@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b" + integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== + dependencies: + brace-expansion "^2.0.1" + minimatch@^5.0.1, minimatch@^5.1.0: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" @@ -15882,7 +16191,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.4.2, mlly@^1.7.0, mlly@^1.7.1: +mlly@^1.1.0, mlly@^1.7.0: version "1.7.1" resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.1.tgz#e0336429bb0731b6a8e887b438cbdae522c8f32f" integrity sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA== @@ -17000,13 +17309,6 @@ p-limit@^4.0.0: dependencies: yocto-queue "^1.0.0" -p-limit@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-5.0.0.tgz#6946d5b7140b649b7a33a027d89b4c625b3a5985" - integrity sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ== - dependencies: - yocto-queue "^1.0.0" - p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -17434,7 +17736,7 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pathe@^1.1.0, pathe@^1.1.1, pathe@^1.1.2: +pathe@^1.1.0, pathe@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== @@ -17444,6 +17746,11 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== +pathval@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" + integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== + pause@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" @@ -17540,26 +17847,26 @@ phin@^2.9.1: resolved "https://registry.yarnpkg.com/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c" integrity sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA== -picocolors@1.0.1, picocolors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== - picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== +picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + pify@5.0.0, pify@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" @@ -17716,15 +18023,6 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-types@^1.0.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.1.3.tgz#161bb1242b21daf7795036803f28e30222e476e3" - integrity sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA== - dependencies: - confbox "^0.1.7" - mlly "^1.7.1" - pathe "^1.1.2" - pkg-types@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.1.1.tgz#07b626880749beb607b0c817af63aac1845a73f2" @@ -18056,10 +18354,10 @@ postcss@^8.1.7, postcss@^8.2.9, postcss@^8.3.11, postcss@^8.4.12, postcss@^8.4.2 picocolors "^1.0.0" source-map-js "^1.2.0" -postcss@^8.4.39: - version "8.4.40" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.40.tgz#eb81f2a4dd7668ed869a6db25999e02e9ad909d8" - integrity sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q== +postcss@^8.4.41: + version "8.4.41" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.41.tgz#d6104d3ba272d882fe18fc07d15dc2da62fa2681" + integrity sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ== dependencies: nanoid "^3.3.7" picocolors "^1.0.1" @@ -18096,9 +18394,9 @@ posthog-js@^1.118.0: preact "^10.19.3" posthog-js@^1.13.4: - version "1.150.1" - resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.150.1.tgz#ce2e0aa0dc30369bf1b1b9a38b9fbf25e5c01ba0" - integrity sha512-jHSnqtAWkUQkiedQgHpD00+z8RUF0loDq7ORakBKfQjdntTJIEk16ewqTNRxnpE86guWDoy2J3iAqLgAYfFaLA== + version "1.157.2" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.157.2.tgz#dc2515818ead408aefb900e90c535fb57beb1f59" + integrity sha512-ATYKGs+Q51u26nHHhrhWNh1whqFm7j/rwQQYw+y6/YzNmRlo+YsqrGZji9nqXb9/4fo0ModDr+ZmuOI3hKkUXA== dependencies: fflate "^0.4.8" preact "^10.19.3" @@ -18526,7 +18824,7 @@ promise.series@^0.2.0: resolved "https://registry.yarnpkg.com/promise.series/-/promise.series-0.2.0.tgz#2cc7ebe959fc3a6619c04ab4dbdc9e452d864bbd" integrity sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ== -prompts@2.4.2, prompts@^2.0.1: +prompts@^2.0.1, prompts@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -18692,9 +18990,9 @@ q@^1.1.2: integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== qs@^6.10.3: - version "6.12.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.3.tgz#e43ce03c8521b9c7fd7f1f13e514e5ca37727754" - integrity sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ== + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== dependencies: side-channel "^1.0.6" @@ -19350,9 +19648,9 @@ rimraf@^4.4.1: glob "^9.2.0" rimraf@^5.0.7: - version "5.0.9" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.9.tgz#c3baa1b886eadc2ec7981a06a593c3d01134ffe9" - integrity sha512-3i7b8OcswU6CpU8Ej89quJD4O98id7TtVM5U4Mybh84zQXdrFmDLouWBEEaD/QfO3gDDfH+AGFCGsR7kngzQnA== + version "5.0.10" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.10.tgz#23b9843d3dc92db71f96e1a2ce92e39fd2a8221c" + integrity sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ== dependencies: glob "^10.3.7" @@ -19518,29 +19816,29 @@ rollup@^3.27.1: optionalDependencies: fsevents "~2.3.2" -rollup@^4.13.0: - version "4.19.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.19.1.tgz#21d865cd60d4a325172ce8b082e60caccd97b309" - integrity sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw== +rollup@^4.20.0: + version "4.21.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.21.0.tgz#28db5f5c556a5180361d35009979ccc749560b9d" + integrity sha512-vo+S/lfA2lMS7rZ2Qoubi6I5hwZwzXeUIctILZLbHI+laNtvhhOIon2S1JksA5UEDQ7l3vberd0fxK44lTYjbQ== dependencies: "@types/estree" "1.0.5" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.19.1" - "@rollup/rollup-android-arm64" "4.19.1" - "@rollup/rollup-darwin-arm64" "4.19.1" - "@rollup/rollup-darwin-x64" "4.19.1" - "@rollup/rollup-linux-arm-gnueabihf" "4.19.1" - "@rollup/rollup-linux-arm-musleabihf" "4.19.1" - "@rollup/rollup-linux-arm64-gnu" "4.19.1" - "@rollup/rollup-linux-arm64-musl" "4.19.1" - "@rollup/rollup-linux-powerpc64le-gnu" "4.19.1" - "@rollup/rollup-linux-riscv64-gnu" "4.19.1" - "@rollup/rollup-linux-s390x-gnu" "4.19.1" - "@rollup/rollup-linux-x64-gnu" "4.19.1" - "@rollup/rollup-linux-x64-musl" "4.19.1" - "@rollup/rollup-win32-arm64-msvc" "4.19.1" - "@rollup/rollup-win32-ia32-msvc" "4.19.1" - "@rollup/rollup-win32-x64-msvc" "4.19.1" + "@rollup/rollup-android-arm-eabi" "4.21.0" + "@rollup/rollup-android-arm64" "4.21.0" + "@rollup/rollup-darwin-arm64" "4.21.0" + "@rollup/rollup-darwin-x64" "4.21.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.21.0" + "@rollup/rollup-linux-arm-musleabihf" "4.21.0" + "@rollup/rollup-linux-arm64-gnu" "4.21.0" + "@rollup/rollup-linux-arm64-musl" "4.21.0" + "@rollup/rollup-linux-powerpc64le-gnu" "4.21.0" + "@rollup/rollup-linux-riscv64-gnu" "4.21.0" + "@rollup/rollup-linux-s390x-gnu" "4.21.0" + "@rollup/rollup-linux-x64-gnu" "4.21.0" + "@rollup/rollup-linux-x64-musl" "4.21.0" + "@rollup/rollup-win32-arm64-msvc" "4.21.0" + "@rollup/rollup-win32-ia32-msvc" "4.21.0" + "@rollup/rollup-win32-x64-msvc" "4.21.0" fsevents "~2.3.2" rollup@^4.9.4, rollup@^4.9.6: @@ -19643,7 +19941,7 @@ safe-regex-test@^1.0.3: es-errors "^1.3.0" is-regex "^1.1.4" -safe-regex@2.1.1: +safe-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-2.1.1.tgz#f7128f00d056e2fe5c11e81a1324dd974aadced2" integrity sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A== @@ -19761,7 +20059,7 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.3, semver@~2.3.1: +"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3, semver@~2.3.1: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== @@ -20361,7 +20659,7 @@ statuses@2.0.1, statuses@^2.0.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== -std-env@^3.3.1, std-env@^3.5.0: +std-env@^3.3.1, std-env@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== @@ -20445,7 +20743,16 @@ 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", "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": + 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: 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== @@ -20536,7 +20843,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@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm: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== @@ -20550,6 +20857,13 @@ 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" @@ -20620,13 +20934,6 @@ strip-literal@^1.0.0: dependencies: acorn "^8.10.0" -strip-literal@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-2.1.0.tgz#6d82ade5e2e74f5c7e8739b6c84692bd65f0bd2a" - integrity sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw== - dependencies: - js-tokens "^9.0.0" - strip-outer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" @@ -21025,7 +21332,7 @@ tarn@^3.0.1, tarn@^3.0.2: resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.2.tgz#73b6140fbb881b71559c4f8bfde3d9a4b3d27693" integrity sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ== -teamcity-service-messages@0.1.14: +teamcity-service-messages@^0.1.14: version "0.1.14" resolved "https://registry.yarnpkg.com/teamcity-service-messages/-/teamcity-service-messages-0.1.14.tgz#193d420a5e4aef8e5e50b8c39e7865e08fbb5d8a" integrity sha512-29aQwaHqm8RMX74u2o/h1KbMLP89FjNiMxD9wbF2BbWOnbM+q+d1sCEC+MqCc4QW3NJykn77OMpTFw/xTHIc0w== @@ -21216,11 +21523,16 @@ 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, tinybench@^2.5.1: +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: + version "2.9.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" + integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== + tinycolor2@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" @@ -21231,20 +21543,25 @@ tinypool@^0.4.0: resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.4.0.tgz#3cf3ebd066717f9f837e8d7d31af3c127fdb5446" integrity sha512-2ksntHOKf893wSAH4z/+JbPpi92esw8Gn9N2deXX+B0EO92hexAVI9GIZZPx7P5aYo5KULfeOSt3kMOmSOy6uA== -tinypool@^0.8.3: - version "0.8.4" - resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.8.4.tgz#e217fe1270d941b39e98c625dcecebb1408c9aa8" - integrity sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ== +tinypool@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.1.tgz#c64233c4fac4304e109a64340178760116dbe1fe" + integrity sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA== + +tinyrainbow@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" + integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ== tinyspy@^1.0.2: version "1.1.1" resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-1.1.1.tgz#0cb91d5157892af38cb2d217f5c7e8507a5bf092" integrity sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g== -tinyspy@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.1.tgz#117b2342f1f38a0dbdcc73a50a454883adf861d1" - integrity sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A== +tinyspy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.0.tgz#cb61644f2713cd84dee184863f4642e06ddf0585" + integrity sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA== tlhunter-sorted-set@^0.1.0: version "0.1.0" @@ -21383,6 +21700,18 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== +ts-api-utils@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" + integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== + +ts-declaration-location@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ts-declaration-location/-/ts-declaration-location-1.0.4.tgz#60c64133202ec5d171fdf0395f70f786f92f14c0" + integrity sha512-r4JoxYhKULbZuH81Pjrp9OEG5St7XWk7zXwGkLKhmVcjiBVHTJXV5wK6dEa9JKW5QGSTW6b1lOjxAKp8R1SQhg== + dependencies: + minimatch "^10.0.0" + ts-graphviz@^1.5.0: version "1.5.4" resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-1.5.4.tgz#61a3059afeac4f6d4be3c6729a4d88546ca9e095" @@ -21421,7 +21750,31 @@ ts-node@10.8.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tsconfig-paths-webpack-plugin@4.1.0: +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tsconfck@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-3.1.1.tgz#c7284913262c293b43b905b8b034f524de4a3162" + integrity sha512-00eoI6WY57SvZEVjm13stEVE90VkEdJAFGgpFLTsZbJyW/LwFQ7uQxJHWpZ2hzSWgCPKc9AnBnNP+0X7o3hAmQ== + +tsconfig-paths-webpack-plugin@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz#3c6892c5e7319c146eee1e7302ed9e6f2be4f763" integrity sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA== @@ -21525,11 +21878,6 @@ type-detect@4.0.8, type-detect@^4.0.0, type-detect@^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.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" @@ -21651,6 +21999,15 @@ typeof@^1.0.0: resolved "https://registry.yarnpkg.com/typeof/-/typeof-1.0.0.tgz#9c84403f2323ae5399167275497638ea1d2f2440" integrity sha512-Pze0mIxYXhaJdpw1ayMzOA7rtGr1OmsTY/Z+FWtRKIqXFz6aoDLjqdbWE/tcIBSC8nhnVXiRrEXujodR/xiFAA== +typescript-eslint@^7.16.1: + version "7.18.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-7.18.0.tgz#e90d57649b2ad37a7475875fa3e834a6d9f61eb2" + integrity sha512-PonBkP603E3tt05lDkbOMyaxJjvKqQrXsnow72sVeOFINDE/qNmnnd+f9b4N+U7W6MXnnYyrhtmF2t08QWwUbA== + dependencies: + "@typescript-eslint/eslint-plugin" "7.18.0" + "@typescript-eslint/parser" "7.18.0" + "@typescript-eslint/utils" "7.18.0" + typescript-eslint@^7.3.1: version "7.3.1" resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-7.3.1.tgz#9f4808abea3b33c4dd3bb51dd801471e91d1bd58" @@ -21659,11 +22016,6 @@ typescript-eslint@^7.3.1: "@typescript-eslint/eslint-plugin" "7.3.1" "@typescript-eslint/parser" "7.3.1" -typescript@5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" - integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== - typescript@5.5.2, "typescript@>=3 < 6": version "5.5.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.2.tgz#c26f023cb0054e657ce04f72583ea2d85f8d0507" @@ -21679,6 +22031,11 @@ typescript@^4.0.0, typescript@^4.5.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +typescript@^5.5.3: + version "5.5.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" + integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== + typo-js@*: version "1.2.2" resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.2.2.tgz#340484d81fe518e77c81a5a770162b14492f183b" @@ -21732,10 +22089,10 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -undici-types@~6.11.1: - version "6.11.1" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.11.1.tgz#432ea6e8efd54a48569705a699e62d8f4981b197" - integrity sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ== +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== undici@^4.14.1: version "4.16.0" @@ -22057,15 +22414,15 @@ vite-node@0.29.8: picocolors "^1.0.0" vite "^3.0.0 || ^4.0.0" -vite-node@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.6.0.tgz#2c7e61129bfecc759478fa592754fd9704aaba7f" - integrity sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw== +vite-node@2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.0.5.tgz#36d909188fc6e3aba3da5fc095b3637d0d18e27b" + integrity sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q== dependencies: cac "^6.7.14" - debug "^4.3.4" - pathe "^1.1.1" - picocolors "^1.0.0" + debug "^4.3.5" + pathe "^1.1.2" + tinyrainbow "^1.2.0" vite "^5.0.0" vite-plugin-static-copy@^0.17.0: @@ -22078,6 +22435,15 @@ vite-plugin-static-copy@^0.17.0: fs-extra "^11.1.0" picocolors "^1.0.0" +vite-tsconfig-paths@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz#321f02e4b736a90ff62f9086467faf4e2da857a9" + integrity sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA== + dependencies: + debug "^4.1.1" + globrex "^0.1.2" + tsconfck "^3.0.3" + "vite@^3.0.0 || ^4.0.0", vite@^4.5.0: version "4.5.3" resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.3.tgz#d88a4529ea58bae97294c7e2e6f0eab39a50fb1a" @@ -22090,13 +22456,13 @@ vite-plugin-static-copy@^0.17.0: fsevents "~2.3.2" vite@^5.0.0: - version "5.3.5" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.3.5.tgz#b847f846fb2b6cb6f6f4ed50a830186138cb83d8" - integrity sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA== + version "5.4.2" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.2.tgz#8acb6ec4bfab823cdfc1cb2d6c53ed311bc4e47e" + integrity sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA== dependencies: esbuild "^0.21.3" - postcss "^8.4.39" - rollup "^4.13.0" + postcss "^8.4.41" + rollup "^4.20.0" optionalDependencies: fsevents "~2.3.3" @@ -22135,31 +22501,30 @@ vitest@^0.29.2: vite-node "0.29.8" why-is-node-running "^2.2.2" -vitest@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.6.0.tgz#9d5ad4752a3c451be919e412c597126cffb9892f" - integrity sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA== +vitest@^2.0.4: + version "2.0.5" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.0.5.tgz#2f15a532704a7181528e399cc5b754c7f335fd62" + integrity sha512-8GUxONfauuIdeSl5f9GTgVEpg5BTOlplET4WEDaeY2QBiN8wSm68vxN/tb5z405OwppfoCavnwXafiaYBC/xOA== dependencies: - "@vitest/expect" "1.6.0" - "@vitest/runner" "1.6.0" - "@vitest/snapshot" "1.6.0" - "@vitest/spy" "1.6.0" - "@vitest/utils" "1.6.0" - acorn-walk "^8.3.2" - chai "^4.3.10" - debug "^4.3.4" + "@ampproject/remapping" "^2.3.0" + "@vitest/expect" "2.0.5" + "@vitest/pretty-format" "^2.0.5" + "@vitest/runner" "2.0.5" + "@vitest/snapshot" "2.0.5" + "@vitest/spy" "2.0.5" + "@vitest/utils" "2.0.5" + chai "^5.1.1" + debug "^4.3.5" execa "^8.0.1" - local-pkg "^0.5.0" - magic-string "^0.30.5" - pathe "^1.1.1" - picocolors "^1.0.0" - std-env "^3.5.0" - strip-literal "^2.0.0" - tinybench "^2.5.1" - tinypool "^0.8.3" + magic-string "^0.30.10" + pathe "^1.1.2" + std-env "^3.7.0" + tinybench "^2.8.0" + tinypool "^1.0.0" + tinyrainbow "^1.2.0" vite "^5.0.0" - vite-node "1.6.0" - why-is-node-running "^2.2.2" + vite-node "2.0.5" + why-is-node-running "^2.3.0" vlq@^0.2.2: version "0.2.3" @@ -22209,7 +22574,7 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" -watskeburt@4.1.0: +watskeburt@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/watskeburt/-/watskeburt-4.1.0.tgz#3c0227669be646a97424b631164b1afe3d4d5344" integrity sha512-KkY5H51ajqy9HYYI+u9SIURcWnqeVVhdH0I+ab6aXPGHfZYxgRCwnR6Lm3+TYB6jJVt5jFqw4GAKmwf1zHmGQw== @@ -22232,9 +22597,9 @@ web-streams-polyfill@^3.2.1: integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== web-vitals@^4.0.1: - version "4.2.2" - resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.2.tgz#e883245180b95e175eb75a5ca8903b1a11597d7a" - integrity sha512-nYfoOqb4EmElljyXU2qdeE76KsvoHdftQKY4DzA9Aw8DervCg2bG634pHLrJ/d6+B4mE3nWTSJv8Mo7B2mbZkw== + version "4.2.3" + resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.3.tgz#270c4baecfbc6ec6fc15da1989e465e5f9b94fb7" + integrity sha512-/CFAm1mNxSmOj6i0Co+iGFJ58OS4NRGVP+AWS/l509uIK5a1bSoIVaHz/ZumpHTfHSZBpgrJ+wjfpAOrTHok5Q== webfinger@^0.4.2: version "0.4.2" @@ -22392,6 +22757,14 @@ why-is-node-running@^2.2.2: siginfo "^2.0.0" stackback "0.0.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== + dependencies: + siginfo "^2.0.0" + stackback "0.0.2" + wide-align@^1.1.2, wide-align@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" @@ -22459,7 +22832,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm: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== @@ -22477,6 +22850,15 @@ 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"