diff --git a/.changeset/rich-cows-try.md b/.changeset/rich-cows-try.md new file mode 100644 index 0000000000..1ee217c46f --- /dev/null +++ b/.changeset/rich-cows-try.md @@ -0,0 +1,47 @@ +--- +'@forgerock/journey-client': minor +'@forgerock/sdk-oidc': minor +'@forgerock/sdk-utilities': minor +'@forgerock/davinci-client': patch +'@forgerock/oidc-client': patch +--- + +### @forgerock/journey-client + +Add well-known OIDC endpoint discovery support. The journey client can now fetch configuration from the `.well-known/openid-configuration` endpoint: + +```typescript +const client = await journey({ + serverConfig: { + baseUrl: 'https://am.example.com/am/', + wellknown: + 'https://am.example.com/am/oauth2/realms/root/realms/alpha/.well-known/openid-configuration', + }, +}); +``` + +The realm path can be automatically inferred from the well-known issuer URL. + +### @forgerock/sdk-oidc + +Add shared well-known module with RTK Query API for OIDC endpoint discovery: + +- `wellknownApi` - RTK Query API for fetching well-known configuration +- `createWellknownSelector` - Selector factory for cached well-known data +- `createWellknownError` - Typed error creation from fetch failures +- Re-exports pure utilities from `@forgerock/sdk-utilities` + +### @forgerock/sdk-utilities + +Add pure well-known utilities: + +- `inferRealmFromIssuer` - Extract realm path from AM issuer URLs +- `isValidWellknownUrl` - Validate well-known URLs (HTTPS required, HTTP allowed for localhost) + +### @forgerock/davinci-client + +Refactored to use shared well-known module from `@forgerock/sdk-oidc`. + +### @forgerock/oidc-client + +Refactored to use shared well-known module from `@forgerock/sdk-oidc`. diff --git a/.changeset/wellknown-only-config.md b/.changeset/wellknown-only-config.md new file mode 100644 index 0000000000..63ddb70f24 --- /dev/null +++ b/.changeset/wellknown-only-config.md @@ -0,0 +1,45 @@ +--- +'@forgerock/journey-client': major +--- + +BREAKING: Unify journey-client around wellknown-only configuration + +This release simplifies the configuration API by requiring the `wellknown` URL and automatically inferring `baseUrl` and `realmPath`. + +## Breaking Changes + +- **Removed `baseUrl` from `JourneyServerConfig`**: The `baseUrl` is now always inferred from the wellknown URL. If inference fails (non-AM server), an error is returned. +- **Removed `hasWellknownConfig` export**: This type guard is no longer needed since all configs use wellknown. + +## Migration + +**Before:** + +```typescript +journey({ + config: { + serverConfig: { baseUrl: 'https://am.example.com/am/' }, + realmPath: 'alpha', + }, +}); +``` + +**After:** + +```typescript +journey({ + config: { + serverConfig: { + wellknown: 'https://am.example.com/am/oauth2/alpha/.well-known/openid-configuration', + }, + // realmPath is now optional - inferred from wellknown issuer + }, +}); +``` + +## Features + +- Automatic `baseUrl` inference from wellknown URL (extracts path before `/oauth2/`) +- Automatic `realmPath` inference from wellknown issuer +- Improved error messages for non-AM servers, guiding users to appropriate clients +- Updated README with comprehensive API documentation diff --git a/e2e/am-mock-api/package.json b/e2e/am-mock-api/package.json index bb3816e1be..075992643e 100644 --- a/e2e/am-mock-api/package.json +++ b/e2e/am-mock-api/package.json @@ -8,12 +8,14 @@ "author": "", "main": "./index.js", "dependencies": { - "@types/express": "^4.17.17", - "body-parser": "^2.2.0", + "body-parser": "^2.2.2", "cookie-parser": "^1.4.7", "cors": "^2.8.5", - "express": "^4.21.2", + "express": "^5.2.1", "superagent": "^10.2.3", "uuid": "^13.0.0" + }, + "devDependencies": { + "@types/express": "^5.0.0" } } diff --git a/e2e/am-mock-api/src/app/routes.auth.js b/e2e/am-mock-api/src/app/routes.auth.js index 158a61e763..bcf0e7c2e9 100644 --- a/e2e/am-mock-api/src/app/routes.auth.js +++ b/e2e/am-mock-api/src/app/routes.auth.js @@ -668,6 +668,11 @@ export default function (app) { res.send(wellKnownForgeRock); }); + // Standard AM wellknown endpoint path (used by journey-client wellknown discovery) + app.get('/am/oauth2/realms/root/.well-known/openid-configuration', (req, res) => { + res.send(wellKnownForgeRock); + }); + app.get('/as/.well-known/new-oidc-configuration', (req, res) => { res.send(newPiWellKnown); }); diff --git a/e2e/am-mock-api/src/app/routes.resource.js b/e2e/am-mock-api/src/app/routes.resource.js index d10dc278a3..b6680ea0b0 100644 --- a/e2e/am-mock-api/src/app/routes.resource.js +++ b/e2e/am-mock-api/src/app/routes.resource.js @@ -63,7 +63,7 @@ async function authorization(req, res, next) { export default function (app) { // Passthrough route that enforces authentication - app.all('/resource/*', async (req, res, next) => { + app.all('/resource/{*splat}', async (req, res, next) => { if (env.NODE_ENV === 'LIVE' && req.hostname === FORGEOPS) { // Only enforce authentication if IG is not used // In other words, the call comes directly from app @@ -156,7 +156,7 @@ export default function (app) { } }); - app.get('/resource/rest/*', wait, authorization, async (req, res) => { + app.get('/resource/rest/{*splat}', wait, authorization, async (req, res) => { if (env.NODE_ENV === 'live') { if (req.access.actions && req.access.actions.GET) { res.json({ message: 'Successfully retrieved resource!' }); diff --git a/e2e/davinci-app/package.json b/e2e/davinci-app/package.json index f9e3c5249d..4dfc5cee73 100644 --- a/e2e/davinci-app/package.json +++ b/e2e/davinci-app/package.json @@ -1,12 +1,9 @@ { "name": "@forgerock/davinci-app", "version": "0.0.0", + "private": true, "description": "Ping DaVinci Client Test App", "type": "module", - "private": true, - "nx": { - "tags": ["scope:e2e"] - }, "scripts": { "build": "pnpm nx nxBuild", "lint": "pnpm nx nxLint", @@ -16,8 +13,11 @@ "dependencies": { "@forgerock/davinci-client": "workspace:*", "@forgerock/javascript-sdk": "4.7.0", - "@forgerock/sdk-logger": "workspace:*", - "@forgerock/protect": "workspace:*" + "@forgerock/protect": "workspace:*", + "@forgerock/sdk-logger": "workspace:*" }, - "devDependencies": {} + "devDependencies": {}, + "nx": { + "tags": ["scope:e2e"] + } } diff --git a/e2e/davinci-app/tsconfig.json b/e2e/davinci-app/tsconfig.json index 3f3d0d96ac..3ee9db7804 100644 --- a/e2e/davinci-app/tsconfig.json +++ b/e2e/davinci-app/tsconfig.json @@ -14,15 +14,6 @@ "skipLibCheck": true }, "references": [ - { - "path": "../../packages/sdk-effects/logger" - }, - { - "path": "../../packages/protect" - }, - { - "path": "../../packages/davinci-client" - }, { "path": "./tsconfig.app.json" }, diff --git a/e2e/device-client-app/package.json b/e2e/device-client-app/package.json index 21818ec78a..c0bd8ec3fb 100644 --- a/e2e/device-client-app/package.json +++ b/e2e/device-client-app/package.json @@ -13,10 +13,10 @@ "@forgerock/javascript-sdk": "4.7.0", "effect": "^3.12.7" }, - "nx": { - "tags": ["scope:e2e"] - }, "devDependencies": { "@effect/language-service": "^0.20.0" + }, + "nx": { + "tags": ["scope:e2e"] } } diff --git a/e2e/device-client-app/tsconfig.json b/e2e/device-client-app/tsconfig.json index 301fbe928b..816e3f36f4 100644 --- a/e2e/device-client-app/tsconfig.json +++ b/e2e/device-client-app/tsconfig.json @@ -3,9 +3,6 @@ "files": [], "include": [], "references": [ - { - "path": "../../packages/device-client" - }, { "path": "./tsconfig.app.json" } diff --git a/e2e/journey-app/main.ts b/e2e/journey-app/main.ts index d5868c1e2f..08f9c1a0d5 100644 --- a/e2e/journey-app/main.ts +++ b/e2e/journey-app/main.ts @@ -6,7 +6,7 @@ */ import './style.css'; -import { journey } from '@forgerock/journey-client'; +import { journey, isJourneyClient } from '@forgerock/journey-client'; import type { RequestMiddleware } from '@forgerock/journey-client/types'; @@ -51,12 +51,23 @@ if (searchParams.get('middleware') === 'true') { } (async () => { - const journeyClient = await journey({ config: config, requestMiddleware }); - const errorEl = document.getElementById('error') as HTMLDivElement; const formEl = document.getElementById('form') as HTMLFormElement; const journeyEl = document.getElementById('journey') as HTMLDivElement; + const journeyClientResult = await journey({ config: config, requestMiddleware }); + if (!isJourneyClient(journeyClientResult)) { + console.error('Failed to initialize journey client:', journeyClientResult.message); + errorEl.textContent = journeyClientResult.message ?? 'Unknown error'; + return; + } + /** + * Re-assign to a new const after type narrowing. + * TypeScript's type narrowing doesn't persist into closures (event handlers, callbacks) + * because it can't prove the variable wasn't reassigned between the guard and closure execution. + * Creating a new const binding after the guard preserves the narrowed type for nested functions. + */ + const journeyClient = journeyClientResult; let step = await journeyClient.start({ journey: journeyName }); function renderComplete() { diff --git a/e2e/journey-app/package.json b/e2e/journey-app/package.json index 7a83f030d8..40a825314b 100644 --- a/e2e/journey-app/package.json +++ b/e2e/journey-app/package.json @@ -1,12 +1,9 @@ { "name": "@forgerock/journey-app", "version": "1.3.0", + "private": true, "description": "Ping Journey Client Test App", "type": "module", - "private": true, - "nx": { - "tags": ["scope:e2e"] - }, "scripts": { "build": "pnpm nx nxBuild", "lint": "pnpm nx nxLint", @@ -18,5 +15,8 @@ "@forgerock/oidc-client": "workspace:*", "@forgerock/protect": "workspace:*", "@forgerock/sdk-logger": "workspace:*" + }, + "nx": { + "tags": ["scope:e2e"] } } diff --git a/e2e/journey-app/server-configs.ts b/e2e/journey-app/server-configs.ts index 4bc08a1b1c..3bfa625157 100644 --- a/e2e/journey-app/server-configs.ts +++ b/e2e/journey-app/server-configs.ts @@ -6,17 +6,27 @@ */ import type { JourneyClientConfig } from '@forgerock/journey-client/types'; +/** + * Server configurations for E2E tests. + * + * Both baseUrl and realmPath are automatically inferred from the wellknown URL: + * - baseUrl: extracted from the path before `/oauth2/` + * - realmPath: extracted from the issuer URL in the wellknown response + */ export const serverConfigs: Record = { basic: { serverConfig: { - baseUrl: 'http://localhost:9443/am', + wellknown: 'http://localhost:9443/am/oauth2/realms/root/.well-known/openid-configuration', + // baseUrl inferred: http://localhost:9443/am/ + // realmPath inferred from issuer: 'root' }, - realmPath: 'root', }, tenant: { serverConfig: { - baseUrl: 'https://openam-sdks.forgeblocks.com/am', + wellknown: + 'https://openam-sdks.forgeblocks.com/am/oauth2/realms/root/realms/alpha/.well-known/openid-configuration', + // baseUrl inferred: https://openam-sdks.forgeblocks.com/am/ + // realmPath inferred from issuer: 'alpha' }, - realmPath: 'alpha', }, }; diff --git a/e2e/journey-app/tsconfig.json b/e2e/journey-app/tsconfig.json index a7028763ec..3ee9db7804 100644 --- a/e2e/journey-app/tsconfig.json +++ b/e2e/journey-app/tsconfig.json @@ -14,18 +14,6 @@ "skipLibCheck": true }, "references": [ - { - "path": "../../packages/sdk-effects/logger" - }, - { - "path": "../../packages/oidc-client" - }, - { - "path": "../../packages/protect" - }, - { - "path": "../../packages/journey-client" - }, { "path": "./tsconfig.app.json" }, diff --git a/e2e/mock-api-v2/package.json b/e2e/mock-api-v2/package.json index 30b2be9111..dfd0688bf4 100644 --- a/e2e/mock-api-v2/package.json +++ b/e2e/mock-api-v2/package.json @@ -26,7 +26,8 @@ "nanoid": "5.1.6" }, "devDependencies": { - "@effect/vitest": "catalog:effect" + "@effect/vitest": "catalog:effect", + "vitest": "catalog:vitest" }, "nx": { "tags": ["scope:e2e"], diff --git a/e2e/oidc-app/tsconfig.json b/e2e/oidc-app/tsconfig.json index 5469f156e4..816e3f36f4 100644 --- a/e2e/oidc-app/tsconfig.json +++ b/e2e/oidc-app/tsconfig.json @@ -3,9 +3,6 @@ "files": [], "include": [], "references": [ - { - "path": "../../packages/oidc-client" - }, { "path": "./tsconfig.app.json" } diff --git a/e2e/protect-app/package.json b/e2e/protect-app/package.json index d081f07ad4..8f3c3c8101 100644 --- a/e2e/protect-app/package.json +++ b/e2e/protect-app/package.json @@ -1,8 +1,8 @@ { "name": "@forgerock/protect-app", "version": "0.0.0", - "description": "Ping Protect Test Apps", "private": true, + "description": "Ping Protect Test Apps", "type": "module", "scripts": { "build": "pnpm nx nxBuild", diff --git a/e2e/protect-app/tsconfig.json b/e2e/protect-app/tsconfig.json index 88029a2ec0..9362c61427 100644 --- a/e2e/protect-app/tsconfig.json +++ b/e2e/protect-app/tsconfig.json @@ -16,9 +16,6 @@ "skipLibCheck": true }, "references": [ - { - "path": "../../packages/protect" - }, { "path": "./tsconfig.app.json" }, diff --git a/nx.json b/nx.json index 540f8f89fc..d2f5805f60 100644 --- a/nx.json +++ b/nx.json @@ -126,7 +126,6 @@ "buildTargetName": "nxBuild", "serveTargetName": "nxServe", "previewTargetName": "nxPreview", - "testTargetName": "nxTest", "serveStaticTargetName": "serve-static", "typecheckTargetName": "typecheck", "buildDepsTargetName": "vite:build-deps", @@ -146,6 +145,13 @@ "configName": "tsconfig.lib.json" } } + }, + { + "plugin": "@nx/vitest", + "options": { + "testTargetName": "nxTest" + }, + "include": ["packages/**/**/*", "e2e/**/**/*", "tools/**/**/*"] } ], "parallel": 1, diff --git a/package.json b/package.json index 0848e18d4a..9246251c1c 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "path": "./node_modules/cz-conventional-changelog" } }, + "dependencies": {}, "devDependencies": { "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "^2.27.9", @@ -58,17 +59,18 @@ "@effect/cli": "catalog:effect", "@eslint/eslintrc": "^3.0.0", "@eslint/js": "~9.39.0", - "@nx/devkit": "21.2.3", - "@nx/eslint": "21.2.3", - "@nx/eslint-plugin": "21.2.3", - "@nx/express": "21.2.3", - "@nx/jest": "21.2.3", - "@nx/js": "21.2.3", - "@nx/playwright": "21.2.3", - "@nx/plugin": "21.2.3", - "@nx/vite": "21.2.3", - "@nx/web": "21.2.3", - "@nx/workspace": "21.2.3", + "@nx/devkit": "22.3.3", + "@nx/eslint": "22.3.3", + "@nx/eslint-plugin": "22.3.3", + "@nx/express": "22.3.3", + "@nx/jest": "22.3.3", + "@nx/js": "22.3.3", + "@nx/playwright": "22.3.3", + "@nx/plugin": "22.3.3", + "@nx/vite": "22.3.3", + "@nx/vitest": "22.3.3", + "@nx/web": "22.3.3", + "@nx/workspace": "22.3.3", "@playwright/test": "^1.47.2", "@swc-node/register": "1.10.10", "@swc/cli": "0.6.0", @@ -82,8 +84,8 @@ "@typescript-eslint/parser": "^8.45.0", "@typescript-eslint/typescript-estree": "8.23.0", "@typescript-eslint/utils": "^8.13.0", - "@vitest/coverage-v8": "^3.0.5", - "@vitest/ui": "3.0.4", + "@vitest/coverage-v8": "4.0.9", + "@vitest/ui": "4.0.9", "conventional-changelog-conventionalcommits": "^8.0.0", "cz-conventional-changelog": "^3.3.0", "cz-git": "^1.6.1", @@ -100,7 +102,7 @@ "jsonc-eslint-parser": "^2.1.0", "lint-staged": "^15.0.0", "madge": "8.0.0", - "nx": "21.2.3", + "nx": "22.3.3", "pkg-pr-new": "^0.0.60", "playwright": "^1.47.2", "prettier": "^3.2.5", @@ -115,9 +117,9 @@ "typescript": "5.8.3", "typescript-eslint": "^8.19.0", "verdaccio": "6.2.1", - "vite": "6.4.1", + "vite": "catalog:vite", "vitest": "catalog:vitest", - "vitest-canvas-mock": "^0.3.3" + "vitest-canvas-mock": "catalog:vitest" }, "packageManager": "pnpm@10.21.0+sha512.da3337267e400fdd3d479a6c68079ac6db01d8ca4f67572083e722775a796788a7a9956613749e000fac20d424b594f7a791a5f4e2e13581c5ef947f26968a40", "engines": { diff --git a/packages/davinci-client/src/lib/client.store.ts b/packages/davinci-client/src/lib/client.store.ts index 851b17db84..5adb6c5543 100644 --- a/packages/davinci-client/src/lib/client.store.ts +++ b/packages/davinci-client/src/lib/client.store.ts @@ -15,7 +15,7 @@ import { createClientStore, handleUpdateValidateError, RootState } from './clien import { nodeSlice } from './node.slice.js'; import { davinciApi } from './davinci.api.js'; import { configSlice } from './config.slice.js'; -import { wellknownApi } from './wellknown.api.js'; +import { wellknownApi, createWellknownError } from '@forgerock/sdk-oidc'; import type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; /** @@ -88,14 +88,14 @@ export async function davinci({ throw error; } - const { data: openIdResponse } = await store.dispatch( - wellknownApi.endpoints.wellknown.initiate(config.serverConfig.wellknown), + const { data: openIdResponse, error: fetchError } = await store.dispatch( + wellknownApi.endpoints.configuration.initiate(config.serverConfig.wellknown), ); - if (!openIdResponse) { - const error = new Error('error fetching `wellknown` response for OpenId Configuration'); - log.error(error.message); - throw error; + if (fetchError || !openIdResponse) { + const genericError = createWellknownError(fetchError); + log.error(`${genericError.error}: ${genericError.message}`); + throw new Error(genericError.message); } store.dispatch(configSlice.actions.set({ ...config, wellknownResponse: openIdResponse })); @@ -249,11 +249,11 @@ export async function davinci({ return node; } catch (err) { - const error = err as Error; - log.error(error.message); + const errorMessage = err instanceof Error ? err.message : String(err); + log.error(errorMessage); return { error: { - message: error.message ?? 'An unexpected error occurred during resume operation', + message: errorMessage || 'An unexpected error occurred during resume operation', type: 'internal_error', }, type: 'internal_error', @@ -336,10 +336,10 @@ export async function davinci({ store.dispatch(nodeSlice.actions.update({ id, value, index })); return null; } catch (err) { - const error = err as Error; + const errorMessage = err instanceof Error ? err.message : String(err); return { type: 'internal_error', - error: { message: error.message, type: 'internal_error' }, + error: { message: errorMessage, type: 'internal_error' }, }; } }; diff --git a/packages/davinci-client/src/lib/client.store.utils.ts b/packages/davinci-client/src/lib/client.store.utils.ts index f46e25642b..e4892e7d48 100644 --- a/packages/davinci-client/src/lib/client.store.utils.ts +++ b/packages/davinci-client/src/lib/client.store.utils.ts @@ -13,7 +13,7 @@ import { configSlice } from './config.slice.js'; import { nodeSlice } from './node.slice.js'; import { davinciApi } from './davinci.api.js'; import { ErrorNode, ContinueNode, StartNode, SuccessNode } from '../types.js'; -import { wellknownApi } from './wellknown.api.js'; +import { wellknownApi } from '@forgerock/sdk-oidc'; import { InternalErrorResponse } from './client.types.js'; export function createClientStore({ diff --git a/packages/davinci-client/src/lib/config.types.test-d.ts b/packages/davinci-client/src/lib/config.types.test-d.ts index 340f7d4634..6b5c1ba7d5 100644 --- a/packages/davinci-client/src/lib/config.types.test-d.ts +++ b/packages/davinci-client/src/lib/config.types.test-d.ts @@ -6,8 +6,7 @@ */ import { describe, expectTypeOf, it } from 'vitest'; import type { DaVinciConfig, InternalDaVinciConfig } from './config.types.js'; -import type { AsyncLegacyConfigOptions } from '@forgerock/sdk-types'; -import type { WellknownResponse } from './wellknown.types.js'; +import type { AsyncLegacyConfigOptions, WellknownResponse } from '@forgerock/sdk-types'; describe('Config Types', () => { describe('DaVinciConfig', () => { @@ -51,30 +50,9 @@ describe('Config Types', () => { authorization_endpoint: 'https://example.com/auth', token_endpoint: 'https://example.com/token', userinfo_endpoint: 'https://example.com/userinfo', - jwks_uri: 'https://example.com/jwks', - revocation_endpoint: 'https://example.com/register', end_session_endpoint: 'https://example.com/logout', - pushed_authorization_request_endpoint: '', - check_session_iframe: '', - introspection_endpoint: '', - device_authorization_endpoint: '', - claims_parameter_supported: '', - request_parameter_supported: '', - request_uri_parameter_supported: '', - require_pushed_authorization_requests: '', - scopes_supported: [], - response_types_supported: [], - response_modes_supported: [], - grant_types_supported: [], - subject_types_supported: [], - id_token_signing_alg_values_supported: [], - userinfo_signing_alg_values_supported: [], - request_object_signing_alg_values_supported: [], - token_endpoint_auth_methods_supported: [], - token_endpoint_auth_signing_alg_values_supported: [], - claim_types_supported: [], - claims_supported: [], - code_challenge_methods_supported: [], + introspection_endpoint: 'https://example.com/introspect', + revocation_endpoint: 'https://example.com/revoke', }, responseType: 'code', serverConfig: {}, @@ -85,7 +63,6 @@ describe('Config Types', () => { it('should combine DaVinciConfig and wellknownResponse', () => { const config: InternalDaVinciConfig = { - // DaVinciConfig properties clientId: 'test-client', scope: 'openid profile', serverConfig: { @@ -94,36 +71,16 @@ describe('Config Types', () => { }, redirectUri: 'https://app.example.com/callback', responseType: 'code', - // InternalDaVinciConfig specific property wellknownResponse: { issuer: 'https://example.com', authorization_endpoint: 'https://example.com/auth', token_endpoint: 'https://example.com/token', userinfo_endpoint: 'https://example.com/userinfo', - jwks_uri: 'https://example.com/jwks', - revocation_endpoint: 'https://example.com/revoke', end_session_endpoint: 'https://example.com/logout', - pushed_authorization_request_endpoint: '', - check_session_iframe: '', - introspection_endpoint: '', - device_authorization_endpoint: '', - claims_parameter_supported: '', - request_parameter_supported: '', - request_uri_parameter_supported: '', - require_pushed_authorization_requests: '', - scopes_supported: [], - response_types_supported: [], - response_modes_supported: [], - grant_types_supported: [], - subject_types_supported: [], - id_token_signing_alg_values_supported: [], - userinfo_signing_alg_values_supported: [], - request_object_signing_alg_values_supported: [], - token_endpoint_auth_methods_supported: [], - token_endpoint_auth_signing_alg_values_supported: [], - claim_types_supported: [], - claims_supported: [], - code_challenge_methods_supported: [], + introspection_endpoint: 'https://example.com/introspect', + revocation_endpoint: 'https://example.com/revoke', + jwks_uri: 'https://example.com/jwks', + scopes_supported: ['openid', 'profile'], }, }; expectTypeOf(config).toMatchTypeOf(); @@ -132,45 +89,24 @@ describe('Config Types', () => { }); describe('WellknownResponse', () => { - it('should have all required OIDC properties', () => { + it('should have required OIDC properties', () => { const wellknown: WellknownResponse = { issuer: 'https://example.com', authorization_endpoint: 'https://example.com/auth', token_endpoint: 'https://example.com/token', userinfo_endpoint: 'https://example.com/userinfo', - jwks_uri: 'https://example.com/jwks', - revocation_endpoint: 'https://example.com/revoke', end_session_endpoint: 'https://example.com/logout', - pushed_authorization_request_endpoint: '', - check_session_iframe: '', - introspection_endpoint: '', - device_authorization_endpoint: '', - claims_parameter_supported: '', - request_parameter_supported: '', - request_uri_parameter_supported: '', - require_pushed_authorization_requests: '', - scopes_supported: [], - response_types_supported: [], - response_modes_supported: [], - grant_types_supported: [], - subject_types_supported: [], - id_token_signing_alg_values_supported: [], - userinfo_signing_alg_values_supported: [], - request_object_signing_alg_values_supported: [], - token_endpoint_auth_methods_supported: [], - token_endpoint_auth_signing_alg_values_supported: [], - claim_types_supported: [], - claims_supported: [], - code_challenge_methods_supported: [], + introspection_endpoint: 'https://example.com/introspect', + revocation_endpoint: 'https://example.com/revoke', }; expectTypeOf().toHaveProperty('issuer').toBeString(); expectTypeOf().toHaveProperty('authorization_endpoint').toBeString(); expectTypeOf().toHaveProperty('token_endpoint').toBeString(); expectTypeOf().toHaveProperty('userinfo_endpoint').toBeString(); - expectTypeOf().toHaveProperty('jwks_uri').toBeString(); - expectTypeOf().toHaveProperty('revocation_endpoint').toBeString(); expectTypeOf().toHaveProperty('end_session_endpoint').toBeString(); + expectTypeOf().toHaveProperty('introspection_endpoint').toBeString(); + expectTypeOf().toHaveProperty('revocation_endpoint').toBeString(); expectTypeOf(wellknown).toMatchTypeOf(); }); @@ -181,93 +117,58 @@ describe('WellknownResponse', () => { authorization_endpoint: 'https://example.com/auth', token_endpoint: 'https://example.com/token', userinfo_endpoint: 'https://example.com/userinfo', - jwks_uri: 'https://example.com/jwks', - revocation_endpoint: 'https://example.com/revoke', end_session_endpoint: 'https://example.com/logout', - // Optional properties + introspection_endpoint: 'https://example.com/introspect', + revocation_endpoint: 'https://example.com/revoke', + jwks_uri: 'https://example.com/jwks', scopes_supported: ['openid', 'profile', 'email'], response_types_supported: ['code', 'token'], grant_types_supported: ['authorization_code', 'refresh_token'], subject_types_supported: ['public'], id_token_signing_alg_values_supported: ['RS256'], token_endpoint_auth_methods_supported: ['client_secret_basic'], - pushed_authorization_request_endpoint: '', - check_session_iframe: '', - introspection_endpoint: '', - device_authorization_endpoint: '', - claims_parameter_supported: '', - request_parameter_supported: '', - request_uri_parameter_supported: '', - require_pushed_authorization_requests: '', - response_modes_supported: [], - userinfo_signing_alg_values_supported: [], - request_object_signing_alg_values_supported: [], - token_endpoint_auth_signing_alg_values_supported: [], - claim_types_supported: [], - claims_supported: [], - code_challenge_methods_supported: [], }; - // Test optional properties are allowed but not required expectTypeOf().toHaveProperty('scopes_supported'); expectTypeOf().toHaveProperty('response_types_supported'); expectTypeOf().toHaveProperty('grant_types_supported'); + expectTypeOf().toHaveProperty('jwks_uri'); expectTypeOf(wellknownWithOptionals).toMatchTypeOf(); }); - it('should validate property types', () => { - // Test that array properties must contain strings - expectTypeOf().toEqualTypeOf(); - expectTypeOf().toEqualTypeOf(); - expectTypeOf().toEqualTypeOf(); - expectTypeOf().toEqualTypeOf(); + it('should validate optional array property types', () => { + expectTypeOf().toEqualTypeOf(); + expectTypeOf().toEqualTypeOf< + string[] | undefined + >(); + expectTypeOf().toEqualTypeOf< + string[] | undefined + >(); + expectTypeOf().toEqualTypeOf< + string[] | undefined + >(); expectTypeOf().toEqualTypeOf< - string[] + string[] | undefined >(); expectTypeOf().toEqualTypeOf< - string[] + string[] | undefined >(); }); - it('should enforce URL format for endpoint properties', () => { + it('should enforce URL format for required endpoint properties', () => { const wellknown: WellknownResponse = { issuer: 'https://example.com', authorization_endpoint: 'https://example.com/auth', token_endpoint: 'https://example.com/token', userinfo_endpoint: 'https://example.com/userinfo', - jwks_uri: 'https://example.com/jwks', - revocation_endpoint: 'https://example.com/register', end_session_endpoint: 'https://example.com/logout', - pushed_authorization_request_endpoint: '', - check_session_iframe: '', - introspection_endpoint: '', - device_authorization_endpoint: '', - claims_parameter_supported: '', - request_parameter_supported: '', - request_uri_parameter_supported: '', - require_pushed_authorization_requests: '', - scopes_supported: [], - response_types_supported: [], - response_modes_supported: [], - grant_types_supported: [], - subject_types_supported: [], - id_token_signing_alg_values_supported: [], - userinfo_signing_alg_values_supported: [], - request_object_signing_alg_values_supported: [], - token_endpoint_auth_methods_supported: [], - token_endpoint_auth_signing_alg_values_supported: [], - claim_types_supported: [], - claims_supported: [], - code_challenge_methods_supported: [], + introspection_endpoint: 'https://example.com/introspect', + revocation_endpoint: 'https://example.com/revoke', }; - // Type assertion to ensure all endpoint properties are strings (URLs) expectTypeOf(wellknown.authorization_endpoint).toBeString(); expectTypeOf(wellknown.token_endpoint).toBeString(); expectTypeOf(wellknown.userinfo_endpoint).toBeString(); - expectTypeOf(wellknown.jwks_uri).toBeString(); - expectTypeOf(wellknown.revocation_endpoint).toBeString(); - expectTypeOf(wellknown.end_session_endpoint).toBeString(); }); }); diff --git a/packages/davinci-client/src/lib/config.types.ts b/packages/davinci-client/src/lib/config.types.ts index c443a704cf..9a16e5940b 100644 --- a/packages/davinci-client/src/lib/config.types.ts +++ b/packages/davinci-client/src/lib/config.types.ts @@ -4,11 +4,8 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -/** - * Import LegacyConfigOptions type from the JavaScript SDK - */ -import type { AsyncLegacyConfigOptions } from '@forgerock/sdk-types'; -import { WellknownResponse } from './wellknown.types.js'; + +import type { AsyncLegacyConfigOptions, WellknownResponse } from '@forgerock/sdk-types'; export interface DaVinciConfig extends AsyncLegacyConfigOptions { responseType?: string; diff --git a/packages/davinci-client/src/lib/wellknown.api.ts b/packages/davinci-client/src/lib/wellknown.api.ts deleted file mode 100644 index 6c3edd6118..0000000000 --- a/packages/davinci-client/src/lib/wellknown.api.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2025 Ping Identity Corporation. All rights reserved. - * - * This software may be modified and distributed under the terms - * of the MIT license. See the LICENSE file for details. - */ -import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'; -import { WellknownResponse } from './wellknown.types.js'; - -export const wellknownApi = createApi({ - reducerPath: 'wellknown', - baseQuery: fetchBaseQuery({ - prepareHeaders: (headers) => { - headers.set('Accept', 'application/json'); - return headers; - }, - }), - endpoints: (builder) => ({ - wellknown: builder.query({ - query: (endpoint: string) => ({ url: endpoint }), - }), - }), -}); diff --git a/packages/davinci-client/src/lib/wellknown.types.ts b/packages/davinci-client/src/lib/wellknown.types.ts index 0fa71de10c..bdf78802a5 100644 --- a/packages/davinci-client/src/lib/wellknown.types.ts +++ b/packages/davinci-client/src/lib/wellknown.types.ts @@ -4,37 +4,14 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -export interface WellknownResponse { - issuer: string; - authorization_endpoint: string; - pushed_authorization_request_endpoint: string; - token_endpoint: string; - userinfo_endpoint: string; - jwks_uri: string; - end_session_endpoint: string; - check_session_iframe: string; - introspection_endpoint: string; - revocation_endpoint: string; - device_authorization_endpoint: string; - claims_parameter_supported: string; - request_parameter_supported: string; - request_uri_parameter_supported: string; - require_pushed_authorization_requests: string; - scopes_supported: string[]; - response_types_supported: string[]; - response_modes_supported: string[]; - grant_types_supported: string[]; - subject_types_supported: string[]; - id_token_signing_alg_values_supported: string[]; - userinfo_signing_alg_values_supported: string[]; - request_object_signing_alg_values_supported: string[]; - token_endpoint_auth_methods_supported: string[]; - token_endpoint_auth_signing_alg_values_supported: string[]; - claim_types_supported: string[]; - claims_supported: string[]; - code_challenge_methods_supported: string[]; -} +// Re-export WellknownResponse from shared types for convenience +export type { WellknownResponse } from '@forgerock/sdk-types'; + +/** + * Simplified endpoint mapping extracted from well-known response. + * Used internally by DaVinci client for OAuth/OIDC operations. + */ export interface Endpoints { authorize: string; issuer: string; diff --git a/packages/journey-client/README.md b/packages/journey-client/README.md index e352fb2a39..2107ab44bf 100644 --- a/packages/journey-client/README.md +++ b/packages/journey-client/README.md @@ -1,13 +1,16 @@ # @forgerock/journey-client -`@forgerock/journey-client` is a modern JavaScript client for interacting with Ping Identity's authentication journeys (formerly ForgeRock authentication trees). It provides a stateful, developer-friendly API that abstracts the complexities of the underlying authentication flow, making it easier to integrate with your applications. +`@forgerock/journey-client` is a JavaScript client for interacting with ForgeRock Access Management (AM) authentication journeys (authentication trees). It provides a stateful, developer-friendly API that abstracts the complexities of the underlying authentication flow. + +> **Note**: This client is designed specifically for ForgeRock AM servers. For PingOne DaVinci flows, use `@forgerock/davinci-client`. For standard OIDC operations, use `@forgerock/oidc-client`. ## Features -- **Stateful Client**: Manages the authentication journey state internally, simplifying interaction compared to stateless approaches. -- **Redux Toolkit & RTK Query**: Built on robust and modern state management and data fetching libraries for predictable state and efficient API interactions. -- **Callback Handling**: Provides a structured way to interact with various authentication callbacks (e.g., username, password, MFA, device profiling). -- **Serializable Redux State**: Ensures the Redux store remains serializable by storing raw API payloads, with class instances created on demand. +- **Wellknown Discovery**: Automatically discovers server configuration from the OIDC wellknown endpoint +- **Stateful Client**: Manages authentication journey state internally +- **Error-as-Value Pattern**: Returns errors as values instead of throwing, enabling type-safe error handling +- **Callback Handling**: Provides a structured way to interact with various authentication callbacks +- **Redux Toolkit & RTK Query**: Built on modern state management for predictable state and efficient API interactions ## Installation @@ -19,116 +22,242 @@ npm install @forgerock/journey-client yarn add @forgerock/journey-client ``` -## Usage - -The `journey-client` is initialized via an asynchronous factory function, `journey()`, which returns a client instance with methods to control the authentication flow. - -### Basic Authentication Flow +## Quick Start ```typescript -import { journey } from '@forgerock/journey-client'; +import { journey, isJourneyClient } from '@forgerock/journey-client'; import { callbackType } from '@forgerock/sdk-types'; -import type { NameCallback, PasswordCallback } from '@forgerock/journey-client/src/lib/callbacks'; async function authenticateUser() { - const client = await journey({ + // Initialize the client with wellknown discovery + const result = await journey({ config: { - serverConfig: { baseUrl: 'https://your-am-instance.com' }, - realmPath: 'root', // e.g., 'root', 'alpha' - tree: 'Login', // The name of your authentication tree/journey + serverConfig: { + wellknown: 'https://am.example.com/am/oauth2/alpha/.well-known/openid-configuration', + }, + // realmPath is optional - inferred from wellknown issuer }, }); - try { - // 1. Start the authentication journey - let step = await client.start(); - - // 2. Handle callbacks in a loop until success or failure - while (step.type === 'Step') { - console.log('Current step:', step.payload); - - // Example: Handle NameCallback - if (step.getCallbacksOfType(callbackType.NameCallback).length > 0) { - const nameCallback = step.getCallbackOfType(callbackType.NameCallback); - console.log('Prompt for username:', nameCallback.getPrompt()); - nameCallback.setName('demo'); // Set the username - } - - // Example: Handle PasswordCallback - if (step.getCallbacksOfType(callbackType.PasswordCallback).length > 0) { - const passwordCallback = step.getCallbackOfType( - callbackType.PasswordCallback, - ); - console.log('Prompt for password:', passwordCallback.getPrompt()); - passwordCallback.setPassword('password'); // Set the password - } - - // ... handle other callback types as needed (e.g., ChoiceCallback, DeviceProfileCallback) - - // Submit the current step and get the next one - step = await client.next({ step: step.payload }); + // Handle initialization errors using the type guard + if (!isJourneyClient(result)) { + console.error('Failed to initialize:', result.message); + return; + } + + const client = result; + + // Start the authentication journey + let step = await client.start({ journey: 'Login' }); + + // Handle callbacks in a loop until success or failure + while (step?.type === 'Step') { + // Handle NameCallback + const nameCallbacks = step.getCallbacksOfType(callbackType.NameCallback); + for (const cb of nameCallbacks) { + cb.setName('demo'); } - // 3. Check the final result - if (step.type === 'LoginSuccess') { - console.log('Login successful!', step.getSessionToken()); - // You can now use the session token for subsequent authenticated requests - } else if (step.type === 'LoginFailure') { - console.error('Login failed:', step.getMessage()); - // Display error message to the user - } else { - console.warn('Unexpected step type:', step.type, step.payload); + // Handle PasswordCallback + const passwordCallbacks = step.getCallbacksOfType(callbackType.PasswordCallback); + for (const cb of passwordCallbacks) { + cb.setPassword('password'); } - } catch (error) { - console.error('An error occurred during the authentication journey:', error); - // Handle network errors or other unexpected issues + + // Submit and get next step + step = await client.next(step); + } + + // Check the final result + if (step?.type === 'LoginSuccess') { + console.log('Login successful!', step.getSessionToken()); + } else if (step?.type === 'LoginFailure') { + console.error('Login failed:', step.payload.message); } } +``` + +## Configuration + +The client uses OIDC wellknown discovery to automatically configure itself: + +```typescript +import type { JourneyClientConfig } from '@forgerock/journey-client/types'; + +const config: JourneyClientConfig = { + serverConfig: { + // Required: OIDC discovery endpoint + wellknown: 'https://am.example.com/am/oauth2/alpha/.well-known/openid-configuration', + // Optional: Custom path overrides + paths: { + authenticate: '/custom/authenticate', + }, + // Optional: Request timeout in milliseconds + timeout: 30000, + }, + // Optional: Realm path (inferred from wellknown issuer if not provided) + realmPath: 'alpha', +}; +``` + +### Automatic Inference -authenticateUser(); +The client automatically infers configuration from the wellknown URL: + +| Property | Inferred From | +| ----------- | ----------------------------------------------------- | +| `baseUrl` | Extracted from wellknown URL path (before `/oauth2/`) | +| `realmPath` | Extracted from the `issuer` in the wellknown response | + +## API Reference + +### `journey(options)` + +Factory function that creates a journey client instance. + +```typescript +const result = await journey({ + config: JourneyClientConfig, + requestMiddleware?: RequestMiddleware[], + logger?: { level: LogLevel; custom?: CustomLogger }, +}); +``` + +**Returns**: `Promise` + +Use the `isJourneyClient()` type guard to narrow the result: + +```typescript +if (!isJourneyClient(result)) { + // result is GenericError + console.error(result.error, result.message); + return; +} +// result is JourneyClient ``` ### Client Methods -The `journey()` factory function returns a client instance with the following methods: +#### `client.start(options?)` -- `client.start(options?: StepOptions): Promise` - Initiates a new authentication journey. Returns the first `JourneyStep` in the journey. +Initiates a new authentication journey. -- `client.next(options: { step: Step; options?: StepOptions }): Promise` - Submits the current `Step` payload (obtained from `JourneyStep.payload`) to the authentication API and retrieves the next `JourneyStep` in the journey. +```typescript +const step = await client.start({ + journey: 'Login', // Required: Journey/tree name + query: { locale: 'en' }, // Optional: Query parameters +}); +``` -- `client.redirect(step: JourneyStep): Promise` - Handles `RedirectCallback`s by storing the current step and redirecting the browser to the specified URL. This is typically used for external authentication providers. +**Returns**: `Promise` -- `client.resume(url: string, options?: StepOptions): Promise` - Resumes an authentication journey after an external redirect (e.g., from an OAuth provider). It retrieves the previously stored step and combines it with URL parameters to continue the flow. +#### `client.next(step, options?)` -### Handling Callbacks +Submits the current step and retrieves the next one. -The `JourneyStep` object provides methods to easily access and manipulate callbacks: +```typescript +const nextStep = await client.next(step, { + query: { noSession: 'true' }, // Optional: Query parameters +}); +``` -- `step.getCallbackOfType(type: CallbackType): T` - Retrieves a single callback of a specific type. Throws an error if zero or more than one callback of that type is found. +**Returns**: `Promise` -- `step.getCallbacksOfType(type: CallbackType): T[]` - Retrieves all callbacks of a specific type as an array. +#### `client.redirect(step)` -- `callback.getPrompt(): string` (example for `NameCallback`, `PasswordCallback`) - Gets the prompt message for the callback. +Handles redirect callbacks by redirecting the browser. -- `callback.setName(value: string): void` (example for `NameCallback`) - Sets the input value for the callback. +```typescript +await client.redirect(step); +``` -- `callback.setPassword(value: string): void` (example for `PasswordCallback`) - Sets the input value for the callback. +#### `client.resume(url, options?)` -- `callback.setProfile(profile: DeviceProfileData): void` (example for `DeviceProfileCallback`) - Sets the device profile data for the callback. +Resumes a journey after an external redirect. -## Building +```typescript +const step = await client.resume(window.location.href, { + journey: 'Login', // Optional: Override journey name +}); +``` + +#### `client.terminate(options?)` + +Ends the current session. + +```typescript +await client.terminate(); +``` + +## Working with Callbacks + +The `JourneyStep` object provides methods to access and manipulate callbacks: + +```typescript +// Get all callbacks of a type +const nameCallbacks = step.getCallbacksOfType(callbackType.NameCallback); + +// Get a single callback (throws if not exactly one) +const nameCallback = step.getCallbackOfType(callbackType.NameCallback); + +// Common callback operations +nameCallback.getPrompt(); // Get the prompt text +nameCallback.setName('value'); // Set the input value + +passwordCallback.getPrompt(); +passwordCallback.setPassword('value'); + +choiceCallback.getChoices(); +choiceCallback.setChoice(0); +``` + +## Request Middleware -This library is part of an Nx monorepo. To build it, run: +Add custom logic to requests using middleware: + +```typescript +import type { RequestMiddleware } from '@forgerock/journey-client/types'; + +const loggingMiddleware: RequestMiddleware = (req, action, next) => { + console.log(`${action.type}: ${req.url}`); + next(); +}; + +const result = await journey({ + config, + requestMiddleware: [loggingMiddleware], +}); +``` + +### Middleware Actions + +| Action Type | Description | +| --------------- | ----------------------- | +| `JOURNEY_START` | Starting a new journey | +| `JOURNEY_NEXT` | Submitting a step | +| `END_SESSION` | Terminating the session | + +## Error Handling + +The client uses an error-as-value pattern instead of throwing exceptions: + +```typescript +const result = await journey({ config }); + +if (!isJourneyClient(result)) { + // Handle initialization error + switch (result.type) { + case 'wellknown_error': + console.error('Configuration error:', result.message); + break; + default: + console.error('Unknown error:', result.error); + } + return; +} +``` + +## Building ```bash pnpm nx build @forgerock/journey-client @@ -136,8 +265,6 @@ pnpm nx build @forgerock/journey-client ## Testing -To run the unit tests for this package, run: - ```bash pnpm nx test @forgerock/journey-client ``` diff --git a/packages/journey-client/package.json b/packages/journey-client/package.json index 13f386b22a..ec322e7847 100644 --- a/packages/journey-client/package.json +++ b/packages/journey-client/package.json @@ -23,19 +23,21 @@ }, "dependencies": { "@forgerock/sdk-logger": "workspace:*", + "@forgerock/sdk-oidc": "workspace:*", "@forgerock/sdk-request-middleware": "workspace:*", "@forgerock/sdk-types": "workspace:*", "@forgerock/sdk-utilities": "workspace:*", "@forgerock/storage": "workspace:*", "@reduxjs/toolkit": "catalog:", "tslib": "^2.3.0", - "vite": "6.4.1", - "vitest-canvas-mock": "^0.3.3" + "vite": "catalog:vite", + "vitest-canvas-mock": "catalog:vitest" }, "devDependencies": { - "@vitest/coverage-v8": "^1.2.0", - "vite": "6.4.1", - "vitest": "^1.2.0" + "@vitest/coverage-v8": "catalog:vitest", + "vite": "catalog:vite", + "vitest": "catalog:vitest", + "vitest-canvas-mock": "catalog:vitest" }, "nx": { "tags": ["scope:package"], diff --git a/packages/journey-client/src/lib/client.store.test.ts b/packages/journey-client/src/lib/client.store.test.ts index dfd8b3151d..059f9792f2 100644 --- a/packages/journey-client/src/lib/client.store.test.ts +++ b/packages/journey-client/src/lib/client.store.test.ts @@ -8,9 +8,9 @@ import { callbackType } from '@forgerock/sdk-types'; import { afterEach, describe, expect, test, vi } from 'vitest'; -import type { Step } from '@forgerock/sdk-types'; +import type { Step, WellknownResponse } from '@forgerock/sdk-types'; -import { journey } from './client.store.js'; +import { journey, isJourneyClient } from './client.store.js'; import { createJourneyStep } from './step.utils.js'; import { JourneyClientConfig } from './config.types.js'; @@ -36,45 +36,129 @@ vi.mock('./device/device-profile.js', () => ({ const mockFetch = vi.fn(); global.fetch = mockFetch; +// Wellknown-based config (new pattern) +const mockWellknownUrl = 'https://test.com/am/oauth2/realms/root/.well-known/openid-configuration'; + +const mockWellknownResponse: WellknownResponse = { + issuer: 'https://test.com/am/oauth2/realms/root', + authorization_endpoint: 'https://test.com/am/oauth2/realms/root/authorize', + token_endpoint: 'https://test.com/am/oauth2/realms/root/access_token', + userinfo_endpoint: 'https://test.com/am/oauth2/realms/root/userinfo', + jwks_uri: 'https://test.com/am/oauth2/realms/root/connect/jwk_uri', + end_session_endpoint: 'https://test.com/am/oauth2/realms/root/connect/endSession', + revocation_endpoint: 'https://test.com/am/oauth2/realms/root/token/revoke', + introspection_endpoint: 'https://test.com/am/oauth2/realms/root/introspect', +}; + const mockConfig: JourneyClientConfig = { serverConfig: { - baseUrl: 'https://test.com', + wellknown: mockWellknownUrl, }, - realmPath: 'root', + // realmPath will be inferred from issuer as 'root' }; +/** + * Helper to setup mock fetch for wellknown + journey responses + */ +function setupMockFetch(journeyResponse: Step | null = null) { + mockFetch.mockImplementation((request: Request) => { + const url = request.url; + + // Wellknown endpoint + if (url.includes('.well-known/openid-configuration')) { + return Promise.resolve(new Response(JSON.stringify(mockWellknownResponse))); + } + + // Journey authenticate endpoint + if (journeyResponse && url.includes('/authenticate')) { + return Promise.resolve(new Response(JSON.stringify(journeyResponse))); + } + + return Promise.reject(new Error(`Unexpected fetch: ${url}`)); + }); +} + describe('journey-client', () => { afterEach(() => { vi.clearAllMocks(); }); - test('should initialize and return a client object with all methods', async () => { - const client = await journey({ config: mockConfig }); - expect(client).toBeDefined(); - expect(client.start).toBeInstanceOf(Function); - expect(client.next).toBeInstanceOf(Function); - expect(client.redirect).toBeInstanceOf(Function); - expect(client.resume).toBeInstanceOf(Function); - expect(client.terminate).toBeInstanceOf(Function); + test('journey_WellknownConfig_ReturnsClientWithAllMethods', async () => { + // Arrange + setupMockFetch(); + + // Act + const result = await journey({ config: mockConfig }); + + // Assert + expect(isJourneyClient(result)).toBe(true); + if (!isJourneyClient(result)) return; + expect(result.start).toBeInstanceOf(Function); + expect(result.next).toBeInstanceOf(Function); + expect(result.redirect).toBeInstanceOf(Function); + expect(result.resume).toBeInstanceOf(Function); + expect(result.terminate).toBeInstanceOf(Function); }); - test('start() should fetch and return the first step', async () => { + test('journey_InvalidWellknownUrl_ReturnsError', async () => { + // Arrange + const invalidConfig: JourneyClientConfig = { + serverConfig: { + wellknown: 'not-a-valid-url', + }, + }; + + // Act + const result = await journey({ config: invalidConfig }); + + // Assert + expect(isJourneyClient(result)).toBe(false); + if (isJourneyClient(result)) return; + expect(result.error).toBe('Invalid wellknown URL'); + expect(result.type).toBe('wellknown_error'); + }); + + test('journey_NonAmWellknownUrl_ReturnsAmRequiredError', async () => { + // Arrange - PingOne URL has no /oauth2/ path + const pingOneConfig: JourneyClientConfig = { + serverConfig: { + wellknown: 'https://auth.pingone.com/env-id/.well-known/openid-configuration', + }, + }; + + // Act + const result = await journey({ config: pingOneConfig }); + + // Assert + expect(isJourneyClient(result)).toBe(false); + if (isJourneyClient(result)) return; + expect(result.error).toBe('AM server required'); + expect(result.type).toBe('wellknown_error'); + expect(result.message).toContain('ForgeRock AM servers only'); + }); + + test('start_WellknownConfig_FetchesFirstStep', async () => { + // Arrange const mockStepResponse: Step = { authId: 'test-auth-id', callbacks: [] }; - mockFetch.mockResolvedValue(new Response(JSON.stringify(mockStepResponse))); + setupMockFetch(mockStepResponse); - const client = await journey({ config: mockConfig }); - const step = await client.start(); - expect(step).toBeDefined(); + // Act + const result = await journey({ config: mockConfig }); + if (!isJourneyClient(result)) throw new Error('Expected client'); + const step = await result.start(); - expect(mockFetch).toHaveBeenCalledTimes(1); - const request = mockFetch.mock.calls[0][0] as Request; - // TODO: This should be /journeys?_action=start, but the current implementation calls /authenticate - expect(request.url).toBe('https://test.com/json/realms/root/authenticate'); + // Assert + expect(step).toBeDefined(); + expect(mockFetch).toHaveBeenCalledTimes(2); // wellknown + start + const requests = mockFetch.mock.calls.map((call) => (call[0] as Request).url); + expect(requests[0]).toContain('.well-known/openid-configuration'); + expect(requests[1]).toBe('https://test.com/am/json/realms/root/authenticate'); expect(step).toHaveProperty('type', 'Step'); expect(step && step.payload).toEqual(mockStepResponse); }); - test('next() should send the current step and return the next step', async () => { + test('next_WellknownConfig_SendsStepAndReturnsNext', async () => { + // Arrange const initialStep = createJourneyStep({ authId: 'test-auth-id', callbacks: [ @@ -95,24 +179,26 @@ describe('journey-client', () => { }, ], }; + setupMockFetch(nextStepPayload); - mockFetch.mockResolvedValue(new Response(JSON.stringify(nextStepPayload))); + // Act + const result = await journey({ config: mockConfig }); + if (!isJourneyClient(result)) throw new Error('Expected client'); + const nextStep = await result.next(initialStep, {}); - const client = await journey({ config: mockConfig }); - const nextStep = await client.next(initialStep, {}); + // Assert expect(nextStep).toBeDefined(); - - expect(mockFetch).toHaveBeenCalledTimes(1); - const request = mockFetch.mock.calls[0][0] as Request; - // TODO: This should be /journeys?_action=next, but the current implementation calls /authenticate - expect(request.url).toBe('https://test.com/json/realms/root/authenticate'); + expect(mockFetch).toHaveBeenCalledTimes(2); // wellknown + next + const request = mockFetch.mock.calls[1][0] as Request; + expect(request.url).toBe('https://test.com/am/json/realms/root/authenticate'); expect(request.method).toBe('POST'); expect(await request.json()).toEqual(initialStep.payload); expect(nextStep).toHaveProperty('type', 'Step'); expect(nextStep && nextStep.payload).toEqual(nextStepPayload); }); - test('redirect() should store the step and call location.assign', async () => { + test('redirect_WellknownConfig_StoresStepAndCallsLocationAssign', async () => { + // Arrange const mockStepPayload: Step = { callbacks: [ { @@ -123,16 +209,19 @@ describe('journey-client', () => { ], }; const step = createJourneyStep(mockStepPayload); - const assignMock = vi.fn(); const locationSpy = vi.spyOn(window, 'location', 'get').mockReturnValue({ ...window.location, assign: assignMock, }); + setupMockFetch(); - const client = await journey({ config: mockConfig }); - await client.redirect(step); + // Act + const result = await journey({ config: mockConfig }); + if (!isJourneyClient(result)) throw new Error('Expected client'); + await result.redirect(step); + // Assert expect(mockStorageInstance.set).toHaveBeenCalledWith({ step: step.payload }); expect(assignMock).toHaveBeenCalledWith('https://sso.com/redirect'); @@ -140,39 +229,39 @@ describe('journey-client', () => { }); describe('resume()', () => { - test('should call next() with URL params when a previous step is in storage', async () => { + test('resume_WithPreviousStepInStorage_CallsNextWithUrlParams', async () => { + // Arrange const previousStepPayload: Step = { callbacks: [{ type: callbackType.RedirectCallback, input: [], output: [] }], }; mockStorageInstance.get.mockResolvedValue({ step: previousStepPayload }); - const nextStepPayload: Step = { authId: 'test-auth-id', callbacks: [] }; - mockFetch.mockResolvedValue(new Response(JSON.stringify(nextStepPayload))); + setupMockFetch(nextStepPayload); - const client = await journey({ config: mockConfig }); + // Act + const result = await journey({ config: mockConfig }); + if (!isJourneyClient(result)) throw new Error('Expected client'); const resumeUrl = 'https://app.com/callback?code=123&state=abc'; + const step = await result.resume(resumeUrl, {}); - const step = await client.resume(resumeUrl, {}); + // Assert expect(step).toBeDefined(); - expect(mockStorageInstance.get).toHaveBeenCalledTimes(1); expect(mockStorageInstance.remove).toHaveBeenCalledTimes(1); - expect(mockFetch).toHaveBeenCalledTimes(1); - const request = mockFetch.mock.calls[0][0] as Request; - - // TODO: This should be /journeys?_action=next, but the current implementation calls /authenticate + expect(mockFetch).toHaveBeenCalledTimes(2); // wellknown + next + const request = mockFetch.mock.calls[1][0] as Request; const url = new URL(request.url); - expect(url.origin + url.pathname).toBe('https://test.com/json/realms/root/authenticate'); + expect(url.origin + url.pathname).toBe('https://test.com/am/json/realms/root/authenticate'); expect(url.searchParams.get('code')).toBe('123'); expect(url.searchParams.get('state')).toBe('abc'); - expect(request.method).toBe('POST'); expect(await request.json()).toEqual(previousStepPayload); expect(step).toHaveProperty('type', 'Step'); expect(step && step.payload).toEqual(nextStepPayload); }); - test('should correctly resume with a plain Step object from storage', async () => { + test('resume_WithPlainStepObjectInStorage_CorrectlyResumes', async () => { + // Arrange const plainStepPayload: Step = { callbacks: [ { type: callbackType.TextOutputCallback, output: [{ name: 'message', value: 'Hello' }] }, @@ -180,145 +269,172 @@ describe('journey-client', () => { stage: 'testStage', }; mockStorageInstance.get.mockResolvedValue({ step: plainStepPayload }); - const nextStepPayload: Step = { authId: 'test-auth-id', callbacks: [] }; - mockFetch.mockResolvedValue(new Response(JSON.stringify(nextStepPayload))); + setupMockFetch(nextStepPayload); - const client = await journey({ config: mockConfig }); + // Act + const result = await journey({ config: mockConfig }); + if (!isJourneyClient(result)) throw new Error('Expected client'); const resumeUrl = 'https://app.com/callback?code=123&state=abc'; + const step = await result.resume(resumeUrl, {}); - const step = await client.resume(resumeUrl, {}); + // Assert expect(step).toBeDefined(); - expect(mockStorageInstance.get).toHaveBeenCalledTimes(1); expect(mockStorageInstance.remove).toHaveBeenCalledTimes(1); - expect(mockFetch).toHaveBeenCalledTimes(1); - - const request = mockFetch.mock.calls[0][0] as Request; + expect(mockFetch).toHaveBeenCalledTimes(2); + const request = mockFetch.mock.calls[1][0] as Request; expect(request.method).toBe('POST'); - expect(await request.json()).toEqual(plainStepPayload); // Expect the plain payload to be sent - expect(step).toHaveProperty('type', 'Step'); // The returned step should still be an JourneyStep instance + expect(await request.json()).toEqual(plainStepPayload); + expect(step).toHaveProperty('type', 'Step'); expect(step && step.payload).toEqual(nextStepPayload); }); - test('should throw an error if a previous step is required but not found', async () => { + test('resume_PreviousStepRequiredButNotFound_ThrowsError', async () => { + // Arrange mockStorageInstance.get.mockResolvedValue(undefined); + setupMockFetch(); - const client = await journey({ config: mockConfig }); + // Act + const result = await journey({ config: mockConfig }); + if (!isJourneyClient(result)) throw new Error('Expected client'); const resumeUrl = 'https://app.com/callback?code=123&state=abc'; - await expect(client.resume(resumeUrl)).rejects.toThrow( + // Assert + await expect(result.resume(resumeUrl)).rejects.toThrow( 'Error: previous step information not found in storage for resume operation.', ); expect(mockStorageInstance.get).toHaveBeenCalledTimes(1); expect(mockStorageInstance.remove).toHaveBeenCalledTimes(1); }); - test('should call start() with URL params when no previous step is required', async () => { + test('resume_NoPreviousStepRequired_CallsStartWithUrlParams', async () => { + // Arrange mockStorageInstance.get.mockResolvedValue(undefined); - const mockStepResponse: Step = { authId: 'test-auth-id', callbacks: [] }; - mockFetch.mockResolvedValue(new Response(JSON.stringify(mockStepResponse))); + setupMockFetch(mockStepResponse); - const client = await journey({ config: mockConfig }); + // Act + const result = await journey({ config: mockConfig }); + if (!isJourneyClient(result)) throw new Error('Expected client'); const resumeUrl = 'https://app.com/callback?foo=bar'; + const step = await result.resume(resumeUrl, {}); - const step = await client.resume(resumeUrl, {}); + // Assert expect(step).toBeDefined(); - expect(mockStorageInstance.get).not.toHaveBeenCalled(); - expect(mockFetch).toHaveBeenCalledTimes(1); - const request = mockFetch.mock.calls[0][0] as Request; - - // TODO: This should be /journeys?_action=start, but the current implementation calls /authenticate + expect(mockFetch).toHaveBeenCalledTimes(2); // wellknown + start + const request = mockFetch.mock.calls[1][0] as Request; const url = new URL(request.url); - expect(url.origin + url.pathname).toBe('https://test.com/json/realms/root/authenticate'); + expect(url.origin + url.pathname).toBe('https://test.com/am/json/realms/root/authenticate'); expect(step).toHaveProperty('type', 'Step'); expect(step && step.payload).toEqual(mockStepResponse); }); }); describe('baseUrl normalization', () => { - test('should add trailing slash to baseUrl without one', async () => { + test('normalizeBaseUrl_WithoutTrailingSlash_AddsSlash', async () => { + // Arrange const configWithoutSlash: JourneyClientConfig = { serverConfig: { - baseUrl: 'http://localhost:9443/am', + wellknown: 'http://localhost:9443/am/oauth2/realms/root/.well-known/openid-configuration', }, - realmPath: 'root', }; - const mockStepResponse: Step = { authId: 'test-auth-id', callbacks: [] }; - mockFetch.mockResolvedValue(new Response(JSON.stringify(mockStepResponse))); - - const client = await journey({ config: configWithoutSlash }); - await client.start(); - - expect(mockFetch).toHaveBeenCalledTimes(1); - const request = mockFetch.mock.calls[0][0] as Request; + mockFetch.mockImplementation((request: Request) => { + if (request.url.includes('.well-known')) { + return Promise.resolve( + new Response( + JSON.stringify({ + ...mockWellknownResponse, + issuer: 'http://localhost:9443/am/oauth2/realms/root', + }), + ), + ); + } + return Promise.resolve(new Response(JSON.stringify(mockStepResponse))); + }); + + // Act + const result = await journey({ config: configWithoutSlash }); + if (!isJourneyClient(result)) throw new Error('Expected client'); + await result.start(); + + // Assert + expect(mockFetch).toHaveBeenCalledTimes(2); + const request = mockFetch.mock.calls[1][0] as Request; expect(request.url).toBe('http://localhost:9443/am/json/realms/root/authenticate'); }); + }); - test('should preserve trailing slash if already present', async () => { - const configWithSlash: JourneyClientConfig = { + describe('realm inference', () => { + test('journey_WellknownWithSubrealm_InfersRealmFromIssuer', async () => { + // Arrange + const alphaConfig: JourneyClientConfig = { serverConfig: { - baseUrl: 'http://localhost:9443/am/', + wellknown: + 'https://test.com/am/oauth2/realms/root/realms/alpha/.well-known/openid-configuration', }, - realmPath: 'root', }; - const mockStepResponse: Step = { authId: 'test-auth-id', callbacks: [] }; - mockFetch.mockResolvedValue(new Response(JSON.stringify(mockStepResponse))); - - const client = await journey({ config: configWithSlash }); - await client.start(); - - expect(mockFetch).toHaveBeenCalledTimes(1); - const request = mockFetch.mock.calls[0][0] as Request; - expect(request.url).toBe('http://localhost:9443/am/json/realms/root/authenticate'); + mockFetch.mockImplementation((request: Request) => { + if (request.url.includes('.well-known')) { + return Promise.resolve( + new Response( + JSON.stringify({ + ...mockWellknownResponse, + issuer: 'https://test.com/am/oauth2/realms/root/realms/alpha', + }), + ), + ); + } + return Promise.resolve(new Response(JSON.stringify(mockStepResponse))); + }); + + // Act + const result = await journey({ config: alphaConfig }); + if (!isJourneyClient(result)) throw new Error('Expected client'); + await result.start(); + + // Assert + const request = mockFetch.mock.calls[1][0] as Request; + // Realm 'alpha' is inferred from issuer; getRealmUrlPath prepends 'root' if needed + expect(request.url).toBe('https://test.com/am/json/realms/root/realms/alpha/authenticate'); }); - test('should work with baseUrl without context path', async () => { - const configNoContext: JourneyClientConfig = { + test('journey_ExplicitRealmPath_OverridesInferredRealm', async () => { + // Arrange + const configWithExplicitRealm: JourneyClientConfig = { serverConfig: { - baseUrl: 'http://localhost:9443', + wellknown: + 'https://test.com/am/oauth2/realms/root/realms/alpha/.well-known/openid-configuration', }, - realmPath: 'root', + realmPath: 'beta', // Explicit override }; - const mockStepResponse: Step = { authId: 'test-auth-id', callbacks: [] }; - mockFetch.mockResolvedValue(new Response(JSON.stringify(mockStepResponse))); - - const client = await journey({ config: configNoContext }); - await client.start(); - - expect(mockFetch).toHaveBeenCalledTimes(1); - const request = mockFetch.mock.calls[0][0] as Request; - expect(request.url).toBe('http://localhost:9443/json/realms/root/authenticate'); + mockFetch.mockImplementation((request: Request) => { + if (request.url.includes('.well-known')) { + return Promise.resolve( + new Response( + JSON.stringify({ + ...mockWellknownResponse, + issuer: 'https://test.com/am/oauth2/realms/root/realms/alpha', + }), + ), + ); + } + return Promise.resolve(new Response(JSON.stringify(mockStepResponse))); + }); + + // Act + const result = await journey({ config: configWithExplicitRealm }); + if (!isJourneyClient(result)) throw new Error('Expected client'); + await result.start(); + + // Assert + const request = mockFetch.mock.calls[1][0] as Request; + // Explicit realmPath 'beta' overrides inferred; getRealmUrlPath prepends 'root' + expect(request.url).toBe('https://test.com/am/json/realms/root/realms/beta/authenticate'); }); }); - - // TODO: Add tests for endSession when the test environment AbortSignal issue is resolved - // test('endSession() should call the sessions endpoint with DELETE method', async () => { - // mockFetch.mockResolvedValue(new Response('', { status: 200 })); - // - // const client = await journey({ config: mockConfig }); - // await client.endSession(); - // - // expect(mockFetch).toHaveBeenCalledTimes(1); - // const request = mockFetch.mock.calls[0][0] as Request; - // expect(request.url).toBe('https://test.com/json/realms/root/sessions/'); - // expect(request.method).toBe('DELETE'); - // }); - // - // test('endSession() should handle query parameters', async () => { - // mockFetch.mockResolvedValue(new Response('', { status: 200 })); - // - // const client = await journey({ config: mockConfig }); - // await client.endSession({ query: { foo: 'bar' } }); - // - // expect(mockFetch).toHaveBeenCalledTimes(1); - // const request = mockFetch.mock.calls[0][0] as Request; - // expect(request.url).toBe('https://test.com/json/realms/root/sessions/?foo=bar'); - // expect(request.method).toBe('DELETE'); - // }); }); diff --git a/packages/journey-client/src/lib/client.store.ts b/packages/journey-client/src/lib/client.store.ts index 9288cd0dc2..d620f00758 100644 --- a/packages/journey-client/src/lib/client.store.ts +++ b/packages/journey-client/src/lib/client.store.ts @@ -7,41 +7,93 @@ import { logger as loggerFn, LogLevel, CustomLogger } from '@forgerock/sdk-logger'; import { callbackType } from '@forgerock/sdk-types'; +import { isGenericError } from '@forgerock/sdk-utilities'; + +import type { GenericError } from '@forgerock/sdk-types'; import type { RequestMiddleware } from '@forgerock/sdk-request-middleware'; -import type { GenericError, Step } from '@forgerock/sdk-types'; +import type { Step } from '@forgerock/sdk-types'; import { createJourneyStore } from './client.store.utils.js'; import { journeyApi } from './journey.api.js'; import { setConfig } from './journey.slice.js'; import { createStorage } from '@forgerock/storage'; import { createJourneyObject } from './journey.utils.js'; +import { wellknownApi, createWellknownError } from '@forgerock/sdk-oidc'; +import { isValidWellknownUrl } from '@forgerock/sdk-utilities'; +import { inferRealmFromIssuer, inferBaseUrlFromWellknown } from './wellknown.utils.js'; import type { JourneyStep } from './step.utils.js'; -import type { JourneyClientConfig } from './config.types.js'; +import type { JourneyClientConfig, InternalJourneyClientConfig } from './config.types.js'; import type { RedirectCallback } from './callbacks/redirect-callback.js'; import { NextOptions, StartParam, ResumeOptions } from './interfaces.js'; +import type { JourneyLoginFailure } from './login-failure.utils.js'; +import type { JourneyLoginSuccess } from './login-success.utils.js'; + +/** Result type for journey client methods. */ +type JourneyResult = JourneyStep | JourneyLoginSuccess | JourneyLoginFailure | undefined; + +/** The journey client instance returned by the `journey()` function. */ +export interface JourneyClient { + start: (options?: StartParam) => Promise; + next: (step: JourneyStep, options?: NextOptions) => Promise; + redirect: (step: JourneyStep) => Promise; + resume: (url: string, options?: ResumeOptions) => Promise; + terminate: (options?: { query?: Record }) => Promise; +} + +/** + * Type guard to check if a value is a JourneyClient (not a GenericError). + */ +export function isJourneyClient(value: JourneyClient | GenericError): value is JourneyClient { + return !isGenericError(value); +} /** * Normalizes the serverConfig to ensure baseUrl has a trailing slash. * This is required for the resolve() function to work correctly with context paths like /am. */ -function normalizeConfig(config: JourneyClientConfig): JourneyClientConfig { - if (config.serverConfig?.baseUrl) { - const url = config.serverConfig.baseUrl; - if (url.charAt(url.length - 1) !== '/') { - return { - ...config, - serverConfig: { - ...config.serverConfig, - baseUrl: url + '/', - }, - }; - } +function normalizeBaseUrl(baseUrl: string): string { + if (baseUrl.charAt(baseUrl.length - 1) !== '/') { + return baseUrl + '/'; } - return config; + return baseUrl; } +/** + * Creates a journey client for AM authentication tree/journey interactions. + * + * Journey-client is designed specifically for ForgeRock Access Management (AM) servers. + * It uses AM-proprietary endpoints for callback-based authentication trees. + * + * @example + * ```typescript + * // Basic usage - baseUrl and realmPath are inferred from wellknown + * const client = await journey({ + * config: { + * serverConfig: { + * wellknown: 'https://am.example.com/am/oauth2/alpha/.well-known/openid-configuration', + * }, + * }, + * }); + * + * // With explicit realmPath (when inference isn't desired) + * const client = await journey({ + * config: { + * serverConfig: { + * wellknown: 'https://am.example.com/am/oauth2/alpha/.well-known/openid-configuration', + * }, + * realmPath: 'alpha', + * }, + * }); + * ``` + * + * @param options - Configuration options for the journey client + * @param options.config - Server configuration with required wellknown URL + * @param options.requestMiddleware - Optional middleware for request customization + * @param options.logger - Optional logger configuration + * @returns A journey client instance, or a GenericError if configuration fails + */ export async function journey({ config, requestMiddleware, @@ -53,14 +105,72 @@ export async function journey({ level: LogLevel; custom?: CustomLogger; }; -}) { +}): Promise { const log = loggerFn({ level: logger?.level || 'error', custom: logger?.custom }); - // Normalize config to ensure baseUrl has trailing slash - const normalizedConfig = normalizeConfig(config); + // Create the store first (config will be set after wellknown fetch) + const store = createJourneyStore({ requestMiddleware, logger: log }); + + const { wellknown, paths, timeout } = config.serverConfig; + + // Step 1: Validate wellknown URL + if (!isValidWellknownUrl(wellknown)) { + const message = `Invalid wellknown URL: ${wellknown}. URL must use HTTPS (or HTTP for localhost).`; + const error: GenericError = { + error: 'Invalid wellknown URL', + message, + type: 'wellknown_error', + }; + log.error(message); + return error; + } + + // Step 2: Infer baseUrl from wellknown URL + // This only works for ForgeRock AM URLs (looks for /oauth2/ in path) + const resolvedBaseUrl = inferBaseUrlFromWellknown(wellknown); + if (!resolvedBaseUrl) { + const message = + 'Journey-client is designed for ForgeRock AM servers only. ' + + `Unable to infer baseUrl from wellknown URL: ${wellknown}. ` + + 'The wellknown URL must contain "/oauth2/" in the path (standard AM format). ' + + 'For PingOne or other OIDC providers, use davinci-client or oidc-client instead.'; + const error: GenericError = { + error: 'AM server required', + message, + type: 'wellknown_error', + }; + log.error(message); + return error; + } + + // Step 3: Fetch the well-known configuration + const { data: wellknownResponse, error: fetchError } = await store.dispatch( + wellknownApi.endpoints.configuration.initiate(wellknown), + ); - const store = createJourneyStore({ requestMiddleware, logger: log, config: normalizedConfig }); - store.dispatch(setConfig(normalizedConfig)); + if (fetchError || !wellknownResponse) { + const error = createWellknownError(fetchError); + log.error(`${error.error}: ${error.message}`); + return error; + } + + // Step 4: Infer realmPath from the issuer URL if not provided + const resolvedRealm = config.realmPath ?? inferRealmFromIssuer(wellknownResponse.issuer); + + // Step 5: Build the resolved internal configuration + const resolvedConfig: InternalJourneyClientConfig = { + serverConfig: { + baseUrl: normalizeBaseUrl(resolvedBaseUrl), + paths, + timeout, + }, + realmPath: resolvedRealm, + middleware: config.middleware, + wellknownResponse, + }; + + // Dispatch the resolved config to the store + store.dispatch(setConfig(resolvedConfig)); const stepStorage = createStorage<{ step: Step }>({ type: 'sessionStorage', @@ -99,7 +209,7 @@ export async function journey({ } const err = await stepStorage.set({ step: step.payload }); - if (err && (err as GenericError).error) { + if (isGenericError(err)) { log.warn('Failed to persist step before redirect', err); } window.location.assign(redirectUrl); @@ -121,11 +231,6 @@ export async function journey({ return (code && state) || form_post_entry || responsekey; } - // Type guard for GenericError (assuming GenericError has 'error' and 'message' properties) - function isGenericError(obj: unknown): obj is GenericError { - return typeof obj === 'object' && obj !== null && 'error' in obj && 'message' in obj; - } - // Type guard for { step: JourneyStep } function isStoredStep(obj: unknown): obj is { step: Step } { return ( diff --git a/packages/journey-client/src/lib/client.store.utils.ts b/packages/journey-client/src/lib/client.store.utils.ts index 27e6200cb0..34e6ad848c 100644 --- a/packages/journey-client/src/lib/client.store.utils.ts +++ b/packages/journey-client/src/lib/client.store.utils.ts @@ -11,21 +11,20 @@ import { combineReducers, configureStore } from '@reduxjs/toolkit'; import { journeyApi } from './journey.api.js'; import { journeySlice } from './journey.slice.js'; -import { JourneyClientConfig } from './config.types.js'; +import { wellknownApi } from '@forgerock/sdk-oidc'; const rootReducer = combineReducers({ [journeyApi.reducerPath]: journeyApi.reducer, [journeySlice.name]: journeySlice.reducer, + [wellknownApi.reducerPath]: wellknownApi.reducer, }); export const createJourneyStore = ({ requestMiddleware, logger, - config, }: { requestMiddleware?: RequestMiddleware[]; logger?: ReturnType; - config: JourneyClientConfig; }) => { return configureStore({ reducer: rootReducer, @@ -36,10 +35,11 @@ export const createJourneyStore = ({ extraArgument: { requestMiddleware, logger, - config, }, }, - }).concat(journeyApi.middleware), + }) + .concat(journeyApi.middleware) + .concat(wellknownApi.middleware), }); }; diff --git a/packages/journey-client/src/lib/config.types.ts b/packages/journey-client/src/lib/config.types.ts index f172c2aa98..ea38e30d3e 100644 --- a/packages/journey-client/src/lib/config.types.ts +++ b/packages/journey-client/src/lib/config.types.ts @@ -5,13 +5,67 @@ * of the MIT license. See the LICENSE file for details. */ -import type { BaseConfig } from '@forgerock/sdk-types'; +import type { WellknownResponse, PathsConfig } from '@forgerock/sdk-types'; import type { RequestMiddleware } from '@forgerock/sdk-request-middleware'; -export interface JourneyClientConfig extends BaseConfig { +/** + * Server configuration for journey-client. + * + * @remarks + * The `wellknown` URL is required for OIDC discovery. The `baseUrl` is + * automatically inferred from the wellknown URL for ForgeRock AM servers. + */ +export interface JourneyServerConfig { + /** Required OIDC discovery endpoint URL */ + wellknown: string; + /** Optional custom path overrides */ + paths?: PathsConfig['paths']; + /** Optional request timeout in milliseconds */ + timeout?: number; +} + +/** + * Configuration for creating a journey client instance. + * + * @example + * ```typescript + * const config: JourneyClientConfig = { + * serverConfig: { + * wellknown: 'https://am.example.com/am/oauth2/alpha/.well-known/openid-configuration', + * }, + * // realmPath is optional - can be inferred from the well-known issuer + * }; + * ``` + */ +export interface JourneyClientConfig { + serverConfig: JourneyServerConfig; + /** Optional middleware for request customization */ + middleware?: Array; + /** Optional realm path - inferred from wellknown issuer if not provided */ + realmPath?: string; +} + +/** + * Internal configuration after wellknown discovery and resolution. + * Used internally by the journey client - not part of public API. + * + * @internal + */ +export interface InternalJourneyClientConfig { + serverConfig: { + /** Resolved base URL (required after inference) */ + baseUrl: string; + /** Optional custom path overrides */ + paths?: PathsConfig['paths']; + /** Optional request timeout in milliseconds */ + timeout?: number; + }; + /** Optional middleware for request customization */ middleware?: Array; + /** Resolved realm path */ realmPath?: string; - // Add any journey-specific config options here + /** Cached wellknown response */ + wellknownResponse: WellknownResponse; } export type { RequestMiddleware }; diff --git a/packages/journey-client/src/lib/device/device-profile.test.ts b/packages/journey-client/src/lib/device/device-profile.test.ts index bf9296e14d..aa2d73a91d 100644 --- a/packages/journey-client/src/lib/device/device-profile.test.ts +++ b/packages/journey-client/src/lib/device/device-profile.test.ts @@ -7,7 +7,7 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { vi, expect, describe, it, afterEach, beforeEach, SpyInstance } from 'vitest'; +import { vi, expect, describe, it, afterEach, beforeEach, Mock } from 'vitest'; import { Device } from './device-profile.js'; @@ -86,7 +86,10 @@ describe('Test DeviceProfile', () => { }); describe('logLevel tests', () => { - let warnSpy: SpyInstance; + let warnSpy: Mock<{ + (...data: unknown[]): void; + (message?: string, ...optionalParams: unknown[]): void; + }>; const originalNavigator = global.navigator; beforeEach(() => { diff --git a/packages/journey-client/src/lib/interfaces.ts b/packages/journey-client/src/lib/interfaces.ts index 28455f86f6..0dc93ca842 100644 --- a/packages/journey-client/src/lib/interfaces.ts +++ b/packages/journey-client/src/lib/interfaces.ts @@ -5,20 +5,19 @@ * of the MIT license. See the LICENSE file for details. */ -import { JourneyClientConfig } from './config.types.js'; import { JourneyStep } from './step.types.js'; -export interface StartParam extends JourneyClientConfig { +export interface StartParam { journey: string; query?: Record; } -export interface ResumeOptions extends JourneyClientConfig { +export interface ResumeOptions { journey?: string; query?: Record; } -export interface NextOptions extends JourneyClientConfig { +export interface NextOptions { query?: Record; } diff --git a/packages/journey-client/src/lib/journey.api.ts b/packages/journey-client/src/lib/journey.api.ts index aafa0b17ff..a7b90d037d 100644 --- a/packages/journey-client/src/lib/journey.api.ts +++ b/packages/journey-client/src/lib/journey.api.ts @@ -22,9 +22,17 @@ import type { import { JourneyStep } from './step.types.js'; -import type { JourneyClientConfig } from './config.types.js'; +import type { JourneyState } from './journey.slice.js'; import { NextOptions, StartParam } from './interfaces.js'; +/** + * Minimal state type for accessing journey config from RTK Query endpoints. + * This avoids circular dependency with client.store.utils.ts. + */ +interface JourneyRootState { + journey: JourneyState; +} + // Move these functions to the top, before journeyApi definition function constructUrl( serverConfig: ServerConfig, @@ -84,7 +92,6 @@ function configureSessionRequest(): RequestInit { interface Extras { requestMiddleware: RequestMiddleware[]; logger: ReturnType; - config: JourneyClientConfig; } export const journeyApi = createApi({ @@ -108,8 +115,9 @@ export const journeyApi = createApi({ _: unknown, baseQuery: BaseQueryFn, ) => { - const { config } = api.extra as Extras; - if (!config.serverConfig) { + const state = api.getState() as JourneyRootState; + const config = state.journey.config; + if (!config?.serverConfig) { throw new Error('Server configuration is missing.'); } const { realmPath, serverConfig } = config; @@ -141,8 +149,9 @@ export const journeyApi = createApi({ _: unknown, baseQuery: BaseQueryFn, ) => { - const { config } = api.extra as Extras; - if (!config.serverConfig) { + const state = api.getState() as JourneyRootState; + const config = state.journey.config; + if (!config?.serverConfig) { throw new Error('Server configuration is missing.'); } const { realmPath, serverConfig } = config; @@ -171,8 +180,9 @@ export const journeyApi = createApi({ _: unknown, baseQuery: BaseQueryFn, ) => { - const { config } = api.extra as Extras; - if (!config.serverConfig) { + const state = api.getState() as JourneyRootState; + const config = state.journey.config; + if (!config?.serverConfig) { throw new Error('Server configuration is missing.'); } const { realmPath, serverConfig } = config; diff --git a/packages/journey-client/src/lib/journey.slice.ts b/packages/journey-client/src/lib/journey.slice.ts index aea31ea438..8cf2c5bbc7 100644 --- a/packages/journey-client/src/lib/journey.slice.ts +++ b/packages/journey-client/src/lib/journey.slice.ts @@ -9,13 +9,22 @@ import { createSlice, PayloadAction, Slice } from '@reduxjs/toolkit'; import type { Step } from '@forgerock/sdk-types'; -import type { JourneyClientConfig } from './config.types.js'; +import type { InternalJourneyClientConfig } from './config.types.js'; +/** + * Redux state for the journey client. + * + * Contains the current authentication state including: + * - authId: The authentication session identifier + * - step: The current authentication step + * - error: Any error that occurred during authentication + * - config: The resolved client configuration (including well-known response if used) + */ export interface JourneyState { authId?: string; step?: Step; error?: Error; - config?: JourneyClientConfig; + config?: InternalJourneyClientConfig; } const initialState: JourneyState = {}; @@ -24,7 +33,7 @@ export const journeySlice: Slice = createSlice({ name: 'journey', initialState, reducers: { - setConfig: (state, action: PayloadAction) => { + setConfig: (state, action: PayloadAction) => { state.config = action.payload; }, }, diff --git a/packages/journey-client/src/lib/wellknown.utils.test.ts b/packages/journey-client/src/lib/wellknown.utils.test.ts new file mode 100644 index 0000000000..2bc66d65ac --- /dev/null +++ b/packages/journey-client/src/lib/wellknown.utils.test.ts @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2025 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +import { describe, it, expect } from 'vitest'; +import { inferRealmFromIssuer, inferBaseUrlFromWellknown } from './wellknown.utils.js'; + +describe('wellknown.utils', () => { + describe('inferRealmFromIssuer', () => { + describe('inferRealmFromIssuer_SimplifiedFormat_ReturnsRealm', () => { + it('should extract realm from simplified AM issuer URL', () => { + const issuer = 'https://openam-sdks.forgeblocks.com:443/am/oauth2/alpha'; + + expect(inferRealmFromIssuer(issuer)).toBe('alpha'); + }); + }); + + describe('inferRealmFromIssuer_SimplifiedFormatNoPort_ReturnsRealm', () => { + it('should extract realm from simplified AM issuer URL without port', () => { + const issuer = 'https://am.example.com/am/oauth2/alpha'; + + expect(inferRealmFromIssuer(issuer)).toBe('alpha'); + }); + }); + + describe('inferRealmFromIssuer_LegacySubrealmFormat_ReturnsRealm', () => { + it('should extract subrealm from legacy AM issuer URL', () => { + const issuer = 'https://am.example.com/am/oauth2/realms/root/realms/alpha'; + + expect(inferRealmFromIssuer(issuer)).toBe('alpha'); + }); + }); + + describe('inferRealmFromIssuer_LegacyNestedSubrealm_ReturnsFullPath', () => { + it('should extract nested subrealm path from legacy format', () => { + const issuer = + 'https://am.example.com/am/oauth2/realms/root/realms/customers/realms/premium'; + + expect(inferRealmFromIssuer(issuer)).toBe('customers/realms/premium'); + }); + }); + + describe('inferRealmFromIssuer_LegacyRootRealm_ReturnsRoot', () => { + it('should return "root" for legacy root realm issuer', () => { + const issuer = 'https://am.example.com/am/oauth2/realms/root'; + + expect(inferRealmFromIssuer(issuer)).toBe('root'); + }); + }); + + describe('inferRealmFromIssuer_NonAmIssuer_ReturnsUndefined', () => { + it('should return undefined for non-AM issuer (PingOne)', () => { + const issuer = 'https://auth.pingone.com/env-id/as'; + + expect(inferRealmFromIssuer(issuer)).toBeUndefined(); + }); + }); + + describe('inferRealmFromIssuer_GenericOidcIssuer_ReturnsUndefined', () => { + it('should return undefined for generic OIDC issuer', () => { + const issuer = 'https://accounts.google.com'; + + expect(inferRealmFromIssuer(issuer)).toBeUndefined(); + }); + }); + + describe('inferRealmFromIssuer_InvalidUrl_ReturnsUndefined', () => { + it('should return undefined for invalid URL', () => { + expect(inferRealmFromIssuer('not-a-valid-url')).toBeUndefined(); + }); + }); + + describe('inferRealmFromIssuer_IssuerWithPort_ReturnsRealm', () => { + it('should correctly parse issuer with port number (legacy format)', () => { + const issuer = 'https://am.example.com:8443/am/oauth2/realms/root/realms/test'; + + expect(inferRealmFromIssuer(issuer)).toBe('test'); + }); + }); + }); + + describe('inferBaseUrlFromWellknown', () => { + describe('inferBaseUrlFromWellknown_SimplifiedFormat_ReturnsBaseUrl', () => { + it('should extract baseUrl from simplified wellknown URL', () => { + const wellknown = 'https://am.example.com/am/oauth2/alpha/.well-known/openid-configuration'; + + expect(inferBaseUrlFromWellknown(wellknown)).toBe('https://am.example.com/am/'); + }); + }); + + describe('inferBaseUrlFromWellknown_LegacyFormat_ReturnsBaseUrl', () => { + it('should extract baseUrl from legacy wellknown URL', () => { + const wellknown = + 'https://am.example.com/am/oauth2/realms/root/realms/alpha/.well-known/openid-configuration'; + + expect(inferBaseUrlFromWellknown(wellknown)).toBe('https://am.example.com/am/'); + }); + }); + + describe('inferBaseUrlFromWellknown_WithNonDefaultPort_ReturnsBaseUrl', () => { + it('should preserve non-default port in extracted baseUrl', () => { + const wellknown = + 'https://am.example.com:8443/am/oauth2/alpha/.well-known/openid-configuration'; + + expect(inferBaseUrlFromWellknown(wellknown)).toBe('https://am.example.com:8443/am/'); + }); + }); + + describe('inferBaseUrlFromWellknown_WithDefaultPort_NormalizesUrl', () => { + it('should normalize default HTTPS port (443) out of URL', () => { + const wellknown = + 'https://openam-sdks.forgeblocks.com:443/am/oauth2/alpha/.well-known/openid-configuration'; + + expect(inferBaseUrlFromWellknown(wellknown)).toBe( + 'https://openam-sdks.forgeblocks.com/am/', + ); + }); + }); + + describe('inferBaseUrlFromWellknown_NoContextPath_ReturnsBaseUrl', () => { + it('should work when there is no context path before oauth2', () => { + const wellknown = 'https://am.example.com/oauth2/alpha/.well-known/openid-configuration'; + + expect(inferBaseUrlFromWellknown(wellknown)).toBe('https://am.example.com/'); + }); + }); + + describe('inferBaseUrlFromWellknown_NoOauth2Path_ReturnsUndefined', () => { + it('should return undefined when oauth2 is not in path', () => { + const wellknown = 'https://auth.pingone.com/env-id/.well-known/openid-configuration'; + + expect(inferBaseUrlFromWellknown(wellknown)).toBeUndefined(); + }); + }); + + describe('inferBaseUrlFromWellknown_InvalidUrl_ReturnsUndefined', () => { + it('should return undefined for invalid URL', () => { + expect(inferBaseUrlFromWellknown('not-a-valid-url')).toBeUndefined(); + }); + }); + + describe('inferBaseUrlFromWellknown_EmptyString_ReturnsUndefined', () => { + it('should return undefined for empty string', () => { + expect(inferBaseUrlFromWellknown('')).toBeUndefined(); + }); + }); + }); +}); diff --git a/packages/journey-client/src/lib/wellknown.utils.ts b/packages/journey-client/src/lib/wellknown.utils.ts new file mode 100644 index 0000000000..5bb69af000 --- /dev/null +++ b/packages/journey-client/src/lib/wellknown.utils.ts @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +/** + * ForgeRock AM URL patterns for realm extraction. + * + * AM has evolved through several URL formats: + * - Legacy subrealm: /oauth2/realms/root/realms/{realm} + * - Legacy root: /oauth2/realms/root + * - Simplified (current): /oauth2/{realm} + */ +const REALM_PATTERNS = [ + /\/oauth2\/realms\/root\/realms\/(.+)$/, + /\/oauth2\/realms\/(root)$/, + /\/oauth2\/([^/]+)$/, +] as const; + +/** + * Infers the realm path from a ForgeRock AM issuer URL. + * Returns undefined for non-AM issuers. + */ +export function inferRealmFromIssuer(issuer: string): string | undefined { + try { + const pathname = new URL(issuer).pathname; + for (const pattern of REALM_PATTERNS) { + const match = pathname.match(pattern); + if (match) return match[1]; + } + return undefined; + } catch { + return undefined; + } +} + +/** + * Infers the base URL from a wellknown endpoint URL. + * Extracts everything before `/oauth2/` in the path. + * + * Example: `https://am.example.com/am/oauth2/alpha/.well-known/openid-configuration` + * Returns: `https://am.example.com/am/` + */ +export function inferBaseUrlFromWellknown(wellknownUrl: string): string | undefined { + try { + const url = new URL(wellknownUrl); + const oauth2Index = url.pathname.indexOf('/oauth2/'); + if (oauth2Index === -1) return undefined; + url.pathname = url.pathname.slice(0, oauth2Index + 1); + url.search = ''; + url.hash = ''; + return url.toString(); + } catch { + return undefined; + } +} diff --git a/packages/journey-client/src/types.ts b/packages/journey-client/src/types.ts index 5ec9b606c9..58b9c09da3 100644 --- a/packages/journey-client/src/types.ts +++ b/packages/journey-client/src/types.ts @@ -23,6 +23,11 @@ export * from './lib/config.types.js'; export * from './lib/interfaces.js'; export * from './lib/step.types.js'; +// Re-export well-known utilities for consumers who need URL inference +export { inferRealmFromIssuer, inferBaseUrlFromWellknown } from './lib/wellknown.utils.js'; +export { isValidWellknownUrl } from '@forgerock/sdk-utilities'; +export { createWellknownError } from '@forgerock/sdk-oidc'; + export * from './lib/callbacks/attribute-input-callback.js'; export * from './lib/callbacks/base-callback.js'; export * from './lib/callbacks/choice-callback.js'; diff --git a/packages/journey-client/tsconfig.json b/packages/journey-client/tsconfig.json index 341e0b5e7f..62ebbd9464 100644 --- a/packages/journey-client/tsconfig.json +++ b/packages/journey-client/tsconfig.json @@ -3,21 +3,6 @@ "files": [], "include": [], "references": [ - { - "path": "../sdk-effects/storage" - }, - { - "path": "../sdk-utilities" - }, - { - "path": "../sdk-types" - }, - { - "path": "../sdk-effects/sdk-request-middleware" - }, - { - "path": "../sdk-effects/logger" - }, { "path": "./tsconfig.lib.json" }, diff --git a/packages/journey-client/tsconfig.lib.json b/packages/journey-client/tsconfig.lib.json index 280db2ff6c..ca3f899b8d 100644 --- a/packages/journey-client/tsconfig.lib.json +++ b/packages/journey-client/tsconfig.lib.json @@ -21,15 +21,18 @@ { "path": "../sdk-effects/storage/tsconfig.lib.json" }, - { - "path": "../sdk-effects/sdk-request-middleware/tsconfig.lib.json" - }, { "path": "../sdk-utilities/tsconfig.lib.json" }, { "path": "../sdk-types/tsconfig.lib.json" }, + { + "path": "../sdk-effects/sdk-request-middleware/tsconfig.lib.json" + }, + { + "path": "../sdk-effects/oidc/tsconfig.lib.json" + }, { "path": "../sdk-effects/logger/tsconfig.lib.json" } diff --git a/packages/oidc-client/src/lib/authorize.request.ts b/packages/oidc-client/src/lib/authorize.request.ts index 0efc570341..96af6a9fc0 100644 --- a/packages/oidc-client/src/lib/authorize.request.ts +++ b/packages/oidc-client/src/lib/authorize.request.ts @@ -15,7 +15,7 @@ import { import { oidcApi } from './oidc.api.js'; import type { ClientStore } from './client.types.js'; -import type { GetAuthorizationUrlOptions, WellKnownResponse } from '@forgerock/sdk-types'; +import type { GetAuthorizationUrlOptions, WellknownResponse } from '@forgerock/sdk-types'; import type { AuthorizationError, AuthorizationSuccess } from './authorize.request.types.js'; import type { OidcConfig } from './config.types.js'; @@ -30,7 +30,7 @@ import type { OidcConfig } from './config.types.js'; * @returns {Micro.Micro} - A micro effect that resolves to the authorization response. */ export function authorizeµ( - wellknown: WellKnownResponse, + wellknown: WellknownResponse, config: OidcConfig, log: CustomLogger, store: ClientStore, diff --git a/packages/oidc-client/src/lib/authorize.request.utils.test.ts b/packages/oidc-client/src/lib/authorize.request.utils.test.ts index dcb7ecc1ff..0a00278a7b 100644 --- a/packages/oidc-client/src/lib/authorize.request.utils.test.ts +++ b/packages/oidc-client/src/lib/authorize.request.utils.test.ts @@ -8,7 +8,7 @@ import { it, expect } from '@effect/vitest'; import { Micro } from 'effect'; import { buildAuthorizeOptionsµ } from './authorize.request.utils.js'; import { OidcConfig } from './config.types.js'; -import { WellKnownResponse } from '@forgerock/sdk-types'; +import { WellknownResponse } from '@forgerock/sdk-types'; const clientId = '123456789'; const redirectUri = 'https://example.com/callback.html'; @@ -23,7 +23,7 @@ const config: OidcConfig = { }, responseType, }; -const wellknown: WellKnownResponse = { +const wellknown: WellknownResponse = { issuer: 'https://example.com/issuer', authorization_endpoint: 'https://example.com/authorize', token_endpoint: 'https://example.com/token', diff --git a/packages/oidc-client/src/lib/authorize.request.utils.ts b/packages/oidc-client/src/lib/authorize.request.utils.ts index ebb971f28f..96557e22ed 100644 --- a/packages/oidc-client/src/lib/authorize.request.utils.ts +++ b/packages/oidc-client/src/lib/authorize.request.utils.ts @@ -7,7 +7,7 @@ import { createAuthorizeUrl } from '@forgerock/sdk-oidc'; import { Micro } from 'effect'; -import type { WellKnownResponse, GetAuthorizationUrlOptions } from '@forgerock/sdk-types'; +import type { WellknownResponse, GetAuthorizationUrlOptions } from '@forgerock/sdk-types'; import type { AuthorizationError, AuthorizationSuccess, @@ -19,12 +19,12 @@ import type { OidcConfig } from './config.types.js'; /** * @function buildAuthorizeOptionsµ * @description Builds the authorization options for the OIDC client. - * @param {WellKnownResponse} wellknown - The well-known configuration for the OIDC server. + * @param {WellknownResponse} wellknown - The well-known configuration for the OIDC server. * @param {OptionalAuthorizeOptions} options - Optional parameters for the authorization request. * @returns {Micro.Micro} */ export function buildAuthorizeOptionsµ( - wellknown: WellKnownResponse, + wellknown: WellknownResponse, config: OidcConfig, options?: OptionalAuthorizeOptions, ): Micro.Micro { @@ -48,14 +48,14 @@ export function buildAuthorizeOptionsµ( * @function createAuthorizeErrorµ * @description Creates an error response with new Authorize URL for the authorization request. * @param { error: string; error_description: string } res - The error response from the authorization request. - * @param {WellKnownResponse} wellknown- The well-known configuration for the OIDC server. + * @param {WellknownResponse} wellknown- The well-known configuration for the OIDC server. * @param { OidcConfig } config- The OIDC client configuration. * @param { GetAuthorizationUrlOptions } options- Optional parameters for the authorization request. * @returns { Micro.Micro } */ export function createAuthorizeErrorµ( res: { error: string; error_description: string }, - wellknown: WellKnownResponse, + wellknown: WellknownResponse, options: GetAuthorizationUrlOptions, ): Micro.Micro { return Micro.tryPromise({ @@ -121,7 +121,7 @@ export function createAuthorizeUrlµ( export function handleResponseµ( response: AuthorizationSuccess | AuthorizationError, - wellknown: WellKnownResponse, + wellknown: WellknownResponse, options: GetAuthorizationUrlOptions, ): Micro.Micro { if ('code' in response) { diff --git a/packages/oidc-client/src/lib/config.types.ts b/packages/oidc-client/src/lib/config.types.ts index 47a186fb25..c0d03efd69 100644 --- a/packages/oidc-client/src/lib/config.types.ts +++ b/packages/oidc-client/src/lib/config.types.ts @@ -6,7 +6,7 @@ */ import type { AsyncLegacyConfigOptions, - WellKnownResponse, + WellknownResponse, ResponseType, } from '@forgerock/sdk-types'; @@ -23,7 +23,7 @@ export interface OidcConfig extends AsyncLegacyConfigOptions { } export interface InternalDaVinciConfig extends OidcConfig { - wellknownResponse: WellKnownResponse; + WellknownResponse: WellknownResponse; } export interface OauthTokens { diff --git a/packages/oidc-client/src/lib/logout.request.ts b/packages/oidc-client/src/lib/logout.request.ts index 40a6defa3e..92ee6869d6 100644 --- a/packages/oidc-client/src/lib/logout.request.ts +++ b/packages/oidc-client/src/lib/logout.request.ts @@ -9,7 +9,7 @@ import { oidcApi } from './oidc.api.js'; import { createLogoutError } from './client.store.utils.js'; import type { OauthTokens, OidcConfig } from './config.types.js'; -import type { WellKnownResponse } from '@forgerock/sdk-types'; +import type { WellknownResponse } from '@forgerock/sdk-types'; import type { StorageClient } from '@forgerock/storage'; import type { ClientStore, LogoutErrorResult, LogoutSuccessResult } from './client.types.js'; @@ -22,7 +22,7 @@ export function logoutµ({ }: { tokens: OauthTokens; config: OidcConfig; - wellknown: WellKnownResponse; + wellknown: WellknownResponse; store: ClientStore; storageClient: StorageClient; }) { diff --git a/packages/oidc-client/src/lib/wellknown.api.ts b/packages/oidc-client/src/lib/wellknown.api.ts index 3315ef345c..6227e2e5c0 100644 --- a/packages/oidc-client/src/lib/wellknown.api.ts +++ b/packages/oidc-client/src/lib/wellknown.api.ts @@ -4,22 +4,32 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ + import { createSelector } from '@reduxjs/toolkit'; -import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'; -import type { WellKnownResponse } from '@forgerock/sdk-types'; import type { RootState } from './client.types.js'; -export const wellknownApi = createApi({ - reducerPath: 'wellknown', - baseQuery: fetchBaseQuery(), - endpoints: (builder) => ({ - configuration: builder.query({ - query: (endpoint) => `${endpoint}`, - }), - }), -}); +/** + * Re-export the shared wellknown RTK Query API from @forgerock/sdk-oidc. + * + * The wellknown API provides OIDC endpoint discovery functionality via + * the `.well-known/openid-configuration` endpoint. + */ +export { wellknownApi, createWellknownSelector } from '@forgerock/sdk-oidc'; + +// Import locally for use in selector below +import { wellknownApi } from '@forgerock/sdk-oidc'; +/** + * Selector to retrieve the cached well-known response from Redux state. + * + * This is a convenience function that wraps the shared createWellknownSelector + * for easier use with oidc-client's RootState type. + * + * @param wellknownUrl - The well-known endpoint URL used as the cache key + * @param state - The Redux root state + * @returns The cached WellknownResponse or undefined if not yet fetched + */ export function wellknownSelector(wellknownUrl: string, state: RootState) { const selector = createSelector( wellknownApi.endpoints.configuration.select(wellknownUrl), diff --git a/packages/oidc-client/src/types.ts b/packages/oidc-client/src/types.ts index 92bab72dfb..10c8b28405 100644 --- a/packages/oidc-client/src/types.ts +++ b/packages/oidc-client/src/types.ts @@ -11,7 +11,7 @@ export * from './lib/exchange.types.js'; export type { GenericError, GetAuthorizationUrlOptions, - WellKnownResponse, + WellknownResponse, } from '@forgerock/sdk-types'; export type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; export type { CustomLogger, LogLevel } from '@forgerock/sdk-logger'; diff --git a/packages/oidc-client/tsconfig.json b/packages/oidc-client/tsconfig.json index 9aae8f1878..9d592a77cf 100644 --- a/packages/oidc-client/tsconfig.json +++ b/packages/oidc-client/tsconfig.json @@ -3,24 +3,6 @@ "files": [], "include": [], "references": [ - { - "path": "../sdk-effects/storage" - }, - { - "path": "../sdk-types" - }, - { - "path": "../sdk-effects/sdk-request-middleware" - }, - { - "path": "../sdk-effects/oidc" - }, - { - "path": "../sdk-effects/logger" - }, - { - "path": "../sdk-effects/iframe-manager" - }, { "path": "./tsconfig.lib.json" }, diff --git a/packages/sdk-effects/oidc/package.json b/packages/sdk-effects/oidc/package.json index 57b74cfe27..c5a7465e75 100644 --- a/packages/sdk-effects/oidc/package.json +++ b/packages/sdk-effects/oidc/package.json @@ -27,7 +27,8 @@ }, "dependencies": { "@forgerock/sdk-types": "workspace:*", - "@forgerock/sdk-utilities": "workspace:*" + "@forgerock/sdk-utilities": "workspace:*", + "@reduxjs/toolkit": "catalog:" }, "nx": { "tags": ["scope:sdk-effects"] diff --git a/packages/sdk-effects/oidc/src/index.ts b/packages/sdk-effects/oidc/src/index.ts index ca093486d6..e03cb69859 100644 --- a/packages/sdk-effects/oidc/src/index.ts +++ b/packages/sdk-effects/oidc/src/index.ts @@ -6,3 +6,5 @@ */ export * from './lib/authorize.effects.js'; export * from './lib/state-pkce.effects.js'; +export * from './lib/wellknown.api.js'; +export * from './lib/wellknown.utils.js'; diff --git a/packages/sdk-effects/oidc/src/lib/wellknown.api.ts b/packages/sdk-effects/oidc/src/lib/wellknown.api.ts new file mode 100644 index 0000000000..93f7292099 --- /dev/null +++ b/packages/sdk-effects/oidc/src/lib/wellknown.api.ts @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +import { createSelector } from '@reduxjs/toolkit'; +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'; + +import type { WellknownResponse } from '@forgerock/sdk-types'; + +/** + * RTK Query API for fetching the OIDC well-known configuration endpoint. + * + * The well-known endpoint (`.well-known/openid-configuration`) provides + * OIDC Discovery information. Common fields include: + * - `issuer` - The OIDC issuer identifier (required) + * - `authorization_endpoint` - URL for authorization requests (required) + * - `token_endpoint` - URL for token exchange (required) + * - `userinfo_endpoint` - URL for user info retrieval + * - `end_session_endpoint` - URL for logout/session termination + * - `revocation_endpoint` - URL for token revocation + * + * See `WellknownResponse` type from `@forgerock/sdk-types` for the complete + * list of available fields. + * + * @example + * ```typescript + * // Add to your Redux store + * const store = configureStore({ + * reducer: { + * [wellknownApi.reducerPath]: wellknownApi.reducer, + * }, + * middleware: (getDefault) => getDefault().concat(wellknownApi.middleware), + * }); + * + * // Fetch the configuration + * const { data, error } = await store.dispatch( + * wellknownApi.endpoints.configuration.initiate(wellknownUrl) + * ); + * ``` + */ +export const wellknownApi = createApi({ + reducerPath: 'wellknown', + baseQuery: fetchBaseQuery({ + prepareHeaders: (headers) => { + headers.set('Accept', 'application/json'); + return headers; + }, + }), + endpoints: (builder) => ({ + configuration: builder.query({ + query: (endpoint) => endpoint, + }), + }), +}); + +/** + * Creates a selector to retrieve the cached well-known response from Redux state. + * + * This is a factory function that works with any Redux store structure, + * as long as the wellknownApi reducer is mounted at the 'wellknown' path. + * + * @param wellknownUrl - The well-known endpoint URL used as the cache key + * @returns A selector function that extracts the WellKnownResponse from state + * + * @example + * ```typescript + * const selector = createWellknownSelector(wellknownUrl); + * const wellknownResponse = selector(store.getState()); + * + * if (wellknownResponse?.authorization_endpoint) { + * // Use the authorization endpoint + * } + * ``` + */ +export function createWellknownSelector(wellknownUrl: string) { + return createSelector( + wellknownApi.endpoints.configuration.select(wellknownUrl), + (result) => result?.data, + ); +} diff --git a/packages/sdk-effects/oidc/src/lib/wellknown.utils.test.ts b/packages/sdk-effects/oidc/src/lib/wellknown.utils.test.ts new file mode 100644 index 0000000000..a719c9819c --- /dev/null +++ b/packages/sdk-effects/oidc/src/lib/wellknown.utils.test.ts @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2025 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +import { describe, it, expect } from 'vitest'; +import { createWellknownError } from './wellknown.utils.js'; + +describe('wellknown.utils', () => { + describe('createWellknownError', () => { + describe('createWellknownError_UndefinedError_ReturnsDefaultMessage', () => { + it('should return default error when no error provided', () => { + const result = createWellknownError(undefined); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('No response received from well-known endpoint'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe('unknown'); + }); + }); + + describe('createWellknownError_FetchErrorWithString_ReturnsErrorString', () => { + it('should extract error string from FETCH_ERROR type', () => { + const fetchError = { + status: 'FETCH_ERROR', + error: 'Network request failed', + } as const; + + const result = createWellknownError(fetchError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('Network request failed'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe('FETCH_ERROR'); + }); + }); + + describe('createWellknownError_HttpErrorWithDataMessage_ReturnsDataMessage', () => { + it('should extract message from HTTP error response data', () => { + const fetchError = { status: 404, data: { message: 'Endpoint not found' } }; + + const result = createWellknownError(fetchError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('Endpoint not found'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe(404); + }); + }); + + describe('createWellknownError_HttpErrorWithDataError_ReturnsDataError', () => { + it('should extract error field from HTTP error response data', () => { + const fetchError = { status: 401, data: { error: 'unauthorized' } }; + + const result = createWellknownError(fetchError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('unauthorized'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe(401); + }); + }); + + describe('createWellknownError_HttpErrorWithErrorDescription_ReturnsDescription', () => { + it('should extract error_description from OAuth-style error response', () => { + const fetchError = { + status: 400, + data: { error_description: 'Invalid client credentials' }, + }; + + const result = createWellknownError(fetchError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('Invalid client credentials'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe(400); + }); + }); + + describe('createWellknownError_HttpErrorWithUnknownData_ReturnsStringifiedData', () => { + it('should stringify unknown data structure', () => { + const fetchError = { + status: 500, + data: { code: 'INTERNAL_ERROR', details: ['Something went wrong'] }, + }; + + const result = createWellknownError(fetchError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('{"code":"INTERNAL_ERROR","details":["Something went wrong"]}'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe(500); + }); + }); + + describe('createWellknownError_HttpErrorWithoutData_ReturnsHttpStatus', () => { + it('should return HTTP status message when no data', () => { + const fetchError = { status: 503, data: undefined }; + + const result = createWellknownError(fetchError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('HTTP error 503'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe(503); + }); + }); + + describe('createWellknownError_HttpErrorWithNullData_ReturnsHttpStatus', () => { + it('should return HTTP status message when data is null', () => { + const fetchError = { status: 500, data: null }; + + const result = createWellknownError(fetchError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('HTTP error 500'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe(500); + }); + }); + + describe('createWellknownError_SerializedErrorWithMessage_ReturnsMessage', () => { + it('should extract message from SerializedError', () => { + const serializedError = { name: 'TypeError', message: 'Cannot read property of undefined' }; + + const result = createWellknownError(serializedError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('Cannot read property of undefined'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe('unknown'); + }); + }); + + describe('createWellknownError_SerializedErrorWithoutMessage_ReturnsDefault', () => { + it('should return default message when SerializedError has no message', () => { + const serializedError = { name: 'Error' }; + + const result = createWellknownError(serializedError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('An unknown error occurred'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe('unknown'); + }); + }); + + describe('createWellknownError_TimeoutError_ReturnsTimeoutMessage', () => { + it('should handle TIMEOUT_ERROR from RTK Query', () => { + const fetchError = { status: 'TIMEOUT_ERROR', error: 'Request timed out' } as const; + + const result = createWellknownError(fetchError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('Request timed out'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe('TIMEOUT_ERROR'); + }); + }); + + describe('createWellknownError_ParsingError_ReturnsParsingMessage', () => { + it('should handle PARSING_ERROR from RTK Query', () => { + const fetchError = { + status: 'PARSING_ERROR', + originalStatus: 200, + error: 'Unexpected token < in JSON at position 0', + data: '', + } as const; + + const result = createWellknownError(fetchError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('Unexpected token < in JSON at position 0'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe('PARSING_ERROR'); + }); + }); + + describe('createWellknownError_CustomError_ReturnsCustomMessage', () => { + it('should handle CUSTOM_ERROR from RTK Query', () => { + const fetchError = { + status: 'CUSTOM_ERROR', + error: 'Custom validation failed', + data: { custom: 'data' }, + } as const; + + const result = createWellknownError(fetchError); + + expect(result.error).toBe('Well-known configuration fetch failed'); + expect(result.message).toBe('Custom validation failed'); + expect(result.type).toBe('wellknown_error'); + expect(result.status).toBe('CUSTOM_ERROR'); + }); + }); + }); +}); diff --git a/packages/sdk-effects/oidc/src/lib/wellknown.utils.ts b/packages/sdk-effects/oidc/src/lib/wellknown.utils.ts new file mode 100644 index 0000000000..b823c73f81 --- /dev/null +++ b/packages/sdk-effects/oidc/src/lib/wellknown.utils.ts @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2025 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +import type { SerializedError } from '@reduxjs/toolkit'; +import type { FetchBaseQueryError } from '@reduxjs/toolkit/query'; +import type { GenericError } from '@forgerock/sdk-types'; + +/** + * Type guard that checks if a value is a non-null object. + * Used for safe property access without `as` casting. + * + * @param value - The value to check + * @returns True if value is a non-null object + */ +function isObject(value: unknown): value is Record { + return typeof value === 'object' && value !== null; +} + +/** + * Extracts a human-readable error message from an RTK Query error. + * + * RTK Query can return two types of errors: + * - `FetchBaseQueryError`: Has `status` and either `error` (string) or `data` (parsed response) + * - `SerializedError`: Has `message`, `name`, `code`, `stack` (from JS errors) + * + * @param error - The error from RTK Query dispatch result + * @returns A human-readable error message + * + * @see https://redux-toolkit.js.org/rtk-query/usage-with-typescript#type-safe-error-handling + */ +function extractErrorMessage(error: FetchBaseQueryError | SerializedError): string { + // FetchBaseQueryError has 'status' property + if ('status' in error) { + // 'error' is present for FETCH_ERROR, PARSING_ERROR, TIMEOUT_ERROR, CUSTOM_ERROR + if ('error' in error) { + return error.error; + } + // 'data' contains the parsed response body for HTTP errors + if ('data' in error && isObject(error.data)) { + const data = error.data; + // Try to extract message from common error response formats + if (typeof data.message === 'string') { + return data.message; + } + if (typeof data.error === 'string') { + return data.error; + } + if (typeof data.error_description === 'string') { + return data.error_description; + } + // Fallback to stringifying the data + return JSON.stringify(data); + } + return `HTTP error ${error.status}`; + } + + // SerializedError has 'message' property + return error.message ?? 'An unknown error occurred'; +} + +/** + * Extracts the HTTP status code from an RTK Query error, if available. + * + * @param error - The error from RTK Query dispatch result + * @returns The HTTP status code, or 'unknown' if not available + */ +function extractErrorStatus(error: FetchBaseQueryError | SerializedError): number | string { + if ('status' in error) { + return error.status; + } + return 'unknown'; +} + +/** + * Creates a GenericError from an RTK Query error for well-known fetch failures. + * + * This follows the established pattern in the codebase for converting RTK Query + * errors to the SDK's GenericError type with `type: 'wellknown_error'`. + * + * @param error - The error from RTK Query dispatch result, or undefined if no response + * @returns A GenericError with type 'wellknown_error' + * + * @example + * ```typescript + * const { data, error } = await store.dispatch( + * wellknownApi.endpoints.configuration.initiate(url) + * ); + * + * if (error || !data) { + * const genericError = createWellknownError(error); + * log.error(genericError.message); + * throw new Error(genericError.message); + * } + * ``` + */ +export function createWellknownError(error?: FetchBaseQueryError | SerializedError): GenericError { + if (error) { + return { + error: 'Well-known configuration fetch failed', + message: extractErrorMessage(error), + type: 'wellknown_error', + status: extractErrorStatus(error), + }; + } + + return { + error: 'Well-known configuration fetch failed', + message: 'No response received from well-known endpoint', + type: 'wellknown_error', + status: 'unknown', + }; +} diff --git a/packages/sdk-effects/oidc/tsconfig.json b/packages/sdk-effects/oidc/tsconfig.json index 6103cbcd4e..3a5af05d8e 100644 --- a/packages/sdk-effects/oidc/tsconfig.json +++ b/packages/sdk-effects/oidc/tsconfig.json @@ -3,12 +3,6 @@ "files": [], "include": [], "references": [ - { - "path": "../../sdk-utilities" - }, - { - "path": "../../sdk-types" - }, { "path": "./tsconfig.lib.json" }, diff --git a/packages/sdk-effects/storage/tsconfig.json b/packages/sdk-effects/storage/tsconfig.json index 4b84682a46..3a5af05d8e 100644 --- a/packages/sdk-effects/storage/tsconfig.json +++ b/packages/sdk-effects/storage/tsconfig.json @@ -3,9 +3,6 @@ "files": [], "include": [], "references": [ - { - "path": "../../sdk-types" - }, { "path": "./tsconfig.lib.json" }, diff --git a/packages/sdk-types/src/lib/legacy-config.types.ts b/packages/sdk-types/src/lib/legacy-config.types.ts index 2eebdfa15d..a66da83553 100644 --- a/packages/sdk-types/src/lib/legacy-config.types.ts +++ b/packages/sdk-types/src/lib/legacy-config.types.ts @@ -47,7 +47,7 @@ export interface ValidLegacyConfigOptions extends LegacyConfigOptions { // needs logger? } -export interface WellKnownResponse { +export interface WellknownResponse { issuer: string; authorization_endpoint: string; pushed_authorization_request_endpoint?: string; diff --git a/packages/sdk-utilities/src/index.ts b/packages/sdk-utilities/src/index.ts index d2ef0ad097..f01a5f77b8 100644 --- a/packages/sdk-utilities/src/index.ts +++ b/packages/sdk-utilities/src/index.ts @@ -11,5 +11,6 @@ export * from './lib/error/index.js'; export * from './lib/oidc/index.js'; export * from './lib/strings/index.js'; export * from './lib/url/index.js'; +export * from './lib/wellknown/index.js'; export * from './lib/object.utils.js'; export * from './lib/constants/index.js'; diff --git a/packages/sdk-utilities/src/lib/error/error.utils.test.ts b/packages/sdk-utilities/src/lib/error/error.utils.test.ts index e7a6a37a36..d71b707167 100644 --- a/packages/sdk-utilities/src/lib/error/error.utils.test.ts +++ b/packages/sdk-utilities/src/lib/error/error.utils.test.ts @@ -157,16 +157,13 @@ describe('isGenericError', () => { }); it('isGenericError_ObjectWithNonStringType_ReturnsFalse', () => { - // Arrange const value = { error: 'storage_error', type: 123, }; - // Act const result = isGenericError(value); - // Assert expect(result).toBe(false); }); diff --git a/packages/sdk-utilities/src/lib/wellknown/index.ts b/packages/sdk-utilities/src/lib/wellknown/index.ts new file mode 100644 index 0000000000..af828cdf18 --- /dev/null +++ b/packages/sdk-utilities/src/lib/wellknown/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2025 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +export * from './wellknown.utils.js'; diff --git a/packages/sdk-utilities/src/lib/wellknown/wellknown.utils.test.ts b/packages/sdk-utilities/src/lib/wellknown/wellknown.utils.test.ts new file mode 100644 index 0000000000..21c5643543 --- /dev/null +++ b/packages/sdk-utilities/src/lib/wellknown/wellknown.utils.test.ts @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +import { describe, it, expect } from 'vitest'; +import { isValidWellknownUrl } from './wellknown.utils.js'; + +describe('wellknown.utils', () => { + describe('isValidWellknownUrl', () => { + describe('isValidWellknownUrl_HttpsUrl_ReturnsTrue', () => { + it('should return true for HTTPS URL', () => { + expect(isValidWellknownUrl('https://am.example.com/.well-known/openid-configuration')).toBe( + true, + ); + }); + }); + + describe('isValidWellknownUrl_HttpLocalhost_ReturnsTrue', () => { + it('should return true for HTTP localhost', () => { + expect(isValidWellknownUrl('http://localhost:8080/.well-known/openid-configuration')).toBe( + true, + ); + }); + }); + + describe('isValidWellknownUrl_Http127001_ReturnsTrue', () => { + it('should return true for HTTP 127.0.0.1', () => { + expect(isValidWellknownUrl('http://127.0.0.1:8080/.well-known/openid-configuration')).toBe( + true, + ); + }); + }); + + describe('isValidWellknownUrl_HttpNonLocalhost_ReturnsFalse', () => { + it('should return false for HTTP non-localhost URL', () => { + expect(isValidWellknownUrl('http://am.example.com/.well-known/openid-configuration')).toBe( + false, + ); + }); + }); + + describe('isValidWellknownUrl_InvalidUrl_ReturnsFalse', () => { + it('should return false for invalid URL', () => { + expect(isValidWellknownUrl('not-a-valid-url')).toBe(false); + }); + }); + + describe('isValidWellknownUrl_EmptyString_ReturnsFalse', () => { + it('should return false for empty string', () => { + expect(isValidWellknownUrl('')).toBe(false); + }); + }); + + describe('isValidWellknownUrl_FtpProtocol_ReturnsFalse', () => { + it('should return false for non-HTTP protocols', () => { + expect(isValidWellknownUrl('ftp://am.example.com/.well-known/openid-configuration')).toBe( + false, + ); + }); + }); + + describe('isValidWellknownUrl_HttpsLocalhost_ReturnsTrue', () => { + it('should return true for HTTPS localhost', () => { + expect(isValidWellknownUrl('https://localhost:8443/.well-known/openid-configuration')).toBe( + true, + ); + }); + }); + }); +}); diff --git a/packages/sdk-utilities/src/lib/wellknown/wellknown.utils.ts b/packages/sdk-utilities/src/lib/wellknown/wellknown.utils.ts new file mode 100644 index 0000000000..9be061e286 --- /dev/null +++ b/packages/sdk-utilities/src/lib/wellknown/wellknown.utils.ts @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +/** + * Validates that a well-known URL is properly formatted. + * + * @param wellknownUrl - The URL to validate + * @returns True if the URL is valid and uses HTTPS (or HTTP for localhost) + * + * @example + * ```typescript + * isValidWellknownUrl('https://am.example.com/.well-known/openid-configuration') + * // Returns: true + * + * isValidWellknownUrl('http://localhost:8080/.well-known/openid-configuration') + * // Returns: true (localhost allows HTTP) + * + * isValidWellknownUrl('http://am.example.com/.well-known/openid-configuration') + * // Returns: false (non-localhost requires HTTPS) + * + * isValidWellknownUrl('not-a-url') + * // Returns: false + * ``` + */ +export function isValidWellknownUrl(wellknownUrl: string): boolean { + try { + const url = new URL(wellknownUrl); + + // Allow HTTP only for localhost (development) + // Note: We intentionally do not check for IPv6 localhost (::1) as it is rarely used + // in local development and adds complexity. Most dev servers bind to localhost or 127.0.0.1. + const isLocalhost = url.hostname === 'localhost' || url.hostname === '127.0.0.1'; + const isSecure = url.protocol === 'https:'; + const isHttpLocalhost = url.protocol === 'http:' && isLocalhost; + + return isSecure || isHttpLocalhost; + } catch { + return false; + } +} diff --git a/packages/sdk-utilities/tsconfig.json b/packages/sdk-utilities/tsconfig.json index 5c1aa3dc5d..9d592a77cf 100644 --- a/packages/sdk-utilities/tsconfig.json +++ b/packages/sdk-utilities/tsconfig.json @@ -3,9 +3,6 @@ "files": [], "include": [], "references": [ - { - "path": "../sdk-types" - }, { "path": "./tsconfig.lib.json" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1145deb954..cc05b55d89 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -37,10 +37,20 @@ catalogs: effect: specifier: ^3.17.2 version: 3.19.3 + vite: + vite: + specifier: ^7.3.1 + version: 7.3.1 vitest: + '@vitest/coverage-v8': + specifier: ^4.0.9 + version: 4.0.9 vitest: - specifier: ^3.0.4 - version: 3.2.4 + specifier: ^4.0.9 + version: 4.0.9 + vitest-canvas-mock: + specifier: ^1.1.3 + version: 1.1.3 importers: @@ -71,38 +81,41 @@ importers: specifier: ~9.39.0 version: 9.39.1 '@nx/devkit': - specifier: 21.2.3 - version: 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + specifier: 22.3.3 + version: 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) '@nx/eslint': - specifier: 21.2.3 - version: 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + specifier: 22.3.3 + version: 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) '@nx/eslint-plugin': - specifier: 21.2.3 - version: 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) + specifier: 22.3.3 + version: 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) '@nx/express': - specifier: 21.2.3 - version: 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(express@4.21.2)(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) + specifier: 22.3.3 + version: 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(express@4.21.2)(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) '@nx/jest': - specifier: 21.2.3 - version: 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) + specifier: 22.3.3 + version: 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) '@nx/js': - specifier: 21.2.3 - version: 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + specifier: 22.3.3 + version: 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) '@nx/playwright': - specifier: 21.2.3 - version: 21.2.3(@babel/traverse@7.28.5)(@playwright/test@1.56.1)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) + specifier: 22.3.3 + version: 22.3.3(@babel/traverse@7.28.5)(@playwright/test@1.56.1)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) '@nx/plugin': - specifier: 21.2.3 - version: 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) + specifier: 22.3.3 + version: 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) '@nx/vite': - specifier: 21.2.3 - version: 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4) + specifier: 22.3.3 + version: 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))(vite@7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.9) + '@nx/vitest': + specifier: 22.3.3 + version: 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))(vite@7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.9) '@nx/web': - specifier: 21.2.3 - version: 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + specifier: 22.3.3 + version: 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) '@nx/workspace': - specifier: 21.2.3 - version: 21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)) + specifier: 22.3.3 + version: 22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)) '@playwright/test': specifier: ^1.47.2 version: 1.56.1 @@ -143,11 +156,11 @@ importers: specifier: ^8.13.0 version: 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) '@vitest/coverage-v8': - specifier: ^3.0.5 - version: 3.2.4(vitest@3.2.4) + specifier: 4.0.9 + version: 4.0.9(vitest@4.0.9) '@vitest/ui': - specifier: 3.0.4 - version: 3.0.4(vitest@3.2.4) + specifier: 4.0.9 + version: 4.0.9(vitest@4.0.9) conventional-changelog-conventionalcommits: specifier: ^8.0.0 version: 8.0.0 @@ -197,8 +210,8 @@ importers: specifier: 8.0.0 version: 8.0.0(typescript@5.8.3) nx: - specifier: 21.2.3 - version: 21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)) + specifier: 22.3.3 + version: 22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)) pkg-pr-new: specifier: ^0.0.60 version: 0.0.60 @@ -242,23 +255,20 @@ importers: specifier: 6.2.1 version: 6.2.1(typanion@3.14.0) vite: - specifier: 6.4.1 - version: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + specifier: catalog:vite + version: 7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) vitest: specifier: catalog:vitest - version: 3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + version: 4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) vitest-canvas-mock: - specifier: ^0.3.3 - version: 0.3.3(vitest@3.2.4) + specifier: catalog:vitest + version: 1.1.3(vitest@4.0.9) e2e/am-mock-api: dependencies: - '@types/express': - specifier: ^4.17.17 - version: 4.17.23 body-parser: - specifier: ^2.2.0 - version: 2.2.0 + specifier: ^2.2.2 + version: 2.2.2 cookie-parser: specifier: ^1.4.7 version: 1.4.7 @@ -266,14 +276,18 @@ importers: specifier: ^2.8.5 version: 2.8.5 express: - specifier: ^4.21.2 - version: 4.21.2 + specifier: ^5.2.1 + version: 5.2.1 superagent: specifier: ^10.2.3 version: 10.2.3 uuid: specifier: ^13.0.0 version: 13.0.0 + devDependencies: + '@types/express': + specifier: ^5.0.0 + version: 5.0.5 e2e/davinci-app: dependencies: @@ -363,7 +377,10 @@ importers: devDependencies: '@effect/vitest': specifier: catalog:effect - version: 0.23.13(effect@3.19.3)(vitest@3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) + version: 0.23.13(effect@3.19.3)(vitest@4.0.9) + vitest: + specifier: catalog:vitest + version: 4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) e2e/oidc-app: dependencies: @@ -416,7 +433,7 @@ importers: devDependencies: vitest: specifier: catalog:vitest - version: 3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + version: 4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) packages/device-client: dependencies: @@ -429,13 +446,16 @@ importers: devDependencies: msw: specifier: 'catalog:' - version: 2.12.1(@types/node@24.9.2)(typescript@5.8.3) + version: 2.12.1(@types/node@24.9.2)(typescript@5.9.3) packages/journey-client: dependencies: '@forgerock/sdk-logger': specifier: workspace:* version: link:../sdk-effects/logger + '@forgerock/sdk-oidc': + specifier: workspace:* + version: link:../sdk-effects/oidc '@forgerock/sdk-request-middleware': specifier: workspace:* version: link:../sdk-effects/sdk-request-middleware @@ -455,18 +475,18 @@ importers: specifier: ^2.3.0 version: 2.8.1 vite: - specifier: 6.4.1 - version: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + specifier: catalog:vite + version: 7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) vitest-canvas-mock: - specifier: ^0.3.3 - version: 0.3.3(vitest@1.6.1(@types/node@24.9.2)(@vitest/ui@3.0.4)(jsdom@27.1.0)(terser@5.44.1)) + specifier: catalog:vitest + version: 1.1.3(vitest@4.0.9) devDependencies: '@vitest/coverage-v8': - specifier: ^1.2.0 - version: 1.6.1(vitest@1.6.1(@types/node@24.9.2)(@vitest/ui@3.0.4)(jsdom@27.1.0)(terser@5.44.1)) + specifier: catalog:vitest + version: 4.0.9(vitest@4.0.9) vitest: - specifier: ^1.2.0 - version: 1.6.1(@types/node@24.9.2)(@vitest/ui@3.0.4)(jsdom@27.1.0)(terser@5.44.1) + specifier: catalog:vitest + version: 4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) packages/oidc-client: dependencies: @@ -497,10 +517,10 @@ importers: devDependencies: '@effect/vitest': specifier: catalog:effect - version: 0.23.13(effect@3.19.3)(vitest@3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) + version: 0.23.13(effect@3.19.3)(vitest@4.0.9) msw: specifier: 'catalog:' - version: 2.12.1(@types/node@24.9.2)(typescript@5.8.3) + version: 2.12.1(@types/node@24.9.2)(typescript@5.9.3) packages/protect: {} @@ -516,6 +536,9 @@ importers: '@forgerock/sdk-utilities': specifier: workspace:* version: link:../../sdk-utilities + '@reduxjs/toolkit': + specifier: 'catalog:' + version: 2.10.1 packages/sdk-effects/sdk-request-middleware: dependencies: @@ -575,14 +598,14 @@ importers: version: 3.19.3 vitest: specifier: catalog:vitest - version: 3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + version: 4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) devDependencies: '@effect/language-service': specifier: catalog:effect version: 0.35.2 '@effect/vitest': specifier: catalog:effect - version: 0.23.13(effect@3.19.3)(vitest@3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) + version: 0.23.13(effect@3.19.3)(vitest@4.0.9) packages: @@ -604,10 +627,6 @@ packages: '@altano/repository-tools@0.1.1': resolution: {integrity: sha512-5vbUs2A98CC3g1AlOBdkBE0BMukkLjLIsMHAtuxg6Pt9dQXxYWdLKOf66v6c/vIqtNcgTMv0oGtddLdMuH9X6w==} - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - '@asamuzakjp/css-color@4.0.5': resolution: {integrity: sha512-lMrXidNhPGsDjytDy11Vwlb6OIGrT3CmLg3VWNFyWkLWtijKl7xjvForlh8vuj0SHGjgl4qZEQzUmYTeQA2JFQ==} @@ -1211,10 +1230,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.28.4': - resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} - engines: {node: '>=6.9.0'} - '@babel/runtime@7.28.6': resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} engines: {node: '>=6.9.0'} @@ -1560,23 +1575,17 @@ packages: '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - '@esbuild/aix-ppc64@0.25.12': resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] + '@esbuild/aix-ppc64@0.27.2': + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] '@esbuild/android-arm64@0.25.12': resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} @@ -1584,10 +1593,10 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] + '@esbuild/android-arm64@0.27.2': + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + engines: {node: '>=18'} + cpu: [arm64] os: [android] '@esbuild/android-arm@0.25.12': @@ -1596,10 +1605,10 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] + '@esbuild/android-arm@0.27.2': + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + engines: {node: '>=18'} + cpu: [arm] os: [android] '@esbuild/android-x64@0.25.12': @@ -1608,11 +1617,11 @@ packages: cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] + '@esbuild/android-x64@0.27.2': + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] '@esbuild/darwin-arm64@0.25.12': resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} @@ -1620,10 +1629,10 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] + '@esbuild/darwin-arm64@0.27.2': + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + engines: {node: '>=18'} + cpu: [arm64] os: [darwin] '@esbuild/darwin-x64@0.25.12': @@ -1632,11 +1641,11 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] + '@esbuild/darwin-x64@0.27.2': + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] '@esbuild/freebsd-arm64@0.25.12': resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} @@ -1644,10 +1653,10 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] + '@esbuild/freebsd-arm64@0.27.2': + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + engines: {node: '>=18'} + cpu: [arm64] os: [freebsd] '@esbuild/freebsd-x64@0.25.12': @@ -1656,11 +1665,11 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] + '@esbuild/freebsd-x64@0.27.2': + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] '@esbuild/linux-arm64@0.25.12': resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} @@ -1668,10 +1677,10 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] + '@esbuild/linux-arm64@0.27.2': + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + engines: {node: '>=18'} + cpu: [arm64] os: [linux] '@esbuild/linux-arm@0.25.12': @@ -1680,10 +1689,10 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] + '@esbuild/linux-arm@0.27.2': + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + engines: {node: '>=18'} + cpu: [arm] os: [linux] '@esbuild/linux-ia32@0.25.12': @@ -1692,10 +1701,10 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] + '@esbuild/linux-ia32@0.27.2': + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + engines: {node: '>=18'} + cpu: [ia32] os: [linux] '@esbuild/linux-loong64@0.25.12': @@ -1704,10 +1713,10 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] + '@esbuild/linux-loong64@0.27.2': + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + engines: {node: '>=18'} + cpu: [loong64] os: [linux] '@esbuild/linux-mips64el@0.25.12': @@ -1716,10 +1725,10 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] + '@esbuild/linux-mips64el@0.27.2': + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + engines: {node: '>=18'} + cpu: [mips64el] os: [linux] '@esbuild/linux-ppc64@0.25.12': @@ -1728,10 +1737,10 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] + '@esbuild/linux-ppc64@0.27.2': + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} + cpu: [ppc64] os: [linux] '@esbuild/linux-riscv64@0.25.12': @@ -1740,10 +1749,10 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] + '@esbuild/linux-riscv64@0.27.2': + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + engines: {node: '>=18'} + cpu: [riscv64] os: [linux] '@esbuild/linux-s390x@0.25.12': @@ -1752,10 +1761,10 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] + '@esbuild/linux-s390x@0.27.2': + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + engines: {node: '>=18'} + cpu: [s390x] os: [linux] '@esbuild/linux-x64@0.25.12': @@ -1764,16 +1773,22 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.27.2': + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.12': resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] + '@esbuild/netbsd-arm64@0.27.2': + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + engines: {node: '>=18'} + cpu: [arm64] os: [netbsd] '@esbuild/netbsd-x64@0.25.12': @@ -1782,16 +1797,22 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.27.2': + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.12': resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] + '@esbuild/openbsd-arm64@0.27.2': + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + engines: {node: '>=18'} + cpu: [arm64] os: [openbsd] '@esbuild/openbsd-x64@0.25.12': @@ -1800,17 +1821,23 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.27.2': + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openharmony-arm64@0.25.12': resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] + '@esbuild/openharmony-arm64@0.27.2': + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] '@esbuild/sunos-x64@0.25.12': resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} @@ -1818,11 +1845,11 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] + '@esbuild/sunos-x64@0.27.2': + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] '@esbuild/win32-arm64@0.25.12': resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} @@ -1830,10 +1857,10 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] + '@esbuild/win32-arm64@0.27.2': + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + engines: {node: '>=18'} + cpu: [arm64] os: [win32] '@esbuild/win32-ia32@0.25.12': @@ -1842,10 +1869,10 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] + '@esbuild/win32-ia32@0.27.2': + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + engines: {node: '>=18'} + cpu: [ia32] os: [win32] '@esbuild/win32-x64@0.25.12': @@ -1854,6 +1881,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.27.2': + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.9.0': resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1974,62 +2007,78 @@ packages: resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} - '@jest/console@29.7.0': - resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/console@30.2.0': + resolution: {integrity: sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/environment@29.7.0': - resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/diff-sequences@30.0.1': + resolution: {integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/expect-utils@29.7.0': - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/environment@30.2.0': + resolution: {integrity: sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/expect@29.7.0': - resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/expect-utils@30.2.0': + resolution: {integrity: sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/fake-timers@29.7.0': - resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/expect@30.2.0': + resolution: {integrity: sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/globals@29.7.0': - resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/fake-timers@30.2.0': + resolution: {integrity: sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/reporters@29.7.0': - resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/get-type@30.1.0': + resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/globals@30.2.0': + resolution: {integrity: sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/pattern@30.0.1': + resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/reporters@30.2.0': + resolution: {integrity: sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/schemas@30.0.5': + resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/snapshot-utils@30.2.0': + resolution: {integrity: sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/source-map@29.6.3': - resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/source-map@30.0.1': + resolution: {integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/test-result@29.7.0': - resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/test-result@30.2.0': + resolution: {integrity: sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/test-sequencer@29.7.0': - resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/test-sequencer@30.2.0': + resolution: {integrity: sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/transform@29.7.0': - resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/transform@30.2.0': + resolution: {integrity: sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/types@29.6.3': - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/types@30.2.0': + resolution: {integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -2225,13 +2274,16 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@nx/devkit@21.2.3': - resolution: {integrity: sha512-H5Hk0qeZwqhxQmqcWaLpMc+otU4TroUzDYoV6kFpZdvcwGnXQKHCuGzZoI18kh9wPXvKFmb1BWmr9as3lHUw3Q==} + '@nx/devkit@22.3.3': + resolution: {integrity: sha512-/hxcdhE+QDalsWEbJurHtZh9aY27taHeImbCVJnogwv85H3RbAE+0YuKXGInutfLszAs7phwzli71yq+d2P45Q==} peerDependencies: - nx: 21.2.3 + nx: '>= 21 <= 23 || ^22.0.0-0' - '@nx/eslint-plugin@21.2.3': - resolution: {integrity: sha512-UryMWwgRYCjCLgqexhv6aQBMnKxJyVlN58Gp6Oa/2/2P/vMnIPjwbI58pZL1D1Se6HL14NKxmVu2KkX6Bf9R1w==} + '@nx/docker@22.3.3': + resolution: {integrity: sha512-Z1Phb+IZP5ofRadrzJQdMOdMKOaJ6nKXifgGPN0uxd9gNQ7V7XiHxK3+RW7nANuotYW5sf5DnLxDbhbSDD3Syw==} + + '@nx/eslint-plugin@22.3.3': + resolution: {integrity: sha512-UGAqvYUlKGupBUsO9ppEzYkai1VrrFrUkzHPOVUu5JM4zYGN30ruoO+j3K5OXu5jQLGCmOVfAQD3jzqT2balmw==} peerDependencies: '@typescript-eslint/parser': ^6.13.2 || ^7.0.0 || ^8.0.0 eslint-config-prettier: ^10.0.0 @@ -2239,8 +2291,8 @@ packages: eslint-config-prettier: optional: true - '@nx/eslint@21.2.3': - resolution: {integrity: sha512-Lr/4FeeNhBIR3pPrENHUtyWtoBKiztaDilNodzizSiXVp32mCL1sPc5UYr5n8BpqAtDT6yK7jF7Pn+YvVD688w==} + '@nx/eslint@22.3.3': + resolution: {integrity: sha512-iG/LvrYf2CFAm2A0kfmRU4VeCTAN5PjUw8xc6oD1zfQ/KTmE/gFG2P1aJBo2mTIyzk9k8ZI0dqIhPLdl/AAtxg==} peerDependencies: '@zkochan/js-yaml': 0.0.7 eslint: ^8.0.0 || ^9.0.0 @@ -2248,100 +2300,111 @@ packages: '@zkochan/js-yaml': optional: true - '@nx/express@21.2.3': - resolution: {integrity: sha512-XUHDpH8ilLUYkuHobm3UZbtkY+09AfjrlR5xfb/fDCimvjyPb/E8MvcYPya+jvUTkNQ5Z8PL51qG/2F5SnUDBw==} + '@nx/express@22.3.3': + resolution: {integrity: sha512-e/vGIocfKklpN7nsd68B2ejH0cdqA3TCpyks9YCIY0CYBS1G5RZ+v1k9eWkie2CWHH3IwPiiW3x7+SEU0sIRqw==} peerDependencies: express: ^4.21.2 peerDependenciesMeta: express: optional: true - '@nx/jest@21.2.3': - resolution: {integrity: sha512-lkH+tX8c1XSRjDa1g/lnYiC4zgs+8tZsj9yUVR2/1x+OO2SYDL8KVld6ZkWzXhRW8ZKXPHkDMWMUNBqsYlAWHA==} + '@nx/jest@22.3.3': + resolution: {integrity: sha512-BC+5E6oAM6h9x67UCtpsapfLRTwqVLtoG39f5tVZNVZ4a1spdMh0tPHRPtu2hSlsHHtaYsmTvjz5L+N7UguAtA==} - '@nx/js@21.2.3': - resolution: {integrity: sha512-9uA+j924UoarVJFLH6iy+PMnTWgrBM3XfjSpjThDwdJ4ffhop8NcED51sO/qUs68py93NxuY6Ud0qSSu8G5I+A==} + '@nx/js@22.3.3': + resolution: {integrity: sha512-L3MOb8cLc2TIg2R3hGC9FLlcuVqlqST/fztmOihw9wS3lo52E4v2gP/BpYGfRh/u9r6Ekm6LF03Or+VwYzPuzA==} peerDependencies: verdaccio: ^6.0.5 peerDependenciesMeta: verdaccio: optional: true - '@nx/node@21.2.3': - resolution: {integrity: sha512-5ivOTIYyXHwZSwpCR3AnKFCzjjzKHMfmVnMLQbiDhYB7nd9RJXsKsPAMdEVFCP/JBTPmQkufXElw/Kxfww7dnA==} + '@nx/node@22.3.3': + resolution: {integrity: sha512-/ICmyoB5oIrJ3CnsB0QqUXSNepL20AFYvmQNP5EoqVb53eAjm4A1fgpNE6JJ4monzsxMexwoO8ZbYdTYUZWjjw==} - '@nx/nx-darwin-arm64@21.2.3': - resolution: {integrity: sha512-5WgOjoX4vqG286A8abYoLCScA2ZF5af/2ZBjaM5EHypgbJLGQuMcP2ahzX66FYohT4wdAej1D0ILkEax71fAKw==} + '@nx/nx-darwin-arm64@22.3.3': + resolution: {integrity: sha512-zBAGFGLal09CxhQkdMpOVwcwa9Y01aFm88jTTn35s/DdIWsfngmPzz0t4mG7u2D05q7TJfGQ31pIf5GkNUjo6g==} cpu: [arm64] os: [darwin] - '@nx/nx-darwin-x64@21.2.3': - resolution: {integrity: sha512-aSaK8Ic9nHTwSuNZZtaKCPIXgD6+Ss9UwkNMIXPLYiYLF+EdSDORHnHutmajZZ8HakoWCQPWvxfWv30zre6iqw==} + '@nx/nx-darwin-x64@22.3.3': + resolution: {integrity: sha512-6ZQ6rMqH8NY4Jz+Gc89D5bIH2NxZb5S/vaA4yJ9RrqAfl4QWchNFD5na+aRivSd+UdsYLPKKl6qohet5SE6vOg==} cpu: [x64] os: [darwin] - '@nx/nx-freebsd-x64@21.2.3': - resolution: {integrity: sha512-hFSbtaYM1gL+XQq88CkmwqeeabmFsLjpsBF+HFIv1UMAjb02ObrYHVVICmmin5c1NkBsEJcQzh3mf8PBSOHW8A==} + '@nx/nx-freebsd-x64@22.3.3': + resolution: {integrity: sha512-J/PP5pIOQtR7ZzrFwP6d6h0yfY7r9EravG2m940GsgzGbtZGYIDqnh5Wdt+4uBWPH8VpdNOwFqH0afELtJA3MA==} cpu: [x64] os: [freebsd] - '@nx/nx-linux-arm-gnueabihf@21.2.3': - resolution: {integrity: sha512-yRzt8dLwTpRP7655We9/ol+Ol+n52R9wsRRnxJFdWHyLrHguZF0dqiZ5rAFFzyvywaDP6CRoPuS7wqFT7K14bw==} + '@nx/nx-linux-arm-gnueabihf@22.3.3': + resolution: {integrity: sha512-/zn0altzM15S7qAgXMaB41vHkEn18HyTVUvRrjmmwaVqk9WfmDmqOQlGWoJ6XCbpvKQ8bh14RyhR9LGw1JJkNA==} cpu: [arm] os: [linux] - '@nx/nx-linux-arm64-gnu@21.2.3': - resolution: {integrity: sha512-5u8mmUogvrNn1xlJk8Y6AJg/g1h2bKxYSyWfxR2mazKj5wI/VgbHuxHAgMXB7WDW2tK5bEcrUTvO8V0DjZQhNA==} + '@nx/nx-linux-arm64-gnu@22.3.3': + resolution: {integrity: sha512-NmPeCexWIZHW9RM3lDdFENN9C3WtlQ5L4RSNFESIjreS921rgePhulsszYdGnHdcnKPYlBBJnX/NxVsfioBbnQ==} cpu: [arm64] os: [linux] - '@nx/nx-linux-arm64-musl@21.2.3': - resolution: {integrity: sha512-4huuq2iuCBOWmJQw60gk5g3yjeHxFzwdDZJPM0680fZ7Pa/haPwamkR6kE2U6aFtFMhi1QVGPEoj4v4vE4ZS5g==} + '@nx/nx-linux-arm64-musl@22.3.3': + resolution: {integrity: sha512-K02U88Q0dpvCfmSXXvY7KbYQSa1m+mkYeqDBRHp11yHk1GoIqaHp8oEWda7FV4gsriNExPSS5tX1/QGVoLZrCw==} cpu: [arm64] os: [linux] - '@nx/nx-linux-x64-gnu@21.2.3': - resolution: {integrity: sha512-qWpJXpF8vjOrZTkgSC8kQAnIh0pIFbsisePicYWj5U9szJYyTUvVbjMAvdUPH4Z3bnrUtt+nzf9mpFCJRLjsOQ==} + '@nx/nx-linux-x64-gnu@22.3.3': + resolution: {integrity: sha512-04TEbvgwRaB9ifr39YwJmWh3RuXb4Ry4m84SOJyjNXAfPrepcWgfIQn1VL2ul1Ybq+P023dLO9ME8uqFh6j1YQ==} cpu: [x64] os: [linux] - '@nx/nx-linux-x64-musl@21.2.3': - resolution: {integrity: sha512-JZHlovF9uzvN3blImysYJmG90/8ookr3jOmEFxmP4RfMUl6EdN9yBLBdx0zIG2ulh7+WQrR3eQ1qrmsWFb6oiw==} + '@nx/nx-linux-x64-musl@22.3.3': + resolution: {integrity: sha512-uxBXx5q+S5OGatbYDxnamsKXRKlYn+Eq1nrCAHaf8rIfRoHlDiRV2PqtWuF+O2pxR5FWKpvr+/sZtt9rAf7KMw==} cpu: [x64] os: [linux] - '@nx/nx-win32-arm64-msvc@21.2.3': - resolution: {integrity: sha512-8Q1ljgFle6F2ZGSe6dLBItSdvYXjO0n2ovZI0zIih9+5OGLdN8wf6iONQJT7he2YST1dowIDPNWdeKiuOzPo6w==} + '@nx/nx-win32-arm64-msvc@22.3.3': + resolution: {integrity: sha512-aOwlfD6ZA1K6hjZtbhBSp7s1yi3sHbMpLCa4stXzfhCCpKUv46HU/EdiWdE1N8AsyNFemPZFq81k1VTowcACdg==} cpu: [arm64] os: [win32] - '@nx/nx-win32-x64-msvc@21.2.3': - resolution: {integrity: sha512-qJpHIZU/D48+EZ2bH02/LIFIkANYryGbcbNQUqC+pYA8ZPCU0wMqZVn4UcNMoI9K4YtXe/SvSBdjiObDuRb8yw==} + '@nx/nx-win32-x64-msvc@22.3.3': + resolution: {integrity: sha512-EDR8BtqeDvVNQ+kPwnfeSfmerYetitU3tDkxOMIybjKJDh69U2JwTB8n9ARwNaZQbNk7sCGNRUSZFTbAAUKvuQ==} cpu: [x64] os: [win32] - '@nx/playwright@21.2.3': - resolution: {integrity: sha512-oFQifAMa4p/o6iHJC8TPKa6Qafyg/tWXnvFzRMId9ZbN/GpNz8yMXRqUXqup+kJ5hO2CAuxUrNr4VZdZC9fHYw==} + '@nx/playwright@22.3.3': + resolution: {integrity: sha512-tn+hQ3pnUQnhWy5iQeb3alqhKOu3LlHTOdqIf/59OLHVQ7d/1wkbODFYHtS/y4bRAtPNoDhukZpNI0orFepteA==} peerDependencies: '@playwright/test': ^1.36.0 peerDependenciesMeta: '@playwright/test': optional: true - '@nx/plugin@21.2.3': - resolution: {integrity: sha512-FJcHFesY47Lw5SSu5lXbcExYKXbgJCX0i7xvrjOd2wGgpw+PlAsGapIR1fxtEBqdy1ACF+yEoEMkKNDBHt+8vA==} + '@nx/plugin@22.3.3': + resolution: {integrity: sha512-Nlf74Q3eTMW8MyjOIG1WFZf4eGBTlhIz6S2jknpNhSzobLd0RGzrOroXsmVCgtZJOTtyFH32AqAobmdcyeKWpw==} + + '@nx/vite@22.3.3': + resolution: {integrity: sha512-JYtQeKJVID6Am65M1gDxCBLyO7pA6p/dBxnQyWEHsbJ5VLiOyCxr+W+YOE4p4roVlQxjAaCMqvtGH3cWnNQWxg==} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 + vitest: ^1.3.1 || ^2.0.0 || ^3.0.0 || ^4.0.0 - '@nx/vite@21.2.3': - resolution: {integrity: sha512-OgmrjnV6fuq/b8P7+KSPc0IKAOD7kE0gWZdNmL9Bzhn+NVew6mMVgGsuqH02twbucp3eEbnpCFQPCXso+5NJTw==} + '@nx/vitest@22.3.3': + resolution: {integrity: sha512-9BNwWadIfT5EAnEPXLM0n/ucuJ7IQyn+QRMUkUBt6wmms9f0OKMtLpiFxHIMrnQDf0eEk845jo21j7Og2cCZyA==} peerDependencies: - vite: ^5.0.0 || ^6.0.0 - vitest: ^1.3.1 || ^2.0.0 || ^3.0.0 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 + vitest: ^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 + peerDependenciesMeta: + vite: + optional: true + vitest: + optional: true - '@nx/web@21.2.3': - resolution: {integrity: sha512-QWkd7+8n7kvhoiB2vqBHBZ2Z383g60lOEl78FFBRCxbRYmUHSOqvhZXahfq/l5YU7DVbbCYsiPdL8KVK22hRMw==} + '@nx/web@22.3.3': + resolution: {integrity: sha512-0iuAxXCljxCAfQ5N4SffMuf0CuUFGJoO5nzOTqnZ60pRy+JIWZ+DXfh7bfHxTEcE3JQ6nT/hbZVLPMVNleoy7Q==} - '@nx/workspace@21.2.3': - resolution: {integrity: sha512-bC3J6pgXvL9JWyYmP7AOGCIZhtI6vmY1YLan1T+FFkSr7yyKvIwnnL9E68whQD5jcbJl1Mvu9l0lVlsVdQYF/g==} + '@nx/workspace@22.3.3': + resolution: {integrity: sha512-A7Qd1Yi/hp/VPvig6tV+JmlYVSA4WhckNkP1giYZoESpGLxRlpwINpd5ii3oafOlglUdEZ8AiS3X+RUg9QmCAQ==} '@octokit/action@6.1.0': resolution: {integrity: sha512-lo+nHx8kAV86bxvOVOI3vFjX3gXPd/L7guAUbvs3pUvnR2KC+R7yjBkA1uACt4gYhs4LcWP3AXSGQzsbeN2XXw==} @@ -2772,8 +2835,8 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@sinclair/typebox@0.34.47': + resolution: {integrity: sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==} '@sindresorhus/is@4.6.0': resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} @@ -2786,8 +2849,8 @@ packages: '@sinonjs/commons@3.0.1': resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - '@sinonjs/fake-timers@10.3.0': - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@sinonjs/fake-timers@13.0.5': + resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} @@ -2985,21 +3048,12 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/express-serve-static-core@4.19.7': - resolution: {integrity: sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==} - '@types/express-serve-static-core@5.1.0': resolution: {integrity: sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==} - '@types/express@4.17.23': - resolution: {integrity: sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==} - '@types/express@5.0.5': resolution: {integrity: sha512-LuIQOcb6UmnF7C1PCFmEU1u2hmiHL43fgFQX67sN3H4Z+0Yk0Neo++mFsBjhOAuLzvlQeqAAkeDOZrJs9rzumQ==} - '@types/graceful-fs@4.1.9': - resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} - '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} @@ -3142,6 +3196,104 @@ packages: resolution: {integrity: sha512-uk574k8IU0rOF/AjniX8qbLSGURJVUCeM5e4MIMKBFFi8weeiLrG1fyQejyLXQpRZbU/1BuQasleV/RfHC3hHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + cpu: [ppc64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + cpu: [s390x] + os: [linux] + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + cpu: [x64] + os: [win32] + '@verdaccio/auth@8.0.0-next-8.24': resolution: {integrity: sha512-stRp0DdTTx3p6dnh2cKOPJZOhu6sZOf8evV2fpYtADYW0UyhhZwELBXukpa5WGQ3H3rWzsXSaccra+D7tB1LgA==} engines: {node: '>=18'} @@ -3221,74 +3373,48 @@ packages: resolution: {integrity: sha512-2e54Z1J1+OPM0LCxjkJHgwFm8jESsCYaX6ARs3+29hjoI75uiSphxFI3Hrhr+67ho/7Mtul0oyakK6l18MN/Dg==} engines: {node: '>=18'} - '@vitest/coverage-v8@1.6.1': - resolution: {integrity: sha512-6YeRZwuO4oTGKxD3bijok756oktHSIm3eczVVzNe3scqzuhLwltIF3S9ZL/vwOVIpURmU6SnZhziXXAfw8/Qlw==} - peerDependencies: - vitest: 1.6.1 - - '@vitest/coverage-v8@3.2.4': - resolution: {integrity: sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==} + '@vitest/coverage-v8@4.0.9': + resolution: {integrity: sha512-70oyhP+Q0HlWBIeGSP74YBw5KSjYhNgSCQjvmuQFciMqnyF36WL2cIkcT7XD85G4JPmBQitEMUsx+XMFv2AzQA==} peerDependencies: - '@vitest/browser': 3.2.4 - vitest: 3.2.4 + '@vitest/browser': 4.0.9 + vitest: 4.0.9 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@1.6.1': - resolution: {integrity: sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==} - - '@vitest/expect@3.2.4': - resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + '@vitest/expect@4.0.9': + resolution: {integrity: sha512-C2vyXf5/Jfj1vl4DQYxjib3jzyuswMi/KHHVN2z+H4v16hdJ7jMZ0OGe3uOVIt6LyJsAofDdaJNIFEpQcrSTFw==} - '@vitest/mocker@3.2.4': - resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + '@vitest/mocker@4.0.9': + resolution: {integrity: sha512-PUyaowQFHW+9FKb4dsvvBM4o025rWMlEDXdWRxIOilGaHREYTi5Q2Rt9VCgXgPy/hHZu1LeuXtrA/GdzOatP2g==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + vite: ^6.0.0 || ^7.0.0-0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@3.0.4': - resolution: {integrity: sha512-ts0fba+dEhK2aC9PFuZ9LTpULHpY/nd6jhAQ5IMU7Gaj7crPCTdCFfgvXxruRBLFS+MLraicCuFXxISEq8C93g==} + '@vitest/pretty-format@4.0.9': + resolution: {integrity: sha512-Hor0IBTwEi/uZqB7pvGepyElaM8J75pYjrrqbC8ZYMB9/4n5QA63KC15xhT+sqHpdGWfdnPo96E8lQUxs2YzSQ==} - '@vitest/pretty-format@3.2.4': - resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + '@vitest/runner@4.0.9': + resolution: {integrity: sha512-aF77tsXdEvIJRkj9uJZnHtovsVIx22Ambft9HudC+XuG/on1NY/bf5dlDti1N35eJT+QZLb4RF/5dTIG18s98w==} - '@vitest/runner@1.6.1': - resolution: {integrity: sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==} + '@vitest/snapshot@4.0.9': + resolution: {integrity: sha512-r1qR4oYstPbnOjg0Vgd3E8ADJbi4ditCzqr+Z9foUrRhIy778BleNyZMeAJ2EjV+r4ASAaDsdciC9ryMy8xMMg==} - '@vitest/runner@3.2.4': - resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + '@vitest/spy@4.0.9': + resolution: {integrity: sha512-J9Ttsq0hDXmxmT8CUOWUr1cqqAj2FJRGTdyEjSR+NjoOGKEqkEWj+09yC0HhI8t1W6t4Ctqawl1onHgipJve1A==} - '@vitest/snapshot@1.6.1': - resolution: {integrity: sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==} - - '@vitest/snapshot@3.2.4': - resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} - - '@vitest/spy@1.6.1': - resolution: {integrity: sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==} - - '@vitest/spy@3.2.4': - resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} - - '@vitest/ui@3.0.4': - resolution: {integrity: sha512-e+s2F9e9FUURkZ5aFIe1Fi3Y8M7UF6gEuShcaV/ur7y/Ldri+1tzWQ1TJq9Vas42NXnXvCAIrU39Z4U2RyET6g==} + '@vitest/ui@4.0.9': + resolution: {integrity: sha512-6HV2HHl9aRJ09TlYj/WAQxaa797Ezb5u0LpgabthlASAUAWKgw/W1DSPX7t848mMZmIUvzZgnUHGIylAoYHP0w==} peerDependencies: - vitest: 3.0.4 + vitest: 4.0.9 - '@vitest/utils@1.6.1': - resolution: {integrity: sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==} - - '@vitest/utils@3.0.4': - resolution: {integrity: sha512-8BqC1ksYsHtbWH+DfpOAKrFw3jl3Uf9J7yeFh85Pz52IWuh1hBBtyfEbRNNZNjl8H8A5yMLH9/t+k7HIKzQcZQ==} - - '@vitest/utils@3.2.4': - resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + '@vitest/utils@4.0.9': + resolution: {integrity: sha512-cEol6ygTzY4rUPvNZM19sDf7zGa35IYTm9wfzkHoT/f5jX10IOY7QleWSOh5T0e3I3WVozwK5Asom79qW8DiuQ==} '@vue/compiler-core@3.5.24': resolution: {integrity: sha512-eDl5H57AOpNakGNAkFDH+y7kTqrQpJkZFXhWZQGyx/5Wh7B1uQYvcWkvZi11BDhscPgj8N7XV3oRwiPnx1Vrig==} @@ -3419,6 +3545,10 @@ packages: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + acorn-import-phases@1.0.4: resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} engines: {node: '>=10.13.0'} @@ -3576,9 +3706,6 @@ packages: resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} engines: {node: '>=0.8'} - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -3629,24 +3756,24 @@ packages: react-native-b4a: optional: true - babel-jest@29.7.0: - resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + babel-jest@30.2.0: + resolution: {integrity: sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: - '@babel/core': ^7.8.0 + '@babel/core': ^7.11.0 || ^8.0.0-0 babel-plugin-const-enum@1.2.0: resolution: {integrity: sha512-o1m/6iyyFnp9MRsK1dHF3bneqyf3AlM2q3A/YbgQr2pCat6B6XJVDv2TXqzfY2RYUi4mak6WAksSBPlyYGx9dg==} peerDependencies: '@babel/core': ^7.0.0-0 - babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} + babel-plugin-istanbul@7.0.1: + resolution: {integrity: sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==} + engines: {node: '>=12'} - babel-plugin-jest-hoist@29.6.3: - resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + babel-plugin-jest-hoist@30.2.0: + resolution: {integrity: sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} @@ -3681,11 +3808,11 @@ packages: peerDependencies: '@babel/core': ^7.0.0 || ^8.0.0-0 - babel-preset-jest@29.6.3: - resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + babel-preset-jest@30.2.0: + resolution: {integrity: sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: - '@babel/core': ^7.0.0 + '@babel/core': ^7.11.0 || ^8.0.0-beta.1 balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -3740,8 +3867,8 @@ packages: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - body-parser@2.2.0: - resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} + body-parser@2.2.2: + resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} engines: {node: '>=18'} brace-expansion@1.1.12: @@ -3784,10 +3911,6 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - cacheable-lookup@6.1.0: resolution: {integrity: sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww==} engines: {node: '>=10.6.0'} @@ -3845,12 +3968,8 @@ packages: caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - chai@4.5.0: - resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} - engines: {node: '>=4'} - - chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} chalk@2.4.2: @@ -3875,13 +3994,6 @@ packages: chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - - check-error@2.1.1: - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} - engines: {node: '>= 16'} - chrome-trace-event@1.0.4: resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} @@ -3890,8 +4002,12 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - cjs-module-lexer@1.4.3: - resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + ci-info@4.3.1: + resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} + engines: {node: '>=8'} + + cjs-module-lexer@2.2.0: + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} @@ -4026,6 +4142,10 @@ packages: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} + content-disposition@1.0.1: + resolution: {integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==} + engines: {node: '>=18'} + content-type@1.0.5: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} @@ -4060,6 +4180,10 @@ packages: cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + cookie@0.7.1: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} @@ -4238,14 +4362,6 @@ packages: babel-plugin-macros: optional: true - deep-eql@4.1.4: - resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} - engines: {node: '>=6'} - - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -4380,10 +4496,6 @@ packages: dezalgo@1.0.4: resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} @@ -4541,16 +4653,16 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - esbuild@0.25.12: resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} hasBin: true + esbuild@0.27.2: + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -4750,8 +4862,8 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} - exit@0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + exit-x@0.2.2: + resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} engines: {node: '>= 0.8.0'} expand-tilde@2.0.2: @@ -4762,9 +4874,9 @@ packages: resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} engines: {node: '>=12.0.0'} - expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + expect@30.2.0: + resolution: {integrity: sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} express-rate-limit@5.5.1: resolution: {integrity: sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==} @@ -4773,6 +4885,10 @@ packages: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} + express@5.2.1: + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} + engines: {node: '>= 18'} + ext-list@2.2.2: resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==} engines: {node: '>=0.10.0'} @@ -4886,6 +5002,10 @@ packages: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} + find-my-way-ts@0.1.6: resolution: {integrity: sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==} @@ -4969,6 +5089,10 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + front-matter@4.0.2: resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} @@ -5030,9 +5154,6 @@ packages: resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} engines: {node: '>=18'} - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -5221,10 +5342,6 @@ packages: resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} engines: {node: '>=0.10.0'} - hosted-git-info@7.0.2: - resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} - engines: {node: ^16.14.0 || >=18.0.0} - html-encoding-sniffer@3.0.0: resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} engines: {node: '>=12'} @@ -5243,6 +5360,10 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} @@ -5506,6 +5627,9 @@ packages: is-promise@2.2.2: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -5619,10 +5743,6 @@ packages: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} - istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - istanbul-lib-instrument@6.0.3: resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} engines: {node: '>=10'} @@ -5631,10 +5751,6 @@ packages: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} - istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - istanbul-lib-source-maps@5.0.6: resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} engines: {node: '>=10'} @@ -5651,64 +5767,60 @@ packages: engines: {node: '>=10'} hasBin: true - jest-canvas-mock@2.5.2: - resolution: {integrity: sha512-vgnpPupjOL6+L5oJXzxTxFrlGEIbHdZqFU+LFNdtLxZ3lRDCl17FlTMM7IatoRQkrcyOTMlDinjUguqmQ6bR2A==} - - jest-circus@29.7.0: - resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-circus@30.2.0: + resolution: {integrity: sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-config@29.7.0: - resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-config@30.2.0: + resolution: {integrity: sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: '@types/node': '*' + esbuild-register: '>=3.4.0' ts-node: '>=9.0.0' peerDependenciesMeta: '@types/node': optional: true + esbuild-register: + optional: true ts-node: optional: true - jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-docblock@29.7.0: - resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-diff@30.2.0: + resolution: {integrity: sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-each@29.7.0: - resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-docblock@30.2.0: + resolution: {integrity: sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-environment-node@29.7.0: - resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-each@30.2.0: + resolution: {integrity: sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-environment-node@30.2.0: + resolution: {integrity: sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-haste-map@29.7.0: - resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-haste-map@30.2.0: + resolution: {integrity: sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-leak-detector@29.7.0: - resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-leak-detector@30.2.0: + resolution: {integrity: sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-matcher-utils@30.2.0: + resolution: {integrity: sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-message-util@30.2.0: + resolution: {integrity: sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-mock@29.7.0: - resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-mock@30.2.0: + resolution: {integrity: sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-pnp-resolver@1.2.3: resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} @@ -5719,45 +5831,45 @@ packages: jest-resolve: optional: true - jest-regex-util@29.6.3: - resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-regex-util@30.0.1: + resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-resolve@29.7.0: - resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-resolve@30.2.0: + resolution: {integrity: sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-runner@29.7.0: - resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-runner@30.2.0: + resolution: {integrity: sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-runtime@29.7.0: - resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-runtime@30.2.0: + resolution: {integrity: sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-snapshot@29.7.0: - resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-snapshot@30.2.0: + resolution: {integrity: sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-util@30.2.0: + resolution: {integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-validate@29.7.0: - resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-validate@30.2.0: + resolution: {integrity: sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-watcher@29.7.0: - resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-watcher@30.2.0: + resolution: {integrity: sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-worker@27.5.1: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} - jest-worker@29.7.0: - resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-worker@30.2.0: + resolution: {integrity: sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} @@ -5769,10 +5881,6 @@ packages: js-tokens@9.0.1: resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} - js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - js-yaml@3.14.2: resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true @@ -5909,10 +6017,6 @@ packages: resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} engines: {node: '>=6.11.5'} - local-pkg@0.5.1: - resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} - engines: {node: '>=14'} - locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -5994,12 +6098,6 @@ packages: resolution: {integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==} engines: {node: '>=0.10.0'} - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - lowdb@1.0.0: resolution: {integrity: sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==} engines: {node: '>=4'} @@ -6042,8 +6140,8 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magicast@0.3.5: - resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + magicast@0.5.1: + resolution: {integrity: sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -6084,6 +6182,10 @@ packages: merge-descriptors@1.0.3: resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -6118,6 +6220,10 @@ packages: resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} engines: {node: '>= 0.6'} + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} @@ -6265,6 +6371,11 @@ packages: engines: {node: ^18 || >=20} hasBin: true + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -6276,6 +6387,10 @@ packages: resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} engines: {node: '>= 0.6'} + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} @@ -6332,10 +6447,6 @@ packages: resolution: {integrity: sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==} engines: {node: '>=14.16'} - npm-package-arg@11.0.1: - resolution: {integrity: sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==} - engines: {node: ^16.14.0 || >=18.0.0} - npm-run-path@2.0.2: resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} engines: {node: '>=4'} @@ -6348,8 +6459,8 @@ packages: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - nx@21.2.3: - resolution: {integrity: sha512-2wL/2fSmIbRWn6zXaQ/g3kj5DfEaTw/aJkPr6ozJh8BUq5iYKE+tS9oh0PjsVVwN6Pybe80Lu+mn9RgWyeV3xw==} + nx@22.3.3: + resolution: {integrity: sha512-pOxtKWUfvf0oD8Geqs8D89Q2xpstRTaSY+F6Ut/Wd0GnEjUjO32SS1ymAM6WggGPHDZN4qpNrd5cfIxQmAbRLg==} hasBin: true peerDependencies: '@swc-node/register': ^1.8.0 @@ -6480,10 +6591,6 @@ packages: resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - p-limit@5.0.0: - resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} - engines: {node: '>=18'} - p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -6578,23 +6685,16 @@ packages: path-to-regexp@6.3.0: resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + path-to-regexp@8.3.0: + resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} - peek-stream@1.1.3: resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==} @@ -6714,18 +6814,14 @@ packages: engines: {node: '>=14'} hasBin: true - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + pretty-format@30.2.0: + resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} pretty-ms@7.0.1: resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==} engines: {node: '>=10'} - proc-log@3.0.0: - resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -6777,6 +6873,10 @@ packages: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} + qs@6.14.1: + resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} + engines: {node: '>=0.6'} + quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} @@ -6968,6 +7068,10 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + run-async@2.4.1: resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} engines: {node: '>=0.12.0'} @@ -7057,6 +7161,10 @@ packages: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} + send@1.2.1: + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} + serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -7064,6 +7172,10 @@ packages: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} + serve-static@2.2.1: + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -7333,12 +7445,6 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-literal@2.1.1: - resolution: {integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==} - - strip-literal@3.1.0: - resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} - strtok3@10.3.4: resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==} engines: {node: '>=18'} @@ -7424,10 +7530,6 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} - test-exclude@7.0.1: - resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} - engines: {node: '>=18'} - text-decoder@1.2.3: resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} @@ -7458,24 +7560,8 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} - tinypool@0.8.4: - resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} - engines: {node: '>=14.0.0'} - - tinypool@1.1.1: - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} - engines: {node: '>=14.0.0'} - - tinyspy@2.2.1: - resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} - engines: {node: '>=14.0.0'} - - tinyspy@4.0.4: - resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + tinyrainbow@3.0.3: + resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} engines: {node: '>=14.0.0'} tldts-core@6.1.86: @@ -7671,6 +7757,11 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + uc.micro@2.1.0: resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} @@ -7750,6 +7841,9 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} + unrs-resolver@1.11.1: + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + until-async@3.0.2: resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} @@ -7828,60 +7922,19 @@ packages: resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} engines: {'0': node >=0.6.0} - vite-node@1.6.1: - resolution: {integrity: sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - - vite-node@3.2.4: - resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - - vite@5.4.21: - resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - - vite@6.4.1: - resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vite@7.3.1: + resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@types/node': ^20.19.0 || >=22.12.0 jiti: '>=1.21.0' - less: '*' + less: ^4.0.0 lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 terser: ^5.16.0 tsx: ^4.8.1 yaml: ^2.4.2 @@ -7909,46 +7962,23 @@ packages: yaml: optional: true - vitest-canvas-mock@0.3.3: - resolution: {integrity: sha512-3P968tYBpqYyzzOaVtqnmYjqbe13576/fkjbDEJSfQAkHtC5/UjuRHOhFEN/ZV5HVZIkaROBUWgazDKJ+Ibw+Q==} + vitest-canvas-mock@1.1.3: + resolution: {integrity: sha512-zlKJR776Qgd+bcACPh0Pq5MG3xWq+CdkACKY/wX4Jyija0BSz8LH3aCCgwFKYFwtm565+050YFEGG9Ki0gE/Hw==} peerDependencies: - vitest: '*' - - vitest@1.6.1: - resolution: {integrity: sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 1.6.1 - '@vitest/ui': 1.6.1 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@types/node': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true + vitest: ^3.0.0 || ^4.0.0 - vitest@3.2.4: - resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vitest@4.0.9: + resolution: {integrity: sha512-E0Ja2AX4th+CG33yAFRC+d1wFx2pzU5r6HtG6LiPSE04flaE0qB6YyjSw9ZcpJAtVPfsvZGtJlKWZpuW7EHRxg==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.2.4 - '@vitest/ui': 3.2.4 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.0.9 + '@vitest/browser-preview': 4.0.9 + '@vitest/browser-webdriverio': 4.0.9 + '@vitest/ui': 4.0.9 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -7958,7 +7988,11 @@ packages: optional: true '@types/node': optional: true - '@vitest/browser': + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': optional: true '@vitest/ui': optional: true @@ -8088,9 +8122,9 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} ws@8.18.3: resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} @@ -8188,11 +8222,6 @@ snapshots: '@altano/repository-tools@0.1.1': {} - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - '@asamuzakjp/css-color@4.0.5': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) @@ -8968,8 +8997,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/runtime@7.28.4': {} - '@babel/runtime@7.28.6': {} '@babel/template@7.27.2': @@ -9438,10 +9465,10 @@ snapshots: dependencies: effect: 3.19.3 - '@effect/vitest@0.23.13(effect@3.19.3)(vitest@3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))': + '@effect/vitest@0.23.13(effect@3.19.3)(vitest@4.0.9)': dependencies: effect: 3.19.3 - vitest: 3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + vitest: 4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) '@effect/workflow@0.8.3(@effect/platform@0.90.10(effect@3.19.3))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.19.3))(effect@3.19.3))(effect@3.19.3)': dependencies: @@ -9462,153 +9489,162 @@ snapshots: dependencies: tslib: 2.8.1 - '@esbuild/aix-ppc64@0.21.5': - optional: true - '@esbuild/aix-ppc64@0.25.12': optional: true - '@esbuild/android-arm64@0.21.5': + '@esbuild/aix-ppc64@0.27.2': optional: true '@esbuild/android-arm64@0.25.12': optional: true - '@esbuild/android-arm@0.21.5': + '@esbuild/android-arm64@0.27.2': optional: true '@esbuild/android-arm@0.25.12': optional: true - '@esbuild/android-x64@0.21.5': + '@esbuild/android-arm@0.27.2': optional: true '@esbuild/android-x64@0.25.12': optional: true - '@esbuild/darwin-arm64@0.21.5': + '@esbuild/android-x64@0.27.2': optional: true '@esbuild/darwin-arm64@0.25.12': optional: true - '@esbuild/darwin-x64@0.21.5': + '@esbuild/darwin-arm64@0.27.2': optional: true '@esbuild/darwin-x64@0.25.12': optional: true - '@esbuild/freebsd-arm64@0.21.5': + '@esbuild/darwin-x64@0.27.2': optional: true '@esbuild/freebsd-arm64@0.25.12': optional: true - '@esbuild/freebsd-x64@0.21.5': + '@esbuild/freebsd-arm64@0.27.2': optional: true '@esbuild/freebsd-x64@0.25.12': optional: true - '@esbuild/linux-arm64@0.21.5': + '@esbuild/freebsd-x64@0.27.2': optional: true '@esbuild/linux-arm64@0.25.12': optional: true - '@esbuild/linux-arm@0.21.5': + '@esbuild/linux-arm64@0.27.2': optional: true '@esbuild/linux-arm@0.25.12': optional: true - '@esbuild/linux-ia32@0.21.5': + '@esbuild/linux-arm@0.27.2': optional: true '@esbuild/linux-ia32@0.25.12': optional: true - '@esbuild/linux-loong64@0.21.5': + '@esbuild/linux-ia32@0.27.2': optional: true '@esbuild/linux-loong64@0.25.12': optional: true - '@esbuild/linux-mips64el@0.21.5': + '@esbuild/linux-loong64@0.27.2': optional: true '@esbuild/linux-mips64el@0.25.12': optional: true - '@esbuild/linux-ppc64@0.21.5': + '@esbuild/linux-mips64el@0.27.2': optional: true '@esbuild/linux-ppc64@0.25.12': optional: true - '@esbuild/linux-riscv64@0.21.5': + '@esbuild/linux-ppc64@0.27.2': optional: true '@esbuild/linux-riscv64@0.25.12': optional: true - '@esbuild/linux-s390x@0.21.5': + '@esbuild/linux-riscv64@0.27.2': optional: true '@esbuild/linux-s390x@0.25.12': optional: true - '@esbuild/linux-x64@0.21.5': + '@esbuild/linux-s390x@0.27.2': optional: true '@esbuild/linux-x64@0.25.12': optional: true + '@esbuild/linux-x64@0.27.2': + optional: true + '@esbuild/netbsd-arm64@0.25.12': optional: true - '@esbuild/netbsd-x64@0.21.5': + '@esbuild/netbsd-arm64@0.27.2': optional: true '@esbuild/netbsd-x64@0.25.12': optional: true + '@esbuild/netbsd-x64@0.27.2': + optional: true + '@esbuild/openbsd-arm64@0.25.12': optional: true - '@esbuild/openbsd-x64@0.21.5': + '@esbuild/openbsd-arm64@0.27.2': optional: true '@esbuild/openbsd-x64@0.25.12': optional: true + '@esbuild/openbsd-x64@0.27.2': + optional: true + '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/sunos-x64@0.21.5': + '@esbuild/openharmony-arm64@0.27.2': optional: true '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/win32-arm64@0.21.5': + '@esbuild/sunos-x64@0.27.2': optional: true '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/win32-ia32@0.21.5': + '@esbuild/win32-arm64@0.27.2': optional: true '@esbuild/win32-ia32@0.25.12': optional: true - '@esbuild/win32-x64@0.21.5': + '@esbuild/win32-ia32@0.27.2': optional: true '@esbuild/win32-x64@0.25.12': optional: true + '@esbuild/win32-x64@0.27.2': + optional: true + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@2.6.1))': dependencies: eslint: 9.39.1(jiti@2.6.1) @@ -9736,127 +9772,143 @@ snapshots: '@istanbuljs/schema@0.1.3': {} - '@jest/console@29.7.0': + '@jest/console@30.2.0': dependencies: - '@jest/types': 29.6.3 + '@jest/types': 30.2.0 '@types/node': 24.9.2 chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 + jest-message-util: 30.2.0 + jest-util: 30.2.0 slash: 3.0.0 - '@jest/environment@29.7.0': + '@jest/diff-sequences@30.0.1': {} + + '@jest/environment@30.2.0': dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 + '@jest/fake-timers': 30.2.0 + '@jest/types': 30.2.0 '@types/node': 24.9.2 - jest-mock: 29.7.0 + jest-mock: 30.2.0 - '@jest/expect-utils@29.7.0': + '@jest/expect-utils@30.2.0': dependencies: - jest-get-type: 29.6.3 + '@jest/get-type': 30.1.0 - '@jest/expect@29.7.0': + '@jest/expect@30.2.0': dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 + expect: 30.2.0 + jest-snapshot: 30.2.0 transitivePeerDependencies: - supports-color - '@jest/fake-timers@29.7.0': + '@jest/fake-timers@30.2.0': dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 + '@jest/types': 30.2.0 + '@sinonjs/fake-timers': 13.0.5 '@types/node': 24.9.2 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 + jest-message-util: 30.2.0 + jest-mock: 30.2.0 + jest-util: 30.2.0 + + '@jest/get-type@30.1.0': {} - '@jest/globals@29.7.0': + '@jest/globals@30.2.0': dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 + '@jest/environment': 30.2.0 + '@jest/expect': 30.2.0 + '@jest/types': 30.2.0 + jest-mock: 30.2.0 transitivePeerDependencies: - supports-color - '@jest/reporters@29.7.0': + '@jest/pattern@30.0.1': + dependencies: + '@types/node': 24.9.2 + jest-regex-util: 30.0.1 + + '@jest/reporters@30.2.0': dependencies: '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 + '@jest/console': 30.2.0 + '@jest/test-result': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 '@jridgewell/trace-mapping': 0.3.31 '@types/node': 24.9.2 chalk: 4.1.2 collect-v8-coverage: 1.0.3 - exit: 0.1.2 - glob: 7.2.3 + exit-x: 0.2.2 + glob: 10.4.5 graceful-fs: 4.2.11 istanbul-lib-coverage: 3.2.2 istanbul-lib-instrument: 6.0.3 istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 + istanbul-lib-source-maps: 5.0.6 istanbul-reports: 3.2.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 + jest-message-util: 30.2.0 + jest-util: 30.2.0 + jest-worker: 30.2.0 slash: 3.0.0 string-length: 4.0.2 - strip-ansi: 6.0.1 v8-to-istanbul: 9.3.0 transitivePeerDependencies: - supports-color - '@jest/schemas@29.6.3': + '@jest/schemas@30.0.5': + dependencies: + '@sinclair/typebox': 0.34.47 + + '@jest/snapshot-utils@30.2.0': dependencies: - '@sinclair/typebox': 0.27.8 + '@jest/types': 30.2.0 + chalk: 4.1.2 + graceful-fs: 4.2.11 + natural-compare: 1.4.0 - '@jest/source-map@29.6.3': + '@jest/source-map@30.0.1': dependencies: '@jridgewell/trace-mapping': 0.3.31 callsites: 3.1.0 graceful-fs: 4.2.11 - '@jest/test-result@29.7.0': + '@jest/test-result@30.2.0': dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 + '@jest/console': 30.2.0 + '@jest/types': 30.2.0 '@types/istanbul-lib-coverage': 2.0.6 collect-v8-coverage: 1.0.3 - '@jest/test-sequencer@29.7.0': + '@jest/test-sequencer@30.2.0': dependencies: - '@jest/test-result': 29.7.0 + '@jest/test-result': 30.2.0 graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 + jest-haste-map: 30.2.0 slash: 3.0.0 - '@jest/transform@29.7.0': + '@jest/transform@30.2.0': dependencies: '@babel/core': 7.28.5 - '@jest/types': 29.6.3 + '@jest/types': 30.2.0 '@jridgewell/trace-mapping': 0.3.31 - babel-plugin-istanbul: 6.1.1 + babel-plugin-istanbul: 7.0.1 chalk: 4.1.2 convert-source-map: 2.0.0 fast-json-stable-stringify: 2.1.0 graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 + jest-haste-map: 30.2.0 + jest-regex-util: 30.0.1 + jest-util: 30.2.0 micromatch: 4.0.8 pirates: 4.0.7 slash: 3.0.0 - write-file-atomic: 4.0.2 + write-file-atomic: 5.0.1 transitivePeerDependencies: - supports-color - '@jest/types@29.6.3': + '@jest/types@30.2.0': dependencies: - '@jest/schemas': 29.6.3 + '@jest/pattern': 30.0.1 + '@jest/schemas': 30.0.5 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 '@types/node': 24.9.2 @@ -10041,22 +10093,29 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 - '@nx/devkit@21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))': + '@nx/devkit@22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))': dependencies: + '@zkochan/js-yaml': 0.0.7 ejs: 3.1.10 enquirer: 2.3.6 - ignore: 5.3.2 minimatch: 9.0.3 - nx: 21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)) + nx: 22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)) semver: 7.7.3 - tmp: 0.2.5 tslib: 2.8.1 yargs-parser: 21.1.1 - '@nx/eslint-plugin@21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))': + '@nx/docker@22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))': + dependencies: + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + enquirer: 2.3.6 + tslib: 2.8.1 + transitivePeerDependencies: + - nx + + '@nx/eslint-plugin@22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))': dependencies: - '@nx/devkit': 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) - '@nx/js': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/js': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.8.3) '@typescript-eslint/parser': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) '@typescript-eslint/type-utils': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) @@ -10080,14 +10139,14 @@ snapshots: - typescript - verdaccio - '@nx/eslint@21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0))': + '@nx/eslint@22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0))': dependencies: - '@nx/devkit': 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) - '@nx/js': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/js': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) eslint: 9.39.1(jiti@2.6.1) semver: 7.7.3 tslib: 2.8.1 - typescript: 5.8.3 + typescript: 5.9.3 optionalDependencies: '@zkochan/js-yaml': 0.0.7 transitivePeerDependencies: @@ -10099,11 +10158,11 @@ snapshots: - supports-color - verdaccio - '@nx/express@21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(express@4.21.2)(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))': + '@nx/express@22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(express@4.21.2)(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))': dependencies: - '@nx/devkit': 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) - '@nx/js': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) - '@nx/node': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/js': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/node': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) tslib: 2.8.1 optionalDependencies: express: 4.21.2 @@ -10115,6 +10174,7 @@ snapshots: - '@zkochan/js-yaml' - babel-plugin-macros - debug + - esbuild-register - eslint - node-notifier - nx @@ -10123,17 +10183,17 @@ snapshots: - typescript - verdaccio - '@nx/jest@21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))': + '@nx/jest@22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))': dependencies: - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@nx/devkit': 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) - '@nx/js': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@jest/reporters': 30.2.0 + '@jest/test-result': 30.2.0 + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/js': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.8.3) identity-obj-proxy: 3.0.0 - jest-config: 29.7.0(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3)) - jest-resolve: 29.7.0 - jest-util: 29.7.0 + jest-config: 30.2.0(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3)) + jest-resolve: 30.2.0 + jest-util: 30.2.0 minimatch: 9.0.3 picocolors: 1.1.1 resolve.exports: 2.0.3 @@ -10147,6 +10207,7 @@ snapshots: - '@types/node' - babel-plugin-macros - debug + - esbuild-register - node-notifier - nx - supports-color @@ -10154,7 +10215,7 @@ snapshots: - typescript - verdaccio - '@nx/js@21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0))': + '@nx/js@22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-proposal-decorators': 7.28.0(@babel/core@7.28.5) @@ -10162,9 +10223,9 @@ snapshots: '@babel/plugin-transform-runtime': 7.28.5(@babel/core@7.28.5) '@babel/preset-env': 7.28.5(@babel/core@7.28.5) '@babel/preset-typescript': 7.28.5(@babel/core@7.28.5) - '@babel/runtime': 7.28.4 - '@nx/devkit': 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) - '@nx/workspace': 21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)) + '@babel/runtime': 7.28.6 + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/workspace': 22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)) '@zkochan/js-yaml': 0.0.7 babel-plugin-const-enum: 1.2.0(@babel/core@7.28.5) babel-plugin-macros: 3.1.0 @@ -10172,13 +10233,10 @@ snapshots: chalk: 4.1.2 columnify: 1.6.0 detect-port: 1.6.1 - enquirer: 2.3.6 ignore: 5.3.2 js-tokens: 4.0.0 jsonc-parser: 3.2.0 - npm-package-arg: 11.0.1 npm-run-path: 4.0.1 - ora: 5.3.0 picocolors: 1.1.1 picomatch: 4.0.2 semver: 7.7.3 @@ -10195,12 +10253,13 @@ snapshots: - nx - supports-color - '@nx/node@21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))': + '@nx/node@22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))': dependencies: - '@nx/devkit': 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) - '@nx/eslint': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) - '@nx/jest': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) - '@nx/js': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/docker': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/eslint': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/jest': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/js': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) kill-port: 1.6.1 tcp-port-used: 1.0.2 tslib: 2.8.1 @@ -10212,6 +10271,7 @@ snapshots: - '@zkochan/js-yaml' - babel-plugin-macros - debug + - esbuild-register - eslint - node-notifier - nx @@ -10220,42 +10280,41 @@ snapshots: - typescript - verdaccio - '@nx/nx-darwin-arm64@21.2.3': + '@nx/nx-darwin-arm64@22.3.3': optional: true - '@nx/nx-darwin-x64@21.2.3': + '@nx/nx-darwin-x64@22.3.3': optional: true - '@nx/nx-freebsd-x64@21.2.3': + '@nx/nx-freebsd-x64@22.3.3': optional: true - '@nx/nx-linux-arm-gnueabihf@21.2.3': + '@nx/nx-linux-arm-gnueabihf@22.3.3': optional: true - '@nx/nx-linux-arm64-gnu@21.2.3': + '@nx/nx-linux-arm64-gnu@22.3.3': optional: true - '@nx/nx-linux-arm64-musl@21.2.3': + '@nx/nx-linux-arm64-musl@22.3.3': optional: true - '@nx/nx-linux-x64-gnu@21.2.3': + '@nx/nx-linux-x64-gnu@22.3.3': optional: true - '@nx/nx-linux-x64-musl@21.2.3': + '@nx/nx-linux-x64-musl@22.3.3': optional: true - '@nx/nx-win32-arm64-msvc@21.2.3': + '@nx/nx-win32-arm64-msvc@22.3.3': optional: true - '@nx/nx-win32-x64-msvc@21.2.3': + '@nx/nx-win32-x64-msvc@22.3.3': optional: true - '@nx/playwright@21.2.3(@babel/traverse@7.28.5)(@playwright/test@1.56.1)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))': + '@nx/playwright@22.3.3(@babel/traverse@7.28.5)(@playwright/test@1.56.1)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0))': dependencies: - '@nx/devkit': 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) - '@nx/eslint': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) - '@nx/js': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) - '@phenomnomnominal/tsquery': 5.0.1(typescript@5.8.3) + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/eslint': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/js': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) minimatch: 9.0.3 tslib: 2.8.1 optionalDependencies: @@ -10269,15 +10328,14 @@ snapshots: - eslint - nx - supports-color - - typescript - verdaccio - '@nx/plugin@21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))': + '@nx/plugin@22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))': dependencies: - '@nx/devkit': 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) - '@nx/eslint': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) - '@nx/jest': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) - '@nx/js': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/eslint': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/jest': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/js': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) tslib: 2.8.1 transitivePeerDependencies: - '@babel/traverse' @@ -10287,6 +10345,7 @@ snapshots: - '@zkochan/js-yaml' - babel-plugin-macros - debug + - esbuild-register - eslint - node-notifier - nx @@ -10295,19 +10354,40 @@ snapshots: - typescript - verdaccio - '@nx/vite@21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)': + '@nx/vite@22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))(vite@7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.9)': dependencies: - '@nx/devkit': 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) - '@nx/js': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/js': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/vitest': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))(vite@7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.9) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.8.3) - '@swc/helpers': 0.5.17 ajv: 8.17.1 enquirer: 2.3.6 picomatch: 4.0.2 semver: 7.7.3 tsconfig-paths: 4.2.0 - vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - vitest: 3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + tslib: 2.8.1 + vite: 7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + vitest: 4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + transitivePeerDependencies: + - '@babel/traverse' + - '@swc-node/register' + - '@swc/core' + - debug + - nx + - supports-color + - typescript + - verdaccio + + '@nx/vitest@22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(typescript@5.8.3)(verdaccio@6.2.1(typanion@3.14.0))(vite@7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.9)': + dependencies: + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/js': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@phenomnomnominal/tsquery': 5.0.1(typescript@5.8.3) + semver: 7.7.3 + tslib: 2.8.1 + optionalDependencies: + vite: 7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + vitest: 4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -10318,10 +10398,10 @@ snapshots: - typescript - verdaccio - '@nx/web@21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0))': + '@nx/web@22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0))': dependencies: - '@nx/devkit': 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) - '@nx/js': 21.2.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/js': 22.3.3(@babel/traverse@7.28.5)(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)))(verdaccio@6.2.1(typanion@3.14.0)) detect-port: 1.6.1 http-server: 14.1.1 picocolors: 1.1.1 @@ -10335,14 +10415,15 @@ snapshots: - supports-color - verdaccio - '@nx/workspace@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))': + '@nx/workspace@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))': dependencies: - '@nx/devkit': 21.2.3(nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@nx/devkit': 22.3.3(nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17))) '@zkochan/js-yaml': 0.0.7 chalk: 4.1.2 enquirer: 2.3.6 - nx: 21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)) + nx: 22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)) picomatch: 4.0.2 + semver: 7.7.3 tslib: 2.8.1 yargs-parser: 21.1.1 transitivePeerDependencies: @@ -10697,7 +10778,7 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} - '@sinclair/typebox@0.27.8': {} + '@sinclair/typebox@0.34.47': {} '@sindresorhus/is@4.6.0': {} @@ -10707,7 +10788,7 @@ snapshots: dependencies: type-detect: 4.0.8 - '@sinonjs/fake-timers@10.3.0': + '@sinonjs/fake-timers@13.0.5': dependencies: '@sinonjs/commons': 3.0.1 @@ -10917,13 +10998,6 @@ snapshots: '@types/estree@1.0.8': {} - '@types/express-serve-static-core@4.19.7': - dependencies: - '@types/node': 24.9.2 - '@types/qs': 6.14.0 - '@types/range-parser': 1.2.7 - '@types/send': 1.2.1 - '@types/express-serve-static-core@5.1.0': dependencies: '@types/node': 24.9.2 @@ -10931,23 +11005,12 @@ snapshots: '@types/range-parser': 1.2.7 '@types/send': 1.2.1 - '@types/express@4.17.23': - dependencies: - '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 4.19.7 - '@types/qs': 6.14.0 - '@types/serve-static': 1.15.10 - '@types/express@5.0.5': dependencies: '@types/body-parser': 1.19.6 '@types/express-serve-static-core': 5.1.0 '@types/serve-static': 1.15.10 - '@types/graceful-fs@4.1.9': - dependencies: - '@types/node': 24.9.2 - '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.3 @@ -11129,6 +11192,67 @@ snapshots: '@typescript-eslint/types': 8.46.3 eslint-visitor-keys: 4.2.1 + '@ungap/structured-clone@1.3.0': {} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + optional: true + + '@unrs/resolver-binding-android-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + optional: true + '@verdaccio/auth@8.0.0-next-8.24': dependencies: '@verdaccio/config': 8.0.0-next-8.24 @@ -11289,138 +11413,84 @@ snapshots: lodash: 4.17.21 minimatch: 7.4.6 - '@vitest/coverage-v8@1.6.1(vitest@1.6.1(@types/node@24.9.2)(@vitest/ui@3.0.4)(jsdom@27.1.0)(terser@5.44.1))': + '@vitest/coverage-v8@4.0.9(vitest@4.0.9)': dependencies: - '@ampproject/remapping': 2.3.0 - '@bcoe/v8-coverage': 0.2.3 - debug: 4.4.3 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.6 - istanbul-reports: 3.2.0 - magic-string: 0.30.21 - magicast: 0.3.5 - picocolors: 1.1.1 - std-env: 3.10.0 - strip-literal: 2.1.1 - test-exclude: 6.0.0 - vitest: 1.6.1(@types/node@24.9.2)(@vitest/ui@3.0.4)(jsdom@27.1.0)(terser@5.44.1) - transitivePeerDependencies: - - supports-color - - '@vitest/coverage-v8@3.2.4(vitest@3.2.4)': - dependencies: - '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.0.9 ast-v8-to-istanbul: 0.3.8 debug: 4.4.3 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 istanbul-reports: 3.2.0 - magic-string: 0.30.21 - magicast: 0.3.5 + magicast: 0.5.1 std-env: 3.10.0 - test-exclude: 7.0.1 - tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + tinyrainbow: 3.0.3 + vitest: 4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - supports-color - '@vitest/expect@1.6.1': - dependencies: - '@vitest/spy': 1.6.1 - '@vitest/utils': 1.6.1 - chai: 4.5.0 - - '@vitest/expect@3.2.4': + '@vitest/expect@4.0.9': dependencies: + '@standard-schema/spec': 1.0.0 '@types/chai': 5.2.3 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 - chai: 5.3.3 - tinyrainbow: 2.0.0 + '@vitest/spy': 4.0.9 + '@vitest/utils': 4.0.9 + chai: 6.2.2 + tinyrainbow: 3.0.3 - '@vitest/mocker@3.2.4(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))': + '@vitest/mocker@4.0.9(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))': dependencies: - '@vitest/spy': 3.2.4 + '@vitest/spy': 4.0.9 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.12.1(@types/node@24.9.2)(typescript@5.8.3) - vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - - '@vitest/pretty-format@3.0.4': - dependencies: - tinyrainbow: 2.0.0 + vite: 7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - '@vitest/pretty-format@3.2.4': + '@vitest/mocker@4.0.9(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))': dependencies: - tinyrainbow: 2.0.0 + '@vitest/spy': 4.0.9 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + msw: 2.12.1(@types/node@24.9.2)(typescript@5.9.3) + vite: 7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - '@vitest/runner@1.6.1': + '@vitest/pretty-format@4.0.9': dependencies: - '@vitest/utils': 1.6.1 - p-limit: 5.0.0 - pathe: 1.1.2 + tinyrainbow: 3.0.3 - '@vitest/runner@3.2.4': + '@vitest/runner@4.0.9': dependencies: - '@vitest/utils': 3.2.4 + '@vitest/utils': 4.0.9 pathe: 2.0.3 - strip-literal: 3.1.0 - - '@vitest/snapshot@1.6.1': - dependencies: - magic-string: 0.30.21 - pathe: 1.1.2 - pretty-format: 29.7.0 - '@vitest/snapshot@3.2.4': + '@vitest/snapshot@4.0.9': dependencies: - '@vitest/pretty-format': 3.2.4 + '@vitest/pretty-format': 4.0.9 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@1.6.1': - dependencies: - tinyspy: 2.2.1 - - '@vitest/spy@3.2.4': - dependencies: - tinyspy: 4.0.4 + '@vitest/spy@4.0.9': {} - '@vitest/ui@3.0.4(vitest@3.2.4)': + '@vitest/ui@4.0.9(vitest@4.0.9)': dependencies: - '@vitest/utils': 3.0.4 + '@vitest/utils': 4.0.9 fflate: 0.8.2 flatted: 3.3.3 pathe: 2.0.3 sirv: 3.0.2 tinyglobby: 0.2.15 - tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + tinyrainbow: 3.0.3 + vitest: 4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - '@vitest/utils@1.6.1': + '@vitest/utils@4.0.9': dependencies: - diff-sequences: 29.6.3 - estree-walker: 3.0.3 - loupe: 2.3.7 - pretty-format: 29.7.0 + '@vitest/pretty-format': 4.0.9 + tinyrainbow: 3.0.3 - '@vitest/utils@3.0.4': - dependencies: - '@vitest/pretty-format': 3.0.4 - loupe: 3.2.1 - tinyrainbow: 2.0.0 - - '@vitest/utils@3.2.4': - dependencies: - '@vitest/pretty-format': 3.2.4 - loupe: 3.2.1 - tinyrainbow: 2.0.0 - - '@vue/compiler-core@3.5.24': + '@vue/compiler-core@3.5.24': dependencies: '@babel/parser': 7.28.5 '@vue/shared': 3.5.24 @@ -11631,7 +11701,7 @@ snapshots: '@yarnpkg/parsers@3.0.2': dependencies: - js-yaml: 3.14.1 + js-yaml: 3.14.2 tslib: 2.8.1 '@zkochan/js-yaml@0.0.7': @@ -11652,6 +11722,11 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 + accepts@2.0.0: + dependencies: + mime-types: 3.0.1 + negotiator: 1.0.0 + acorn-import-phases@1.0.4(acorn@8.15.0): dependencies: acorn: 8.15.0 @@ -11810,8 +11885,6 @@ snapshots: assert-plus@1.0.0: {} - assertion-error@1.1.0: {} - assertion-error@2.0.1: {} ast-module-types@6.0.1: {} @@ -11850,13 +11923,13 @@ snapshots: b4a@1.7.3: {} - babel-jest@29.7.0(@babel/core@7.28.5): + babel-jest@30.2.0(@babel/core@7.28.5): dependencies: '@babel/core': 7.28.5 - '@jest/transform': 29.7.0 + '@jest/transform': 30.2.0 '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.28.5) + babel-plugin-istanbul: 7.0.1 + babel-preset-jest: 30.2.0(@babel/core@7.28.5) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -11872,26 +11945,23 @@ snapshots: transitivePeerDependencies: - supports-color - babel-plugin-istanbul@6.1.1: + babel-plugin-istanbul@7.0.1: dependencies: '@babel/helper-plugin-utils': 7.27.1 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 + istanbul-lib-instrument: 6.0.3 test-exclude: 6.0.0 transitivePeerDependencies: - supports-color - babel-plugin-jest-hoist@29.6.3: + babel-plugin-jest-hoist@30.2.0: dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.28.0 babel-plugin-macros@3.1.0: dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 cosmiconfig: 7.1.0 resolve: 1.22.11 @@ -11945,10 +12015,10 @@ snapshots: '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.5) '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.5) - babel-preset-jest@29.6.3(@babel/core@7.28.5): + babel-preset-jest@30.2.0(@babel/core@7.28.5): dependencies: '@babel/core': 7.28.5 - babel-plugin-jest-hoist: 29.6.3 + babel-plugin-jest-hoist: 30.2.0 babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.5) balanced-match@1.0.2: {} @@ -12013,15 +12083,15 @@ snapshots: transitivePeerDependencies: - supports-color - body-parser@2.2.0: + body-parser@2.2.2: dependencies: bytes: 3.1.2 content-type: 1.0.5 - debug: 4.4.1 + debug: 4.4.3 http-errors: 2.0.0 - iconv-lite: 0.6.3 + iconv-lite: 0.7.2 on-finished: 2.4.1 - qs: 6.14.0 + qs: 6.14.1 raw-body: 3.0.1 type-is: 2.0.1 transitivePeerDependencies: @@ -12074,8 +12144,6 @@ snapshots: bytes@3.1.2: {} - cac@6.7.14: {} - cacheable-lookup@6.1.0: {} cacheable-lookup@7.0.0: {} @@ -12133,23 +12201,7 @@ snapshots: caseless@0.12.0: {} - chai@4.5.0: - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.4 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.1.0 - - chai@5.3.3: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.1 - deep-eql: 5.0.2 - loupe: 3.2.1 - pathval: 2.0.1 + chai@6.2.2: {} chalk@2.4.2: dependencies: @@ -12170,17 +12222,13 @@ snapshots: chardet@2.1.1: {} - check-error@1.0.3: - dependencies: - get-func-name: 2.0.2 - - check-error@2.1.1: {} - chrome-trace-event@1.0.4: {} ci-info@3.9.0: {} - cjs-module-lexer@1.4.3: {} + ci-info@4.3.1: {} + + cjs-module-lexer@2.2.0: {} cli-cursor@3.1.0: dependencies: @@ -12313,6 +12361,8 @@ snapshots: dependencies: safe-buffer: 5.2.1 + content-disposition@1.0.1: {} + content-type@1.0.5: {} conventional-changelog-angular@7.0.0: @@ -12345,6 +12395,8 @@ snapshots: cookie-signature@1.0.6: {} + cookie-signature@1.2.2: {} + cookie@0.7.1: {} cookie@0.7.2: {} @@ -12504,12 +12556,6 @@ snapshots: optionalDependencies: babel-plugin-macros: 3.1.0 - deep-eql@4.1.4: - dependencies: - type-detect: 4.1.0 - - deep-eql@5.0.2: {} - deep-extend@0.6.0: {} deep-is@0.1.4: {} @@ -12638,8 +12684,6 @@ snapshots: asap: 2.0.6 wrappy: 1.0.2 - diff-sequences@29.6.3: {} - diff@4.0.2: {} dir-glob@3.0.1: @@ -12834,32 +12878,6 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - esbuild@0.21.5: - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - esbuild@0.25.12: optionalDependencies: '@esbuild/aix-ppc64': 0.25.12 @@ -12889,6 +12907,35 @@ snapshots: '@esbuild/win32-ia32': 0.25.12 '@esbuild/win32-x64': 0.25.12 + esbuild@0.27.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.2 + '@esbuild/android-arm': 0.27.2 + '@esbuild/android-arm64': 0.27.2 + '@esbuild/android-x64': 0.27.2 + '@esbuild/darwin-arm64': 0.27.2 + '@esbuild/darwin-x64': 0.27.2 + '@esbuild/freebsd-arm64': 0.27.2 + '@esbuild/freebsd-x64': 0.27.2 + '@esbuild/linux-arm': 0.27.2 + '@esbuild/linux-arm64': 0.27.2 + '@esbuild/linux-ia32': 0.27.2 + '@esbuild/linux-loong64': 0.27.2 + '@esbuild/linux-mips64el': 0.27.2 + '@esbuild/linux-ppc64': 0.27.2 + '@esbuild/linux-riscv64': 0.27.2 + '@esbuild/linux-s390x': 0.27.2 + '@esbuild/linux-x64': 0.27.2 + '@esbuild/netbsd-arm64': 0.27.2 + '@esbuild/netbsd-x64': 0.27.2 + '@esbuild/openbsd-arm64': 0.27.2 + '@esbuild/openbsd-x64': 0.27.2 + '@esbuild/openharmony-arm64': 0.27.2 + '@esbuild/sunos-x64': 0.27.2 + '@esbuild/win32-arm64': 0.27.2 + '@esbuild/win32-ia32': 0.27.2 + '@esbuild/win32-x64': 0.27.2 + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -13134,7 +13181,7 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 - exit@0.1.2: {} + exit-x@0.2.2: {} expand-tilde@2.0.2: dependencies: @@ -13142,13 +13189,14 @@ snapshots: expect-type@1.2.2: {} - expect@29.7.0: + expect@30.2.0: dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 + '@jest/expect-utils': 30.2.0 + '@jest/get-type': 30.1.0 + jest-matcher-utils: 30.2.0 + jest-message-util: 30.2.0 + jest-mock: 30.2.0 + jest-util: 30.2.0 express-rate-limit@5.5.1: {} @@ -13188,6 +13236,39 @@ snapshots: transitivePeerDependencies: - supports-color + express@5.2.1: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.2 + content-disposition: 1.0.1 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.3 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.1 + fresh: 2.0.0 + http-errors: 2.0.0 + merge-descriptors: 2.0.0 + mime-types: 3.0.1 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.14.0 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 + statuses: 2.0.2 + type-is: 2.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + ext-list@2.2.2: dependencies: mime-db: 1.54.0 @@ -13312,6 +13393,17 @@ snapshots: transitivePeerDependencies: - supports-color + finalhandler@2.1.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + find-my-way-ts@0.1.6: {} find-node-modules@2.1.3: @@ -13392,9 +13484,11 @@ snapshots: fresh@0.5.2: {} + fresh@2.0.0: {} + front-matter@4.0.2: dependencies: - js-yaml: 3.14.1 + js-yaml: 3.14.2 fs-constants@1.0.0: {} @@ -13451,8 +13545,6 @@ snapshots: get-east-asian-width@1.4.0: {} - get-func-name@2.0.2: {} - get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -13676,10 +13768,6 @@ snapshots: dependencies: parse-passwd: 1.0.0 - hosted-git-info@7.0.2: - dependencies: - lru-cache: 10.4.3 - html-encoding-sniffer@3.0.0: dependencies: whatwg-encoding: 2.0.0 @@ -13700,6 +13788,14 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 @@ -13973,6 +14069,8 @@ snapshots: is-promise@2.2.2: {} + is-promise@4.0.0: {} + is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -14064,16 +14162,6 @@ snapshots: istanbul-lib-coverage@3.2.2: {} - istanbul-lib-instrument@5.2.1: - dependencies: - '@babel/core': 7.28.5 - '@babel/parser': 7.28.5 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - istanbul-lib-instrument@6.0.3: dependencies: '@babel/core': 7.28.5 @@ -14090,14 +14178,6 @@ snapshots: make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@4.0.1: - dependencies: - debug: 4.4.3 - istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - istanbul-lib-source-maps@5.0.6: dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -14123,59 +14203,56 @@ snapshots: filelist: 1.0.4 picocolors: 1.1.1 - jest-canvas-mock@2.5.2: + jest-circus@30.2.0(babel-plugin-macros@3.1.0): dependencies: - cssfontparser: 1.2.1 - moo-color: 1.0.3 - - jest-circus@29.7.0(babel-plugin-macros@3.1.0): - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 + '@jest/environment': 30.2.0 + '@jest/expect': 30.2.0 + '@jest/test-result': 30.2.0 + '@jest/types': 30.2.0 '@types/node': 24.9.2 chalk: 4.1.2 co: 4.6.0 dedent: 1.7.0(babel-plugin-macros@3.1.0) is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 + jest-each: 30.2.0 + jest-matcher-utils: 30.2.0 + jest-message-util: 30.2.0 + jest-runtime: 30.2.0 + jest-snapshot: 30.2.0 + jest-util: 30.2.0 p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.1.0 + pretty-format: 30.2.0 + pure-rand: 7.0.1 slash: 3.0.0 stack-utils: 2.0.6 transitivePeerDependencies: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3)): + jest-config@30.2.0(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@24.9.2)(typescript@5.8.3)): dependencies: '@babel/core': 7.28.5 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.28.5) + '@jest/get-type': 30.1.0 + '@jest/pattern': 30.0.1 + '@jest/test-sequencer': 30.2.0 + '@jest/types': 30.2.0 + babel-jest: 30.2.0(@babel/core@7.28.5) chalk: 4.1.2 - ci-info: 3.9.0 + ci-info: 4.3.1 deepmerge: 4.3.1 - glob: 7.2.3 + glob: 10.4.5 graceful-fs: 4.2.11 - jest-circus: 29.7.0(babel-plugin-macros@3.1.0) - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 + jest-circus: 30.2.0(babel-plugin-macros@3.1.0) + jest-docblock: 30.2.0 + jest-environment-node: 30.2.0 + jest-regex-util: 30.0.1 + jest-resolve: 30.2.0 + jest-runner: 30.2.0 + jest-util: 30.2.0 + jest-validate: 30.2.0 micromatch: 4.0.8 parse-json: 5.2.0 - pretty-format: 29.7.0 + pretty-format: 30.2.0 slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: @@ -14185,205 +14262,204 @@ snapshots: - babel-plugin-macros - supports-color - jest-diff@29.7.0: + jest-diff@30.2.0: dependencies: + '@jest/diff-sequences': 30.0.1 + '@jest/get-type': 30.1.0 chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 + pretty-format: 30.2.0 - jest-docblock@29.7.0: + jest-docblock@30.2.0: dependencies: detect-newline: 3.1.0 - jest-each@29.7.0: + jest-each@30.2.0: dependencies: - '@jest/types': 29.6.3 + '@jest/get-type': 30.1.0 + '@jest/types': 30.2.0 chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 + jest-util: 30.2.0 + pretty-format: 30.2.0 - jest-environment-node@29.7.0: + jest-environment-node@30.2.0: dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 + '@jest/environment': 30.2.0 + '@jest/fake-timers': 30.2.0 + '@jest/types': 30.2.0 '@types/node': 24.9.2 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - jest-get-type@29.6.3: {} + jest-mock: 30.2.0 + jest-util: 30.2.0 + jest-validate: 30.2.0 - jest-haste-map@29.7.0: + jest-haste-map@30.2.0: dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.9 + '@jest/types': 30.2.0 '@types/node': 24.9.2 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 + jest-regex-util: 30.0.1 + jest-util: 30.2.0 + jest-worker: 30.2.0 micromatch: 4.0.8 walker: 1.0.8 optionalDependencies: fsevents: 2.3.3 - jest-leak-detector@29.7.0: + jest-leak-detector@30.2.0: dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 + '@jest/get-type': 30.1.0 + pretty-format: 30.2.0 - jest-matcher-utils@29.7.0: + jest-matcher-utils@30.2.0: dependencies: + '@jest/get-type': 30.1.0 chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 + jest-diff: 30.2.0 + pretty-format: 30.2.0 - jest-message-util@29.7.0: + jest-message-util@30.2.0: dependencies: '@babel/code-frame': 7.27.1 - '@jest/types': 29.6.3 + '@jest/types': 30.2.0 '@types/stack-utils': 2.0.3 chalk: 4.1.2 graceful-fs: 4.2.11 micromatch: 4.0.8 - pretty-format: 29.7.0 + pretty-format: 30.2.0 slash: 3.0.0 stack-utils: 2.0.6 - jest-mock@29.7.0: + jest-mock@30.2.0: dependencies: - '@jest/types': 29.6.3 + '@jest/types': 30.2.0 '@types/node': 24.9.2 - jest-util: 29.7.0 + jest-util: 30.2.0 - jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + jest-pnp-resolver@1.2.3(jest-resolve@30.2.0): optionalDependencies: - jest-resolve: 29.7.0 + jest-resolve: 30.2.0 - jest-regex-util@29.6.3: {} + jest-regex-util@30.0.1: {} - jest-resolve@29.7.0: + jest-resolve@30.2.0: dependencies: chalk: 4.1.2 graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.11 - resolve.exports: 2.0.3 + jest-haste-map: 30.2.0 + jest-pnp-resolver: 1.2.3(jest-resolve@30.2.0) + jest-util: 30.2.0 + jest-validate: 30.2.0 slash: 3.0.0 + unrs-resolver: 1.11.1 - jest-runner@29.7.0: + jest-runner@30.2.0: dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 + '@jest/console': 30.2.0 + '@jest/environment': 30.2.0 + '@jest/test-result': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 '@types/node': 24.9.2 chalk: 4.1.2 emittery: 0.13.1 + exit-x: 0.2.2 graceful-fs: 4.2.11 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 + jest-docblock: 30.2.0 + jest-environment-node: 30.2.0 + jest-haste-map: 30.2.0 + jest-leak-detector: 30.2.0 + jest-message-util: 30.2.0 + jest-resolve: 30.2.0 + jest-runtime: 30.2.0 + jest-util: 30.2.0 + jest-watcher: 30.2.0 + jest-worker: 30.2.0 p-limit: 3.1.0 source-map-support: 0.5.13 transitivePeerDependencies: - supports-color - jest-runtime@29.7.0: + jest-runtime@30.2.0: dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 + '@jest/environment': 30.2.0 + '@jest/fake-timers': 30.2.0 + '@jest/globals': 30.2.0 + '@jest/source-map': 30.0.1 + '@jest/test-result': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 '@types/node': 24.9.2 chalk: 4.1.2 - cjs-module-lexer: 1.4.3 + cjs-module-lexer: 2.2.0 collect-v8-coverage: 1.0.3 - glob: 7.2.3 + glob: 10.4.5 graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 + jest-haste-map: 30.2.0 + jest-message-util: 30.2.0 + jest-mock: 30.2.0 + jest-regex-util: 30.0.1 + jest-resolve: 30.2.0 + jest-snapshot: 30.2.0 + jest-util: 30.2.0 slash: 3.0.0 strip-bom: 4.0.0 transitivePeerDependencies: - supports-color - jest-snapshot@29.7.0: + jest-snapshot@30.2.0: dependencies: '@babel/core': 7.28.5 '@babel/generator': 7.28.5 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) '@babel/types': 7.28.5 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 + '@jest/expect-utils': 30.2.0 + '@jest/get-type': 30.1.0 + '@jest/snapshot-utils': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.5) chalk: 4.1.2 - expect: 29.7.0 + expect: 30.2.0 graceful-fs: 4.2.11 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 + jest-diff: 30.2.0 + jest-matcher-utils: 30.2.0 + jest-message-util: 30.2.0 + jest-util: 30.2.0 + pretty-format: 30.2.0 semver: 7.7.3 + synckit: 0.11.11 transitivePeerDependencies: - supports-color - jest-util@29.7.0: + jest-util@30.2.0: dependencies: - '@jest/types': 29.6.3 + '@jest/types': 30.2.0 '@types/node': 24.9.2 chalk: 4.1.2 - ci-info: 3.9.0 + ci-info: 4.3.1 graceful-fs: 4.2.11 - picomatch: 2.3.1 + picomatch: 4.0.3 - jest-validate@29.7.0: + jest-validate@30.2.0: dependencies: - '@jest/types': 29.6.3 + '@jest/get-type': 30.1.0 + '@jest/types': 30.2.0 camelcase: 6.3.0 chalk: 4.1.2 - jest-get-type: 29.6.3 leven: 3.1.0 - pretty-format: 29.7.0 + pretty-format: 30.2.0 - jest-watcher@29.7.0: + jest-watcher@30.2.0: dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 + '@jest/test-result': 30.2.0 + '@jest/types': 30.2.0 '@types/node': 24.9.2 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 - jest-util: 29.7.0 + jest-util: 30.2.0 string-length: 4.0.2 jest-worker@27.5.1: @@ -14392,10 +14468,11 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest-worker@29.7.0: + jest-worker@30.2.0: dependencies: '@types/node': 24.9.2 - jest-util: 29.7.0 + '@ungap/structured-clone': 1.3.0 + jest-util: 30.2.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -14405,11 +14482,6 @@ snapshots: js-tokens@9.0.1: {} - js-yaml@3.14.1: - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - js-yaml@3.14.2: dependencies: argparse: 1.0.10 @@ -14506,7 +14578,7 @@ snapshots: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.7.2 + semver: 7.7.3 jsprim@2.0.2: dependencies: @@ -14580,11 +14652,6 @@ snapshots: loader-runner@4.3.1: {} - local-pkg@0.5.1: - dependencies: - mlly: 1.8.0 - pkg-types: 1.3.1 - locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -14652,12 +14719,6 @@ snapshots: longest@2.0.1: {} - loupe@2.3.7: - dependencies: - get-func-name: 2.0.2 - - loupe@3.2.1: {} - lowdb@1.0.0: dependencies: graceful-fs: 4.2.11 @@ -14705,7 +14766,7 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magicast@0.3.5: + magicast@0.5.1: dependencies: '@babel/parser': 7.28.5 '@babel/types': 7.28.5 @@ -14744,6 +14805,8 @@ snapshots: merge-descriptors@1.0.3: {} + merge-descriptors@2.0.0: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -14769,6 +14832,10 @@ snapshots: dependencies: mime-db: 1.54.0 + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + mime@1.6.0: {} mime@2.6.0: {} @@ -14888,6 +14955,32 @@ snapshots: typescript: 5.8.3 transitivePeerDependencies: - '@types/node' + optional: true + + msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3): + dependencies: + '@inquirer/confirm': 5.1.20(@types/node@24.9.2) + '@mswjs/interceptors': 0.40.0 + '@open-draft/deferred-promise': 2.2.0 + '@types/statuses': 2.0.6 + cookie: 1.0.2 + graphql: 16.12.0 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + picocolors: 1.1.1 + rettime: 0.7.0 + statuses: 2.0.2 + strict-event-emitter: 0.5.1 + tough-cookie: 6.0.0 + type-fest: 4.41.0 + until-async: 3.0.2 + yargs: 17.7.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@types/node' multipasta@0.2.7: {} @@ -14901,12 +14994,16 @@ snapshots: nanoid@5.1.6: {} + napi-postinstall@0.3.4: {} + natural-compare@1.4.0: {} negotiator@0.6.3: {} negotiator@0.6.4: {} + negotiator@1.0.0: {} + neo-async@2.6.2: {} nice-try@1.0.5: {} @@ -14942,13 +15039,6 @@ snapshots: normalize-url@8.1.0: {} - npm-package-arg@11.0.1: - dependencies: - hosted-git-info: 7.0.2 - proc-log: 3.0.0 - semver: 7.7.3 - validate-npm-package-name: 5.0.1 - npm-run-path@2.0.2: dependencies: path-key: 2.0.1 @@ -14961,7 +15051,7 @@ snapshots: dependencies: path-key: 4.0.0 - nx@21.2.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)): + nx@22.3.3(@swc-node/register@1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3))(@swc/core@1.11.21(@swc/helpers@0.5.17)): dependencies: '@napi-rs/wasm-runtime': 0.2.4 '@yarnpkg/lockfile': 1.1.0 @@ -14978,8 +15068,8 @@ snapshots: figures: 3.2.0 flat: 5.0.2 front-matter: 4.0.2 - ignore: 5.3.2 - jest-diff: 29.7.0 + ignore: 7.0.5 + jest-diff: 30.2.0 jsonc-parser: 3.2.0 lines-and-columns: 2.0.3 minimatch: 9.0.3 @@ -14999,16 +15089,16 @@ snapshots: yargs: 17.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@nx/nx-darwin-arm64': 21.2.3 - '@nx/nx-darwin-x64': 21.2.3 - '@nx/nx-freebsd-x64': 21.2.3 - '@nx/nx-linux-arm-gnueabihf': 21.2.3 - '@nx/nx-linux-arm64-gnu': 21.2.3 - '@nx/nx-linux-arm64-musl': 21.2.3 - '@nx/nx-linux-x64-gnu': 21.2.3 - '@nx/nx-linux-x64-musl': 21.2.3 - '@nx/nx-win32-arm64-msvc': 21.2.3 - '@nx/nx-win32-x64-msvc': 21.2.3 + '@nx/nx-darwin-arm64': 22.3.3 + '@nx/nx-darwin-x64': 22.3.3 + '@nx/nx-freebsd-x64': 22.3.3 + '@nx/nx-linux-arm-gnueabihf': 22.3.3 + '@nx/nx-linux-arm64-gnu': 22.3.3 + '@nx/nx-linux-arm64-musl': 22.3.3 + '@nx/nx-linux-x64-gnu': 22.3.3 + '@nx/nx-linux-x64-musl': 22.3.3 + '@nx/nx-win32-arm64-msvc': 22.3.3 + '@nx/nx-win32-x64-msvc': 22.3.3 '@swc-node/register': 1.10.10(@swc/core@1.11.21(@swc/helpers@0.5.17))(@swc/types@0.1.25)(typescript@5.8.3) '@swc/core': 1.11.21(@swc/helpers@0.5.17) transitivePeerDependencies: @@ -15163,10 +15253,6 @@ snapshots: dependencies: yocto-queue: 1.2.1 - p-limit@5.0.0: - dependencies: - yocto-queue: 1.2.1 - p-locate@4.1.0: dependencies: p-limit: 2.3.0 @@ -15239,16 +15325,12 @@ snapshots: path-to-regexp@6.3.0: {} - path-type@4.0.0: {} + path-to-regexp@8.3.0: {} - pathe@1.1.2: {} + path-type@4.0.0: {} pathe@2.0.3: {} - pathval@1.1.1: {} - - pathval@2.0.1: {} - peek-stream@1.1.3: dependencies: buffer-from: 1.1.2 @@ -15383,9 +15465,9 @@ snapshots: prettier@3.6.2: {} - pretty-format@29.7.0: + pretty-format@30.2.0: dependencies: - '@jest/schemas': 29.6.3 + '@jest/schemas': 30.0.5 ansi-styles: 5.2.0 react-is: 18.3.1 @@ -15393,8 +15475,6 @@ snapshots: dependencies: parse-ms: 2.1.0 - proc-log@3.0.0: {} - process-nextick-args@2.0.1: {} process-warning@1.0.0: {} @@ -15442,6 +15522,10 @@ snapshots: dependencies: side-channel: 1.1.0 + qs@6.14.1: + dependencies: + side-channel: 1.1.0 + quansync@0.2.11: {} query-registry@3.0.1: @@ -15672,6 +15756,16 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.53.2 fsevents: 2.3.3 + router@2.2.0: + dependencies: + debug: 4.4.3 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.3.0 + transitivePeerDependencies: + - supports-color + run-async@2.4.1: {} run-async@3.0.0: {} @@ -15765,6 +15859,22 @@ snapshots: transitivePeerDependencies: - supports-color + send@1.2.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.1 + mime-types: 3.0.2 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 @@ -15778,6 +15888,15 @@ snapshots: transitivePeerDependencies: - supports-color + serve-static@2.2.1: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.1 + transitivePeerDependencies: + - supports-color + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -16081,14 +16200,6 @@ snapshots: strip-json-comments@3.1.1: {} - strip-literal@2.1.1: - dependencies: - js-tokens: 9.0.1 - - strip-literal@3.1.0: - dependencies: - js-tokens: 9.0.1 - strtok3@10.3.4: dependencies: '@tokenizer/token': 0.3.0 @@ -16189,12 +16300,6 @@ snapshots: glob: 7.2.3 minimatch: 3.1.2 - test-exclude@7.0.1: - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 10.4.5 - minimatch: 9.0.5 - text-decoder@1.2.3: dependencies: b4a: 1.7.3 @@ -16225,15 +16330,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 - tinypool@0.8.4: {} - - tinypool@1.1.1: {} - - tinyrainbow@2.0.0: {} - - tinyspy@2.2.1: {} - - tinyspy@4.0.4: {} + tinyrainbow@3.0.3: {} tldts-core@6.1.86: {} @@ -16446,6 +16543,8 @@ snapshots: typescript@5.8.3: {} + typescript@5.9.3: {} + uc.micro@2.1.0: {} ufo@1.6.1: {} @@ -16492,7 +16591,7 @@ snapshots: union@0.5.0: dependencies: - qs: 6.14.0 + qs: 6.14.1 universal-user-agent@6.0.1: {} @@ -16504,6 +16603,30 @@ snapshots: unpipe@1.0.0: {} + unrs-resolver@1.11.1: + dependencies: + napi-postinstall: 0.3.4 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + until-async@3.0.2: {} update-browserslist-db@1.1.4(browserslist@4.27.0): @@ -16614,58 +16737,9 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite-node@1.6.1(@types/node@24.9.2)(terser@5.44.1): - dependencies: - cac: 6.7.14 - debug: 4.4.3 - pathe: 1.1.2 - picocolors: 1.1.1 - vite: 5.4.21(@types/node@24.9.2)(terser@5.44.1) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - vite-node@3.2.4(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1): - dependencies: - cac: 6.7.14 - debug: 4.4.3 - es-module-lexer: 1.7.0 - pathe: 2.0.3 - vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - transitivePeerDependencies: - - '@types/node' - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - vite@5.4.21(@types/node@24.9.2)(terser@5.44.1): - dependencies: - esbuild: 0.21.5 - postcss: 8.5.6 - rollup: 4.53.2 - optionalDependencies: - '@types/node': 24.9.2 - fsevents: 2.3.3 - terser: 5.44.1 - - vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1): + vite@7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1): dependencies: - esbuild: 0.25.12 + esbuild: 0.27.2 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 @@ -16679,64 +16753,63 @@ snapshots: tsx: 4.20.6 yaml: 2.8.1 - vitest-canvas-mock@0.3.3(vitest@1.6.1(@types/node@24.9.2)(@vitest/ui@3.0.4)(jsdom@27.1.0)(terser@5.44.1)): - dependencies: - jest-canvas-mock: 2.5.2 - vitest: 1.6.1(@types/node@24.9.2)(@vitest/ui@3.0.4)(jsdom@27.1.0)(terser@5.44.1) - - vitest-canvas-mock@0.3.3(vitest@3.2.4): + vitest-canvas-mock@1.1.3(vitest@4.0.9): dependencies: - jest-canvas-mock: 2.5.2 - vitest: 3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + cssfontparser: 1.2.1 + moo-color: 1.0.3 + vitest: 4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - vitest@1.6.1(@types/node@24.9.2)(@vitest/ui@3.0.4)(jsdom@27.1.0)(terser@5.44.1): + vitest@4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1): dependencies: - '@vitest/expect': 1.6.1 - '@vitest/runner': 1.6.1 - '@vitest/snapshot': 1.6.1 - '@vitest/spy': 1.6.1 - '@vitest/utils': 1.6.1 - acorn-walk: 8.3.4 - chai: 4.5.0 + '@vitest/expect': 4.0.9 + '@vitest/mocker': 4.0.9(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) + '@vitest/pretty-format': 4.0.9 + '@vitest/runner': 4.0.9 + '@vitest/snapshot': 4.0.9 + '@vitest/spy': 4.0.9 + '@vitest/utils': 4.0.9 debug: 4.4.3 - execa: 8.0.1 - local-pkg: 0.5.1 + es-module-lexer: 1.7.0 + expect-type: 1.2.2 magic-string: 0.30.21 - pathe: 1.1.2 - picocolors: 1.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 std-env: 3.10.0 - strip-literal: 2.1.1 tinybench: 2.9.0 - tinypool: 0.8.4 - vite: 5.4.21(@types/node@24.9.2)(terser@5.44.1) - vite-node: 1.6.1(@types/node@24.9.2)(terser@5.44.1) + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 24.9.2 - '@vitest/ui': 3.0.4(vitest@3.2.4) + '@vitest/ui': 4.0.9(vitest@4.0.9) jsdom: 27.1.0 transitivePeerDependencies: + - jiti - less - lightningcss + - msw - sass - sass-embedded - stylus - sugarss - supports-color - terser + - tsx + - yaml - vitest@3.2.4(@types/node@24.9.2)(@vitest/ui@3.0.4)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1): + vitest@4.0.9(@types/node@24.9.2)(@vitest/ui@4.0.9)(jiti@2.6.1)(jsdom@27.1.0)(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1): dependencies: - '@types/chai': 5.2.3 - '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) - '@vitest/pretty-format': 3.2.4 - '@vitest/runner': 3.2.4 - '@vitest/snapshot': 3.2.4 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 - chai: 5.3.3 + '@vitest/expect': 4.0.9 + '@vitest/mocker': 4.0.9(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) + '@vitest/pretty-format': 4.0.9 + '@vitest/runner': 4.0.9 + '@vitest/snapshot': 4.0.9 + '@vitest/spy': 4.0.9 + '@vitest/utils': 4.0.9 debug: 4.4.3 + es-module-lexer: 1.7.0 expect-type: 1.2.2 magic-string: 0.30.21 pathe: 2.0.3 @@ -16745,14 +16818,12 @@ snapshots: tinybench: 2.9.0 tinyexec: 0.3.2 tinyglobby: 0.2.15 - tinypool: 1.1.1 - tinyrainbow: 2.0.0 - vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + tinyrainbow: 3.0.3 + vite: 7.3.1(@types/node@24.9.2)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 24.9.2 - '@vitest/ui': 3.0.4(vitest@3.2.4) + '@vitest/ui': 4.0.9(vitest@4.0.9) jsdom: 27.1.0 transitivePeerDependencies: - jiti @@ -16933,10 +17004,10 @@ snapshots: wrappy@1.0.2: {} - write-file-atomic@4.0.2: + write-file-atomic@5.0.1: dependencies: imurmurhash: 0.1.4 - signal-exit: 3.0.7 + signal-exit: 4.1.0 ws@8.18.3: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index b26a216c0e..e3832dda83 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,28 +4,29 @@ packages: - 'packages/utils/*' - '!**/test/**' - 'e2e/*' - - tools/* + - 'tools/*' - 'scratchpad' - catalog: - '@reduxjs/toolkit': ^2.8.2 - immer: ^10.1.1 - msw: ^2.5.1 - + '@reduxjs/toolkit': '^2.8.2' + immer: '^10.1.1' + msw: '^2.5.1' catalogs: effect: - 'effect': '^3.17.2' + effect: '^3.17.2' '@effect/cli': '^0.69.0' '@effect/language-service': '^0.35.2' '@effect/platform': '^0.90.0' '@effect/platform-node': '0.94.2' '@effect/vitest': '^0.23.9' '@effect/opentelemetry': '^0.56.1' - vitest: - 'vitest': '^3.0.4' + vitest: '^4.0.9' + '@vitest/coverage-v8': '^4.0.9' + 'vitest-canvas-mock': '^1.1.3' + vite: + vite: '^7.3.1' link-workspace-packages: true strict-peer-dependencies: false -save-workspace-protocol: rolling +save-workspace-protocol: 'rolling' save-prefix: '' diff --git a/tools/user-scripts/package.json b/tools/user-scripts/package.json index 2287b1f46a..2b84381db6 100644 --- a/tools/user-scripts/package.json +++ b/tools/user-scripts/package.json @@ -22,7 +22,8 @@ }, "devDependencies": { "@effect/language-service": "catalog:effect", - "@effect/vitest": "catalog:effect" + "@effect/vitest": "catalog:effect", + "vitest": "catalog:vitest" }, "nx": { "tags": ["scope:tool"]