From 010d73e09a1b3dad251759f5831707e1daf7d9e5 Mon Sep 17 00:00:00 2001 From: DonOmalVindula Date: Thu, 19 Feb 2026 13:49:35 +0530 Subject: [PATCH 1/6] Introduce @asgardeo/angular SDK --- packages/angular/.eslintignore | 4 + packages/angular/.eslintrc.cjs | 31 ++ packages/angular/esbuild.config.mjs | 45 ++ packages/angular/package.json | 70 +++ packages/angular/prettier.config.cjs | 19 + packages/angular/src/AsgardeoAngularClient.ts | 361 +++++++++++++ .../angular/src/api/createOrganization.ts | 125 +++++ .../angular/src/api/getAllOrganizations.ts | 116 ++++ .../angular/src/api/getMeOrganizations.ts | 120 +++++ packages/angular/src/api/getOrganization.ts | 112 ++++ packages/angular/src/api/getSchemas.ts | 106 ++++ packages/angular/src/api/getScim2Me.ts | 106 ++++ packages/angular/src/api/updateMeProfile.ts | 95 ++++ .../angular/src/api/updateOrganization.ts | 123 +++++ .../components/callback/callback.component.ts | 153 ++++++ .../src/directives/loading.directive.ts | 58 ++ .../src/directives/signed-in.directive.ts | 58 ++ .../src/directives/signed-out.directive.ts | 59 +++ packages/angular/src/guards/asgardeo.guard.ts | 81 +++ packages/angular/src/index.ts | 79 +++ .../src/interceptors/asgardeo.interceptor.ts | 72 +++ packages/angular/src/models/config.ts | 21 + .../src/providers/asgardeo-config.token.ts | 27 + .../angular/src/providers/asgardeo.module.ts | 72 +++ .../angular/src/providers/provide-asgardeo.ts | 63 +++ .../src/services/asgardeo-auth.service.ts | 494 ++++++++++++++++++ .../services/asgardeo-organization.service.ts | 120 +++++ .../src/services/asgardeo-user.service.ts | 102 ++++ packages/angular/tsconfig.eslint.json | 4 + packages/angular/tsconfig.json | 35 ++ packages/angular/tsconfig.lib.json | 14 + packages/angular/tsconfig.spec.json | 12 + packages/angular/vitest.config.ts | 26 + pnpm-lock.yaml | 199 +++++-- tsconfig.json | 1 + 35 files changed, 3149 insertions(+), 34 deletions(-) create mode 100644 packages/angular/.eslintignore create mode 100644 packages/angular/.eslintrc.cjs create mode 100644 packages/angular/esbuild.config.mjs create mode 100644 packages/angular/package.json create mode 100644 packages/angular/prettier.config.cjs create mode 100644 packages/angular/src/AsgardeoAngularClient.ts create mode 100644 packages/angular/src/api/createOrganization.ts create mode 100644 packages/angular/src/api/getAllOrganizations.ts create mode 100644 packages/angular/src/api/getMeOrganizations.ts create mode 100644 packages/angular/src/api/getOrganization.ts create mode 100644 packages/angular/src/api/getSchemas.ts create mode 100644 packages/angular/src/api/getScim2Me.ts create mode 100644 packages/angular/src/api/updateMeProfile.ts create mode 100644 packages/angular/src/api/updateOrganization.ts create mode 100644 packages/angular/src/components/callback/callback.component.ts create mode 100644 packages/angular/src/directives/loading.directive.ts create mode 100644 packages/angular/src/directives/signed-in.directive.ts create mode 100644 packages/angular/src/directives/signed-out.directive.ts create mode 100644 packages/angular/src/guards/asgardeo.guard.ts create mode 100644 packages/angular/src/index.ts create mode 100644 packages/angular/src/interceptors/asgardeo.interceptor.ts create mode 100644 packages/angular/src/models/config.ts create mode 100644 packages/angular/src/providers/asgardeo-config.token.ts create mode 100644 packages/angular/src/providers/asgardeo.module.ts create mode 100644 packages/angular/src/providers/provide-asgardeo.ts create mode 100644 packages/angular/src/services/asgardeo-auth.service.ts create mode 100644 packages/angular/src/services/asgardeo-organization.service.ts create mode 100644 packages/angular/src/services/asgardeo-user.service.ts create mode 100644 packages/angular/tsconfig.eslint.json create mode 100644 packages/angular/tsconfig.json create mode 100644 packages/angular/tsconfig.lib.json create mode 100644 packages/angular/tsconfig.spec.json create mode 100644 packages/angular/vitest.config.ts diff --git a/packages/angular/.eslintignore b/packages/angular/.eslintignore new file mode 100644 index 000000000..99b0b518a --- /dev/null +++ b/packages/angular/.eslintignore @@ -0,0 +1,4 @@ +/dist +/build +/node_modules +/coverage diff --git a/packages/angular/.eslintrc.cjs b/packages/angular/.eslintrc.cjs new file mode 100644 index 000000000..236d65fc8 --- /dev/null +++ b/packages/angular/.eslintrc.cjs @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const path = require('path'); + +module.exports = { + extends: ['plugin:@wso2/typescript', 'plugin:@wso2/strict', 'plugin:@wso2/internal', 'plugin:@wso2/prettier'], + parserOptions: { + project: [path.resolve(__dirname, 'tsconfig.json'), path.resolve(__dirname, 'tsconfig.eslint.json')], + }, + plugins: ['@wso2'], + rules: { + 'import/no-extraneous-dependencies': ['error', {devDependencies: true}], + 'no-underscore-dangle': ['off'], + }, +}; diff --git a/packages/angular/esbuild.config.mjs b/packages/angular/esbuild.config.mjs new file mode 100644 index 000000000..630e63373 --- /dev/null +++ b/packages/angular/esbuild.config.mjs @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {readFileSync} from 'fs'; +import {build} from 'esbuild'; + +const pkg = JSON.parse(readFileSync('./package.json', 'utf8')); + +const commonOptions = { + bundle: true, + entryPoints: ['src/index.ts'], + external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})], + metafile: true, + platform: 'browser', + target: ['es2020'], +}; + +await build({ + ...commonOptions, + format: 'esm', + outfile: 'dist/index.js', + sourcemap: true, +}); + +await build({ + ...commonOptions, + format: 'cjs', + outfile: 'dist/cjs/index.js', + sourcemap: true, +}); diff --git a/packages/angular/package.json b/packages/angular/package.json new file mode 100644 index 000000000..896dfefae --- /dev/null +++ b/packages/angular/package.json @@ -0,0 +1,70 @@ +{ + "name": "@asgardeo/angular", + "version": "0.1.0", + "description": "Angular implementation of Asgardeo JavaScript SDK.", + "keywords": [ + "asgardeo", + "angular", + "spa", + "authentication", + "oidc" + ], + "homepage": "https://github.com/asgardeo/javascript/tree/main/packages/angular#readme", + "bugs": { + "url": "https://github.com/asgardeo/javascript/issues" + }, + "author": "WSO2", + "license": "Apache-2.0", + "type": "module", + "main": "dist/cjs/index.js", + "module": "dist/index.js", + "exports": { + "import": "./dist/index.js", + "require": "./dist/cjs/index.js" + }, + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "types": "dist/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/asgardeo/javascript", + "directory": "packages/angular" + }, + "scripts": { + "build": "pnpm clean && node esbuild.config.mjs && tsc -p tsconfig.lib.json --emitDeclarationOnly --outDir dist", + "clean": "rimraf dist", + "fix:lint": "eslint . --ext .js,.ts,.cjs,.mjs", + "lint": "eslint . --ext .js,.ts,.cjs,.mjs", + "test": "vitest", + "typecheck": "tsc -p tsconfig.lib.json" + }, + "devDependencies": { + "@types/node": "22.15.3", + "@wso2/eslint-plugin": "catalog:", + "@wso2/prettier-config": "catalog:", + "esbuild": "0.25.9", + "eslint": "8.57.0", + "jsdom": "26.1.0", + "prettier": "2.6.2", + "rimraf": "6.1.0", + "typescript": "5.7.2", + "vitest": "3.1.3" + }, + "peerDependencies": { + "@angular/common": ">=17.0.0", + "@angular/core": ">=17.0.0", + "@angular/router": ">=17.0.0", + "rxjs": ">=7.0.0" + }, + "dependencies": { + "@asgardeo/browser": "workspace:*", + "@asgardeo/i18n": "workspace:*", + "tslib": "2.8.1" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/angular/prettier.config.cjs b/packages/angular/prettier.config.cjs new file mode 100644 index 000000000..ce60a8c85 --- /dev/null +++ b/packages/angular/prettier.config.cjs @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +module.exports = require('@wso2/prettier-config'); diff --git a/packages/angular/src/AsgardeoAngularClient.ts b/packages/angular/src/AsgardeoAngularClient.ts new file mode 100644 index 000000000..70b8238b4 --- /dev/null +++ b/packages/angular/src/AsgardeoAngularClient.ts @@ -0,0 +1,361 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + AsgardeoBrowserClient, + AsgardeoSPAClient, + AsgardeoRuntimeError, + flattenUserSchema, + generateFlattenedUserProfile, + generateUserProfile, + extractUserClaimsFromIdToken, + deriveOrganizationHandleFromBaseUrl, + navigate, + getRedirectBasedSignUpUrl, + User, + UserProfile, + Organization, + IdToken, + TokenResponse, + HttpRequestConfig, + HttpResponse, + AllOrganizationsApiResponse, + TokenExchangeRequestConfig, + SignInOptions, + SignUpOptions, + Config, + Platform, +} from '@asgardeo/browser'; +import getAllOrganizations from './api/getAllOrganizations'; +import getMeOrganizations from './api/getMeOrganizations'; +import getSchemas from './api/getSchemas'; +import getScim2Me from './api/getScim2Me'; +import {AsgardeoAngularConfig} from './models/config'; + +/** + * Client for implementing Asgardeo in Angular applications. + * This class provides the core functionality for managing user authentication and sessions. + * It uses AsgardeoSPAClient directly without the __temp__/api.ts wrapper layer. + * + * @typeParam T - Configuration type that extends AsgardeoAngularConfig. + */ +class AsgardeoAngularClient extends AsgardeoBrowserClient { + private spaClient: AsgardeoSPAClient; + + private loadingState: boolean = false; + + private clientInstanceId: number; + + /** + * Creates a new AsgardeoAngularClient instance. + * @param instanceId - Optional instance ID for multi-auth context support. Defaults to 0. + */ + constructor(instanceId: number = 0) { + super(); + this.clientInstanceId = instanceId; + this.spaClient = AsgardeoSPAClient.getInstance(instanceId); + } + + /** + * Get the instance ID for this client. + * @returns The instance ID used for multi-auth context support. + */ + public getInstanceId(): number { + return this.clientInstanceId; + } + + private setLoading(loading: boolean): void { + this.loadingState = loading; + } + + private async withLoading(operation: () => Promise): Promise { + this.setLoading(true); + try { + const result: TResult = await operation(); + return result; + } finally { + this.setLoading(false); + } + } + + override initialize(config: AsgardeoAngularConfig): Promise { + let resolvedOrganizationHandle: string | undefined = config?.organizationHandle; + + if (!resolvedOrganizationHandle) { + resolvedOrganizationHandle = deriveOrganizationHandleFromBaseUrl(config?.baseUrl); + } + + return this.withLoading(async () => + this.spaClient.initialize({...config, organizationHandle: resolvedOrganizationHandle} as any), + ); + } + + override reInitialize(config: Partial): Promise { + return this.withLoading(async () => { + try { + await this.spaClient.reInitialize(config as any); + return true; + } catch (error) { + throw new AsgardeoRuntimeError( + `Failed to re-initialize the client: ${error instanceof Error ? error.message : String(error)}`, + 'AsgardeoAngularClient-reInitialize-RuntimeError-001', + 'angular', + 'An error occurred while re-initializing the client.', + ); + } + }); + } + + // eslint-disable-next-line class-methods-use-this + override async updateUserProfile(): Promise { + throw new Error('Not implemented'); + } + + override async getUser(options?: any): Promise { + try { + let baseUrl: string = options?.baseUrl; + + if (!baseUrl) { + const configData: any = await this.spaClient.getConfigData(); + baseUrl = configData?.baseUrl; + } + + const profile: User = await getScim2Me({baseUrl}); + const schemas: any = await getSchemas({baseUrl}); + + return generateUserProfile(profile, flattenUserSchema(schemas)); + } catch (error) { + return extractUserClaimsFromIdToken(await this.getDecodedIdToken()); + } + } + + async getDecodedIdToken(sessionId?: string): Promise { + return this.spaClient.getDecodedIdToken(sessionId); + } + + async getIdToken(): Promise { + return this.withLoading(async () => this.spaClient.getIdToken()); + } + + async getUserProfile(options?: any): Promise { + return this.withLoading(async () => { + try { + let baseUrl: string = options?.baseUrl; + + if (!baseUrl) { + const configData: any = await this.spaClient.getConfigData(); + baseUrl = configData?.baseUrl; + } + + const profile: User = await getScim2Me({baseUrl, instanceId: this.getInstanceId()}); + const schemas: any = await getSchemas({baseUrl, instanceId: this.getInstanceId()}); + + const processedSchemas: any = flattenUserSchema(schemas); + + const output: UserProfile = { + flattenedProfile: generateFlattenedUserProfile(profile, processedSchemas), + profile, + schemas: processedSchemas, + }; + + return output; + } catch (error) { + return { + flattenedProfile: extractUserClaimsFromIdToken(await this.getDecodedIdToken()), + profile: extractUserClaimsFromIdToken(await this.getDecodedIdToken()), + schemas: [], + }; + } + }); + } + + override async getMyOrganizations(options?: any): Promise { + try { + let baseUrl: string = options?.baseUrl; + + if (!baseUrl) { + const configData: any = await this.spaClient.getConfigData(); + baseUrl = configData?.baseUrl; + } + + return await getMeOrganizations({baseUrl, instanceId: this.getInstanceId()}); + } catch (error) { + throw new AsgardeoRuntimeError( + `Failed to fetch the user's associated organizations: ${ + error instanceof Error ? error.message : String(error) + }`, + 'AsgardeoAngularClient-getMyOrganizations-RuntimeError-001', + 'angular', + 'An error occurred while fetching associated organizations of the signed-in user.', + ); + } + } + + override async getAllOrganizations(options?: any): Promise { + try { + let baseUrl: string = options?.baseUrl; + + if (!baseUrl) { + const configData: any = await this.spaClient.getConfigData(); + baseUrl = configData?.baseUrl; + } + + return await getAllOrganizations({baseUrl, instanceId: this.getInstanceId()}); + } catch (error) { + throw new AsgardeoRuntimeError( + `Failed to fetch all organizations: ${error instanceof Error ? error.message : String(error)}`, + 'AsgardeoAngularClient-getAllOrganizations-RuntimeError-001', + 'angular', + 'An error occurred while fetching all the organizations associated with the user.', + ); + } + } + + override async getCurrentOrganization(): Promise { + try { + return await this.withLoading(async () => { + const idToken: IdToken = await this.getDecodedIdToken(); + return { + id: idToken?.org_id, + name: idToken?.org_name, + orgHandle: idToken?.org_handle, + }; + }); + } catch (error) { + throw new AsgardeoRuntimeError( + `Failed to fetch the current organization: ${error instanceof Error ? error.message : String(error)}`, + 'AsgardeoAngularClient-getCurrentOrganization-RuntimeError-001', + 'angular', + 'An error occurred while fetching the current organization of the signed-in user.', + ); + } + } + + override async switchOrganization(organization: Organization): Promise { + return this.withLoading(async () => { + try { + if (!organization.id) { + throw new AsgardeoRuntimeError( + 'Organization ID is required for switching organizations', + 'angular-AsgardeoAngularClient-SwitchOrganizationError-001', + 'angular', + 'The organization object must contain a valid ID to perform the organization switch.', + ); + } + + const exchangeConfig: TokenExchangeRequestConfig = { + attachToken: false, + data: { + client_id: '{{clientId}}', + grant_type: 'organization_switch', + scope: '{{scopes}}', + switching_organization: organization.id, + token: '{{accessToken}}', + }, + id: 'organization-switch', + returnsSession: true, + signInRequired: true, + }; + + return (await this.spaClient.exchangeToken(exchangeConfig)) as TokenResponse | Response; + } catch (error) { + throw new AsgardeoRuntimeError( + `Failed to switch organization: ${error instanceof Error ? error.message : String(error)}`, + 'angular-AsgardeoAngularClient-SwitchOrganizationError-003', + 'angular', + 'An error occurred while switching to the specified organization. Please try again.', + ); + } + }); + } + + override isLoading(): boolean { + return this.loadingState; + } + + async isInitialized(): Promise { + return this.spaClient.isInitialized(); + } + + override async isSignedIn(): Promise { + return this.spaClient.isSignedIn(); + } + + override getConfiguration(): T { + return this.spaClient.getConfigData() as unknown as T; + } + + override async exchangeToken(config: TokenExchangeRequestConfig): Promise { + return this.withLoading(async () => this.spaClient.exchangeToken(config) as unknown as TokenResponse | Response); + } + + override async signIn(options?: SignInOptions): Promise { + return this.withLoading(async () => (await this.spaClient.signIn(options as any)) as unknown as Promise); + } + + override async signInSilently(options?: SignInOptions): Promise { + return this.spaClient.signInSilently(options as Record); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + override async signOut(..._args: any[]): Promise { + const config: AsgardeoAngularConfig = (await this.spaClient.getConfigData()) as any; + + if (config.platform === Platform.AsgardeoV2) { + this.spaClient.clearSession(); + return Promise.resolve(config.afterSignOutUrl || ''); + } + + const response: boolean = await this.spaClient.signOut(); + return Promise.resolve(String(response)); + } + + override async signUp(options?: SignUpOptions): Promise; + override async signUp(payload: any): Promise; + // eslint-disable-next-line @typescript-eslint/no-unused-vars + override async signUp(..._args: any[]): Promise { + const config: AsgardeoAngularConfig = (await this.spaClient.getConfigData()) as any; + navigate(getRedirectBasedSignUpUrl(config as Config)); + } + + async request(requestConfig?: HttpRequestConfig): Promise> { + return this.spaClient.httpRequest(requestConfig); + } + + async requestAll(requestConfigs?: HttpRequestConfig[]): Promise[]> { + return this.spaClient.httpRequestAll(requestConfigs); + } + + override async getAccessToken(sessionId?: string): Promise { + return this.spaClient.getAccessToken(sessionId); + } + + override clearSession(sessionId?: string): void { + this.spaClient.clearSession(sessionId); + } + + override async setSession(sessionData: Record, sessionId?: string): Promise { + return (await this.spaClient.getStorageManager()).setSessionData(sessionData, sessionId); + } + + override decodeJwtToken>(token: string): Promise { + return this.spaClient.decodeJwtToken(token); + } +} + +export default AsgardeoAngularClient; diff --git a/packages/angular/src/api/createOrganization.ts b/packages/angular/src/api/createOrganization.ts new file mode 100644 index 000000000..ab369622f --- /dev/null +++ b/packages/angular/src/api/createOrganization.ts @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + Organization, + HttpInstance, + HttpResponse, + AsgardeoSPAClient, + HttpRequestConfig, + createOrganization as baseCreateOrganization, + CreateOrganizationConfig as BaseCreateOrganizationConfig, +} from '@asgardeo/browser'; + +/** + * Configuration for the createOrganization request (Angular-specific) + */ +export interface CreateOrganizationConfig extends Omit { + /** + * Optional custom fetcher function. If not provided, the Asgardeo SPA client's httpClient will be used + * which is a wrapper around axios http.request + */ + fetcher?: (url: string, config: RequestInit) => Promise; + /** + * Optional instance ID for multi-instance support. Defaults to 0. + */ + instanceId?: number; +} + +/** + * Creates a new organization. + * This function uses the Asgardeo SPA client's httpClient by default, but allows for custom fetchers. + * + * @param config - Configuration object containing baseUrl, payload and optional request config. + * @returns A promise that resolves with the created organization information. + * @example + * ```typescript + * // Using default Asgardeo SPA client httpClient + * try { + * const organization = await createOrganization({ + * baseUrl: "https://api.asgardeo.io/t/", + * payload: { + * description: "Share your screens", + * name: "Team Viewer", + * orgHandle: "team-viewer", + * parentId: "f4825104-4948-40d9-ab65-a960eee3e3d5", + * type: "TENANT" + * } + * }); + * console.log(organization); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to create organization:', error.message); + * } + * } + * ``` + * + * @example + * ```typescript + * // Using custom fetcher + * try { + * const organization = await createOrganization({ + * baseUrl: "https://api.asgardeo.io/t/", + * payload: { + * description: "Share your screens", + * name: "Team Viewer", + * orgHandle: "team-viewer", + * parentId: "f4825104-4948-40d9-ab65-a960eee3e3d5", + * type: "TENANT" + * }, + * fetcher: customFetchFunction + * }); + * console.log(organization); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to create organization:', error.message); + * } + * } + * ``` + */ +const createOrganization = async ({ + fetcher, + instanceId = 0, + ...requestConfig +}: CreateOrganizationConfig): Promise => { + const defaultFetcher = async (url: string, config: RequestInit): Promise => { + const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); + const httpClient: HttpInstance = client.httpRequest.bind(client); + const response: HttpResponse = await httpClient({ + data: config.body ? JSON.parse(config.body as string) : undefined, + headers: config.headers as Record, + method: config.method || 'POST', + url, + } as HttpRequestConfig); + + return { + json: () => Promise.resolve(response.data), + ok: response.status >= 200 && response.status < 300, + status: response.status, + statusText: response.statusText || '', + text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), + } as Response; + }; + + return baseCreateOrganization({ + ...requestConfig, + fetcher: fetcher || defaultFetcher, + }); +}; + +export default createOrganization; diff --git a/packages/angular/src/api/getAllOrganizations.ts b/packages/angular/src/api/getAllOrganizations.ts new file mode 100644 index 000000000..1f3aae276 --- /dev/null +++ b/packages/angular/src/api/getAllOrganizations.ts @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + HttpInstance, + HttpResponse, + AsgardeoSPAClient, + HttpRequestConfig, + getAllOrganizations as baseGetAllOrganizations, + GetAllOrganizationsConfig as BaseGetAllOrganizationsConfig, + AllOrganizationsApiResponse, +} from '@asgardeo/browser'; + +/** + * Configuration for the getAllOrganizations request (Angular-specific) + */ +export interface GetAllOrganizationsConfig extends Omit { + /** + * Optional custom fetcher function. If not provided, the Asgardeo SPA client's httpClient will be used + * which is a wrapper around axios http.request + */ + fetcher?: (url: string, config: RequestInit) => Promise; + /** + * Optional instance ID for multi-instance support. Defaults to 0. + */ + instanceId?: number; +} + +/** + * Retrieves all organizations with pagination support. + * This function uses the Asgardeo SPA client's httpClient by default, but allows for custom fetchers. + * + * @param config - Configuration object containing baseUrl, optional query parameters, and request config. + * @returns A promise that resolves with the paginated organizations information. + * @example + * ```typescript + * // Using default Asgardeo SPA client httpClient + * try { + * const response = await getAllOrganizations({ + * baseUrl: "https://api.asgardeo.io/t/", + * filter: "", + * limit: 10, + * recursive: false + * }); + * console.log(response.organizations); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to get organizations:', error.message); + * } + * } + * ``` + * + * @example + * ```typescript + * // Using custom fetcher + * try { + * const response = await getAllOrganizations({ + * baseUrl: "https://api.asgardeo.io/t/", + * filter: "", + * limit: 10, + * recursive: false, + * fetcher: customFetchFunction + * }); + * console.log(response.organizations); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to get organizations:', error.message); + * } + * } + * ``` + */ +const getAllOrganizations = async ({ + fetcher, + instanceId = 0, + ...requestConfig +}: GetAllOrganizationsConfig): Promise => { + const defaultFetcher = async (url: string, config: RequestInit): Promise => { + const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); + const httpClient: HttpInstance = client.httpRequest.bind(client); + const response: HttpResponse = await httpClient({ + headers: config.headers as Record, + method: config.method || 'GET', + url, + } as HttpRequestConfig); + + return { + json: () => Promise.resolve(response.data), + ok: response.status >= 200 && response.status < 300, + status: response.status, + statusText: response.statusText || '', + text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), + } as Response; + }; + + return baseGetAllOrganizations({ + ...requestConfig, + fetcher: fetcher || defaultFetcher, + }); +}; + +export default getAllOrganizations; diff --git a/packages/angular/src/api/getMeOrganizations.ts b/packages/angular/src/api/getMeOrganizations.ts new file mode 100644 index 000000000..40a706944 --- /dev/null +++ b/packages/angular/src/api/getMeOrganizations.ts @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + Organization, + HttpInstance, + HttpResponse, + AsgardeoSPAClient, + HttpRequestConfig, + getMeOrganizations as baseGetMeOrganizations, + GetMeOrganizationsConfig as BaseGetMeOrganizationsConfig, +} from '@asgardeo/browser'; + +/** + * Configuration for the getMeOrganizations request (Angular-specific) + */ +export interface GetMeOrganizationsConfig extends Omit { + /** + * Optional custom fetcher function. If not provided, the Asgardeo SPA client's httpClient will be used + * which is a wrapper around axios http.request + */ + fetcher?: (url: string, config: RequestInit) => Promise; + /** + * Optional instance ID for multi-instance support. Defaults to 0. + */ + instanceId?: number; +} + +/** + * Retrieves the organizations associated with the current user. + * This function uses the Asgardeo SPA client's httpClient by default, but allows for custom fetchers. + * + * @param config - Configuration object containing baseUrl, optional query parameters, and request config. + * @returns A promise that resolves with the organizations information. + * @example + * ```typescript + * // Using default Asgardeo SPA client httpClient + * try { + * const organizations = await getMeOrganizations({ + * baseUrl: "https://api.asgardeo.io/t/", + * after: "", + * before: "", + * filter: "", + * limit: 10, + * recursive: false + * }); + * console.log(organizations); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to get organizations:', error.message); + * } + * } + * ``` + * + * @example + * ```typescript + * // Using custom fetcher + * try { + * const organizations = await getMeOrganizations({ + * baseUrl: "https://api.asgardeo.io/t/", + * after: "", + * before: "", + * filter: "", + * limit: 10, + * recursive: false, + * fetcher: customFetchFunction + * }); + * console.log(organizations); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to get organizations:', error.message); + * } + * } + * ``` + */ +const getMeOrganizations = async ({ + fetcher, + instanceId = 0, + ...requestConfig +}: GetMeOrganizationsConfig): Promise => { + const defaultFetcher = async (url: string, config: RequestInit): Promise => { + const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); + const httpClient: HttpInstance = client.httpRequest.bind(client); + const response: HttpResponse = await httpClient({ + headers: config.headers as Record, + method: config.method || 'GET', + url, + } as HttpRequestConfig); + + return { + json: () => Promise.resolve(response.data), + ok: response.status >= 200 && response.status < 300, + status: response.status, + statusText: response.statusText || '', + text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), + } as Response; + }; + + return baseGetMeOrganizations({ + ...requestConfig, + fetcher: fetcher || defaultFetcher, + }); +}; + +export default getMeOrganizations; diff --git a/packages/angular/src/api/getOrganization.ts b/packages/angular/src/api/getOrganization.ts new file mode 100644 index 000000000..badebe69d --- /dev/null +++ b/packages/angular/src/api/getOrganization.ts @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + HttpInstance, + HttpResponse, + AsgardeoSPAClient, + HttpRequestConfig, + getOrganization as baseGetOrganization, + GetOrganizationConfig as BaseGetOrganizationConfig, + OrganizationDetails, +} from '@asgardeo/browser'; + +/** + * Configuration for the getOrganization request (Angular-specific) + */ +export interface GetOrganizationConfig extends Omit { + /** + * Optional custom fetcher function. If not provided, the Asgardeo SPA client's httpClient will be used + * which is a wrapper around axios http.request + */ + fetcher?: (url: string, config: RequestInit) => Promise; + /** + * Optional instance ID for multi-instance support. Defaults to 0. + */ + instanceId?: number; +} + +/** + * Retrieves detailed information for a specific organization. + * This function uses the Asgardeo SPA client's httpClient by default, but allows for custom fetchers. + * + * @param config - Configuration object containing baseUrl, organizationId, and request config. + * @returns A promise that resolves with the organization details. + * @example + * ```typescript + * // Using default Asgardeo SPA client httpClient + * try { + * const organization = await getOrganization({ + * baseUrl: "https://api.asgardeo.io/t/dxlab", + * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1" + * }); + * console.log(organization); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to get organization:', error.message); + * } + * } + * ``` + * + * @example + * ```typescript + * // Using custom fetcher + * try { + * const organization = await getOrganization({ + * baseUrl: "https://api.asgardeo.io/t/dxlab", + * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1", + * fetcher: customFetchFunction + * }); + * console.log(organization); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to get organization:', error.message); + * } + * } + * ``` + */ +const getOrganization = async ({ + fetcher, + instanceId = 0, + ...requestConfig +}: GetOrganizationConfig): Promise => { + const defaultFetcher = async (url: string, config: RequestInit): Promise => { + const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); + const httpClient: HttpInstance = client.httpRequest.bind(client); + const response: HttpResponse = await httpClient({ + headers: config.headers as Record, + method: config.method || 'GET', + url, + } as HttpRequestConfig); + + return { + json: () => Promise.resolve(response.data), + ok: response.status >= 200 && response.status < 300, + status: response.status, + statusText: response.statusText || '', + text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), + } as Response; + }; + + return baseGetOrganization({ + ...requestConfig, + fetcher: fetcher || defaultFetcher, + }); +}; + +export default getOrganization; diff --git a/packages/angular/src/api/getSchemas.ts b/packages/angular/src/api/getSchemas.ts new file mode 100644 index 000000000..cc16dc115 --- /dev/null +++ b/packages/angular/src/api/getSchemas.ts @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + Schema, + HttpInstance, + HttpResponse, + AsgardeoSPAClient, + HttpRequestConfig, + getSchemas as baseGetSchemas, + GetSchemasConfig as BaseGetSchemasConfig, +} from '@asgardeo/browser'; + +/** + * Configuration for the getSchemas request (Angular-specific) + */ +export interface GetSchemasConfig extends Omit { + /** + * Optional custom fetcher function. If not provided, the Asgardeo SPA client's httpClient will be used + * which is a wrapper around axios http.request + */ + fetcher?: (url: string, config: RequestInit) => Promise; + /** + * Optional instance ID for multi-instance support. Defaults to 0. + */ + instanceId?: number; +} + +/** + * Retrieves the SCIM2 schemas from the specified endpoint. + * This function uses the Asgardeo SPA client's httpClient by default, but allows for custom fetchers. + * + * @param config - Request configuration object. + * @returns A promise that resolves with the SCIM2 schemas information. + * @example + * ```typescript + * // Using default Asgardeo SPA client httpClient + * try { + * const schemas = await getSchemas({ + * url: "https://api.asgardeo.io/t//scim2/Schemas", + * }); + * console.log(schemas); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to get schemas:', error.message); + * } + * } + * ``` + * + * @example + * ```typescript + * // Using custom fetcher + * try { + * const schemas = await getSchemas({ + * url: "https://api.asgardeo.io/t//scim2/Schemas", + * fetcher: customFetchFunction + * }); + * console.log(schemas); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to get schemas:', error.message); + * } + * } + * ``` + */ +const getSchemas = async ({fetcher, instanceId = 0, ...requestConfig}: GetSchemasConfig): Promise => { + const defaultFetcher = async (url: string, config: RequestInit): Promise => { + const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); + const httpClient: HttpInstance = client.httpRequest.bind(client); + const response: HttpResponse = await httpClient({ + headers: config.headers as Record, + method: config.method || 'GET', + url, + } as HttpRequestConfig); + + return { + json: () => Promise.resolve(response.data), + ok: response.status >= 200 && response.status < 300, + status: response.status, + statusText: response.statusText || '', + text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), + } as Response; + }; + + return baseGetSchemas({ + ...requestConfig, + fetcher: fetcher || defaultFetcher, + }); +}; + +export default getSchemas; diff --git a/packages/angular/src/api/getScim2Me.ts b/packages/angular/src/api/getScim2Me.ts new file mode 100644 index 000000000..319cf95a8 --- /dev/null +++ b/packages/angular/src/api/getScim2Me.ts @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + User, + HttpInstance, + HttpResponse, + AsgardeoSPAClient, + HttpRequestConfig, + getScim2Me as baseGetScim2Me, + GetScim2MeConfig as BaseGetScim2MeConfig, +} from '@asgardeo/browser'; + +/** + * Configuration for the getScim2Me request (Angular-specific) + */ +export interface GetScim2MeConfig extends Omit { + /** + * Optional custom fetcher function. If not provided, the Asgardeo SPA client's httpClient will be used + * which is a wrapper around axios http.request + */ + fetcher?: (url: string, config: RequestInit) => Promise; + /** + * Optional instance ID for multi-instance support. Defaults to 0. + */ + instanceId?: number; +} + +/** + * Retrieves the user profile information from the specified SCIM2 /Me endpoint. + * This function uses the Asgardeo SPA client's httpClient by default, but allows for custom fetchers. + * + * @param requestConfig - Request configuration object. + * @returns A promise that resolves with the user profile information. + * @example + * ```typescript + * // Using default Asgardeo SPA client httpClient + * try { + * const userProfile = await getScim2Me({ + * url: "https://api.asgardeo.io/t//scim2/Me", + * }); + * console.log(userProfile); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to get user profile:', error.message); + * } + * } + * ``` + * + * @example + * ```typescript + * // Using custom fetcher + * try { + * const userProfile = await getScim2Me({ + * url: "https://api.asgardeo.io/t//scim2/Me", + * fetcher: customFetchFunction + * }); + * console.log(userProfile); + * } catch (error) { + * if (error instanceof AsgardeoAPIError) { + * console.error('Failed to get user profile:', error.message); + * } + * } + * ``` + */ +const getScim2Me = async ({fetcher, instanceId = 0, ...requestConfig}: GetScim2MeConfig): Promise => { + const defaultFetcher = async (url: string, config: RequestInit): Promise => { + const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); + const httpClient: HttpInstance = client.httpRequest.bind(client); + const response: HttpResponse = await httpClient({ + headers: config.headers as Record, + method: config.method || 'GET', + url, + } as HttpRequestConfig); + + return { + json: () => Promise.resolve(response.data), + ok: response.status >= 200 && response.status < 300, + status: response.status, + statusText: response.statusText || '', + text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), + } as Response; + }; + + return baseGetScim2Me({ + ...requestConfig, + fetcher: fetcher || defaultFetcher, + }); +}; + +export default getScim2Me; diff --git a/packages/angular/src/api/updateMeProfile.ts b/packages/angular/src/api/updateMeProfile.ts new file mode 100644 index 000000000..122a1b9ae --- /dev/null +++ b/packages/angular/src/api/updateMeProfile.ts @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + User, + HttpInstance, + HttpResponse, + AsgardeoSPAClient, + HttpRequestConfig, + updateMeProfile as baseUpdateMeProfile, + UpdateMeProfileConfig as BaseUpdateMeProfileConfig, +} from '@asgardeo/browser'; + +/** + * Configuration for the updateMeProfile request (Angular-specific) + */ +export interface UpdateMeProfileConfig extends Omit { + /** + * Optional custom fetcher function. If not provided, the Asgardeo SPA client's httpClient will be used + * which is a wrapper around axios http.request + */ + fetcher?: (url: string, config: RequestInit) => Promise; + /** + * Optional instance ID for multi-instance support. Defaults to 0. + */ + instanceId?: number; +} + +/** + * Updates the user profile information at the specified SCIM2 Me endpoint. + * This function uses the Asgardeo SPA client's httpClient by default, but allows for custom fetchers. + * + * @param config - Configuration object with URL, payload and optional request config. + * @returns A promise that resolves with the updated user profile information. + * @example + * ```typescript + * // Using default Asgardeo SPA client httpClient + * await updateMeProfile({ + * url: "https://api.asgardeo.io/t//scim2/Me", + * payload: { "urn:scim:wso2:schema": { mobileNumbers: ["0777933830"] } } + * }); + * ``` + * + * @example + * ```typescript + * // Using custom fetcher + * await updateMeProfile({ + * url: "https://api.asgardeo.io/t//scim2/Me", + * payload: { "urn:scim:wso2:schema": { mobileNumbers: ["0777933830"] } }, + * fetcher: customFetchFunction + * }); + * ``` + */ +const updateMeProfile = async ({fetcher, instanceId = 0, ...requestConfig}: UpdateMeProfileConfig): Promise => { + const defaultFetcher = async (url: string, config: RequestInit): Promise => { + const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); + const httpClient: HttpInstance = client.httpRequest.bind(client); + const response: HttpResponse = await httpClient({ + data: config.body ? JSON.parse(config.body as string) : undefined, + headers: config.headers as Record, + method: config.method || 'PATCH', + url, + } as HttpRequestConfig); + + return { + json: () => Promise.resolve(response.data), + ok: response.status >= 200 && response.status < 300, + status: response.status, + statusText: response.statusText || '', + text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), + } as Response; + }; + + return baseUpdateMeProfile({ + ...requestConfig, + fetcher: fetcher || defaultFetcher, + }); +}; + +export default updateMeProfile; diff --git a/packages/angular/src/api/updateOrganization.ts b/packages/angular/src/api/updateOrganization.ts new file mode 100644 index 000000000..9a756e41f --- /dev/null +++ b/packages/angular/src/api/updateOrganization.ts @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + HttpInstance, + HttpResponse, + AsgardeoSPAClient, + HttpRequestConfig, + updateOrganization as baseUpdateOrganization, + UpdateOrganizationConfig as BaseUpdateOrganizationConfig, + OrganizationDetails, + createPatchOperations, +} from '@asgardeo/browser'; + +/** + * Configuration for the updateOrganization request (Angular-specific) + */ +export interface UpdateOrganizationConfig extends Omit { + /** + * Optional custom fetcher function. If not provided, the Asgardeo SPA client's httpClient will be used + * which is a wrapper around axios http.request + */ + fetcher?: (url: string, config: RequestInit) => Promise; + /** + * Optional instance ID for multi-instance support. Defaults to 0. + */ + instanceId?: number; +} + +/** + * Updates the organization information using the Organizations Management API. + * This function uses the Asgardeo SPA client's httpClient by default, but allows for custom fetchers. + * + * @param config - Configuration object with baseUrl, organizationId, operations and optional request config. + * @returns A promise that resolves with the updated organization information. + * @example + * ```typescript + * // Using the helper function to create operations automatically + * const operations = createPatchOperations({ + * name: "Updated Organization Name", // Will use REPLACE + * description: "", // Will use REMOVE (empty string) + * customField: "Some value" // Will use REPLACE + * }); + * + * await updateOrganization({ + * baseUrl: "https://api.asgardeo.io/t/", + * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1", + * operations + * }); + * + * // Or manually specify operations + * await updateOrganization({ + * baseUrl: "https://api.asgardeo.io/t/", + * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1", + * operations: [ + * { operation: "REPLACE", path: "/name", value: "Updated Organization Name" }, + * { operation: "REMOVE", path: "/description" } + * ] + * }); + * ``` + * + * @example + * ```typescript + * // Using custom fetcher + * await updateOrganization({ + * baseUrl: "https://api.asgardeo.io/t/", + * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1", + * operations: [ + * { operation: "REPLACE", path: "/name", value: "Updated Organization Name" } + * ], + * fetcher: customFetchFunction + * }); + * ``` + */ +const updateOrganization = async ({ + fetcher, + instanceId = 0, + ...requestConfig +}: UpdateOrganizationConfig): Promise => { + const defaultFetcher = async (url: string, config: RequestInit): Promise => { + const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); + const httpClient: HttpInstance = client.httpRequest.bind(client); + const response: HttpResponse = await httpClient({ + data: config.body ? JSON.parse(config.body as string) : undefined, + headers: config.headers as Record, + method: config.method || 'PATCH', + url, + } as HttpRequestConfig); + + return { + json: () => Promise.resolve(response.data), + ok: response.status >= 200 && response.status < 300, + status: response.status, + statusText: response.statusText || '', + text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), + } as Response; + }; + + return baseUpdateOrganization({ + ...requestConfig, + fetcher: fetcher || defaultFetcher, + }); +}; + +// Re-export the helper function +export {createPatchOperations}; + +export default updateOrganization; diff --git a/packages/angular/src/components/callback/callback.component.ts b/packages/angular/src/components/callback/callback.component.ts new file mode 100644 index 000000000..a7cd4b106 --- /dev/null +++ b/packages/angular/src/components/callback/callback.component.ts @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Component, OnInit, Output, EventEmitter, inject} from '@angular/core'; +import {Router} from '@angular/router'; +import {navigate as browserNavigate} from '@asgardeo/browser'; + +/** + * Headless component that handles OAuth callback parameter forwarding. + * + * This component extracts OAuth parameters (code, state, error) from the URL and forwards them + * to the original component that initiated the OAuth flow. + * + * Adapted from React's `` component. + * + * @example + * ```typescript + * // In your routes + * const routes: Routes = [ + * { path: 'callback', component: AsgardeoCallbackComponent }, + * ]; + * ``` + */ +@Component({ + selector: 'asgardeo-callback', + standalone: true, + template: '', +}) +export class AsgardeoCallbackComponent implements OnInit { + private router: Router | null = inject(Router, {optional: true}); + + @Output() readonly error: EventEmitter = new EventEmitter(); + + ngOnInit(): void { + this.processOAuthCallback(); + } + + private processOAuthCallback(): void { + let returnPath: string = '/'; + + try { + // 1. Extract OAuth parameters from URL + const urlParams: URLSearchParams = new URLSearchParams(window.location.search); + const code: string | null = urlParams.get('code'); + const state: string | null = urlParams.get('state'); + const nonce: string | null = urlParams.get('nonce'); + const oauthError: string | null = urlParams.get('error'); + const errorDescription: string | null = urlParams.get('error_description'); + + // 2. Validate and retrieve OAuth state from sessionStorage + if (!state) { + throw new Error('Missing OAuth state parameter - possible security issue'); + } + + const storedData: string | null = sessionStorage.getItem(`asgardeo_oauth_${state}`); + if (!storedData) { + if (oauthError) { + const errorMsg: string = errorDescription || oauthError || 'OAuth authentication failed'; + const err: Error = new Error(errorMsg); + this.error.emit(err); + + const params: URLSearchParams = new URLSearchParams(); + params.set('error', oauthError); + if (errorDescription) { + params.set('error_description', errorDescription); + } + + this.navigate(`/?${params.toString()}`); + return; + } + throw new Error('Invalid OAuth state - possible CSRF attack'); + } + + const {path, timestamp} = JSON.parse(storedData); + returnPath = path || '/'; + + // 3. Validate state freshness + const MAX_STATE_AGE: number = 600000; // 10 minutes + if (Date.now() - timestamp > MAX_STATE_AGE) { + sessionStorage.removeItem(`asgardeo_oauth_${state}`); + throw new Error('OAuth state expired - please try again'); + } + + // 4. Clean up state + sessionStorage.removeItem(`asgardeo_oauth_${state}`); + + // 5. Handle OAuth error response + if (oauthError) { + const errorMsg: string = errorDescription || oauthError || 'OAuth authentication failed'; + const err: Error = new Error(errorMsg); + this.error.emit(err); + + const params: URLSearchParams = new URLSearchParams(); + params.set('error', oauthError); + if (errorDescription) { + params.set('error_description', errorDescription); + } + + this.navigate(`${returnPath}?${params.toString()}`); + return; + } + + // 6. Validate required parameters + if (!code) { + throw new Error('Missing OAuth authorization code'); + } + + // 7. Forward OAuth code to original component + const params: URLSearchParams = new URLSearchParams(); + params.set('code', code); + if (nonce) { + params.set('nonce', nonce); + } + + this.navigate(`${returnPath}?${params.toString()}`); + } catch (err) { + const errorMessage: string = err instanceof Error ? err.message : 'OAuth callback processing failed'; + // eslint-disable-next-line no-console + console.error('OAuth callback error:', err); + + this.error.emit(err instanceof Error ? err : new Error(errorMessage)); + + const params: URLSearchParams = new URLSearchParams(); + params.set('error', 'callback_error'); + params.set('error_description', errorMessage); + + this.navigate(`${returnPath}?${params.toString()}`); + } + } + + private navigate(path: string): void { + if (this.router) { + this.router.navigateByUrl(path); + } else { + browserNavigate(path); + } + } +} diff --git a/packages/angular/src/directives/loading.directive.ts b/packages/angular/src/directives/loading.directive.ts new file mode 100644 index 000000000..25f496f68 --- /dev/null +++ b/packages/angular/src/directives/loading.directive.ts @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Directive, TemplateRef, ViewContainerRef, effect, inject} from '@angular/core'; +import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; + +/** + * Structural directive that renders its template only when the SDK is in a loading state. + * Angular equivalent of React's `` component. + * + * @example + * ```html + *
+ *

Loading...

+ *
+ * ``` + */ +@Directive({ + selector: '[asgardeoLoading]', + standalone: true, +}) +export class AsgardeoLoadingDirective { + private authService: AsgardeoAuthService = inject(AsgardeoAuthService); + + private templateRef: TemplateRef = inject(TemplateRef); + + private viewContainer: ViewContainerRef = inject(ViewContainerRef); + + private hasView: boolean = false; + + constructor() { + effect(() => { + const loading: boolean = this.authService.isLoading(); + if (loading && !this.hasView) { + this.viewContainer.createEmbeddedView(this.templateRef); + this.hasView = true; + } else if (!loading && this.hasView) { + this.viewContainer.clear(); + this.hasView = false; + } + }); + } +} diff --git a/packages/angular/src/directives/signed-in.directive.ts b/packages/angular/src/directives/signed-in.directive.ts new file mode 100644 index 000000000..682ea7fcb --- /dev/null +++ b/packages/angular/src/directives/signed-in.directive.ts @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Directive, TemplateRef, ViewContainerRef, effect, inject} from '@angular/core'; +import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; + +/** + * Structural directive that renders its template only when the user is signed in. + * Angular equivalent of React's `` component. + * + * @example + * ```html + *
+ *

Welcome! You are signed in.

+ *
+ * ``` + */ +@Directive({ + selector: '[asgardeoSignedIn]', + standalone: true, +}) +export class AsgardeoSignedInDirective { + private authService: AsgardeoAuthService = inject(AsgardeoAuthService); + + private templateRef: TemplateRef = inject(TemplateRef); + + private viewContainer: ViewContainerRef = inject(ViewContainerRef); + + private hasView: boolean = false; + + constructor() { + effect(() => { + const isSignedIn: boolean = this.authService.isSignedIn(); + if (isSignedIn && !this.hasView) { + this.viewContainer.createEmbeddedView(this.templateRef); + this.hasView = true; + } else if (!isSignedIn && this.hasView) { + this.viewContainer.clear(); + this.hasView = false; + } + }); + } +} diff --git a/packages/angular/src/directives/signed-out.directive.ts b/packages/angular/src/directives/signed-out.directive.ts new file mode 100644 index 000000000..30d866729 --- /dev/null +++ b/packages/angular/src/directives/signed-out.directive.ts @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Directive, TemplateRef, ViewContainerRef, effect, inject} from '@angular/core'; +import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; + +/** + * Structural directive that renders its template only when the user is NOT signed in + * and the SDK is not in a loading state. + * Angular equivalent of React's `` component. + * + * @example + * ```html + *
+ * + *
+ * ``` + */ +@Directive({ + selector: '[asgardeoSignedOut]', + standalone: true, +}) +export class AsgardeoSignedOutDirective { + private authService: AsgardeoAuthService = inject(AsgardeoAuthService); + + private templateRef: TemplateRef = inject(TemplateRef); + + private viewContainer: ViewContainerRef = inject(ViewContainerRef); + + private hasView: boolean = false; + + constructor() { + effect(() => { + const isSignedOut: boolean = !this.authService.isSignedIn() && !this.authService.isLoading(); + if (isSignedOut && !this.hasView) { + this.viewContainer.createEmbeddedView(this.templateRef); + this.hasView = true; + } else if (!isSignedOut && this.hasView) { + this.viewContainer.clear(); + this.hasView = false; + } + }); + } +} diff --git a/packages/angular/src/guards/asgardeo.guard.ts b/packages/angular/src/guards/asgardeo.guard.ts new file mode 100644 index 000000000..b2a0cd59d --- /dev/null +++ b/packages/angular/src/guards/asgardeo.guard.ts @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {inject} from '@angular/core'; +import {ActivatedRouteSnapshot, CanActivateFn, Router, RouterStateSnapshot, UrlTree} from '@angular/router'; +import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; + +/** + * Functional route guard that protects routes requiring authentication. + * + * If the user is signed in, the route is activated. If not, the guard either: + * - Triggers the signIn() flow (redirect to Asgardeo), or + * - Redirects to a configured `signInUrl` from route data. + * + * @example + * ```typescript + * const routes: Routes = [ + * { + * path: 'dashboard', + * component: DashboardComponent, + * canActivate: [asgardeoGuard], + * }, + * { + * path: 'admin', + * component: AdminComponent, + * canActivate: [asgardeoGuard], + * data: { signInUrl: '/login' }, + * }, + * ]; + * ``` + */ +export const asgardeoGuard: CanActivateFn = async ( + route: ActivatedRouteSnapshot, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _state: RouterStateSnapshot, +): Promise => { + const authService: AsgardeoAuthService = inject(AsgardeoAuthService); + const router: Router = inject(Router); + + // Wait for initialization to complete if still loading + if (authService.isLoading()) { + await new Promise((resolve: () => void) => { + const check: ReturnType = setInterval(() => { + if (!authService.isLoading()) { + clearInterval(check); + resolve(); + } + }, 50); + }); + } + + if (authService.isSignedIn()) { + return true; + } + + // Check if a custom sign-in URL is provided via route data + const signInUrl: string | undefined = route.data?.['signInUrl'] as string | undefined; + + if (signInUrl) { + return router.createUrlTree([signInUrl]); + } + + // Trigger the redirect-based sign-in flow + await authService.signIn(); + return false; +}; diff --git a/packages/angular/src/index.ts b/packages/angular/src/index.ts new file mode 100644 index 000000000..ed71dc5b2 --- /dev/null +++ b/packages/angular/src/index.ts @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// --- Client --- +export {default as AsgardeoAngularClient} from './AsgardeoAngularClient'; + +// --- Config --- +export type {AsgardeoAngularConfig} from './models/config'; + +// --- Providers --- +export {provideAsgardeo} from './providers/provide-asgardeo'; +export {AsgardeoModule} from './providers/asgardeo.module'; +export {ASGARDEO_CONFIG} from './providers/asgardeo-config.token'; + +// --- Services --- +export {AsgardeoAuthService} from './services/asgardeo-auth.service'; +export {AsgardeoUserService} from './services/asgardeo-user.service'; +export {AsgardeoOrganizationService} from './services/asgardeo-organization.service'; + +// --- Guard --- +export {asgardeoGuard} from './guards/asgardeo.guard'; + +// --- Interceptor --- +export {asgardeoInterceptor} from './interceptors/asgardeo.interceptor'; + +// --- Directives --- +export {AsgardeoSignedInDirective} from './directives/signed-in.directive'; +export {AsgardeoSignedOutDirective} from './directives/signed-out.directive'; +export {AsgardeoLoadingDirective} from './directives/loading.directive'; + +// --- Components --- +export {AsgardeoCallbackComponent} from './components/callback/callback.component'; + +// --- API --- +export {default as getAllOrganizations, GetAllOrganizationsConfig} from './api/getAllOrganizations'; +export {default as createOrganization, CreateOrganizationConfig} from './api/createOrganization'; +export {default as getMeOrganizations, GetMeOrganizationsConfig} from './api/getMeOrganizations'; +export {default as getOrganization, GetOrganizationConfig} from './api/getOrganization'; +export {default as updateOrganization, createPatchOperations, UpdateOrganizationConfig} from './api/updateOrganization'; +export {default as getSchemas, GetSchemasConfig} from './api/getSchemas'; +export {default as updateMeProfile, UpdateMeProfileConfig} from './api/updateMeProfile'; +export {default as getMeProfile} from './api/getScim2Me'; +export * from './api/getScim2Me'; + +// --- Re-exports from @asgardeo/browser --- +export { + AsgardeoRuntimeError, + http, + navigate, + type User, + type UserProfile, + type Organization, + type IdToken, + type TokenResponse, + type HttpRequestConfig, + type HttpResponse, + type AllOrganizationsApiResponse, + type TokenExchangeRequestConfig, + type SignInOptions, + type SignOutOptions, + type SignUpOptions, + type Config, + Platform, +} from '@asgardeo/browser'; diff --git a/packages/angular/src/interceptors/asgardeo.interceptor.ts b/packages/angular/src/interceptors/asgardeo.interceptor.ts new file mode 100644 index 000000000..03f7b7574 --- /dev/null +++ b/packages/angular/src/interceptors/asgardeo.interceptor.ts @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {HttpInterceptorFn, HttpHandlerFn, HttpRequest} from '@angular/common/http'; +import {inject} from '@angular/core'; +import {from, switchMap} from 'rxjs'; +import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; + +/** + * Functional HTTP interceptor that automatically attaches the access token + * to outgoing HTTP requests as a Bearer token in the Authorization header. + * + * Skips token attachment if: + * - The request already has an Authorization header + * - The user is not signed in + * + * @example + * ```typescript + * // app.config.ts + * import { provideHttpClient, withInterceptors } from '@angular/common/http'; + * import { asgardeoInterceptor } from '@asgardeo/angular'; + * + * export const appConfig = { + * providers: [ + * provideHttpClient(withInterceptors([asgardeoInterceptor])), + * provideAsgardeo({ ... }), + * ], + * }; + * ``` + */ +export const asgardeoInterceptor: HttpInterceptorFn = (req: HttpRequest, next: HttpHandlerFn) => { + const authService: AsgardeoAuthService = inject(AsgardeoAuthService); + + // Skip if the request already has an Authorization header + if (req.headers.has('Authorization')) { + return next(req); + } + + // Skip token attachment if the user is not signed in + if (!authService.isSignedIn()) { + return next(req); + } + + return from(authService.getAccessToken()).pipe( + switchMap((token: string) => { + if (token) { + const authReq: HttpRequest = req.clone({ + setHeaders: { + Authorization: `Bearer ${token}`, + }, + }); + return next(authReq); + } + return next(req); + }), + ); +}; diff --git a/packages/angular/src/models/config.ts b/packages/angular/src/models/config.ts new file mode 100644 index 000000000..3c0c89807 --- /dev/null +++ b/packages/angular/src/models/config.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {AsgardeoBrowserConfig} from '@asgardeo/browser'; + +export type AsgardeoAngularConfig = AsgardeoBrowserConfig; diff --git a/packages/angular/src/providers/asgardeo-config.token.ts b/packages/angular/src/providers/asgardeo-config.token.ts new file mode 100644 index 000000000..764bf66f1 --- /dev/null +++ b/packages/angular/src/providers/asgardeo-config.token.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {InjectionToken} from '@angular/core'; +import {AsgardeoAngularConfig} from '../models/config'; + +/** + * Injection token for providing the Asgardeo configuration to Angular services. + */ +export const ASGARDEO_CONFIG: InjectionToken = new InjectionToken( + 'AsgardeoAngularConfig', +); diff --git a/packages/angular/src/providers/asgardeo.module.ts b/packages/angular/src/providers/asgardeo.module.ts new file mode 100644 index 000000000..33275230b --- /dev/null +++ b/packages/angular/src/providers/asgardeo.module.ts @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {NgModule, ModuleWithProviders, APP_INITIALIZER} from '@angular/core'; +import {ASGARDEO_CONFIG} from './asgardeo-config.token'; +import {AsgardeoCallbackComponent} from '../components/callback/callback.component'; +import {AsgardeoLoadingDirective} from '../directives/loading.directive'; +import {AsgardeoSignedInDirective} from '../directives/signed-in.directive'; +import {AsgardeoSignedOutDirective} from '../directives/signed-out.directive'; +import {AsgardeoAngularConfig} from '../models/config'; +import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; +import {AsgardeoOrganizationService} from '../services/asgardeo-organization.service'; +import {AsgardeoUserService} from '../services/asgardeo-user.service'; + +/** + * NgModule for Asgardeo authentication in module-based Angular applications. + * Use `AsgardeoModule.forRoot(config)` in your root module. + * + * For standalone Angular 17+ apps, prefer `provideAsgardeo()` instead. + * + * @example + * ```typescript + * @NgModule({ + * imports: [ + * AsgardeoModule.forRoot({ + * baseUrl: 'https://api.asgardeo.io/t/myorg', + * clientId: 'my-client-id', + * afterSignInUrl: window.location.origin, + * }), + * ], + * }) + * export class AppModule {} + * ``` + */ +@NgModule({ + exports: [AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoLoadingDirective, AsgardeoCallbackComponent], + imports: [AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoLoadingDirective, AsgardeoCallbackComponent], +}) +export class AsgardeoModule { + static forRoot(config: AsgardeoAngularConfig): ModuleWithProviders { + return { + ngModule: AsgardeoModule, + providers: [ + {provide: ASGARDEO_CONFIG, useValue: config}, + AsgardeoAuthService, + AsgardeoUserService, + AsgardeoOrganizationService, + { + deps: [AsgardeoAuthService], + multi: true, + provide: APP_INITIALIZER, + useFactory: (authService: AsgardeoAuthService) => () => authService.initialize(), + }, + ], + }; + } +} diff --git a/packages/angular/src/providers/provide-asgardeo.ts b/packages/angular/src/providers/provide-asgardeo.ts new file mode 100644 index 000000000..ed9db0eb1 --- /dev/null +++ b/packages/angular/src/providers/provide-asgardeo.ts @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {EnvironmentProviders, makeEnvironmentProviders, APP_INITIALIZER} from '@angular/core'; +import {ASGARDEO_CONFIG} from './asgardeo-config.token'; +import {AsgardeoAngularConfig} from '../models/config'; +import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; +import {AsgardeoOrganizationService} from '../services/asgardeo-organization.service'; +import {AsgardeoUserService} from '../services/asgardeo-user.service'; + +/** + * Provides Asgardeo authentication services for standalone Angular applications (Angular 17+). + * + * @param config - The Asgardeo configuration object. + * @returns EnvironmentProviders to be used in the app's providers array. + * + * @example + * ```typescript + * // app.config.ts + * import { provideAsgardeo } from '@asgardeo/angular'; + * + * export const appConfig = { + * providers: [ + * provideAsgardeo({ + * baseUrl: 'https://api.asgardeo.io/t/myorg', + * clientId: 'my-client-id', + * afterSignInUrl: window.location.origin, + * afterSignOutUrl: window.location.origin, + * scopes: ['openid', 'profile', 'email'], + * }), + * ], + * }; + * ``` + */ +export function provideAsgardeo(config: AsgardeoAngularConfig): EnvironmentProviders { + return makeEnvironmentProviders([ + {provide: ASGARDEO_CONFIG, useValue: config}, + AsgardeoAuthService, + AsgardeoUserService, + AsgardeoOrganizationService, + { + deps: [AsgardeoAuthService], + multi: true, + provide: APP_INITIALIZER, + useFactory: (authService: AsgardeoAuthService) => () => authService.initialize(), + }, + ]); +} diff --git a/packages/angular/src/services/asgardeo-auth.service.ts b/packages/angular/src/services/asgardeo-auth.service.ts new file mode 100644 index 000000000..69887c722 --- /dev/null +++ b/packages/angular/src/services/asgardeo-auth.service.ts @@ -0,0 +1,494 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Injectable, Inject, signal, computed, OnDestroy, Signal, WritableSignal} from '@angular/core'; +import { + AsgardeoRuntimeError, + User, + UserProfile, + Organization, + IdToken, + TokenResponse, + SignInOptions, + SignOutOptions, + HttpRequestConfig, + HttpResponse, + TokenExchangeRequestConfig, + hasAuthParamsInUrl, + hasCalledForThisInstanceInUrl, + Platform, + extractUserClaimsFromIdToken, +} from '@asgardeo/browser'; +import {BehaviorSubject, Observable} from 'rxjs'; +import AsgardeoAngularClient from '../AsgardeoAngularClient'; +import {AsgardeoAngularConfig} from '../models/config'; +import {ASGARDEO_CONFIG} from '../providers/asgardeo-config.token'; + +/** + * Core authentication service for Asgardeo Angular SDK. + * + * This service manages the authentication lifecycle and provides reactive state + * via both Angular Signals and RxJS Observables. + * + * It is the Angular equivalent of React's `AsgardeoProvider` + `useAsgardeo()` hook. + */ +@Injectable() +export class AsgardeoAuthService implements OnDestroy { + // --- Angular Signals (primary reactive state) --- + private readonly _isLoading: WritableSignal = signal(true); + + private readonly _isSignedIn: WritableSignal = signal(false); + + private readonly _isInitialized: WritableSignal = signal(false); + + private readonly _user: WritableSignal = signal(null); + + private readonly _currentOrganization: WritableSignal = signal(null); + + private readonly _userProfile: WritableSignal = signal(null); + + private readonly _myOrganizations: WritableSignal = signal([]); + + private readonly _baseUrl: WritableSignal = signal(''); + + // --- Read-only public signals --- + readonly isLoading: Signal = this._isLoading.asReadonly(); + + readonly isSignedIn: Signal = this._isSignedIn.asReadonly(); + + readonly isInitialized: Signal = this._isInitialized.asReadonly(); + + readonly user: Signal = this._user.asReadonly(); + + readonly currentOrganization: Signal = this._currentOrganization.asReadonly(); + + readonly userProfile: Signal = this._userProfile.asReadonly(); + + readonly myOrganizations: Signal = this._myOrganizations.asReadonly(); + + // --- Computed signals --- + readonly flattenedProfile: Signal = computed(() => this._userProfile()?.flattenedProfile ?? null); + + readonly profile: Signal = computed(() => this._userProfile()?.profile ?? null); + + // --- RxJS Observables (for consumers preferring Observable API) --- + private readonly _isLoading$: BehaviorSubject = new BehaviorSubject(true); + + private readonly _isSignedIn$: BehaviorSubject = new BehaviorSubject(false); + + private readonly _isInitialized$: BehaviorSubject = new BehaviorSubject(false); + + private readonly _user$: BehaviorSubject = new BehaviorSubject(null); + + readonly isLoading$: Observable = this._isLoading$.asObservable(); + + readonly isSignedIn$: Observable = this._isSignedIn$.asObservable(); + + readonly isInitialized$: Observable = this._isInitialized$.asObservable(); + + readonly user$: Observable = this._user$.asObservable(); + + // --- Internal state --- + private client: AsgardeoAngularClient; + + private config: AsgardeoAngularConfig; + + private signInCheckInterval: ReturnType | null = null; + + private loadingCheckInterval: ReturnType | null = null; + + private isUpdatingSession: boolean = false; + + constructor(@Inject(ASGARDEO_CONFIG) config: AsgardeoAngularConfig) { + this.config = {...config}; + this.client = new AsgardeoAngularClient(config.instanceId ?? 0); + this._baseUrl.set(config.baseUrl || ''); + } + + /** + * Initialize the Asgardeo client. This is called automatically via APP_INITIALIZER. + * It mirrors the initialization logic from AsgardeoProvider's useEffect. + */ + async initialize(): Promise { + try { + await this.client.initialize(this.config); + const initializedConfig: AsgardeoAngularConfig = this.client.getConfiguration(); + this.config = initializedConfig; + + if (initializedConfig?.platform) { + sessionStorage.setItem('asgardeo_platform', initializedConfig.platform); + } + if (initializedConfig?.baseUrl) { + sessionStorage.setItem('asgardeo_base_url', initializedConfig.baseUrl); + this._baseUrl.set(initializedConfig.baseUrl); + } + + this.syncState('isInitialized', true); + + // Check if user is already signed in + const isAlreadySignedIn: boolean = await this.client.isSignedIn(); + + if (isAlreadySignedIn) { + await this.updateSession(); + this.startSignInPolling(); + return; + } + + // Check for auth params in URL (OAuth callback handling) + const currentUrl: URL = new URL(window.location.href); + const afterSignInUrl: string = this.config.afterSignInUrl || window.location.origin; + const instanceId: number = this.config.instanceId ?? 0; + + const hasParams: boolean = + hasAuthParamsInUrl() && + new URL(currentUrl.origin + currentUrl.pathname).toString() === new URL(afterSignInUrl).toString(); + const isForThisInstance: boolean = hasCalledForThisInstanceInUrl(instanceId, currentUrl.search); + + if (hasParams && isForThisInstance) { + try { + this.isUpdatingSession = true; + this.syncState('isLoading', true); + + await this.client.signIn({callOnlyOnRedirect: true} as any); + + if (await this.client.isSignedIn()) { + await this.updateSession(); + } + } catch (error) { + throw new AsgardeoRuntimeError( + `Sign in failed: ${error instanceof Error ? error.message : String(JSON.stringify(error))}`, + 'asgardeo-signIn-Error', + 'angular', + 'An error occurred while trying to sign in.', + ); + } finally { + this.isUpdatingSession = false; + this.syncState('isLoading', this.client.isLoading()); + } + } else { + this.syncState('isLoading', false); + } + + this.startSignInPolling(); + this.startLoadingStateTracking(); + } catch (error) { + this.syncState('isLoading', false); + throw error; + } + } + + // --- Auth Methods --- + + async signIn(options?: SignInOptions): Promise { + try { + this.isUpdatingSession = true; + this.syncState('isLoading', true); + + const response: User = await this.client.signIn(options); + + if (await this.client.isSignedIn()) { + await this.updateSession(); + } + + return response; + } catch (error) { + throw new AsgardeoRuntimeError( + `Sign in failed: ${error instanceof Error ? error.message : String(JSON.stringify(error))}`, + 'asgardeo-signIn-Error', + 'angular', + 'An error occurred while trying to sign in.', + ); + } finally { + this.isUpdatingSession = false; + this.syncState('isLoading', this.client.isLoading()); + } + } + + async signInSilently(options?: SignInOptions): Promise { + try { + this.isUpdatingSession = true; + this.syncState('isLoading', true); + const response: User | boolean = await this.client.signInSilently(options); + + if (await this.client.isSignedIn()) { + await this.updateSession(); + } + + return response; + } catch (error) { + throw new AsgardeoRuntimeError( + `Error while signing in silently: ${error instanceof Error ? error.message : String(JSON.stringify(error))}`, + 'asgardeo-signInSilently-Error', + 'angular', + 'An error occurred while trying to sign in silently.', + ); + } finally { + this.isUpdatingSession = false; + this.syncState('isLoading', this.client.isLoading()); + } + } + + async signOut(options?: SignOutOptions): Promise { + return this.client.signOut(options); + } + + async signUp(): Promise { + return this.client.signUp(); + } + + async switchOrganization(organization: Organization): Promise { + try { + this.isUpdatingSession = true; + this.syncState('isLoading', true); + const response: TokenResponse | Response = await this.client.switchOrganization(organization); + + if (await this.client.isSignedIn()) { + await this.updateSession(); + } + + return response; + } catch (error) { + throw new AsgardeoRuntimeError( + `Failed to switch organization: ${error instanceof Error ? error.message : String(JSON.stringify(error))}`, + 'asgardeo-switchOrganization-Error', + 'angular', + 'An error occurred while switching to the specified organization.', + ); + } finally { + this.isUpdatingSession = false; + this.syncState('isLoading', this.client.isLoading()); + } + } + + // --- Token Methods --- + + async getAccessToken(sessionId?: string): Promise { + return this.client.getAccessToken(sessionId); + } + + async getIdToken(): Promise { + return this.client.getIdToken(); + } + + async getDecodedIdToken(sessionId?: string): Promise { + return this.client.getDecodedIdToken(sessionId); + } + + async exchangeToken(config: TokenExchangeRequestConfig): Promise { + return this.client.exchangeToken(config); + } + + async decodeJwtToken(token: string): Promise { + return this.client.decodeJwtToken(token); + } + + // --- HTTP --- + + async request(requestConfig?: HttpRequestConfig): Promise> { + return this.client.request(requestConfig); + } + + async requestAll(requestConfigs?: HttpRequestConfig[]): Promise[]> { + return this.client.requestAll(requestConfigs); + } + + // --- Session --- + + clearSession(sessionId?: string): void { + this.client.clearSession(sessionId); + } + + async setSession(data: Record, sessionId?: string): Promise { + return this.client.setSession(data, sessionId); + } + + // --- Configuration --- + + getConfiguration(): AsgardeoAngularConfig { + return this.config; + } + + async reInitialize(config: Partial): Promise { + return this.client.reInitialize(config); + } + + // --- Internal: Expose client for secondary services --- + + /** @internal */ + getClient(): AsgardeoAngularClient { + return this.client; + } + + // --- Private Methods --- + + /** + * Fetches user, user profile, and organization data after sign-in. + * Mirrors AsgardeoProvider's updateSession() function. + */ + private async updateSession(): Promise { + try { + this.isUpdatingSession = true; + this.syncState('isLoading', true); + let resolvedBaseUrl: string = this._baseUrl(); + + const decodedToken: IdToken = await this.client.getDecodedIdToken(); + + // If there's a `user_org` claim, treat this as an organization login + if (decodedToken?.['user_org']) { + resolvedBaseUrl = `${this.client.getConfiguration().baseUrl}/o`; + this._baseUrl.set(resolvedBaseUrl); + } + + if (this.config.platform === Platform.AsgardeoV2) { + const claims: Record = extractUserClaimsFromIdToken(decodedToken); + this._user.set(claims as User); + this._user$.next(claims as User); + this._userProfile.set({ + flattenedProfile: claims as User, + profile: claims as User, + schemas: [], + }); + } else { + try { + const fetchedUser: User = await this.client.getUser({baseUrl: resolvedBaseUrl}); + this._user.set(fetchedUser); + this._user$.next(fetchedUser); + } catch { + // Silently handle user fetch failure + } + + try { + const fetchedUserProfile: UserProfile = await this.client.getUserProfile({baseUrl: resolvedBaseUrl}); + this._userProfile.set(fetchedUserProfile); + } catch { + // Silently handle profile fetch failure + } + + try { + const fetchedOrganization: Organization = await this.client.getCurrentOrganization(); + this._currentOrganization.set(fetchedOrganization); + } catch { + // Silently handle organization fetch failure + } + + try { + const fetchedMyOrganizations: Organization[] = await this.client.getMyOrganizations(); + this._myOrganizations.set(fetchedMyOrganizations); + } catch { + // Silently handle organizations list fetch failure + } + } + + // Update sign-in status BEFORE setting loading to false + const currentSignInStatus: boolean = await this.client.isSignedIn(); + this.syncState('isSignedIn', currentSignInStatus); + } catch { + // Silently handle session update failure + } finally { + this.isUpdatingSession = false; + this.syncState('isLoading', this.client.isLoading()); + } + } + + /** + * Polls for sign-in status changes. Mirrors AsgardeoProvider's sign-in status polling useEffect. + */ + private startSignInPolling(): void { + if (this.signInCheckInterval) { + return; + } + + this.client.isSignedIn().then((status: boolean) => { + this.syncState('isSignedIn', status); + + if (!status) { + this.signInCheckInterval = setInterval(async () => { + const newStatus: boolean = await this.client.isSignedIn(); + + if (newStatus) { + this.syncState('isSignedIn', true); + if (this.signInCheckInterval) { + clearInterval(this.signInCheckInterval); + this.signInCheckInterval = null; + } + } + }, 1000); + } + }); + } + + /** + * Tracks loading state changes from the client. Mirrors AsgardeoProvider's loading state tracking useEffect. + */ + private startLoadingStateTracking(): void { + this.loadingCheckInterval = setInterval(() => { + if (this.isUpdatingSession) { + return; + } + + const currentUrl: URL = new URL(window.location.href); + const afterSignInUrl: string = this.config.afterSignInUrl || window.location.origin; + if (!this._isSignedIn() && hasAuthParamsInUrl()) { + const currentPathUrl: string = new URL(currentUrl.origin + currentUrl.pathname).toString(); + const afterSignInPathUrl: string = new URL(afterSignInUrl).toString(); + if (currentPathUrl === afterSignInPathUrl) { + return; + } + } + + this.syncState('isLoading', this.client.isLoading()); + }, 100); + } + + /** + * Syncs a state value across both the signal and BehaviorSubject. + */ + private syncState(key: string, value: any): void { + switch (key) { + case 'isLoading': + this._isLoading.set(value); + this._isLoading$.next(value); + break; + case 'isSignedIn': + this._isSignedIn.set(value); + this._isSignedIn$.next(value); + break; + case 'isInitialized': + this._isInitialized.set(value); + this._isInitialized$.next(value); + break; + default: + break; + } + } + + ngOnDestroy(): void { + if (this.signInCheckInterval) { + clearInterval(this.signInCheckInterval); + this.signInCheckInterval = null; + } + if (this.loadingCheckInterval) { + clearInterval(this.loadingCheckInterval); + this.loadingCheckInterval = null; + } + this._isLoading$.complete(); + this._isSignedIn$.complete(); + this._isInitialized$.complete(); + this._user$.complete(); + } +} diff --git a/packages/angular/src/services/asgardeo-organization.service.ts b/packages/angular/src/services/asgardeo-organization.service.ts new file mode 100644 index 000000000..249d2cf0a --- /dev/null +++ b/packages/angular/src/services/asgardeo-organization.service.ts @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Injectable, Signal, WritableSignal, signal} from '@angular/core'; +import {Organization, AllOrganizationsApiResponse, TokenResponse} from '@asgardeo/browser'; +import {BehaviorSubject, Observable} from 'rxjs'; +import {AsgardeoAuthService} from './asgardeo-auth.service'; +import createOrganization, {CreateOrganizationConfig} from '../api/createOrganization'; + +/** + * Service for managing organizations. + * Angular equivalent of React's `OrganizationProvider` + `useOrganization()` hook. + */ +@Injectable() +export class AsgardeoOrganizationService { + private readonly _isLoading: WritableSignal = signal(false); + + private readonly _error: WritableSignal = signal(null); + + readonly isLoading: Signal = this._isLoading.asReadonly(); + + readonly error: Signal = this._error.asReadonly(); + + /** Delegates to AsgardeoAuthService signals. */ + readonly myOrganizations: Signal; + + readonly currentOrganization: Signal; + + // Observable variants + private readonly _isLoading$: BehaviorSubject = new BehaviorSubject(false); + + readonly isLoading$: Observable = this._isLoading$.asObservable(); + + constructor(private authService: AsgardeoAuthService) { + this.myOrganizations = this.authService.myOrganizations; + this.currentOrganization = this.authService.currentOrganization; + } + + /** + * Fetches all organizations with pagination support. + */ + async getAllOrganizations(): Promise { + this._isLoading.set(true); + this._isLoading$.next(true); + this._error.set(null); + + try { + return await this.authService.getClient().getAllOrganizations(); + } catch (error) { + const errorMessage: string = error instanceof Error ? error.message : 'Failed to fetch organizations'; + this._error.set(errorMessage); + throw error; + } finally { + this._isLoading.set(false); + this._isLoading$.next(false); + } + } + + /** + * Switches to the specified organization. + */ + async switchOrganization(organization: Organization): Promise { + return this.authService.switchOrganization(organization); + } + + /** + * Re-fetches the user's organizations from the server. + */ + async revalidateMyOrganizations(): Promise { + this._isLoading.set(true); + this._isLoading$.next(true); + this._error.set(null); + + try { + return await this.authService.getClient().getMyOrganizations(); + } catch (error) { + const errorMessage: string = error instanceof Error ? error.message : 'Failed to fetch organizations'; + this._error.set(errorMessage); + throw error; + } finally { + this._isLoading.set(false); + this._isLoading$.next(false); + } + } + + /** + * Creates a new organization. + */ + async createOrganization(config: CreateOrganizationConfig): Promise { + this._isLoading.set(true); + this._isLoading$.next(true); + this._error.set(null); + + try { + return await createOrganization(config); + } catch (error) { + const errorMessage: string = error instanceof Error ? error.message : 'Failed to create organization'; + this._error.set(errorMessage); + throw error; + } finally { + this._isLoading.set(false); + this._isLoading$.next(false); + } + } +} diff --git a/packages/angular/src/services/asgardeo-user.service.ts b/packages/angular/src/services/asgardeo-user.service.ts new file mode 100644 index 000000000..c75b3901c --- /dev/null +++ b/packages/angular/src/services/asgardeo-user.service.ts @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Injectable, Signal, WritableSignal, computed, signal} from '@angular/core'; +import {User, UserProfile} from '@asgardeo/browser'; +import {BehaviorSubject, Observable} from 'rxjs'; +import {AsgardeoAuthService} from './asgardeo-auth.service'; +import updateMeProfile, {UpdateMeProfileConfig} from '../api/updateMeProfile'; + +/** + * Service for managing user profile data. + * Angular equivalent of React's `UserProvider` + `useUser()` hook. + */ +@Injectable() +export class AsgardeoUserService { + private readonly _isLoading: WritableSignal = signal(false); + + private readonly _error: WritableSignal = signal(null); + + readonly isLoading: Signal = this._isLoading.asReadonly(); + + readonly error: Signal = this._error.asReadonly(); + + /** The full user profile (profile, flattenedProfile, schemas). Delegates to AsgardeoAuthService. */ + readonly userProfile: Signal; + + readonly flattenedProfile: Signal; + + readonly profile: Signal; + + readonly schemas: Signal; + + // Observable variants + private readonly _isLoading$: BehaviorSubject = new BehaviorSubject(false); + + readonly isLoading$: Observable = this._isLoading$.asObservable(); + + constructor(private authService: AsgardeoAuthService) { + // Delegate to auth service's user profile signal + this.userProfile = this.authService.userProfile; + this.flattenedProfile = this.authService.flattenedProfile; + this.profile = this.authService.profile; + this.schemas = computed(() => this.authService.userProfile()?.schemas ?? []); + } + + /** + * Refreshes the user profile by re-fetching from the server. + */ + async refreshUser(): Promise { + this._isLoading.set(true); + this._isLoading$.next(true); + this._error.set(null); + + try { + // Re-initialize to trigger updateSession which refreshes the user data + await this.authService.reInitialize({}); + } catch (error) { + this._error.set(error instanceof Error ? error : new Error('Failed to refresh user profile')); + } finally { + this._isLoading.set(false); + this._isLoading$.next(false); + } + } + + /** + * Updates the user profile via the SCIM2 API. + * + * @param config - The update configuration containing operations and baseUrl. + * @returns The updated user profile data. + */ + async updateUser(config: UpdateMeProfileConfig): Promise { + this._isLoading.set(true); + this._isLoading$.next(true); + this._error.set(null); + + try { + const result: User = await updateMeProfile(config); + return result; + } catch (error) { + this._error.set(error instanceof Error ? error : new Error('Failed to update user profile')); + throw error; + } finally { + this._isLoading.set(false); + this._isLoading$.next(false); + } + } +} diff --git a/packages/angular/tsconfig.eslint.json b/packages/angular/tsconfig.eslint.json new file mode 100644 index 000000000..d5eefbbbb --- /dev/null +++ b/packages/angular/tsconfig.eslint.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["**/.*.js", "**/.*.cjs", "**/.*.ts", "**/*.js", "**/*.cjs", "**/*.ts"] +} diff --git a/packages/angular/tsconfig.json b/packages/angular/tsconfig.json new file mode 100644 index 000000000..b405f5dd6 --- /dev/null +++ b/packages/angular/tsconfig.json @@ -0,0 +1,35 @@ +{ + "extends": "../../tsconfig.json", + "compileOnSave": false, + "compilerOptions": { + "declaration": false, + "emitDecoratorMetadata": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "importHelpers": true, + "lib": ["ESNext", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "sourceMap": true, + "target": "ESNext", + "forceConsistentCasingInFileNames": true, + "strict": false, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "exclude": ["node_modules", "tmp", "dist"], + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/packages/angular/tsconfig.lib.json b/packages/angular/tsconfig.lib.json new file mode 100644 index 000000000..6a51b0159 --- /dev/null +++ b/packages/angular/tsconfig.lib.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "declaration": true, + "outDir": "dist", + "declarationDir": "dist", + "types": ["node"] + }, + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts" + ], + "include": ["src/**/*.ts"] +} diff --git a/packages/angular/tsconfig.spec.json b/packages/angular/tsconfig.spec.json new file mode 100644 index 000000000..66ed73f27 --- /dev/null +++ b/packages/angular/tsconfig.spec.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "types": ["node"] + }, + "include": [ + "**/*.test.ts", + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/packages/angular/vitest.config.ts b/packages/angular/vitest.config.ts new file mode 100644 index 000000000..8d3773a21 --- /dev/null +++ b/packages/angular/vitest.config.ts @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import {defineConfig} from 'vitest/config'; + +export default defineConfig({ + test: { + environment: 'jsdom', + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dae95cfc2..9d07303a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -84,6 +84,61 @@ importers: specifier: ^7.21.0 version: 7.21.0 + packages/angular: + dependencies: + '@angular/common': + specifier: '>=17.0.0' + version: 21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2) + '@angular/core': + specifier: '>=17.0.0' + version: 21.1.5(rxjs@7.8.2) + '@angular/router': + specifier: '>=17.0.0' + version: 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)))(rxjs@7.8.2) + '@asgardeo/browser': + specifier: workspace:* + version: link:../browser + '@asgardeo/i18n': + specifier: workspace:* + version: link:../i18n + rxjs: + specifier: '>=7.0.0' + version: 7.8.2 + tslib: + specifier: 2.8.1 + version: 2.8.1 + devDependencies: + '@types/node': + specifier: 22.15.3 + version: 22.15.3 + '@wso2/eslint-plugin': + specifier: 'catalog:' + version: https://codeload.github.com/brionmario/wso2-ui-configs/tar.gz/d3041825a4f8f235c8f9fa36b55cf29d54e791c8#path:packages/eslint-plugin(eslint@8.57.0)(typescript@5.7.2) + '@wso2/prettier-config': + specifier: 'catalog:' + version: https://codeload.github.com/brionmario/wso2-ui-configs/tar.gz/d3041825a4f8f235c8f9fa36b55cf29d54e791c8#path:packages/prettier-config(prettier@2.6.2)(typescript@5.7.2) + esbuild: + specifier: 0.25.9 + version: 0.25.9 + eslint: + specifier: 8.57.0 + version: 8.57.0 + jsdom: + specifier: 26.1.0 + version: 26.1.0 + prettier: + specifier: 2.6.2 + version: 2.6.2 + rimraf: + specifier: 6.1.0 + version: 6.1.0 + typescript: + specifier: 5.7.2 + version: 5.7.2 + vitest: + specifier: 3.1.3 + version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@26.1.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + packages/browser: dependencies: '@asgardeo/javascript': @@ -321,7 +376,7 @@ importers: version: 8.57.0 next: specifier: 15.5.12 - version: 15.5.12(@babel/core@7.27.1)(@playwright/test@1.58.2)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)(sass@1.92.1) + version: 15.5.12(@playwright/test@1.58.2)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)(sass@1.92.1) prettier: specifier: 2.6.2 version: 2.6.2 @@ -840,6 +895,46 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@angular/common@21.1.5': + resolution: {integrity: sha512-olO2F0b+H8YBfsuQFEwo9Hjf+B714xGcttDW37+4jnY2IRS2uYeMu2RGIpY7ps+0uZ017c4iK3CCgSPBgmbTcA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@angular/core': 21.1.5 + rxjs: ^6.5.3 || ^7.4.0 + + '@angular/core@21.1.5': + resolution: {integrity: sha512-m61YHiyE+SIvS8UXcFLjYCucv6ShJJCwz9xxEk7ysYW9wOtHdfIf9tgyOsucZDAvrvpSyQLRj5jGBCGm1VIvXA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@angular/compiler': 21.1.5 + rxjs: ^6.5.3 || ^7.4.0 + zone.js: ~0.15.0 || ~0.16.0 + peerDependenciesMeta: + '@angular/compiler': + optional: true + zone.js: + optional: true + + '@angular/platform-browser@21.1.5': + resolution: {integrity: sha512-rAN0cu05Pg7HHe9JMRd3g5JyyVCeFW8QiB/jG6klUrOTF4QzyCbmwlm7MX0uTx3CWAZraWCGbdahUkLyYtuqFA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@angular/animations': 21.1.5 + '@angular/common': 21.1.5 + '@angular/core': 21.1.5 + peerDependenciesMeta: + '@angular/animations': + optional: true + + '@angular/router@21.1.5': + resolution: {integrity: sha512-OjFn6Nw51CU712CMbl2U9TxlCkzOmjMLYPAfnV4+RdG7o+/eOS2nV0oapJ88RNCw7Yl04PA1amc3ql3agDFd4A==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@angular/common': 21.1.5 + '@angular/core': 21.1.5 + '@angular/platform-browser': 21.1.5 + rxjs: ^6.5.3 || ^7.4.0 + '@asamuzakjp/css-color@3.2.0': resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} @@ -4994,10 +5089,6 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.1.0: - resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} - engines: {node: 20 || >=22} - lru-cache@11.2.4: resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} engines: {node: 20 || >=22} @@ -7138,6 +7229,31 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 + '@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2)': + dependencies: + '@angular/core': 21.1.5(rxjs@7.8.2) + rxjs: 7.8.2 + tslib: 2.8.1 + + '@angular/core@21.1.5(rxjs@7.8.2)': + dependencies: + rxjs: 7.8.2 + tslib: 2.8.1 + + '@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2))': + dependencies: + '@angular/common': 21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2) + '@angular/core': 21.1.5(rxjs@7.8.2) + tslib: 2.8.1 + + '@angular/router@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)))(rxjs@7.8.2)': + dependencies: + '@angular/common': 21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2) + '@angular/core': 21.1.5(rxjs@7.8.2) + '@angular/platform-browser': 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)) + rxjs: 7.8.2 + tslib: 2.8.1 + '@asamuzakjp/css-color@3.2.0': 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) @@ -9020,7 +9136,7 @@ snapshots: magic-string: 0.30.17 sirv: 3.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vitest: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@26.1.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) ws: 8.18.2 optionalDependencies: playwright: 1.58.2 @@ -9297,14 +9413,14 @@ snapshots: '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6) '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.1.6) eslint: 8.57.0 - eslint-config-airbnb: 19.0.4(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.0))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.37.5(eslint@8.57.0))(eslint@8.57.0) - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0) - eslint-config-airbnb-typescript: 17.1.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0) + eslint-config-airbnb: 19.0.4(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.0))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.37.5(eslint@8.57.0))(eslint@8.57.0) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0))(eslint@8.57.0) + eslint-config-airbnb-typescript: 17.1.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6))(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0))(eslint@8.57.0) eslint-config-prettier: 8.10.0(eslint@8.57.0) eslint-plugin-eslint-plugin: 5.5.1(eslint@8.57.0) eslint-plugin-header: 3.1.1(eslint@8.57.0) eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0) - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.1.6) + eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.0) eslint-plugin-node: 11.1.0(eslint@8.57.0) eslint-plugin-prettier: 4.2.5(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.6.2) @@ -10431,6 +10547,15 @@ snapshots: escape-string-regexp@4.0.0: {} + eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0))(eslint@8.57.0): + dependencies: + confusing-browser-globals: 1.0.11 + eslint: 8.57.0 + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0) + object.assign: 4.1.7 + object.entries: 1.1.9 + semver: 6.3.1 + eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0): dependencies: confusing-browser-globals: 1.0.11 @@ -10440,13 +10565,13 @@ snapshots: object.entries: 1.1.9 semver: 6.3.1 - eslint-config-airbnb-typescript@17.1.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0): + eslint-config-airbnb-typescript@17.1.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6))(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0))(eslint@8.57.0): dependencies: - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2) + '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6) '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.1.6) eslint: 8.57.0 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0) eslint-config-airbnb-typescript@17.1.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0): dependencies: @@ -10456,6 +10581,17 @@ snapshots: eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0) + eslint-config-airbnb@19.0.4(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.0))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.37.5(eslint@8.57.0))(eslint@8.57.0): + dependencies: + eslint: 8.57.0 + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0) + eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.0) + eslint-plugin-react: 7.37.5(eslint@8.57.0) + eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) + object.assign: 4.1.7 + object.entries: 1.1.9 + eslint-config-airbnb@19.0.4(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.0))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.37.5(eslint@8.57.0))(eslint@8.57.0): dependencies: eslint: 8.57.0 @@ -10573,12 +10709,12 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.1.6): + eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6): dependencies: '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.1.6) eslint: 8.57.0 optionalDependencies: - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2) + '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6) transitivePeerDependencies: - supports-color - typescript @@ -10772,7 +10908,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.1 + debug: 4.4.3 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -11821,8 +11957,6 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@11.1.0: {} - lru-cache@11.2.4: {} lru-cache@5.1.1: @@ -11997,7 +12131,7 @@ snapshots: negotiator@1.0.0: {} - next@15.5.12(@babel/core@7.27.1)(@playwright/test@1.58.2)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)(sass@1.92.1): + next@15.5.12(@playwright/test@1.58.2)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)(sass@1.92.1): dependencies: '@next/env': 15.5.12 '@swc/helpers': 0.5.15 @@ -12005,7 +12139,7 @@ snapshots: postcss: 8.4.31 react: 19.1.4 react-dom: 19.1.4(react@19.1.4) - styled-jsx: 5.1.6(@babel/core@7.27.1)(react@19.1.4) + styled-jsx: 5.1.6(react@19.1.4) optionalDependencies: '@next/swc-darwin-arm64': 15.5.12 '@next/swc-darwin-x64': 15.5.12 @@ -12293,7 +12427,7 @@ snapshots: path-scurry@2.0.0: dependencies: - lru-cache: 11.1.0 + lru-cache: 11.2.4 minipass: 7.1.2 path-to-regexp@8.2.0: {} @@ -12909,7 +13043,6 @@ snapshots: rxjs@7.8.2: dependencies: tslib: 2.8.1 - optional: true safe-array-concat@1.1.3: dependencies: @@ -13356,12 +13489,10 @@ snapshots: style-search@0.1.0: {} - styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.1.4): + styled-jsx@5.1.6(react@19.1.4): dependencies: client-only: 0.0.1 react: 19.1.4 - optionalDependencies: - '@babel/core': 7.27.1 stylehacks@5.1.1(postcss@8.4.31): dependencies: @@ -13812,7 +13943,7 @@ snapshots: vite-node@3.1.3(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: cac: 6.7.14 - debug: 4.4.1 + debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 vite: 6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) @@ -13833,7 +13964,7 @@ snapshots: vite-node@3.1.3(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: cac: 6.7.14 - debug: 4.4.1 + debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 vite: 6.4.1(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) @@ -13995,14 +14126,14 @@ snapshots: '@vitest/spy': 3.1.3 '@vitest/utils': 3.1.3 chai: 5.2.0 - debug: 4.4.1 + debug: 4.4.3 expect-type: 1.2.1 magic-string: 0.30.17 pathe: 2.0.3 std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinyglobby: 0.2.14 + tinyglobby: 0.2.15 tinypool: 1.0.2 tinyrainbow: 2.0.0 vite: 6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) @@ -14036,14 +14167,14 @@ snapshots: '@vitest/spy': 3.1.3 '@vitest/utils': 3.1.3 chai: 5.2.0 - debug: 4.4.1 + debug: 4.4.3 expect-type: 1.2.1 magic-string: 0.30.17 pathe: 2.0.3 std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinyglobby: 0.2.14 + tinyglobby: 0.2.15 tinypool: 1.0.2 tinyrainbow: 2.0.0 vite: 6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) @@ -14077,14 +14208,14 @@ snapshots: '@vitest/spy': 3.1.3 '@vitest/utils': 3.1.3 chai: 5.2.0 - debug: 4.4.1 + debug: 4.4.3 expect-type: 1.2.1 magic-string: 0.30.17 pathe: 2.0.3 std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinyglobby: 0.2.14 + tinyglobby: 0.2.15 tinypool: 1.0.2 tinyrainbow: 2.0.0 vite: 6.4.1(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) diff --git a/tsconfig.json b/tsconfig.json index dc121f199..c88e56dc4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ "baseUrl": ".", "paths": { "@asgardeo/react": ["packages/react/src/index.ts"], + "@asgardeo/angular": ["packages/angular/src/index.ts"], } } } From b3114eac627739c186b1c53d7aee925616d277ff Mon Sep 17 00:00:00 2001 From: DonOmalVindula Date: Fri, 20 Feb 2026 10:20:50 +0530 Subject: [PATCH 2/6] Add teamspace-angular sample app --- pnpm-lock.yaml | 1919 ++++++++++++++++- samples/teamspace-angular/.env.local.example | 5 + samples/teamspace-angular/.gitignore | 27 + samples/teamspace-angular/index.html | 14 + samples/teamspace-angular/package.json | 34 + samples/teamspace-angular/public/vite.svg | 1 + .../src/app/app.component.ts | 33 + .../teamspace-angular/src/app/app.config.ts | 21 + .../teamspace-angular/src/app/app.routes.ts | 20 + .../src/app/components/header.component.ts | 87 + .../src/app/guards/auth.guard.ts | 69 + .../app/layouts/dashboard-layout.component.ts | 17 + .../app/layouts/landing-layout.component.ts | 15 + .../src/app/pages/callback.component.ts | 47 + .../src/app/pages/create-org.component.ts | 134 ++ .../src/app/pages/dashboard.component.ts | 214 ++ .../src/app/pages/debug.component.ts | 236 ++ .../src/app/pages/landing.component.ts | 265 +++ .../src/app/pages/organizations.component.ts | 142 ++ .../src/app/pages/profile.component.ts | 154 ++ samples/teamspace-angular/src/env.d.ts | 16 + samples/teamspace-angular/src/main.ts | 7 + samples/teamspace-angular/src/styles.css | 32 + samples/teamspace-angular/tsconfig.app.json | 9 + samples/teamspace-angular/tsconfig.json | 28 + samples/teamspace-angular/vite.config.ts | 11 + 26 files changed, 3484 insertions(+), 73 deletions(-) create mode 100644 samples/teamspace-angular/.env.local.example create mode 100644 samples/teamspace-angular/.gitignore create mode 100644 samples/teamspace-angular/index.html create mode 100644 samples/teamspace-angular/package.json create mode 100644 samples/teamspace-angular/public/vite.svg create mode 100644 samples/teamspace-angular/src/app/app.component.ts create mode 100644 samples/teamspace-angular/src/app/app.config.ts create mode 100644 samples/teamspace-angular/src/app/app.routes.ts create mode 100644 samples/teamspace-angular/src/app/components/header.component.ts create mode 100644 samples/teamspace-angular/src/app/guards/auth.guard.ts create mode 100644 samples/teamspace-angular/src/app/layouts/dashboard-layout.component.ts create mode 100644 samples/teamspace-angular/src/app/layouts/landing-layout.component.ts create mode 100644 samples/teamspace-angular/src/app/pages/callback.component.ts create mode 100644 samples/teamspace-angular/src/app/pages/create-org.component.ts create mode 100644 samples/teamspace-angular/src/app/pages/dashboard.component.ts create mode 100644 samples/teamspace-angular/src/app/pages/debug.component.ts create mode 100644 samples/teamspace-angular/src/app/pages/landing.component.ts create mode 100644 samples/teamspace-angular/src/app/pages/organizations.component.ts create mode 100644 samples/teamspace-angular/src/app/pages/profile.component.ts create mode 100644 samples/teamspace-angular/src/env.d.ts create mode 100644 samples/teamspace-angular/src/main.ts create mode 100644 samples/teamspace-angular/src/styles.css create mode 100644 samples/teamspace-angular/tsconfig.app.json create mode 100644 samples/teamspace-angular/tsconfig.json create mode 100644 samples/teamspace-angular/vite.config.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9d07303a9..66d9f2e69 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -88,13 +88,13 @@ importers: dependencies: '@angular/common': specifier: '>=17.0.0' - version: 21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2) + version: 21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) '@angular/core': specifier: '>=17.0.0' - version: 21.1.5(rxjs@7.8.2) + version: 21.1.5(rxjs@7.8.2)(zone.js@0.15.0) '@angular/router': specifier: '>=17.0.0' - version: 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)))(rxjs@7.8.2) + version: 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) '@asgardeo/browser': specifier: workspace:* version: link:../browser @@ -789,6 +789,67 @@ importers: specifier: 6.4.1 version: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + samples/teamspace-angular: + dependencies: + '@angular/common': + specifier: 19.2.4 + version: 19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1) + '@angular/core': + specifier: 19.2.4 + version: 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) + '@angular/forms': + specifier: 19.2.4 + version: 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1) + '@angular/platform-browser': + specifier: 19.2.4 + version: 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)) + '@angular/platform-browser-dynamic': + specifier: 19.2.4 + version: 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/compiler@19.2.4)(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))) + '@angular/router': + specifier: 19.2.4 + version: 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1) + '@asgardeo/angular': + specifier: workspace:* + version: link:../../packages/angular + rxjs: + specifier: 7.8.1 + version: 7.8.1 + tslib: + specifier: 2.8.1 + version: 2.8.1 + zone.js: + specifier: 0.15.0 + version: 0.15.0 + devDependencies: + '@analogjs/vite-plugin-angular': + specifier: 1.16.2 + version: 1.16.2(@angular/build@19.2.4(@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3))(@angular/compiler@19.2.4)(@types/node@24.0.3)(chokidar@4.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.0)) + '@angular/build': + specifier: 19.2.4 + version: 19.2.4(@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3))(@angular/compiler@19.2.4)(@types/node@24.0.3)(chokidar@4.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.0) + '@angular/compiler': + specifier: 19.2.4 + version: 19.2.4 + '@angular/compiler-cli': + specifier: 19.2.4 + version: 19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3) + '@tailwindcss/vite': + specifier: 4.1.8 + version: 4.1.8(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + '@vitejs/plugin-basic-ssl': + specifier: 2.0.0 + version: 2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + tailwindcss: + specifier: 4.1.8 + version: 4.1.8 + typescript: + specifier: 5.8.3 + version: 5.8.3 + vite: + specifier: 6.4.1 + version: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + samples/teamspace-react: dependencies: '@asgardeo/i18n': @@ -895,6 +956,73 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@analogjs/vite-plugin-angular@1.16.2': + resolution: {integrity: sha512-2dHwp11/oyUnxXXU5vXgRdyN7nrwEZWGYAfOEYMkk2bHfOohH6BAPpR3+eiHbLVAxt7kt+igBcOCrvRFUkJ30A==} + peerDependencies: + '@angular-devkit/build-angular': ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + '@angular/build': ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@angular-devkit/build-angular': + optional: true + '@angular/build': + optional: true + + '@angular-devkit/architect@0.1902.4': + resolution: {integrity: sha512-YTLiJ7uVItZTAxRuSgASP0M5qILESWH8xGmfR+YWR1JiJem09DWEOpWeLdha1BFzUui5L+6j1btzh4FUHJOtAg==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + + '@angular-devkit/core@19.2.4': + resolution: {integrity: sha512-dL6AmCQsKh+CFVvO/jxX8qZpamVwt9r4iIo7fYcAI2+mTSDGxxBGWbS+onIfdPFuRp2HgKa+AT6WiHmRqu63AA==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + chokidar: ^4.0.0 + peerDependenciesMeta: + chokidar: + optional: true + + '@angular/build@19.2.4': + resolution: {integrity: sha512-poCXvmwKri3snWa9zVJ2sW7wyJatZjkwnH6GUBdJrM2dXRQ+LYLk/oXqEjlSRBYNna7P1ZcKNqBbzu0/SnnngA==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + '@angular/compiler': ^19.0.0 || ^19.2.0-next.0 + '@angular/compiler-cli': ^19.0.0 || ^19.2.0-next.0 + '@angular/localize': ^19.0.0 || ^19.2.0-next.0 + '@angular/platform-server': ^19.0.0 || ^19.2.0-next.0 + '@angular/service-worker': ^19.0.0 || ^19.2.0-next.0 + '@angular/ssr': ^19.2.4 + karma: ^6.4.0 + less: ^4.2.0 + ng-packagr: ^19.0.0 || ^19.2.0-next.0 + postcss: ^8.4.0 + tailwindcss: ^2.0.0 || ^3.0.0 || ^4.0.0 + typescript: '>=5.5 <5.9' + peerDependenciesMeta: + '@angular/localize': + optional: true + '@angular/platform-server': + optional: true + '@angular/service-worker': + optional: true + '@angular/ssr': + optional: true + karma: + optional: true + less: + optional: true + ng-packagr: + optional: true + postcss: + optional: true + tailwindcss: + optional: true + + '@angular/common@19.2.4': + resolution: {integrity: sha512-5iBerI1hkY8rAt0gZQgOlfzR69jj5j25JyfkDOhdZhezE0pqhDc69OnbkUM20LTau4bFRYOj015eiKWzE2DOzQ==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + '@angular/core': 19.2.4 + rxjs: ^6.5.3 || ^7.4.0 + '@angular/common@21.1.5': resolution: {integrity: sha512-olO2F0b+H8YBfsuQFEwo9Hjf+B714xGcttDW37+4jnY2IRS2uYeMu2RGIpY7ps+0uZ017c4iK3CCgSPBgmbTcA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -902,6 +1030,25 @@ packages: '@angular/core': 21.1.5 rxjs: ^6.5.3 || ^7.4.0 + '@angular/compiler-cli@19.2.4': + resolution: {integrity: sha512-zIWWJm0L+OGMGoRJ73WW96+LDSmZsWqNpwYYXBAEzzoMtPMsWg8uiOIxxjF9ZUWQ1Y5ODUSADnBJwt5vtiLbzA==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + hasBin: true + peerDependencies: + '@angular/compiler': 19.2.4 + typescript: '>=5.5 <5.9' + + '@angular/compiler@19.2.4': + resolution: {integrity: sha512-HxUwmkoXMlj9EiSmRMRTI4vR3d5hSxiIZazq7OWtlEm8uKedzLzf72dF+hdc3yF6JCdF87vWiQN22bcGeTxYZw==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + + '@angular/core@19.2.4': + resolution: {integrity: sha512-ZuSMg+LWG0ADLEvMzSqU+D6M5KcQtxBssEFq4UskGIYuvNGqC91hAl4sbnXDQ5C7GgFcLY6ouaemS6dBOIfc/g==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + rxjs: ^6.5.3 || ^7.4.0 + zone.js: ~0.15.0 + '@angular/core@21.1.5': resolution: {integrity: sha512-m61YHiyE+SIvS8UXcFLjYCucv6ShJJCwz9xxEk7ysYW9wOtHdfIf9tgyOsucZDAvrvpSyQLRj5jGBCGm1VIvXA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -915,6 +1062,35 @@ packages: zone.js: optional: true + '@angular/forms@19.2.4': + resolution: {integrity: sha512-XzFVmy2BduohtV6E304VCiCvayqV6hiYfPDvkzQnPiFfnQqRCGOTKSDOqxBDsSoDoZW7vZNHe3HmNMdyPg3Rog==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + '@angular/common': 19.2.4 + '@angular/core': 19.2.4 + '@angular/platform-browser': 19.2.4 + rxjs: ^6.5.3 || ^7.4.0 + + '@angular/platform-browser-dynamic@19.2.4': + resolution: {integrity: sha512-KEVf5YTVBFrFAAW7nOVARy+A/xFJ56iDaeoqn63XB3VF5btEGpqoAxKbQGWRRB9G68uZBFXalJ9wXjS6v2T4ng==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + '@angular/common': 19.2.4 + '@angular/compiler': 19.2.4 + '@angular/core': 19.2.4 + '@angular/platform-browser': 19.2.4 + + '@angular/platform-browser@19.2.4': + resolution: {integrity: sha512-skP+Oq9hxh0hkLcs2bXgnt7Z+KKP5xZYzaHPEToLtPat6l6kSPjT0CJ+DE/8ce443hItAcCbn+JrKGC29nd2pw==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + '@angular/animations': 19.2.4 + '@angular/common': 19.2.4 + '@angular/core': 19.2.4 + peerDependenciesMeta: + '@angular/animations': + optional: true + '@angular/platform-browser@21.1.5': resolution: {integrity: sha512-rAN0cu05Pg7HHe9JMRd3g5JyyVCeFW8QiB/jG6klUrOTF4QzyCbmwlm7MX0uTx3CWAZraWCGbdahUkLyYtuqFA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -926,6 +1102,15 @@ packages: '@angular/animations': optional: true + '@angular/router@19.2.4': + resolution: {integrity: sha512-pnQX6gk8Z+YQFtnuqRDPEv+d9Up2oP1ZJk9/i/vnYS53PguSEtKgCBuiy6FQmn7SdrYFJ3+ZoV6ow9jhv00eqA==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + peerDependencies: + '@angular/common': 19.2.4 + '@angular/core': 19.2.4 + '@angular/platform-browser': 19.2.4 + rxjs: ^6.5.3 || ^7.4.0 + '@angular/router@21.1.5': resolution: {integrity: sha512-OjFn6Nw51CU712CMbl2U9TxlCkzOmjMLYPAfnV4+RdG7o+/eOS2nV0oapJ88RNCw7Yl04PA1amc3ql3agDFd4A==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -964,6 +1149,14 @@ packages: resolution: {integrity: sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==} engines: {node: '>=6.9.0'} + '@babel/core@7.26.10': + resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.9': + resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} + engines: {node: '>=6.9.0'} + '@babel/core@7.27.1': resolution: {integrity: sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==} engines: {node: '>=6.9.0'} @@ -979,6 +1172,10 @@ packages: resolution: {integrity: sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==} engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.25.9': + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.27.2': resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} @@ -997,6 +1194,10 @@ packages: resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} + '@babel/helper-split-export-declaration@7.24.7': + resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -1018,6 +1219,12 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-react-jsx-self@7.27.1': resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} engines: {node: '>=6.9.0'} @@ -1211,6 +1418,12 @@ packages: '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} + '@esbuild/aix-ppc64@0.25.1': + resolution: {integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/aix-ppc64@0.25.9': resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==} engines: {node: '>=18'} @@ -1223,6 +1436,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/android-arm64@0.25.1': + resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm64@0.25.9': resolution: {integrity: sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==} engines: {node: '>=18'} @@ -1235,6 +1454,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm@0.25.1': + resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.25.9': resolution: {integrity: sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==} engines: {node: '>=18'} @@ -1247,6 +1472,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-x64@0.25.1': + resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/android-x64@0.25.9': resolution: {integrity: sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==} engines: {node: '>=18'} @@ -1259,6 +1490,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/darwin-arm64@0.25.1': + resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-arm64@0.25.9': resolution: {integrity: sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==} engines: {node: '>=18'} @@ -1271,6 +1508,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-x64@0.25.1': + resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.25.9': resolution: {integrity: sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==} engines: {node: '>=18'} @@ -1283,6 +1526,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/freebsd-arm64@0.25.1': + resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-arm64@0.25.9': resolution: {integrity: sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==} engines: {node: '>=18'} @@ -1295,6 +1544,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-x64@0.25.1': + resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.9': resolution: {integrity: sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==} engines: {node: '>=18'} @@ -1307,6 +1562,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/linux-arm64@0.25.1': + resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.25.9': resolution: {integrity: sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==} engines: {node: '>=18'} @@ -1319,6 +1580,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm@0.25.1': + resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-arm@0.25.9': resolution: {integrity: sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==} engines: {node: '>=18'} @@ -1331,6 +1598,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-ia32@0.25.1': + resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-ia32@0.25.9': resolution: {integrity: sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==} engines: {node: '>=18'} @@ -1343,6 +1616,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-loong64@0.25.1': + resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.25.9': resolution: {integrity: sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==} engines: {node: '>=18'} @@ -1355,6 +1634,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-mips64el@0.25.1': + resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-mips64el@0.25.9': resolution: {integrity: sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==} engines: {node: '>=18'} @@ -1367,6 +1652,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-ppc64@0.25.1': + resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-ppc64@0.25.9': resolution: {integrity: sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==} engines: {node: '>=18'} @@ -1379,6 +1670,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-riscv64@0.25.1': + resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-riscv64@0.25.9': resolution: {integrity: sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==} engines: {node: '>=18'} @@ -1391,6 +1688,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-s390x@0.25.1': + resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-s390x@0.25.9': resolution: {integrity: sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==} engines: {node: '>=18'} @@ -1403,6 +1706,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-x64@0.25.1': + resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.25.9': resolution: {integrity: sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==} engines: {node: '>=18'} @@ -1415,6 +1724,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/netbsd-arm64@0.25.1': + resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-arm64@0.25.9': resolution: {integrity: sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==} engines: {node: '>=18'} @@ -1427,6 +1742,12 @@ packages: cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-x64@0.25.1': + resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.9': resolution: {integrity: sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==} engines: {node: '>=18'} @@ -1439,6 +1760,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/openbsd-arm64@0.25.1': + resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-arm64@0.25.9': resolution: {integrity: sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==} engines: {node: '>=18'} @@ -1451,6 +1778,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-x64@0.25.1': + resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.9': resolution: {integrity: sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==} engines: {node: '>=18'} @@ -1475,6 +1808,12 @@ packages: cpu: [arm64] os: [openharmony] + '@esbuild/sunos-x64@0.25.1': + resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.25.9': resolution: {integrity: sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==} engines: {node: '>=18'} @@ -1487,6 +1826,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/win32-arm64@0.25.1': + resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-arm64@0.25.9': resolution: {integrity: sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==} engines: {node: '>=18'} @@ -1499,6 +1844,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-ia32@0.25.1': + resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.25.9': resolution: {integrity: sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==} engines: {node: '>=18'} @@ -1511,6 +1862,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-x64@0.25.1': + resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.25.9': resolution: {integrity: sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==} engines: {node: '>=18'} @@ -1785,6 +2142,28 @@ packages: cpu: [x64] os: [win32] + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} + engines: {node: '>=18'} + + '@inquirer/confirm@5.1.6': + resolution: {integrity: sha512-6ZXYK3M1XmaVBZX6FCfChgtponnL0R6I7k8Nu+kaoNkT828FVZTcca1MqmWQipaW2oNREQl5AaPCUOOCVNdRMw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@10.3.2': + resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + '@inquirer/external-editor@1.0.3': resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} engines: {node: '>=18'} @@ -1794,6 +2173,19 @@ packages: '@types/node': optional: true + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} + + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} engines: {node: 20 || >=22} @@ -1851,6 +2243,36 @@ packages: '@jspm/core@2.1.0': resolution: {integrity: sha512-3sRl+pkyFY/kLmHl0cgHiFp2xEqErA8N3ECjMs7serSUBmoJ70lBa0PG5t0IM6WJgdZNyyI0R8YFfi5wM8+mzg==} + '@lmdb/lmdb-darwin-arm64@3.2.6': + resolution: {integrity: sha512-yF/ih9EJJZc72psFQbwnn8mExIWfTnzWJg+N02hnpXtDPETYLmQswIMBn7+V88lfCaFrMozJsUvcEQIkEPU0Gg==} + cpu: [arm64] + os: [darwin] + + '@lmdb/lmdb-darwin-x64@3.2.6': + resolution: {integrity: sha512-5BbCumsFLbCi586Bb1lTWQFkekdQUw8/t8cy++Uq251cl3hbDIGEwD9HAwh8H6IS2F6QA9KdKmO136LmipRNkg==} + cpu: [x64] + os: [darwin] + + '@lmdb/lmdb-linux-arm64@3.2.6': + resolution: {integrity: sha512-l5VmJamJ3nyMmeD1ANBQCQqy7do1ESaJQfKPSm2IG9/ADZryptTyCj8N6QaYgIWewqNUrcbdMkJajRQAt5Qjfg==} + cpu: [arm64] + os: [linux] + + '@lmdb/lmdb-linux-arm@3.2.6': + resolution: {integrity: sha512-+6XgLpMb7HBoWxXj+bLbiiB4s0mRRcDPElnRS3LpWRzdYSe+gFk5MT/4RrVNqd2MESUDmb53NUXw1+BP69bjiQ==} + cpu: [arm] + os: [linux] + + '@lmdb/lmdb-linux-x64@3.2.6': + resolution: {integrity: sha512-nDYT8qN9si5+onHYYaI4DiauDMx24OAiuZAUsEqrDy+ja/3EbpXPX/VAkMV8AEaQhy3xc4dRC+KcYIvOFefJ4Q==} + cpu: [x64] + os: [linux] + + '@lmdb/lmdb-win32-x64@3.2.6': + resolution: {integrity: sha512-XlqVtILonQnG+9fH2N3Aytria7P/1fwDgDhl29rde96uH2sLB8CHORIf2PfuLVzFQJ7Uqp8py9AYwr3ZUCFfWg==} + cpu: [x64] + os: [win32] + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -1863,6 +2285,149 @@ packages: '@microsoft/tsdoc@0.14.2': resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} + cpu: [arm64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==} + cpu: [x64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==} + cpu: [arm64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==} + cpu: [arm] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==} + cpu: [x64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==} + cpu: [x64] + os: [win32] + + '@napi-rs/nice-android-arm-eabi@1.1.1': + resolution: {integrity: sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + + '@napi-rs/nice-android-arm64@1.1.1': + resolution: {integrity: sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@napi-rs/nice-darwin-arm64@1.1.1': + resolution: {integrity: sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@napi-rs/nice-darwin-x64@1.1.1': + resolution: {integrity: sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@napi-rs/nice-freebsd-x64@1.1.1': + resolution: {integrity: sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@napi-rs/nice-linux-arm-gnueabihf@1.1.1': + resolution: {integrity: sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@napi-rs/nice-linux-arm64-gnu@1.1.1': + resolution: {integrity: sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-arm64-musl@1.1.1': + resolution: {integrity: sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@napi-rs/nice-linux-ppc64-gnu@1.1.1': + resolution: {integrity: sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==} + engines: {node: '>= 10'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-riscv64-gnu@1.1.1': + resolution: {integrity: sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-s390x-gnu@1.1.1': + resolution: {integrity: sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==} + engines: {node: '>= 10'} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-x64-gnu@1.1.1': + resolution: {integrity: sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-x64-musl@1.1.1': + resolution: {integrity: sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@napi-rs/nice-openharmony-arm64@1.1.1': + resolution: {integrity: sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [openharmony] + + '@napi-rs/nice-win32-arm64-msvc@1.1.1': + resolution: {integrity: sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@napi-rs/nice-win32-ia32-msvc@1.1.1': + resolution: {integrity: sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@napi-rs/nice-win32-x64-msvc@1.1.1': + resolution: {integrity: sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@napi-rs/nice@1.1.1': + resolution: {integrity: sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==} + engines: {node: '>= 10'} + '@napi-rs/wasm-runtime@0.2.4': resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} @@ -2221,6 +2786,11 @@ packages: cpu: [arm] os: [android] + '@rollup/rollup-android-arm-eabi@4.34.8': + resolution: {integrity: sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==} + cpu: [arm] + os: [android] + '@rollup/rollup-android-arm-eabi@4.50.0': resolution: {integrity: sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==} cpu: [arm] @@ -2231,6 +2801,11 @@ packages: cpu: [arm64] os: [android] + '@rollup/rollup-android-arm64@4.34.8': + resolution: {integrity: sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==} + cpu: [arm64] + os: [android] + '@rollup/rollup-android-arm64@4.50.0': resolution: {integrity: sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==} cpu: [arm64] @@ -2241,6 +2816,11 @@ packages: cpu: [arm64] os: [darwin] + '@rollup/rollup-darwin-arm64@4.34.8': + resolution: {integrity: sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==} + cpu: [arm64] + os: [darwin] + '@rollup/rollup-darwin-arm64@4.50.0': resolution: {integrity: sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==} cpu: [arm64] @@ -2251,6 +2831,11 @@ packages: cpu: [x64] os: [darwin] + '@rollup/rollup-darwin-x64@4.34.8': + resolution: {integrity: sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==} + cpu: [x64] + os: [darwin] + '@rollup/rollup-darwin-x64@4.50.0': resolution: {integrity: sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==} cpu: [x64] @@ -2261,6 +2846,11 @@ packages: cpu: [arm64] os: [freebsd] + '@rollup/rollup-freebsd-arm64@4.34.8': + resolution: {integrity: sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==} + cpu: [arm64] + os: [freebsd] + '@rollup/rollup-freebsd-arm64@4.50.0': resolution: {integrity: sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==} cpu: [arm64] @@ -2271,6 +2861,11 @@ packages: cpu: [x64] os: [freebsd] + '@rollup/rollup-freebsd-x64@4.34.8': + resolution: {integrity: sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==} + cpu: [x64] + os: [freebsd] + '@rollup/rollup-freebsd-x64@4.50.0': resolution: {integrity: sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==} cpu: [x64] @@ -2282,6 +2877,12 @@ packages: os: [linux] libc: [glibc] + '@rollup/rollup-linux-arm-gnueabihf@4.34.8': + resolution: {integrity: sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==} + cpu: [arm] + os: [linux] + libc: [glibc] + '@rollup/rollup-linux-arm-gnueabihf@4.50.0': resolution: {integrity: sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==} cpu: [arm] @@ -2294,6 +2895,12 @@ packages: os: [linux] libc: [musl] + '@rollup/rollup-linux-arm-musleabihf@4.34.8': + resolution: {integrity: sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==} + cpu: [arm] + os: [linux] + libc: [musl] + '@rollup/rollup-linux-arm-musleabihf@4.50.0': resolution: {integrity: sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==} cpu: [arm] @@ -2306,6 +2913,12 @@ packages: os: [linux] libc: [glibc] + '@rollup/rollup-linux-arm64-gnu@4.34.8': + resolution: {integrity: sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rollup/rollup-linux-arm64-gnu@4.50.0': resolution: {integrity: sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==} cpu: [arm64] @@ -2318,6 +2931,12 @@ packages: os: [linux] libc: [musl] + '@rollup/rollup-linux-arm64-musl@4.34.8': + resolution: {integrity: sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==} + cpu: [arm64] + os: [linux] + libc: [musl] + '@rollup/rollup-linux-arm64-musl@4.50.0': resolution: {integrity: sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==} cpu: [arm64] @@ -2330,6 +2949,12 @@ packages: os: [linux] libc: [glibc] + '@rollup/rollup-linux-loongarch64-gnu@4.34.8': + resolution: {integrity: sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==} + cpu: [loong64] + os: [linux] + libc: [glibc] + '@rollup/rollup-linux-loongarch64-gnu@4.50.0': resolution: {integrity: sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==} cpu: [loong64] @@ -2342,6 +2967,12 @@ packages: os: [linux] libc: [glibc] + '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': + resolution: {integrity: sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@rollup/rollup-linux-ppc64-gnu@4.50.0': resolution: {integrity: sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==} cpu: [ppc64] @@ -2354,6 +2985,12 @@ packages: os: [linux] libc: [glibc] + '@rollup/rollup-linux-riscv64-gnu@4.34.8': + resolution: {integrity: sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + '@rollup/rollup-linux-riscv64-gnu@4.50.0': resolution: {integrity: sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==} cpu: [riscv64] @@ -2372,6 +3009,12 @@ packages: os: [linux] libc: [glibc] + '@rollup/rollup-linux-s390x-gnu@4.34.8': + resolution: {integrity: sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@rollup/rollup-linux-s390x-gnu@4.50.0': resolution: {integrity: sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==} cpu: [s390x] @@ -2384,6 +3027,12 @@ packages: os: [linux] libc: [glibc] + '@rollup/rollup-linux-x64-gnu@4.34.8': + resolution: {integrity: sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rollup/rollup-linux-x64-gnu@4.50.0': resolution: {integrity: sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==} cpu: [x64] @@ -2396,6 +3045,12 @@ packages: os: [linux] libc: [musl] + '@rollup/rollup-linux-x64-musl@4.34.8': + resolution: {integrity: sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==} + cpu: [x64] + os: [linux] + libc: [musl] + '@rollup/rollup-linux-x64-musl@4.50.0': resolution: {integrity: sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==} cpu: [x64] @@ -2412,6 +3067,11 @@ packages: cpu: [arm64] os: [win32] + '@rollup/rollup-win32-arm64-msvc@4.34.8': + resolution: {integrity: sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==} + cpu: [arm64] + os: [win32] + '@rollup/rollup-win32-arm64-msvc@4.50.0': resolution: {integrity: sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==} cpu: [arm64] @@ -2422,6 +3082,11 @@ packages: cpu: [ia32] os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.34.8': + resolution: {integrity: sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==} + cpu: [ia32] + os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.50.0': resolution: {integrity: sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==} cpu: [ia32] @@ -2432,6 +3097,11 @@ packages: cpu: [x64] os: [win32] + '@rollup/rollup-win32-x64-msvc@4.34.8': + resolution: {integrity: sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==} + cpu: [x64] + os: [win32] + '@rollup/rollup-win32-x64-msvc@4.50.0': resolution: {integrity: sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==} cpu: [x64] @@ -2608,6 +3278,9 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} + '@ts-morph/common@0.22.0': + resolution: {integrity: sha512-HqNBuV/oIlMKdkLshXd1zKBqNQCsuPEsgQOkfFQ/eUKjRlwndXW1AjN9LVkBEIukm00gGXSRmfkl0Wv5VXLnlw==} + '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} @@ -2687,6 +3360,9 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + '@typescript-eslint/eslint-plugin@6.21.0': resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} engines: {node: ^16.0.0 || >=18.0.0} @@ -2828,6 +3504,12 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@vitejs/plugin-basic-ssl@1.2.0': + resolution: {integrity: sha512-mkQnxTkcldAzIsomk1UuLfAu9n+kpQ3JbHcpCp7d2Oo6ITtji8pHS3QToOWjhPFvNQSnhlkAjmGbhv2QvwO/7Q==} + engines: {node: '>=14.21.3'} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + '@vitejs/plugin-basic-ssl@2.0.0': resolution: {integrity: sha512-gc9Tjg8bUxBVSTzeWT3Njc0Cl3PakHFKdNfABnZWiUgbxqmHDEn7uECv3fHVylxoYgNzAcmU7ZrILz+BwSo3sA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -3078,6 +3760,14 @@ packages: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -3091,6 +3781,10 @@ packages: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} + ansi-escapes@7.3.0: + resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} + engines: {node: '>=18'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -3228,6 +3922,10 @@ packages: resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==} engines: {node: '>=6.0.0'} + beasties@0.2.0: + resolution: {integrity: sha512-Ljqskqx/tbZagIglYoJIMzH5zgssyp+in9+9sAyh15N22AornBeIDnb8EZ6Rk+6ShfMxd92uO3gfpT0NtZbpow==} + engines: {node: '>=14.0.0'} + better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} @@ -3386,10 +4084,22 @@ packages: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + cli-spinners@2.6.1: resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} engines: {node: '>=6'} + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} @@ -3405,6 +4115,9 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + code-block-writer@12.0.0: + resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -3415,6 +4128,9 @@ packages: colord@2.9.3: resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + colorjs.io@0.5.2: resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==} @@ -3532,6 +4248,9 @@ packages: css-select@4.3.0: resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + css-tree@1.1.3: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} engines: {node: '>=8.0.0'} @@ -3706,10 +4425,6 @@ packages: engines: {node: '>=0.10'} hasBin: true - detect-libc@2.0.4: - resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} - engines: {node: '>=8'} - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -3739,6 +4454,9 @@ packages: dom-serializer@1.4.1: resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dom-walk@0.1.2: resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} @@ -3749,12 +4467,19 @@ packages: resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} engines: {node: '>= 4'} + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + dompurify@3.2.7: resolution: {integrity: sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==} domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + dotenv-expand@11.0.7: resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} engines: {node: '>=12'} @@ -3788,6 +4513,9 @@ packages: elliptic@6.6.1: resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -3824,6 +4552,10 @@ packages: resolution: {integrity: sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==} engines: {node: '>=0.12'} + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -3882,6 +4614,11 @@ packages: peerDependencies: esbuild: '>=0.14.0 <=0.25.x' + esbuild@0.25.1: + resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==} + engines: {node: '>=18'} + hasBin: true + esbuild@0.25.9: resolution: {integrity: sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==} engines: {node: '>=18'} @@ -4181,6 +4918,9 @@ packages: eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + evp_bytestokey@1.0.3: resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} @@ -4375,6 +5115,10 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -4402,6 +5146,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + glob@10.5.0: resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me @@ -4548,6 +5295,9 @@ packages: resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} engines: {node: '>=8'} + htmlparser2@9.1.0: + resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} + http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -4692,6 +5442,14 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.1.0: + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} + engines: {node: '>=18'} + is-generator-function@1.1.2: resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} engines: {node: '>= 0.4'} @@ -4813,6 +5571,10 @@ packages: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + istanbul-lib-report@3.0.1: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} @@ -4932,6 +5694,9 @@ packages: jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} @@ -5042,6 +5807,14 @@ packages: resolution: {integrity: sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + listr2@8.2.5: + resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} + engines: {node: '>=18.0.0'} + + lmdb@3.2.6: + resolution: {integrity: sha512-SuHqzPl7mYStna8WRotY8XX/EUZBjjv3QyKIByeCLFfC9uXT/OIHByEcA07PzbMfQAM0KYJtLgtpMRlIe5dErQ==} + hasBin: true + local-pkg@1.1.1: resolution: {integrity: sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==} engines: {node: '>=14'} @@ -5079,6 +5852,10 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -5197,6 +5974,10 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + min-document@2.19.1: resolution: {integrity: sha512-8lqe85PkqQJzIcs2iD7xW/WSxcncC3/DPVbTOafKNJDIMXwGfwXS350mH4SJslomntN2iYtFBuC0yNO3CEap6g==} @@ -5252,6 +6033,11 @@ packages: resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} engines: {node: '>= 18'} + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + mlly@1.7.4: resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} @@ -5266,9 +6052,20 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + msgpackr-extract@3.0.3: + resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==} + hasBin: true + + msgpackr@1.11.8: + resolution: {integrity: sha512-bC4UGzHhVvgDNS7kn9tV8fAucIYUBuGojcaLiz7v+P63Lmtm0Xeji8B/8tYKddALXxJLpwIeBmUN3u64C4YkRA==} + muggle-string@0.4.1: resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -5305,6 +6102,9 @@ packages: sass: optional: true + node-addon-api@6.1.0: + resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} + node-addon-api@7.1.1: resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} @@ -5317,6 +6117,10 @@ packages: encoding: optional: true + node-gyp-build-optional-packages@5.2.2: + resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} + hasBin: true + node-machine-id@1.1.12: resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==} @@ -5412,6 +6216,10 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -5424,6 +6232,9 @@ packages: resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} engines: {node: '>=10'} + ordered-binary@1.6.1: + resolution: {integrity: sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==} + outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} @@ -5489,6 +6300,12 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + parse5-html-rewriting-stream@7.0.0: + resolution: {integrity: sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==} + + parse5-sax-parser@7.0.0: + resolution: {integrity: sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==} + parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} @@ -5551,10 +6368,17 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + picomatch@4.0.3: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + piscina@4.8.0: + resolution: {integrity: sha512-EZJb+ZxDrQf3dihsUL7p42pjNyrNIFJCrRHPMgxu/svsj+P3xS3fuEWp7k2+rfsavfl1N0G29b1HGs7J0m8rZA==} + pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -5962,6 +6786,9 @@ packages: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -6017,10 +6844,17 @@ packages: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -6061,6 +6895,11 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rollup@4.34.8: + resolution: {integrity: sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + rollup@4.50.0: resolution: {integrity: sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -6076,6 +6915,9 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} @@ -6222,6 +7064,11 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + sass@1.85.0: + resolution: {integrity: sha512-3ToiC1xZ1Y8aU7+CkgCI/tqyuPXEmYGJXO7H4uqp0xkLXUqp88rQQ4j1HmP37xSJLbCJPaIiv+cT1y+grssrww==} + engines: {node: '>=14.0.0'} + hasBin: true + sass@1.92.1: resolution: {integrity: sha512-ffmsdbwqb3XeyR8jJR6KelIXARM9bFQe8A6Q3W4Klmwy5Ckd5gz7jgUNHo4UOqutU5Sk1DtKLbpDP0nLCg1xqQ==} engines: {node: '>=14.0.0'} @@ -6250,6 +7097,11 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + semver@7.7.2: resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} engines: {node: '>=10'} @@ -6351,6 +7203,14 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.2: + resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} + engines: {node: '>=18'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -6366,6 +7226,10 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + spawndamnit@3.0.1: resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} @@ -6422,6 +7286,10 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + string.prototype.includes@2.0.1: resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} engines: {node: '>= 0.4'} @@ -6630,10 +7498,6 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyglobby@0.2.14: - resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} - engines: {node: '>=12.0.0'} - tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} @@ -6719,6 +7583,9 @@ packages: peerDependencies: typescript: '>=4.8.4' + ts-morph@21.0.1: + resolution: {integrity: sha512-dbDtVdEAncKctzrVZ+Nr7kHpHkv+0JDJb2MjjpBaj8bFeCkePU9rHfMklmhuLFnpeq/EJZk2IhStY6NzqgjOkg==} + tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} @@ -6831,6 +7698,9 @@ packages: resolution: {integrity: sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg==} engines: {node: '>=20.18.1'} + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -6877,6 +7747,12 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + vite-node@3.0.8: resolution: {integrity: sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -6887,6 +7763,46 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true + vite@6.2.0: + resolution: {integrity: sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + 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} @@ -7059,9 +7975,16 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} + watchpack@2.4.2: + resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} + engines: {node: '>=10.13.0'} + wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + weak-lru-cache@1.2.2: + resolution: {integrity: sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -7131,6 +8054,10 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -7139,6 +8066,10 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -7199,58 +8130,201 @@ packages: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} - yaml@2.8.0: - resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==} - engines: {node: '>= 14.6'} - hasBin: true + yaml@2.8.0: + resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} + + zone.js@0.15.0: + resolution: {integrity: sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA==} + +snapshots: + + '@acemir/cssom@0.9.31': {} + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + + '@analogjs/vite-plugin-angular@1.16.2(@angular/build@19.2.4(@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3))(@angular/compiler@19.2.4)(@types/node@24.0.3)(chokidar@4.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.0))': + dependencies: + ts-morph: 21.0.1 + vfile: 6.0.3 + optionalDependencies: + '@angular/build': 19.2.4(@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3))(@angular/compiler@19.2.4)(@types/node@24.0.3)(chokidar@4.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.0) + + '@angular-devkit/architect@0.1902.4(chokidar@4.0.3)': + dependencies: + '@angular-devkit/core': 19.2.4(chokidar@4.0.3) + rxjs: 7.8.1 + transitivePeerDependencies: + - chokidar + + '@angular-devkit/core@19.2.4(chokidar@4.0.3)': + dependencies: + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + jsonc-parser: 3.3.1 + picomatch: 4.0.2 + rxjs: 7.8.1 + source-map: 0.7.4 + optionalDependencies: + chokidar: 4.0.3 + + '@angular/build@19.2.4(@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3))(@angular/compiler@19.2.4)(@types/node@24.0.3)(chokidar@4.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.0)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@angular-devkit/architect': 0.1902.4(chokidar@4.0.3) + '@angular/compiler': 19.2.4 + '@angular/compiler-cli': 19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3) + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.10) + '@inquirer/confirm': 5.1.6(@types/node@24.0.3) + '@vitejs/plugin-basic-ssl': 1.2.0(vite@6.2.0(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + beasties: 0.2.0 + browserslist: 4.24.5 + esbuild: 0.25.1 + fast-glob: 3.3.3 + https-proxy-agent: 7.0.6 + istanbul-lib-instrument: 6.0.3 + listr2: 8.2.5 + magic-string: 0.30.17 + mrmime: 2.0.1 + parse5-html-rewriting-stream: 7.0.0 + picomatch: 4.0.2 + piscina: 4.8.0 + rollup: 4.34.8 + sass: 1.85.0 + semver: 7.7.1 + source-map-support: 0.5.21 + typescript: 5.8.3 + vite: 6.2.0(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + watchpack: 2.4.2 + optionalDependencies: + lmdb: 3.2.6 + postcss: 8.5.6 + tailwindcss: 4.1.8 + transitivePeerDependencies: + - '@types/node' + - chokidar + - jiti + - lightningcss + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + '@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)': + dependencies: + '@angular/core': 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) + rxjs: 7.8.1 + tslib: 2.8.1 - yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} + '@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)': + dependencies: + '@angular/core': 21.1.5(rxjs@7.8.2)(zone.js@0.15.0) + rxjs: 7.8.2 + tslib: 2.8.1 - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} + '@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3)': + dependencies: + '@angular/compiler': 19.2.4 + '@babel/core': 7.26.9 + '@jridgewell/sourcemap-codec': 1.5.5 + chokidar: 4.0.3 + convert-source-map: 1.9.0 + reflect-metadata: 0.2.2 + semver: 7.7.3 + tslib: 2.8.1 + typescript: 5.8.3 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + '@angular/compiler@19.2.4': + dependencies: + tslib: 2.8.1 - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} + '@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)': + dependencies: + rxjs: 7.8.1 + tslib: 2.8.1 + zone.js: 0.15.0 -snapshots: + '@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0)': + dependencies: + rxjs: 7.8.2 + tslib: 2.8.1 + optionalDependencies: + zone.js: 0.15.0 - '@acemir/cssom@0.9.31': {} + '@angular/forms@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)': + dependencies: + '@angular/common': 19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1) + '@angular/core': 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) + '@angular/platform-browser': 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)) + rxjs: 7.8.1 + tslib: 2.8.1 - '@ampproject/remapping@2.3.0': + '@angular/platform-browser-dynamic@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/compiler@19.2.4)(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)))': dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 + '@angular/common': 19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1) + '@angular/compiler': 19.2.4 + '@angular/core': 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) + '@angular/platform-browser': 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)) + tslib: 2.8.1 - '@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2)': + '@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))': dependencies: - '@angular/core': 21.1.5(rxjs@7.8.2) - rxjs: 7.8.2 + '@angular/common': 19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1) + '@angular/core': 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) tslib: 2.8.1 - '@angular/core@21.1.5(rxjs@7.8.2)': + '@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))': dependencies: - rxjs: 7.8.2 + '@angular/common': 21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + '@angular/core': 21.1.5(rxjs@7.8.2)(zone.js@0.15.0) tslib: 2.8.1 - '@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2))': + '@angular/router@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)': dependencies: - '@angular/common': 21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2) - '@angular/core': 21.1.5(rxjs@7.8.2) + '@angular/common': 19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1) + '@angular/core': 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) + '@angular/platform-browser': 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)) + rxjs: 7.8.1 tslib: 2.8.1 - '@angular/router@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)))(rxjs@7.8.2)': + '@angular/router@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2) - '@angular/core': 21.1.5(rxjs@7.8.2) - '@angular/platform-browser': 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)) + '@angular/common': 21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + '@angular/core': 21.1.5(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/platform-browser': 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0)) rxjs: 7.8.2 tslib: 2.8.1 @@ -7310,6 +8384,46 @@ snapshots: '@babel/compat-data@7.27.2': {} + '@babel/core@7.26.10': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.1 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.27.1(@babel/core@7.26.10) + '@babel/helpers': 7.27.1 + '@babel/parser': 7.27.2 + '@babel/template': 7.27.2 + '@babel/traverse': 7.27.1 + '@babel/types': 7.27.1 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/core@7.26.9': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.1 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.27.1(@babel/core@7.26.9) + '@babel/helpers': 7.27.1 + '@babel/parser': 7.27.2 + '@babel/template': 7.27.2 + '@babel/traverse': 7.27.1 + '@babel/types': 7.27.1 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/core@7.27.1': dependencies: '@ampproject/remapping': 2.3.0 @@ -7346,6 +8460,10 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 + '@babel/helper-annotate-as-pure@7.25.9': + dependencies: + '@babel/types': 7.27.1 + '@babel/helper-compilation-targets@7.27.2': dependencies: '@babel/compat-data': 7.27.2 @@ -7361,6 +8479,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.27.1(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.27.1(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.27.1 + transitivePeerDependencies: + - supports-color + '@babel/helper-module-transforms@7.27.1(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 @@ -7372,6 +8508,10 @@ snapshots: '@babel/helper-plugin-utils@7.27.1': {} + '@babel/helper-split-export-declaration@7.24.7': + dependencies: + '@babel/types': 7.27.1 + '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.27.1': {} @@ -7387,6 +8527,11 @@ snapshots: dependencies: '@babel/types': 7.27.1 + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 @@ -7695,126 +8840,189 @@ snapshots: '@emotion/weak-memoize@0.4.0': {} + '@esbuild/aix-ppc64@0.25.1': + optional: true + '@esbuild/aix-ppc64@0.25.9': optional: true '@esbuild/aix-ppc64@0.27.3': optional: true + '@esbuild/android-arm64@0.25.1': + optional: true + '@esbuild/android-arm64@0.25.9': optional: true '@esbuild/android-arm64@0.27.3': optional: true + '@esbuild/android-arm@0.25.1': + optional: true + '@esbuild/android-arm@0.25.9': optional: true '@esbuild/android-arm@0.27.3': optional: true + '@esbuild/android-x64@0.25.1': + optional: true + '@esbuild/android-x64@0.25.9': optional: true '@esbuild/android-x64@0.27.3': optional: true + '@esbuild/darwin-arm64@0.25.1': + optional: true + '@esbuild/darwin-arm64@0.25.9': optional: true '@esbuild/darwin-arm64@0.27.3': optional: true + '@esbuild/darwin-x64@0.25.1': + optional: true + '@esbuild/darwin-x64@0.25.9': optional: true '@esbuild/darwin-x64@0.27.3': optional: true + '@esbuild/freebsd-arm64@0.25.1': + optional: true + '@esbuild/freebsd-arm64@0.25.9': optional: true '@esbuild/freebsd-arm64@0.27.3': optional: true + '@esbuild/freebsd-x64@0.25.1': + optional: true + '@esbuild/freebsd-x64@0.25.9': optional: true '@esbuild/freebsd-x64@0.27.3': optional: true + '@esbuild/linux-arm64@0.25.1': + optional: true + '@esbuild/linux-arm64@0.25.9': optional: true '@esbuild/linux-arm64@0.27.3': optional: true + '@esbuild/linux-arm@0.25.1': + optional: true + '@esbuild/linux-arm@0.25.9': optional: true '@esbuild/linux-arm@0.27.3': optional: true + '@esbuild/linux-ia32@0.25.1': + optional: true + '@esbuild/linux-ia32@0.25.9': optional: true '@esbuild/linux-ia32@0.27.3': optional: true + '@esbuild/linux-loong64@0.25.1': + optional: true + '@esbuild/linux-loong64@0.25.9': optional: true '@esbuild/linux-loong64@0.27.3': optional: true + '@esbuild/linux-mips64el@0.25.1': + optional: true + '@esbuild/linux-mips64el@0.25.9': optional: true '@esbuild/linux-mips64el@0.27.3': optional: true + '@esbuild/linux-ppc64@0.25.1': + optional: true + '@esbuild/linux-ppc64@0.25.9': optional: true '@esbuild/linux-ppc64@0.27.3': optional: true + '@esbuild/linux-riscv64@0.25.1': + optional: true + '@esbuild/linux-riscv64@0.25.9': optional: true '@esbuild/linux-riscv64@0.27.3': optional: true + '@esbuild/linux-s390x@0.25.1': + optional: true + '@esbuild/linux-s390x@0.25.9': optional: true '@esbuild/linux-s390x@0.27.3': optional: true + '@esbuild/linux-x64@0.25.1': + optional: true + '@esbuild/linux-x64@0.25.9': optional: true '@esbuild/linux-x64@0.27.3': optional: true + '@esbuild/netbsd-arm64@0.25.1': + optional: true + '@esbuild/netbsd-arm64@0.25.9': optional: true '@esbuild/netbsd-arm64@0.27.3': optional: true + '@esbuild/netbsd-x64@0.25.1': + optional: true + '@esbuild/netbsd-x64@0.25.9': optional: true '@esbuild/netbsd-x64@0.27.3': optional: true + '@esbuild/openbsd-arm64@0.25.1': + optional: true + '@esbuild/openbsd-arm64@0.25.9': optional: true '@esbuild/openbsd-arm64@0.27.3': optional: true + '@esbuild/openbsd-x64@0.25.1': + optional: true + '@esbuild/openbsd-x64@0.25.9': optional: true @@ -7827,24 +9035,36 @@ snapshots: '@esbuild/openharmony-arm64@0.27.3': optional: true + '@esbuild/sunos-x64@0.25.1': + optional: true + '@esbuild/sunos-x64@0.25.9': optional: true '@esbuild/sunos-x64@0.27.3': optional: true + '@esbuild/win32-arm64@0.25.1': + optional: true + '@esbuild/win32-arm64@0.25.9': optional: true '@esbuild/win32-arm64@0.27.3': optional: true + '@esbuild/win32-ia32@0.25.1': + optional: true + '@esbuild/win32-ia32@0.25.9': optional: true '@esbuild/win32-ia32@0.27.3': optional: true + '@esbuild/win32-x64@0.25.1': + optional: true + '@esbuild/win32-x64@0.25.9': optional: true @@ -8067,6 +9287,28 @@ snapshots: '@img/sharp-win32-x64@0.34.5': optional: true + '@inquirer/ansi@1.0.2': {} + + '@inquirer/confirm@5.1.6(@types/node@24.0.3)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@24.0.3) + '@inquirer/type': 3.0.10(@types/node@24.0.3) + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/core@10.3.2(@types/node@24.0.3)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@24.0.3) + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 24.0.3 + '@inquirer/external-editor@1.0.3(@types/node@24.0.3)': dependencies: chardet: 2.1.1 @@ -8074,6 +9316,12 @@ snapshots: optionalDependencies: '@types/node': 24.0.3 + '@inquirer/figures@1.0.15': {} + + '@inquirer/type@3.0.10(@types/node@24.0.3)': + optionalDependencies: + '@types/node': 24.0.3 + '@isaacs/balanced-match@4.0.1': {} '@isaacs/brace-expansion@5.0.1': @@ -8103,7 +9351,6 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.29 - optional: true '@jridgewell/gen-mapping@0.3.8': dependencies: @@ -8123,8 +9370,7 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.0': {} - '@jridgewell/sourcemap-codec@1.5.5': - optional: true + '@jridgewell/sourcemap-codec@1.5.5': {} '@jridgewell/trace-mapping@0.3.25': dependencies: @@ -8135,10 +9381,27 @@ snapshots: dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - optional: true '@jspm/core@2.1.0': {} + '@lmdb/lmdb-darwin-arm64@3.2.6': + optional: true + + '@lmdb/lmdb-darwin-x64@3.2.6': + optional: true + + '@lmdb/lmdb-linux-arm64@3.2.6': + optional: true + + '@lmdb/lmdb-linux-arm@3.2.6': + optional: true + + '@lmdb/lmdb-linux-x64@3.2.6': + optional: true + + '@lmdb/lmdb-win32-x64@3.2.6': + optional: true + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.27.1 @@ -8164,6 +9427,96 @@ snapshots: '@microsoft/tsdoc@0.14.2': {} + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + optional: true + + '@napi-rs/nice-android-arm-eabi@1.1.1': + optional: true + + '@napi-rs/nice-android-arm64@1.1.1': + optional: true + + '@napi-rs/nice-darwin-arm64@1.1.1': + optional: true + + '@napi-rs/nice-darwin-x64@1.1.1': + optional: true + + '@napi-rs/nice-freebsd-x64@1.1.1': + optional: true + + '@napi-rs/nice-linux-arm-gnueabihf@1.1.1': + optional: true + + '@napi-rs/nice-linux-arm64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-arm64-musl@1.1.1': + optional: true + + '@napi-rs/nice-linux-ppc64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-riscv64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-s390x-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-x64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-x64-musl@1.1.1': + optional: true + + '@napi-rs/nice-openharmony-arm64@1.1.1': + optional: true + + '@napi-rs/nice-win32-arm64-msvc@1.1.1': + optional: true + + '@napi-rs/nice-win32-ia32-msvc@1.1.1': + optional: true + + '@napi-rs/nice-win32-x64-msvc@1.1.1': + optional: true + + '@napi-rs/nice@1.1.1': + optionalDependencies: + '@napi-rs/nice-android-arm-eabi': 1.1.1 + '@napi-rs/nice-android-arm64': 1.1.1 + '@napi-rs/nice-darwin-arm64': 1.1.1 + '@napi-rs/nice-darwin-x64': 1.1.1 + '@napi-rs/nice-freebsd-x64': 1.1.1 + '@napi-rs/nice-linux-arm-gnueabihf': 1.1.1 + '@napi-rs/nice-linux-arm64-gnu': 1.1.1 + '@napi-rs/nice-linux-arm64-musl': 1.1.1 + '@napi-rs/nice-linux-ppc64-gnu': 1.1.1 + '@napi-rs/nice-linux-riscv64-gnu': 1.1.1 + '@napi-rs/nice-linux-s390x-gnu': 1.1.1 + '@napi-rs/nice-linux-x64-gnu': 1.1.1 + '@napi-rs/nice-linux-x64-musl': 1.1.1 + '@napi-rs/nice-openharmony-arm64': 1.1.1 + '@napi-rs/nice-win32-arm64-msvc': 1.1.1 + '@napi-rs/nice-win32-ia32-msvc': 1.1.1 + '@napi-rs/nice-win32-x64-msvc': 1.1.1 + optional: true + '@napi-rs/wasm-runtime@0.2.4': dependencies: '@emnapi/core': 1.4.3 @@ -8410,7 +9763,10 @@ snapshots: optionalDependencies: rollup: 4.32.0 - '@rollup/rollup-android-arm-eabi@4.32.0': + '@rollup/rollup-android-arm-eabi@4.32.0': + optional: true + + '@rollup/rollup-android-arm-eabi@4.34.8': optional: true '@rollup/rollup-android-arm-eabi@4.50.0': @@ -8419,72 +9775,108 @@ snapshots: '@rollup/rollup-android-arm64@4.32.0': optional: true + '@rollup/rollup-android-arm64@4.34.8': + optional: true + '@rollup/rollup-android-arm64@4.50.0': optional: true '@rollup/rollup-darwin-arm64@4.32.0': optional: true + '@rollup/rollup-darwin-arm64@4.34.8': + optional: true + '@rollup/rollup-darwin-arm64@4.50.0': optional: true '@rollup/rollup-darwin-x64@4.32.0': optional: true + '@rollup/rollup-darwin-x64@4.34.8': + optional: true + '@rollup/rollup-darwin-x64@4.50.0': optional: true '@rollup/rollup-freebsd-arm64@4.32.0': optional: true + '@rollup/rollup-freebsd-arm64@4.34.8': + optional: true + '@rollup/rollup-freebsd-arm64@4.50.0': optional: true '@rollup/rollup-freebsd-x64@4.32.0': optional: true + '@rollup/rollup-freebsd-x64@4.34.8': + optional: true + '@rollup/rollup-freebsd-x64@4.50.0': optional: true '@rollup/rollup-linux-arm-gnueabihf@4.32.0': optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.34.8': + optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.50.0': optional: true '@rollup/rollup-linux-arm-musleabihf@4.32.0': optional: true + '@rollup/rollup-linux-arm-musleabihf@4.34.8': + optional: true + '@rollup/rollup-linux-arm-musleabihf@4.50.0': optional: true '@rollup/rollup-linux-arm64-gnu@4.32.0': optional: true + '@rollup/rollup-linux-arm64-gnu@4.34.8': + optional: true + '@rollup/rollup-linux-arm64-gnu@4.50.0': optional: true '@rollup/rollup-linux-arm64-musl@4.32.0': optional: true + '@rollup/rollup-linux-arm64-musl@4.34.8': + optional: true + '@rollup/rollup-linux-arm64-musl@4.50.0': optional: true '@rollup/rollup-linux-loongarch64-gnu@4.32.0': optional: true + '@rollup/rollup-linux-loongarch64-gnu@4.34.8': + optional: true + '@rollup/rollup-linux-loongarch64-gnu@4.50.0': optional: true '@rollup/rollup-linux-powerpc64le-gnu@4.32.0': optional: true + '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': + optional: true + '@rollup/rollup-linux-ppc64-gnu@4.50.0': optional: true '@rollup/rollup-linux-riscv64-gnu@4.32.0': optional: true + '@rollup/rollup-linux-riscv64-gnu@4.34.8': + optional: true + '@rollup/rollup-linux-riscv64-gnu@4.50.0': optional: true @@ -8494,18 +9886,27 @@ snapshots: '@rollup/rollup-linux-s390x-gnu@4.32.0': optional: true + '@rollup/rollup-linux-s390x-gnu@4.34.8': + optional: true + '@rollup/rollup-linux-s390x-gnu@4.50.0': optional: true '@rollup/rollup-linux-x64-gnu@4.32.0': optional: true + '@rollup/rollup-linux-x64-gnu@4.34.8': + optional: true + '@rollup/rollup-linux-x64-gnu@4.50.0': optional: true '@rollup/rollup-linux-x64-musl@4.32.0': optional: true + '@rollup/rollup-linux-x64-musl@4.34.8': + optional: true + '@rollup/rollup-linux-x64-musl@4.50.0': optional: true @@ -8515,18 +9916,27 @@ snapshots: '@rollup/rollup-win32-arm64-msvc@4.32.0': optional: true + '@rollup/rollup-win32-arm64-msvc@4.34.8': + optional: true + '@rollup/rollup-win32-arm64-msvc@4.50.0': optional: true '@rollup/rollup-win32-ia32-msvc@4.32.0': optional: true + '@rollup/rollup-win32-ia32-msvc@4.34.8': + optional: true + '@rollup/rollup-win32-ia32-msvc@4.50.0': optional: true '@rollup/rollup-win32-x64-msvc@4.32.0': optional: true + '@rollup/rollup-win32-x64-msvc@4.34.8': + optional: true + '@rollup/rollup-win32-x64-msvc@4.50.0': optional: true @@ -8586,7 +9996,7 @@ snapshots: '@tailwindcss/oxide@4.1.8': dependencies: - detect-libc: 2.0.4 + detect-libc: 2.1.2 tar: 7.5.8 optionalDependencies: '@tailwindcss/oxide-android-arm64': 4.1.8 @@ -8602,6 +10012,13 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.8 '@tailwindcss/oxide-win32-x64-msvc': 4.1.8 + '@tailwindcss/vite@4.1.8(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + dependencies: + '@tailwindcss/node': 4.1.8 + '@tailwindcss/oxide': 4.1.8 + tailwindcss: 4.1.8 + vite: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + '@tailwindcss/vite@4.1.8(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': dependencies: '@tailwindcss/node': 4.1.8 @@ -8678,6 +10095,13 @@ snapshots: '@trysound/sax@0.2.0': {} + '@ts-morph/common@0.22.0': + dependencies: + fast-glob: 3.3.3 + minimatch: 9.0.5 + mkdirp: 3.0.1 + path-browserify: 1.0.1 + '@tybys/wasm-util@0.9.0': dependencies: tslib: 2.8.1 @@ -8763,6 +10187,8 @@ snapshots: '@types/trusted-types@2.0.7': optional: true + '@types/unist@3.0.3': {} + '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -9088,6 +10514,14 @@ snapshots: '@ungap/structured-clone@1.3.0': {} + '@vitejs/plugin-basic-ssl@1.2.0(vite@6.2.0(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + dependencies: + vite: 6.2.0(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + + '@vitejs/plugin-basic-ssl@2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + dependencies: + vite: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + '@vitejs/plugin-basic-ssl@2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': dependencies: vite: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) @@ -9521,6 +10955,10 @@ snapshots: agent-base@7.1.3: {} + ajv-formats@3.0.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -9539,6 +10977,10 @@ snapshots: ansi-colors@4.1.3: {} + ansi-escapes@7.3.0: + dependencies: + environment: 1.1.0 + ansi-regex@5.0.1: {} ansi-regex@6.2.2: {} @@ -9693,6 +11135,17 @@ snapshots: base64url@3.0.1: {} + beasties@0.2.0: + dependencies: + css-select: 5.2.2 + css-what: 6.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + htmlparser2: 9.1.0 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-media-query-parser: 0.2.3 + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 @@ -9790,8 +11243,7 @@ snapshots: buffer-builder@0.2.0: optional: true - buffer-from@1.1.2: - optional: true + buffer-from@1.1.2: {} buffer-xor@1.0.3: {} @@ -9879,7 +11331,6 @@ snapshots: chokidar@4.0.3: dependencies: readdirp: 4.1.2 - optional: true chownr@3.0.0: {} @@ -9898,8 +11349,19 @@ snapshots: dependencies: restore-cursor: 3.1.0 + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + cli-spinners@2.6.1: {} + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + cli-width@4.1.0: {} + client-only@0.0.1: {} cliui@8.0.1: @@ -9912,6 +11374,8 @@ snapshots: clsx@2.1.1: {} + code-block-writer@12.0.0: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -9920,6 +11384,8 @@ snapshots: colord@2.9.3: {} + colorette@2.0.20: {} + colorjs.io@0.5.2: optional: true @@ -10056,6 +11522,14 @@ snapshots: domutils: 2.8.0 nth-check: 2.1.1 + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + css-tree@1.1.3: dependencies: mdn-data: 2.0.14 @@ -10234,10 +11708,7 @@ snapshots: detect-libc@1.0.3: optional: true - detect-libc@2.0.4: {} - - detect-libc@2.1.2: - optional: true + detect-libc@2.1.2: {} diff-sequences@29.6.3: {} @@ -10267,6 +11738,12 @@ snapshots: domhandler: 4.3.1 entities: 2.2.0 + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + dom-walk@0.1.2: {} domelementtype@2.3.0: {} @@ -10275,6 +11752,10 @@ snapshots: dependencies: domelementtype: 2.3.0 + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + dompurify@3.2.7: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -10285,6 +11766,12 @@ snapshots: domelementtype: 2.3.0 domhandler: 4.3.1 + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dotenv-expand@11.0.7: dependencies: dotenv: 16.4.7 @@ -10322,6 +11809,8 @@ snapshots: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 + emoji-regex@10.6.0: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -10352,6 +11841,8 @@ snapshots: entities@6.0.0: {} + environment@1.1.0: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -10481,6 +11972,34 @@ snapshots: local-pkg: 1.1.1 resolve.exports: 2.0.3 + esbuild@0.25.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.1 + '@esbuild/android-arm': 0.25.1 + '@esbuild/android-arm64': 0.25.1 + '@esbuild/android-x64': 0.25.1 + '@esbuild/darwin-arm64': 0.25.1 + '@esbuild/darwin-x64': 0.25.1 + '@esbuild/freebsd-arm64': 0.25.1 + '@esbuild/freebsd-x64': 0.25.1 + '@esbuild/linux-arm': 0.25.1 + '@esbuild/linux-arm64': 0.25.1 + '@esbuild/linux-ia32': 0.25.1 + '@esbuild/linux-loong64': 0.25.1 + '@esbuild/linux-mips64el': 0.25.1 + '@esbuild/linux-ppc64': 0.25.1 + '@esbuild/linux-riscv64': 0.25.1 + '@esbuild/linux-s390x': 0.25.1 + '@esbuild/linux-x64': 0.25.1 + '@esbuild/netbsd-arm64': 0.25.1 + '@esbuild/netbsd-x64': 0.25.1 + '@esbuild/openbsd-arm64': 0.25.1 + '@esbuild/openbsd-x64': 0.25.1 + '@esbuild/sunos-x64': 0.25.1 + '@esbuild/win32-arm64': 0.25.1 + '@esbuild/win32-ia32': 0.25.1 + '@esbuild/win32-x64': 0.25.1 + esbuild@0.25.9: optionalDependencies: '@esbuild/aix-ppc64': 0.25.9 @@ -11016,6 +12535,8 @@ snapshots: eventemitter3@4.0.7: {} + eventemitter3@5.0.4: {} + evp_bytestokey@1.0.3: dependencies: md5.js: 1.3.5 @@ -11228,6 +12749,8 @@ snapshots: get-caller-file@2.0.5: {} + get-east-asian-width@1.5.0: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -11268,6 +12791,8 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regexp@0.4.1: {} + glob@10.5.0: dependencies: foreground-child: 3.3.1 @@ -11432,6 +12957,13 @@ snapshots: html-tags@3.3.1: {} + htmlparser2@9.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 4.5.0 + http-errors@2.0.0: dependencies: depd: 2.0.0 @@ -11482,8 +13014,7 @@ snapshots: immutable@4.3.7: {} - immutable@5.1.2: - optional: true + immutable@5.1.2: {} import-fresh@3.3.1: dependencies: @@ -11575,6 +13106,12 @@ snapshots: is-fullwidth-code-point@3.0.0: {} + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.1.0: + dependencies: + get-east-asian-width: 1.5.0 + is-generator-function@1.1.2: dependencies: call-bound: 1.0.4 @@ -11677,6 +13214,16 @@ snapshots: istanbul-lib-coverage@3.2.2: {} + istanbul-lib-instrument@6.0.3: + dependencies: + '@babel/core': 7.27.1 + '@babel/parser': 7.27.2 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.7.3 + transitivePeerDependencies: + - supports-color + istanbul-lib-report@3.0.1: dependencies: istanbul-lib-coverage: 3.2.2 @@ -11829,6 +13376,8 @@ snapshots: jsonc-parser@3.2.0: {} + jsonc-parser@3.3.1: {} + jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 @@ -11897,7 +13446,7 @@ snapshots: lightningcss@1.30.1: dependencies: - detect-libc: 2.0.4 + detect-libc: 2.1.2 optionalDependencies: lightningcss-darwin-arm64: 1.30.1 lightningcss-darwin-x64: 1.30.1 @@ -11916,6 +13465,31 @@ snapshots: lines-and-columns@2.0.3: {} + listr2@8.2.5: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.4 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.2 + + lmdb@3.2.6: + dependencies: + msgpackr: 1.11.8 + node-addon-api: 6.1.0 + node-gyp-build-optional-packages: 5.2.2 + ordered-binary: 1.6.1 + weak-lru-cache: 1.2.2 + optionalDependencies: + '@lmdb/lmdb-darwin-arm64': 3.2.6 + '@lmdb/lmdb-darwin-x64': 3.2.6 + '@lmdb/lmdb-linux-arm': 3.2.6 + '@lmdb/lmdb-linux-arm64': 3.2.6 + '@lmdb/lmdb-linux-x64': 3.2.6 + '@lmdb/lmdb-win32-x64': 3.2.6 + optional: true + local-pkg@1.1.1: dependencies: mlly: 1.7.4 @@ -11949,6 +13523,14 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 + log-update@6.1.0: + dependencies: + ansi-escapes: 7.3.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.1.2 + wrap-ansi: 9.0.2 + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -12058,6 +13640,8 @@ snapshots: mimic-fn@2.1.0: {} + mimic-function@5.0.1: {} + min-document@2.19.1: dependencies: dom-walk: 0.1.2 @@ -12108,6 +13692,8 @@ snapshots: dependencies: minipass: 7.1.2 + mkdirp@3.0.1: {} + mlly@1.7.4: dependencies: acorn: 8.15.0 @@ -12121,8 +13707,27 @@ snapshots: ms@2.1.3: {} + msgpackr-extract@3.0.3: + dependencies: + node-gyp-build-optional-packages: 5.2.2 + optionalDependencies: + '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3 + optional: true + + msgpackr@1.11.8: + optionalDependencies: + msgpackr-extract: 3.0.3 + optional: true + muggle-string@0.4.1: {} + mute-stream@2.0.0: {} + nanoid@3.3.11: {} natural-compare-lite@1.4.0: {} @@ -12156,6 +13761,9 @@ snapshots: - '@babel/core' - babel-plugin-macros + node-addon-api@6.1.0: + optional: true + node-addon-api@7.1.1: optional: true @@ -12163,6 +13771,11 @@ snapshots: dependencies: whatwg-url: 5.0.0 + node-gyp-build-optional-packages@5.2.2: + dependencies: + detect-libc: 2.1.2 + optional: true + node-machine-id@1.1.12: {} node-releases@2.0.19: {} @@ -12305,6 +13918,10 @@ snapshots: dependencies: mimic-fn: 2.1.0 + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + open@8.4.2: dependencies: define-lazy-prop: 2.0.0 @@ -12331,6 +13948,9 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 + ordered-binary@1.6.1: + optional: true + outdent@0.5.0: {} own-keys@1.0.1: @@ -12400,6 +14020,16 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parse5-html-rewriting-stream@7.0.0: + dependencies: + entities: 4.5.0 + parse5: 7.3.0 + parse5-sax-parser: 7.0.0 + + parse5-sax-parser@7.0.0: + dependencies: + parse5: 7.3.0 + parse5@7.3.0: dependencies: entities: 6.0.0 @@ -12451,8 +14081,14 @@ snapshots: picomatch@2.3.1: {} + picomatch@4.0.2: {} + picomatch@4.0.3: {} + piscina@4.8.0: + optionalDependencies: + '@napi-rs/nice': 1.1.1 + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -12850,14 +14486,15 @@ snapshots: dependencies: picomatch: 2.3.1 - readdirp@4.1.2: - optional: true + readdirp@4.1.2: {} redent@3.0.0: dependencies: indent-string: 4.0.0 strip-indent: 3.0.0 + reflect-metadata@0.2.2: {} + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -12916,8 +14553,15 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + reusify@1.1.0: {} + rfdc@1.4.1: {} + rimraf@3.0.2: dependencies: glob: 7.2.3 @@ -12997,6 +14641,31 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.32.0 fsevents: 2.3.3 + rollup@4.34.8: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.34.8 + '@rollup/rollup-android-arm64': 4.34.8 + '@rollup/rollup-darwin-arm64': 4.34.8 + '@rollup/rollup-darwin-x64': 4.34.8 + '@rollup/rollup-freebsd-arm64': 4.34.8 + '@rollup/rollup-freebsd-x64': 4.34.8 + '@rollup/rollup-linux-arm-gnueabihf': 4.34.8 + '@rollup/rollup-linux-arm-musleabihf': 4.34.8 + '@rollup/rollup-linux-arm64-gnu': 4.34.8 + '@rollup/rollup-linux-arm64-musl': 4.34.8 + '@rollup/rollup-linux-loongarch64-gnu': 4.34.8 + '@rollup/rollup-linux-powerpc64le-gnu': 4.34.8 + '@rollup/rollup-linux-riscv64-gnu': 4.34.8 + '@rollup/rollup-linux-s390x-gnu': 4.34.8 + '@rollup/rollup-linux-x64-gnu': 4.34.8 + '@rollup/rollup-linux-x64-musl': 4.34.8 + '@rollup/rollup-win32-arm64-msvc': 4.34.8 + '@rollup/rollup-win32-ia32-msvc': 4.34.8 + '@rollup/rollup-win32-x64-msvc': 4.34.8 + fsevents: 2.3.3 + rollup@4.50.0: dependencies: '@types/estree': 1.0.8 @@ -13040,6 +14709,10 @@ snapshots: dependencies: queue-microtask: 1.2.3 + rxjs@7.8.1: + dependencies: + tslib: 2.8.1 + rxjs@7.8.2: dependencies: tslib: 2.8.1 @@ -13133,7 +14806,7 @@ snapshots: buffer-builder: 0.2.0 colorjs.io: 0.5.2 immutable: 5.1.2 - rxjs: 7.8.2 + rxjs: 7.8.1 supports-color: 8.1.1 sync-child-process: 1.0.2 varint: 6.0.0 @@ -13164,6 +14837,14 @@ snapshots: immutable: 4.3.7 source-map-js: 1.2.1 + sass@1.85.0: + dependencies: + chokidar: 4.0.3 + immutable: 5.1.2 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.1 + sass@1.92.1: dependencies: chokidar: 4.0.3 @@ -13191,6 +14872,8 @@ snapshots: semver@6.3.1: {} + semver@7.7.1: {} + semver@7.7.2: {} semver@7.7.3: {} @@ -13344,18 +15027,29 @@ snapshots: astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.2: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + source-map-js@1.2.1: {} source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - optional: true source-map@0.5.7: {} source-map@0.6.1: {} + source-map@0.7.4: {} + spawndamnit@3.0.1: dependencies: cross-spawn: 7.0.6 @@ -13411,6 +15105,12 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.2 + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.5.0 + strip-ansi: 7.1.2 + string.prototype.includes@2.0.1: dependencies: call-bind: 1.0.8 @@ -13684,11 +15384,6 @@ snapshots: tinyexec@0.3.2: {} - tinyglobby@0.2.14: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) @@ -13760,6 +15455,11 @@ snapshots: dependencies: typescript: 5.8.3 + ts-morph@21.0.1: + dependencies: + '@ts-morph/common': 0.22.0 + code-block-writer: 12.0.0 + tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29 @@ -13883,6 +15583,10 @@ snapshots: undici@7.21.0: {} + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + universalify@0.1.2: {} universalify@2.0.1: {} @@ -13919,6 +15623,16 @@ snapshots: vary@1.1.2: {} + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + vite-node@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: cac: 6.7.14 @@ -13982,6 +15696,22 @@ snapshots: - tsx - yaml + vite@6.2.0(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + dependencies: + esbuild: 0.25.9 + postcss: 8.5.6 + rollup: 4.32.0 + optionalDependencies: + '@types/node': 24.0.3 + fsevents: 2.3.3 + jiti: 2.6.0 + lightningcss: 1.30.1 + sass: 1.85.0 + sass-embedded: 1.92.1 + terser: 5.39.2 + tsx: 4.21.0 + yaml: 2.8.0 + vite@6.4.1(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: esbuild: 0.25.9 @@ -13989,7 +15719,7 @@ snapshots: picomatch: 4.0.3 postcss: 8.5.6 rollup: 4.50.0 - tinyglobby: 0.2.14 + tinyglobby: 0.2.15 optionalDependencies: '@types/node': 20.12.7 fsevents: 2.3.3 @@ -14008,7 +15738,7 @@ snapshots: picomatch: 4.0.3 postcss: 8.5.6 rollup: 4.50.0 - tinyglobby: 0.2.14 + tinyglobby: 0.2.15 optionalDependencies: '@types/node': 22.15.3 fsevents: 2.3.3 @@ -14027,7 +15757,7 @@ snapshots: picomatch: 4.0.3 postcss: 8.5.6 rollup: 4.50.0 - tinyglobby: 0.2.14 + tinyglobby: 0.2.15 optionalDependencies: '@types/node': 22.15.30 fsevents: 2.3.3 @@ -14039,6 +15769,25 @@ snapshots: tsx: 4.21.0 yaml: 2.8.0 + vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + dependencies: + esbuild: 0.25.9 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.50.0 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.0.3 + fsevents: 2.3.3 + jiti: 2.6.0 + lightningcss: 1.30.1 + sass: 1.85.0 + sass-embedded: 1.92.1 + terser: 5.39.2 + tsx: 4.21.0 + yaml: 2.8.0 + vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: esbuild: 0.25.9 @@ -14046,7 +15795,7 @@ snapshots: picomatch: 4.0.3 postcss: 8.5.6 rollup: 4.50.0 - tinyglobby: 0.2.14 + tinyglobby: 0.2.15 optionalDependencies: '@types/node': 24.0.3 fsevents: 2.3.3 @@ -14289,10 +16038,18 @@ snapshots: dependencies: xml-name-validator: 5.0.0 + watchpack@2.4.2: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + wcwidth@1.0.1: dependencies: defaults: 1.0.4 + weak-lru-cache@1.2.2: + optional: true + webidl-conversions@3.0.1: {} webidl-conversions@7.0.0: {} @@ -14378,6 +16135,12 @@ snapshots: word-wrap@1.2.5: {} + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -14390,6 +16153,12 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.2 + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.1.2 + wrappy@1.0.2: {} write-file-atomic@5.0.1: @@ -14434,3 +16203,7 @@ snapshots: yargs-parser: 21.1.1 yocto-queue@0.1.0: {} + + yoctocolors-cjs@2.1.3: {} + + zone.js@0.15.0: {} diff --git a/samples/teamspace-angular/.env.local.example b/samples/teamspace-angular/.env.local.example new file mode 100644 index 000000000..da7cf4a6a --- /dev/null +++ b/samples/teamspace-angular/.env.local.example @@ -0,0 +1,5 @@ +# Asgardeo Configuration +VITE_ASGARDEO_BASE_URL='https://api.asgardeo.io/t/' +VITE_ASGARDEO_CLIENT_ID='' +VITE_ASGARDEO_AFTER_SIGN_IN_URL='https://localhost:5173/dashboard' +VITE_ASGARDEO_AFTER_SIGN_OUT_URL='https://localhost:5173' diff --git a/samples/teamspace-angular/.gitignore b/samples/teamspace-angular/.gitignore new file mode 100644 index 000000000..cbdfe197f --- /dev/null +++ b/samples/teamspace-angular/.gitignore @@ -0,0 +1,27 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local +# allow .env.local.example to be committed with sample values. +!.env.local.example + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.angular diff --git a/samples/teamspace-angular/index.html b/samples/teamspace-angular/index.html new file mode 100644 index 000000000..11763a2e8 --- /dev/null +++ b/samples/teamspace-angular/index.html @@ -0,0 +1,14 @@ + + + + + + + Teamspace Angular + + + + + + + diff --git a/samples/teamspace-angular/package.json b/samples/teamspace-angular/package.json new file mode 100644 index 000000000..321d765e4 --- /dev/null +++ b/samples/teamspace-angular/package.json @@ -0,0 +1,34 @@ +{ + "private": true, + "name": "@asgardeo/teamspace-angular", + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@asgardeo/angular": "workspace:*", + "@angular/common": "19.2.4", + "@angular/core": "19.2.4", + "@angular/forms": "19.2.4", + "@angular/platform-browser": "19.2.4", + "@angular/platform-browser-dynamic": "19.2.4", + "@angular/router": "19.2.4", + "rxjs": "7.8.1", + "tslib": "2.8.1", + "zone.js": "0.15.0" + }, + "devDependencies": { + "@analogjs/vite-plugin-angular": "1.16.2", + "@angular/build": "19.2.4", + "@angular/compiler": "19.2.4", + "@angular/compiler-cli": "19.2.4", + "@tailwindcss/vite": "4.1.8", + "@vitejs/plugin-basic-ssl": "2.0.0", + "tailwindcss": "4.1.8", + "typescript": "5.8.3", + "vite": "6.4.1" + } +} diff --git a/samples/teamspace-angular/public/vite.svg b/samples/teamspace-angular/public/vite.svg new file mode 100644 index 000000000..e7b8dfb1b --- /dev/null +++ b/samples/teamspace-angular/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/teamspace-angular/src/app/app.component.ts b/samples/teamspace-angular/src/app/app.component.ts new file mode 100644 index 000000000..069fef926 --- /dev/null +++ b/samples/teamspace-angular/src/app/app.component.ts @@ -0,0 +1,33 @@ +import {Component, inject, OnInit} from '@angular/core'; +import {Router, RouterOutlet} from '@angular/router'; +import {AsgardeoAuthService} from '@asgardeo/angular'; + +@Component({ + selector: 'app-root', + standalone: true, + imports: [RouterOutlet], + template: '', +}) +export class AppComponent implements OnInit { + private authService = inject(AsgardeoAuthService); + private router = inject(Router); + + async ngOnInit(): Promise { + const url = new URL(window.location.href); + + // Workaround: The SDK's APP_INITIALIZER may skip the OAuth code exchange + // because the state param format doesn't match. If we detect OAuth params + // in the URL and we're not signed in, trigger the code exchange manually. + if (url.searchParams.has('code') && !this.authService.isSignedIn()) { + try { + await this.authService.signIn({callOnlyOnRedirect: true}); + } catch { + // signIn may fail if the code has already been consumed + } + // After successful sign-in, clean the URL + if (this.authService.isSignedIn()) { + this.router.navigateByUrl(url.pathname); + } + } + } +} diff --git a/samples/teamspace-angular/src/app/app.config.ts b/samples/teamspace-angular/src/app/app.config.ts new file mode 100644 index 000000000..d5fdca589 --- /dev/null +++ b/samples/teamspace-angular/src/app/app.config.ts @@ -0,0 +1,21 @@ +import {ApplicationConfig, provideZoneChangeDetection} from '@angular/core'; +import {provideRouter} from '@angular/router'; +import {provideHttpClient, withInterceptors} from '@angular/common/http'; +import {provideAsgardeo, asgardeoInterceptor} from '@asgardeo/angular'; +import {routes} from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideZoneChangeDetection({eventCoalescing: true}), + provideRouter(routes), + provideHttpClient(withInterceptors([asgardeoInterceptor])), + provideAsgardeo({ + baseUrl: import.meta.env['VITE_ASGARDEO_BASE_URL'] || '', + clientId: import.meta.env['VITE_ASGARDEO_CLIENT_ID'] || '', + afterSignInUrl: import.meta.env['VITE_ASGARDEO_AFTER_SIGN_IN_URL'] || window.location.origin + '/dashboard', + afterSignOutUrl: import.meta.env['VITE_ASGARDEO_AFTER_SIGN_OUT_URL'] || window.location.origin, + scopes: + 'openid address email profile internal_organization_create internal_organization_view internal_organization_update internal_organization_delete internal_org_organization_update internal_org_organization_create internal_org_organization_view internal_org_organization_delete', + }), + ], +}; diff --git a/samples/teamspace-angular/src/app/app.routes.ts b/samples/teamspace-angular/src/app/app.routes.ts new file mode 100644 index 000000000..7359ba492 --- /dev/null +++ b/samples/teamspace-angular/src/app/app.routes.ts @@ -0,0 +1,20 @@ +import {Routes} from '@angular/router'; +import {LandingComponent} from './pages/landing.component'; +import {CallbackPageComponent} from './pages/callback.component'; +import {DashboardComponent} from './pages/dashboard.component'; +import {ProfileComponent} from './pages/profile.component'; +import {OrganizationsComponent} from './pages/organizations.component'; +import {CreateOrgComponent} from './pages/create-org.component'; +import {DebugComponent} from './pages/debug.component'; +import {authGuard} from './guards/auth.guard'; + +export const routes: Routes = [ + {path: '', component: LandingComponent}, + {path: 'callback', component: CallbackPageComponent}, + {path: 'dashboard', component: DashboardComponent, canActivate: [authGuard]}, + {path: 'profile', component: ProfileComponent, canActivate: [authGuard]}, + {path: 'organizations', component: OrganizationsComponent, canActivate: [authGuard]}, + {path: 'organizations/new', component: CreateOrgComponent, canActivate: [authGuard]}, + {path: 'debug', component: DebugComponent, canActivate: [authGuard]}, + {path: '**', redirectTo: ''}, +]; diff --git a/samples/teamspace-angular/src/app/components/header.component.ts b/samples/teamspace-angular/src/app/components/header.component.ts new file mode 100644 index 000000000..f93e15070 --- /dev/null +++ b/samples/teamspace-angular/src/app/components/header.component.ts @@ -0,0 +1,87 @@ +import {Component, inject} from '@angular/core'; +import {RouterLink} from '@angular/router'; +import {AsgardeoAuthService, AsgardeoSignedInDirective, AsgardeoSignedOutDirective} from '@asgardeo/angular'; + +@Component({ + selector: 'app-header', + standalone: true, + imports: [RouterLink, AsgardeoSignedInDirective, AsgardeoSignedOutDirective], + template: ` +
+
+
+ + + + + + + +
+ +
+ {{ authService.user()?.given_name || 'User' }} + +
+ + +
+ + +
+
+
+
+
+ `, +}) +export class HeaderComponent { + authService = inject(AsgardeoAuthService); + + signIn(): void { + this.authService.signIn(); + } + + signUp(): void { + this.authService.signUp(); + } + + signOut(): void { + this.authService.signOut(); + } +} diff --git a/samples/teamspace-angular/src/app/guards/auth.guard.ts b/samples/teamspace-angular/src/app/guards/auth.guard.ts new file mode 100644 index 000000000..d5abea7d6 --- /dev/null +++ b/samples/teamspace-angular/src/app/guards/auth.guard.ts @@ -0,0 +1,69 @@ +import {inject} from '@angular/core'; +import {CanActivateFn, Router, UrlTree} from '@angular/router'; +import {AsgardeoAuthService} from '@asgardeo/angular'; + +/** + * Custom auth guard that waits for the OAuth token exchange to complete + * before checking authentication status. + * + * The SDK's APP_INITIALIZER may resolve before the async token exchange finishes, + * so this guard polls isSignedIn() when OAuth params are detected in the URL. + */ +export const authGuard: CanActivateFn = async (): Promise => { + const authService = inject(AsgardeoAuthService); + const router = inject(Router); + + // If already signed in, allow immediately + if (authService.isSignedIn()) { + return true; + } + + // If the URL has OAuth params (code), the token exchange is likely in progress. + // Wait for it to complete. + const urlParams = new URLSearchParams(window.location.search); + if (urlParams.has('code')) { + await waitForSignIn(authService, 10000); + + if (authService.isSignedIn()) { + // Clean the OAuth params from the URL + router.navigateByUrl(window.location.pathname); + return true; + } + } + + // If still loading, wait for loading to finish + if (authService.isLoading()) { + await waitForLoading(authService, 10000); + + if (authService.isSignedIn()) { + return true; + } + } + + // Not signed in — redirect to landing page + return router.createUrlTree(['/']); +}; + +function waitForSignIn(authService: AsgardeoAuthService, timeoutMs: number): Promise { + return new Promise((resolve) => { + const start = Date.now(); + const interval = setInterval(() => { + if (authService.isSignedIn() || Date.now() - start > timeoutMs) { + clearInterval(interval); + resolve(); + } + }, 50); + }); +} + +function waitForLoading(authService: AsgardeoAuthService, timeoutMs: number): Promise { + return new Promise((resolve) => { + const start = Date.now(); + const interval = setInterval(() => { + if (!authService.isLoading() || Date.now() - start > timeoutMs) { + clearInterval(interval); + resolve(); + } + }, 50); + }); +} diff --git a/samples/teamspace-angular/src/app/layouts/dashboard-layout.component.ts b/samples/teamspace-angular/src/app/layouts/dashboard-layout.component.ts new file mode 100644 index 000000000..571d15b38 --- /dev/null +++ b/samples/teamspace-angular/src/app/layouts/dashboard-layout.component.ts @@ -0,0 +1,17 @@ +import {Component} from '@angular/core'; +import {HeaderComponent} from '../components/header.component'; + +@Component({ + selector: 'app-dashboard-layout', + standalone: true, + imports: [HeaderComponent], + template: ` +
+ +
+ +
+
+ `, +}) +export class DashboardLayoutComponent {} diff --git a/samples/teamspace-angular/src/app/layouts/landing-layout.component.ts b/samples/teamspace-angular/src/app/layouts/landing-layout.component.ts new file mode 100644 index 000000000..6c0dfce43 --- /dev/null +++ b/samples/teamspace-angular/src/app/layouts/landing-layout.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import {HeaderComponent} from '../components/header.component'; + +@Component({ + selector: 'app-landing-layout', + standalone: true, + imports: [HeaderComponent], + template: ` +
+ + +
+ `, +}) +export class LandingLayoutComponent {} diff --git a/samples/teamspace-angular/src/app/pages/callback.component.ts b/samples/teamspace-angular/src/app/pages/callback.component.ts new file mode 100644 index 000000000..17aaf656b --- /dev/null +++ b/samples/teamspace-angular/src/app/pages/callback.component.ts @@ -0,0 +1,47 @@ +import {Component, inject, OnInit} from '@angular/core'; +import {Router} from '@angular/router'; +import {AsgardeoAuthService} from '@asgardeo/angular'; + +@Component({ + selector: 'app-callback-page', + standalone: true, + template: ` +
+
+
+

Processing authentication...

+
+
+ `, +}) +export class CallbackPageComponent implements OnInit { + private authService = inject(AsgardeoAuthService); + private router = inject(Router); + + async ngOnInit(): Promise { + // The SDK's APP_INITIALIZER processes the OAuth code on this page + // (because afterSignInUrl points here). Wait for it to finish. + await this.waitForAuth(); + + if (this.authService.isSignedIn()) { + this.router.navigate(['/dashboard']); + } else { + this.router.navigate(['/']); + } + } + + private waitForAuth(): Promise { + return new Promise((resolve) => { + if (!this.authService.isLoading()) { + resolve(); + return; + } + const interval = setInterval(() => { + if (!this.authService.isLoading()) { + clearInterval(interval); + resolve(); + } + }, 50); + }); + } +} diff --git a/samples/teamspace-angular/src/app/pages/create-org.component.ts b/samples/teamspace-angular/src/app/pages/create-org.component.ts new file mode 100644 index 000000000..2814d2315 --- /dev/null +++ b/samples/teamspace-angular/src/app/pages/create-org.component.ts @@ -0,0 +1,134 @@ +import {Component, inject, signal} from '@angular/core'; +import {Router, RouterLink} from '@angular/router'; +import {FormsModule} from '@angular/forms'; +import {AsgardeoOrganizationService} from '@asgardeo/angular'; +import {HeaderComponent} from '../components/header.component'; + +@Component({ + selector: 'app-create-org', + standalone: true, + imports: [RouterLink, FormsModule, HeaderComponent], + template: ` +
+ + +
+ +
+ + + + + Back to organizations + +

Create a new organization

+

+ Organizations are shared accounts where teams can collaborate across many projects at once. +

+
+ + +
+
+
+ + +

This will be the display name for your organization.

+
+ +
+ + +
+ + @if (error()) { +
+

{{ error() }}

+
+ } + + @if (success()) { +
+

Organization created successfully! Redirecting...

+
+ } + +
+ + Cancel + + +
+
+
+
+
+ `, +}) +export class CreateOrgComponent { + private orgService = inject(AsgardeoOrganizationService); + private router = inject(Router); + + orgName = ''; + orgDescription = ''; + isSubmitting = signal(false); + error = signal(null); + success = signal(false); + + async onCreate(): Promise { + if (!this.orgName.trim()) return; + + this.isSubmitting.set(true); + this.error.set(null); + this.success.set(false); + + try { + await this.orgService.createOrganization({name: this.orgName.trim(), description: this.orgDescription.trim()}); + await this.orgService.revalidateMyOrganizations(); + this.success.set(true); + setTimeout(() => { + this.router.navigate(['/organizations']); + }, 1500); + } catch (err: any) { + this.error.set(err?.message || 'Failed to create organization'); + } finally { + this.isSubmitting.set(false); + } + } +} diff --git a/samples/teamspace-angular/src/app/pages/dashboard.component.ts b/samples/teamspace-angular/src/app/pages/dashboard.component.ts new file mode 100644 index 000000000..a01166166 --- /dev/null +++ b/samples/teamspace-angular/src/app/pages/dashboard.component.ts @@ -0,0 +1,214 @@ +import {Component, inject} from '@angular/core'; +import {RouterLink} from '@angular/router'; +import {AsgardeoAuthService} from '@asgardeo/angular'; +import {HeaderComponent} from '../components/header.component'; + +@Component({ + selector: 'app-dashboard', + standalone: true, + imports: [RouterLink, HeaderComponent], + template: ` +
+ + +
+ +
+

+ Welcome back {{ getUserFullName() }}! +

+ @if (authService.currentOrganization(); as org) { +

+ Here's what's happening with + {{ org.orgHandle ? '@' + org.orgHandle : org.name || org.id }} + today. +

+ } +
+ + +
+ @for (stat of stats; track stat.name) { +
+
+
+

{{ stat.name }}

+

{{ stat.value }}

+
+
+ + + +
+
+
+ + + + + {{ stat.change }} + + from last month +
+
+ } +
+ +
+ +
+
+

Recent Activity

+
+
+
+ @for (activity of recentActivity; track activity.id) { +
+
+
+ + + +
+
+
+

+ {{ activity.user }} {{ activity.action }} +

+

{{ activity.time }}

+
+
+ } +
+
+
+ + +
+
+

Upcoming Tasks

+
+
+
+ @for (task of upcomingTasks; track task.id) { +
+
+

{{ task.title }}

+

{{ task.project }}

+
+
+
+ + + + {{ task.dueDate }} +
+ + @if (task.priority === 'high') { + + + + } + {{ task.priority }} + +
+
+ } +
+
+
+
+
+
+ `, +}) +export class DashboardComponent { + authService = inject(AsgardeoAuthService); + + stats = [ + { + name: 'Active Projects', + value: '12', + change: '+2.1%', + changeType: 'positive', + iconPath: 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z', + }, + { + name: 'Team Members', + value: '0', + change: '+5.4%', + changeType: 'positive', + iconPath: 'M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z', + }, + { + name: 'Messages Today', + value: '89', + change: '+12.5%', + changeType: 'positive', + iconPath: 'M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z', + }, + { + name: 'Meetings This Week', + value: '7', + change: '-2.3%', + changeType: 'negative', + iconPath: 'M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z', + }, + ]; + + recentActivity = [ + { + id: 1, + user: 'Sarah Chen', + action: 'completed task "Design Review"', + time: '2 hours ago', + bgClass: 'bg-green-100', + iconClass: 'text-green-600', + iconPath: 'M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z', + }, + { + id: 2, + user: 'Mike Johnson', + action: 'created new project "Mobile App"', + time: '4 hours ago', + bgClass: 'bg-blue-100', + iconClass: 'text-blue-600', + iconPath: 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z', + }, + { + id: 3, + user: 'Emily Davis', + action: 'scheduled team meeting', + time: '6 hours ago', + bgClass: 'bg-purple-100', + iconClass: 'text-purple-600', + iconPath: 'M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z', + }, + { + id: 4, + user: 'Alex Rodriguez', + action: 'uploaded 3 files to "Q4 Planning"', + time: '1 day ago', + bgClass: 'bg-orange-100', + iconClass: 'text-orange-600', + iconPath: 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z', + }, + ]; + + upcomingTasks = [ + {id: 1, title: 'Review quarterly reports', dueDate: 'Today, 3:00 PM', priority: 'high', project: 'Q4 Planning'}, + {id: 2, title: 'Team standup meeting', dueDate: 'Tomorrow, 9:00 AM', priority: 'medium', project: 'Daily Operations'}, + {id: 3, title: 'Client presentation prep', dueDate: 'Friday, 2:00 PM', priority: 'high', project: 'Client Work'}, + ]; + + getUserFullName(): string { + const user = this.authService.user(); + if (!user) return ''; + const givenName = (user as any)['givenName'] || (user as any)['name']?.['givenName'] || (user as any)['given_name'] || ''; + const familyName = (user as any)['name']?.['familyName'] || (user as any)['familyName'] || (user as any)['family_name'] || ''; + return [givenName, familyName].filter(Boolean).join(' '); + } +} diff --git a/samples/teamspace-angular/src/app/pages/debug.component.ts b/samples/teamspace-angular/src/app/pages/debug.component.ts new file mode 100644 index 000000000..09e708712 --- /dev/null +++ b/samples/teamspace-angular/src/app/pages/debug.component.ts @@ -0,0 +1,236 @@ +import {Component, inject, signal, OnInit} from '@angular/core'; +import {JsonPipe} from '@angular/common'; +import {RouterLink} from '@angular/router'; +import {AsgardeoAuthService} from '@asgardeo/angular'; +import {HeaderComponent} from '../components/header.component'; + +@Component({ + selector: 'app-debug', + standalone: true, + imports: [JsonPipe, RouterLink, HeaderComponent], + template: ` +
+ + +
+ +
+ + + + + Back to dashboard + +

+ + + + Debug Information +

+

View session data and decoded tokens for debugging purposes.

+
+ + +
+
+

Signed In

+

+ {{ authService.isSignedIn() ? 'Yes' : 'No' }} +

+
+
+

Loading

+

+ {{ authService.isLoading() ? 'Yes' : 'No' }} +

+
+
+

Initialized

+

+ {{ authService.isInitialized() ? 'Yes' : 'No' }} +

+
+
+ +
+ +
+
+

Access Token

+ +
+
+ @if (accessToken()) { +
+
{{ accessToken() }}
+
+ } @else { +

No access token available

+ } +
+
+ + +
+
+

ID Token (JWT)

+ +
+
+ @if (idToken()) { +
+
{{ idToken() }}
+
+ } @else { +

No ID token available

+ } +
+
+ + +
+
+

Decoded ID Token

+ +
+
+ @if (decodedIdToken()) { +
+
{{ decodedIdToken() | json }}
+
+ } @else { +

No decoded ID token available

+ } +
+
+ + +
+
+

User Signal

+
+
+ @if (authService.user()) { +
+
{{ authService.user() | json }}
+
+ } @else { +

No user data available

+ } +
+
+ + +
+
+

Current Organization

+
+
+ @if (authService.currentOrganization()) { +
+
{{ authService.currentOrganization() | json }}
+
+ } @else { +

No organization context

+ } +
+
+ + +
+
+

My Organizations

+
+
+ @if (authService.myOrganizations().length > 0) { +
+
{{ authService.myOrganizations() | json }}
+
+ } @else { +

No organizations

+ } +
+
+
+ + +
+
+

SDK Configuration

+
+
+
+
{{ getConfig() | json }}
+
+
+
+
+
+ `, +}) +export class DebugComponent implements OnInit { + authService = inject(AsgardeoAuthService); + + accessToken = signal(null); + idToken = signal(null); + decodedIdToken = signal | null>(null); + + ngOnInit(): void { + this.fetchAll(); + } + + async fetchAll(): Promise { + await Promise.all([this.fetchAccessToken(), this.fetchIdToken(), this.fetchDecodedIdToken()]); + } + + async fetchAccessToken(): Promise { + try { + const token = await this.authService.getAccessToken(); + this.accessToken.set(token); + } catch { + this.accessToken.set(null); + } + } + + async fetchIdToken(): Promise { + try { + const token = await this.authService.getIdToken(); + this.idToken.set(token); + } catch { + this.idToken.set(null); + } + } + + async fetchDecodedIdToken(): Promise { + try { + const token = await this.authService.getDecodedIdToken(); + this.decodedIdToken.set(token as Record); + } catch { + this.decodedIdToken.set(null); + } + } + + getConfig(): Record { + try { + const config = this.authService.getConfiguration(); + return config as unknown as Record; + } catch { + return {}; + } + } +} diff --git a/samples/teamspace-angular/src/app/pages/landing.component.ts b/samples/teamspace-angular/src/app/pages/landing.component.ts new file mode 100644 index 000000000..55068f249 --- /dev/null +++ b/samples/teamspace-angular/src/app/pages/landing.component.ts @@ -0,0 +1,265 @@ +import {Component, inject} from '@angular/core'; +import {RouterLink} from '@angular/router'; +import { + AsgardeoAuthService, + AsgardeoSignedInDirective, + AsgardeoSignedOutDirective, + AsgardeoLoadingDirective, +} from '@asgardeo/angular'; +import {HeaderComponent} from '../components/header.component'; + +@Component({ + selector: 'app-landing', + standalone: true, + imports: [RouterLink, HeaderComponent, AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoLoadingDirective], + template: ` +
+ + + +
+
+
+

Loading...

+
+
+ + +
+
+
+
+ Powered by Asgardeo Angular SDK +
+ +

+ Where teams + collaborate and ideas come to life +

+ +

+ Streamline your team's workflow with our all-in-one collaboration platform. Built with Angular and + Asgardeo authentication. +

+ +
+ + +
+ + + +
+
+ + + + Redirect-based authentication +
+
+ + + + Angular Signals +
+
+
+
+
+ + +
+
+
+

SDK Features Demonstrated

+
+
+
+
3
+
Services
+
+
+
3
+
Directives
+
+
+
1
+
Route Guard
+
+
+
1
+
HTTP Interceptor
+
+
+
+
+ + +
+
+
+

SDK Features

+

+ This sample app demonstrates all the key features of the Asgardeo Angular SDK. +

+
+ +
+
+
+ + + +
+

Redirect Authentication

+

+ Sign in and sign up via Asgardeo's hosted login page with OAuth 2.0 redirect flow. +

+
+ +
+
+ + + +
+

Route Guards

+

+ Protect routes with asgardeoGuard — automatically redirects unauthenticated users. +

+
+ +
+
+ + + +
+

User Profile

+

+ Access user data via Angular Signals — user, userProfile, flattenedProfile, and more. +

+
+ +
+
+ + + +
+

Organizations

+

+ List, create, and switch between organizations using AsgardeoOrganizationService. +

+
+ +
+
+ + + +
+

Token Management

+

+ Access and decode tokens, with automatic Bearer token attachment via HTTP interceptor. +

+
+ +
+
+ + + +
+

Structural Directives

+

+ Conditionally render content with *asgardeoSignedIn, *asgardeoSignedOut, and *asgardeoLoading. +

+
+
+
+
+ + +
+
+
+
+ T +
+ Teamspace +
+

+ Built with Angular 19 and @asgardeo/angular SDK. A sample application for demonstration purposes. +

+
+
+
+ `, +}) +export class LandingComponent { + authService = inject(AsgardeoAuthService); + + signIn(): void { + this.authService.signIn(); + } + + signUp(): void { + this.authService.signUp(); + } +} diff --git a/samples/teamspace-angular/src/app/pages/organizations.component.ts b/samples/teamspace-angular/src/app/pages/organizations.component.ts new file mode 100644 index 000000000..3eca51ead --- /dev/null +++ b/samples/teamspace-angular/src/app/pages/organizations.component.ts @@ -0,0 +1,142 @@ +import {Component, inject} from '@angular/core'; +import {RouterLink} from '@angular/router'; +import {AsgardeoOrganizationService} from '@asgardeo/angular'; +import {HeaderComponent} from '../components/header.component'; + +@Component({ + selector: 'app-organizations', + standalone: true, + imports: [RouterLink, HeaderComponent], + template: ` +
+ + +
+ +
+ + + + + Back to dashboard + +
+
+

Organizations

+

Manage your organizations and switch between them

+
+ + + + + New Organization + +
+
+ + @if (orgService.isLoading()) { +
+
+
+ } @else if (orgService.error()) { +
+

{{ orgService.error() }}

+
+ } @else { + + @if (orgService.currentOrganization(); as currentOrg) { +
+
+
+

Current Organization

+

{{ currentOrg.name || currentOrg.id }}

+
+
Active
+
+
+ } + + +
+ @if (orgService.myOrganizations().length === 0) { +
+ + + +

No organizations found

+ + Create your first organization + +
+ } @else { +
    + @for (org of orgService.myOrganizations(); track org.id) { +
  • +
    +
    +
    + + + +
    +
    +

    {{ org.name || org.id }}

    + @if (org.id) { +

    {{ org.id }}

    + } +
    +
    +
    + @if (orgService.currentOrganization()?.id === org.id) { + Current + } @else { + + } +
    +
    +
  • + } +
+ } +
+ + +
+ +
+ } +
+
+ `, +}) +export class OrganizationsComponent { + orgService = inject(AsgardeoOrganizationService); + + async switchTo(org: any): Promise { + await this.orgService.switchOrganization(org); + } + + async revalidate(): Promise { + await this.orgService.revalidateMyOrganizations(); + } +} diff --git a/samples/teamspace-angular/src/app/pages/profile.component.ts b/samples/teamspace-angular/src/app/pages/profile.component.ts new file mode 100644 index 000000000..be005a7d1 --- /dev/null +++ b/samples/teamspace-angular/src/app/pages/profile.component.ts @@ -0,0 +1,154 @@ +import {Component, inject} from '@angular/core'; +import {RouterLink} from '@angular/router'; +import {JsonPipe} from '@angular/common'; +import {AsgardeoUserService} from '@asgardeo/angular'; +import {HeaderComponent} from '../components/header.component'; + +@Component({ + selector: 'app-profile', + standalone: true, + imports: [RouterLink, JsonPipe, HeaderComponent], + template: ` +
+ + +
+ +
+ + + + + Back to dashboard + +

Profile

+

+ View your profile information, including your display name, email, and other details. +

+
+ + @if (userService.isLoading()) { +
+
+
+ } @else { + +
+ +
+
+
+ {{ getInitials() }} +
+
+

{{ getDisplayName() }}

+ @if (getEmail()) { +

{{ getEmail() }}

+ } +
+
+
+ + +
+ @if (userService.flattenedProfile(); as profile) { + +
+

Basic Information

+
+ @if (profile['given_name'] || profile['name']?.['givenName']) { +
+ First Name + {{ profile['given_name'] || profile['name']?.['givenName'] }} +
+ } + @if (profile['family_name'] || profile['name']?.['familyName']) { +
+ Last Name + {{ profile['family_name'] || profile['name']?.['familyName'] }} +
+ } + @if (getEmail()) { +
+ Email + {{ getEmail() }} +
+ } + @if (profile['phone_number']) { +
+ Phone + {{ profile['phone_number'] }} +
+ } + @if (profile['sub']) { +
+ User ID + {{ profile['sub'] }} +
+ } +
+
+ } + + +
+

Raw Profile Data

+
+
{{ userService.flattenedProfile() | json }}
+
+
+ + +
+ +
+
+
+ } +
+
+ `, +}) +export class ProfileComponent { + userService = inject(AsgardeoUserService); + + getDisplayName(): string { + const profile = this.userService.flattenedProfile(); + if (!profile) return 'User'; + return ( + (profile as Record)['given_name'] || + (profile as Record)['name']?.['givenName'] || + (profile as Record)['email'] || + 'User' + ); + } + + getEmail(): string { + const profile = this.userService.flattenedProfile(); + if (!profile) return ''; + return (profile as Record)['email'] || ''; + } + + getInitials(): string { + const name = this.getDisplayName(); + return name + .split(' ') + .map((n: string) => n[0]) + .join('') + .toUpperCase() + .slice(0, 2); + } + + async refresh(): Promise { + await this.userService.refreshUser(); + } +} diff --git a/samples/teamspace-angular/src/env.d.ts b/samples/teamspace-angular/src/env.d.ts new file mode 100644 index 000000000..f481c1db3 --- /dev/null +++ b/samples/teamspace-angular/src/env.d.ts @@ -0,0 +1,16 @@ +/// + +interface ImportMetaEnv { + readonly VITE_ASGARDEO_BASE_URL: string; + readonly VITE_ASGARDEO_CLIENT_ID: string; + readonly VITE_ASGARDEO_AFTER_SIGN_IN_URL?: string; + readonly VITE_ASGARDEO_AFTER_SIGN_OUT_URL?: string; + readonly VITE_ASGARDEO_SIGN_IN_URL?: string; + readonly VITE_ASGARDEO_SIGN_UP_URL?: string; + readonly VITE_ASGARDEO_APPLICATION_ID?: string; + readonly VITE_ASGARDEO_PLATFORM?: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/samples/teamspace-angular/src/main.ts b/samples/teamspace-angular/src/main.ts new file mode 100644 index 000000000..698395dce --- /dev/null +++ b/samples/teamspace-angular/src/main.ts @@ -0,0 +1,7 @@ +import 'zone.js'; +import '@angular/compiler'; +import {bootstrapApplication} from '@angular/platform-browser'; +import {AppComponent} from './app/app.component'; +import {appConfig} from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err: unknown) => console.error(err)); diff --git a/samples/teamspace-angular/src/styles.css b/samples/teamspace-angular/src/styles.css new file mode 100644 index 000000000..0ff56f21d --- /dev/null +++ b/samples/teamspace-angular/src/styles.css @@ -0,0 +1,32 @@ +@import "tailwindcss"; +@source "./**/*.ts"; + +:root { + --radius: 0.625rem; +} + +/* Custom scrollbar */ +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + background: #f1f5f9; +} + +::-webkit-scrollbar-thumb { + background: #cbd5e1; + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: #94a3b8; +} + +body { + font-family: + -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + margin: 0; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/samples/teamspace-angular/tsconfig.app.json b/samples/teamspace-angular/tsconfig.app.json new file mode 100644 index 000000000..22fef6040 --- /dev/null +++ b/samples/teamspace-angular/tsconfig.app.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist/out-tsc", + "types": ["node"] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.ts"] +} diff --git a/samples/teamspace-angular/tsconfig.json b/samples/teamspace-angular/tsconfig.json new file mode 100644 index 000000000..c3088529a --- /dev/null +++ b/samples/teamspace-angular/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "bundler", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "declaration": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "isolatedModules": true, + "useDefineForClassFields": false, + "sourceMap": true, + "outDir": "./dist/out-tsc", + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/samples/teamspace-angular/vite.config.ts b/samples/teamspace-angular/vite.config.ts new file mode 100644 index 000000000..f8f4c6576 --- /dev/null +++ b/samples/teamspace-angular/vite.config.ts @@ -0,0 +1,11 @@ +import {defineConfig} from 'vite'; +import angular from '@analogjs/vite-plugin-angular'; +import tailwindcss from '@tailwindcss/vite'; +import basicSsl from '@vitejs/plugin-basic-ssl'; + +export default defineConfig({ + plugins: [angular(), tailwindcss(), basicSsl()], + resolve: { + mainFields: ['browser', 'module', 'main'], + }, +}); From 863af6e7fe59bf26a873294583aa639e575cfb7d Mon Sep 17 00:00:00 2001 From: DonOmalVindula Date: Fri, 20 Feb 2026 14:36:13 +0530 Subject: [PATCH 3/6] Implement user profile component in angular SDK --- packages/angular/src/AsgardeoAngularClient.ts | 10 + .../user-profile/user-profile.component.ts | 855 ++++++++++++++++++ packages/angular/src/index.ts | 1 + .../src/services/asgardeo-auth.service.ts | 32 +- .../src/app/app.component.ts | 29 +- .../src/app/components/header.component.ts | 318 ++++++- .../src/app/pages/create-org.component.ts | 16 +- .../src/app/pages/organizations.component.ts | 36 +- .../src/app/pages/profile.component.ts | 18 +- 9 files changed, 1252 insertions(+), 63 deletions(-) create mode 100644 packages/angular/src/components/user-profile/user-profile.component.ts diff --git a/packages/angular/src/AsgardeoAngularClient.ts b/packages/angular/src/AsgardeoAngularClient.ts index 70b8238b4..a5cb343c6 100644 --- a/packages/angular/src/AsgardeoAngularClient.ts +++ b/packages/angular/src/AsgardeoAngularClient.ts @@ -296,10 +296,20 @@ class AsgardeoAngularClient at runtime. + // Callers MUST await the result. The sync return type is inherited from the base interface. override getConfiguration(): T { return this.spaClient.getConfigData() as unknown as T; } + /** + * Async version of getConfiguration that properly awaits the config data. + * Use this instead of getConfiguration() for correct behavior. + */ + async getConfigurationAsync(): Promise { + return (await this.spaClient.getConfigData()) as unknown as T; + } + override async exchangeToken(config: TokenExchangeRequestConfig): Promise { return this.withLoading(async () => this.spaClient.exchangeToken(config) as unknown as TokenResponse | Response); } diff --git a/packages/angular/src/components/user-profile/user-profile.component.ts b/packages/angular/src/components/user-profile/user-profile.component.ts new file mode 100644 index 000000000..952b28bd7 --- /dev/null +++ b/packages/angular/src/components/user-profile/user-profile.component.ts @@ -0,0 +1,855 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + Component, + Input, + Output, + EventEmitter, + inject, + signal, + computed, + OnChanges, + SimpleChanges, + HostListener, +} from '@angular/core'; +import {AsgardeoAuthService} from '../../services/asgardeo-auth.service'; +import updateMeProfile from '../../api/updateMeProfile'; + +/** Fields that should never be displayed in the profile fields list. + * Matches React SDK's BaseUserProfile.fieldsToSkip. */ +const FIELDS_TO_SKIP: string[] = [ + 'roles.default', + 'active', + 'groups', + 'accountLocked', + 'accountDisabled', + 'oneTimePassword', + 'userSourceId', + 'idpType', + 'localCredentialExists', + 'ResourceType', + 'ExternalID', + 'MetaData', + 'verifiedMobileNumbers', + 'verifiedEmailAddresses', + 'phoneNumbers.mobile', + 'emailAddresses', + 'preferredMFAOption', +]; + +/** Fields that cannot be edited */ +const READONLY_FIELDS: string[] = ['username', 'userName', 'user_name']; + +/** Well-known SCIM2 schema IDs */ +const WELL_KNOWN_USER_SCHEMA = 'urn:ietf:params:scim:schemas:core:2.0:User'; + +interface SchemaField { + caseExact?: boolean; + description?: string; + displayName?: string; + displayOrder?: string; + multiValued?: boolean; + mutability?: string; + name?: string; + required?: boolean; + returned?: string; + subAttributes?: SchemaField[]; + type?: string; + uniqueness?: string; + value?: any; + path?: string; + schemaId?: string; +} + +/** + * Angular User Profile component matching the React SDK's ``. + * + * Supports both inline and popup (dialog) modes with SCIM schema-based + * field rendering and inline editing. + * + * @example + * ```html + * + * + * + * + * + * ``` + */ +@Component({ + selector: 'asgardeo-user-profile', + standalone: true, + template: ` + @if (mode === 'popup') { + @if (open) { +
+
+
+

{{ title || 'Profile' }}

+ +
+ +
+
+ } + } @else { + + } + `, + styles: ` + /* Dialog Overlay */ + .asgardeo-dialog__overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + } + + .asgardeo-dialog__content { + background: #fff; + border-radius: 12px; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15); + max-width: 600px; + width: 90vw; + max-height: 85vh; + display: flex; + flex-direction: column; + z-index: 10000; + padding: 2rem; + } + + .asgardeo-dialog__header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 2rem; + border-bottom: 1px solid #e5e7eb; + } + + .asgardeo-dialog__heading { + font-size: 1.2rem; + font-weight: 600; + color: #111827; + margin: 0; + } + + .asgardeo-dialog__close { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + background: none; + border: none; + border-radius: 6px; + cursor: pointer; + color: #6b7280; + + &:hover { + background: rgba(0, 0, 0, 0.05); + color: #111827; + } + } + + /* Profile Content */ + .asgardeo-user-profile__popup { + padding: 2rem; + overflow-y: auto; + } + + .asgardeo-user-profile { + min-width: 0; + } + + /* Alert */ + .asgardeo-alert { + padding: 12px 16px; + border-radius: 8px; + margin-bottom: 24px; + } + + .asgardeo-alert--error { + background: #fef2f2; + border: 1px solid #fecaca; + } + + .asgardeo-alert__title { + font-size: 0.875rem; + font-weight: 600; + color: #991b1b; + } + + .asgardeo-alert__description { + font-size: 0.875rem; + color: #b91c1c; + margin-top: 2px; + } + + /* Avatar */ + .asgardeo-avatar { + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + color: white; + font-weight: 500; + overflow: hidden; + flex-shrink: 0; + } + + .asgardeo-avatar--lg { + width: 70px; + height: 70px; + font-size: 24px; + } + + .asgardeo-avatar img { + width: 100%; + height: 100%; + object-fit: cover; + } + + /* Profile Summary */ + .asgardeo-user-profile__summary { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 4px; + margin-bottom: 12px; + } + + .asgardeo-user-profile__summary-name { + font-size: 1.5rem; + font-weight: 600; + color: #111827; + margin-top: 8px; + } + + .asgardeo-user-profile__summary-email { + font-size: 0.875rem; + color: #6b7280; + } + + /* Divider */ + .asgardeo-divider { + border-bottom: 1px solid #e5e7eb; + } + + /* Field info row — wraps each field + divider with vertical padding and bottom border */ + .asgardeo-user-profile__info { + padding: 12px 0; + border-bottom: 1px solid #e5e7eb; + + &:last-child { + border-bottom: none; + } + } + + /* Field */ + .asgardeo-user-profile__field { + display: flex; + align-items: center; + padding: 4px 0; + min-height: 28px; + } + + .asgardeo-user-profile__field-inner { + flex: 1; + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + } + + .asgardeo-user-profile__field-label { + width: 120px; + flex-shrink: 0; + font-size: 0.875rem; + font-weight: 500; + color: #6b7280; + line-height: 28px; + } + + .asgardeo-user-profile__field-value { + flex: 1; + font-size: 0.875rem; + color: #111827; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + max-width: 350px; + line-height: 28px; + word-break: break-word; + } + + .asgardeo-user-profile__field-placeholder { + font-style: italic; + opacity: 0.7; + cursor: pointer; + text-decoration: underline; + font-size: 0.875rem; + } + + .asgardeo-user-profile__field-actions { + display: flex; + align-items: center; + gap: 4px; + margin-left: 32px; + } + + /* Text Field */ + .asgardeo-text-field { + width: 100%; + max-width: 280px; + padding: 6px 10px; + font-size: 0.875rem; + border: 1px solid #d1d5db; + border-radius: 6px; + outline: none; + font-family: inherit; + + &:focus { + border-color: #6366f1; + box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2); + } + } + + /* Checkbox */ + .asgardeo-checkbox { + display: flex; + align-items: center; + cursor: pointer; + } + + .asgardeo-checkbox input { + width: 16px; + height: 16px; + } + + /* Buttons */ + .asgardeo-btn { + display: inline-flex; + align-items: center; + justify-content: center; + border: none; + cursor: pointer; + font-family: inherit; + border-radius: 6px; + transition: background-color 0.15s; + } + + .asgardeo-btn--sm { + padding: 4px 12px; + font-size: 0.8125rem; + font-weight: 500; + } + + .asgardeo-btn--primary { + background: #4f46e5; + color: white; + + &:hover { + background: #4338ca; + } + } + + .asgardeo-btn--secondary { + background: #f3f4f6; + color: #374151; + + &:hover { + background: #e5e7eb; + } + } + + .asgardeo-btn--icon { + width: 28px; + height: 28px; + padding: 0; + background: none; + color: #9ca3af; + border-radius: 4px; + + &:hover { + background: rgba(0, 0, 0, 0.05); + color: #6b7280; + } + } + `, +}) +export class AsgardeoUserProfileComponent implements OnChanges { + /** Display mode: inline (default) or popup dialog */ + @Input() mode: 'inline' | 'popup' = 'inline'; + + /** Whether the popup dialog is open (popup mode only) */ + @Input() open = false; + + /** Dialog title (popup mode only) */ + @Input() title = ''; + + /** Whether fields can be edited */ + @Input() editable = true; + + /** Whitelist of field names to show (if set, only these are shown) */ + @Input() showFields?: string[]; + + /** Blacklist of field names to hide */ + @Input() hideFields?: string[]; + + /** Emitted when the popup open state changes */ + @Output() openChange = new EventEmitter(); + + private authService = inject(AsgardeoAuthService); + private editingFields = signal>({}); + private editedValues = signal>({}); + + error = signal(null); + + schemasAvailable = computed(() => { + const up = this.authService.userProfile(); + return up?.schemas && up.schemas.length > 0; + }); + + displayName = computed(() => { + const user = this.authService.flattenedProfile() || this.authService.user(); + if (!user) return 'User'; + const u = user as Record; + const firstName = u['name']?.['givenName'] || u['given_name'] || ''; + const lastName = u['name']?.['familyName'] || u['family_name'] || ''; + if (firstName && lastName) return `${firstName} ${lastName}`; + return u['userName'] || u['username'] || u['email'] || 'User'; + }); + + emailValue = computed(() => { + const user = this.authService.flattenedProfile() || this.authService.user(); + if (!user) return ''; + const u = user as Record; + const emails = u['emails']; + if (Array.isArray(emails)) return emails[0] || ''; + return u['email'] || ''; + }); + + profileImageUrl = computed(() => { + const user = this.authService.flattenedProfile() || this.authService.user(); + if (!user) return null; + const u = user as Record; + return u['profile'] || u['profileUrl'] || u['picture'] || u['URL'] || null; + }); + + initials = computed(() => { + const name = this.displayName(); + return name + .split(' ') + .map((p: string) => p[0]) + .slice(0, 2) + .join('') + .toUpperCase(); + }); + + avatarGradient = computed(() => { + const name = this.displayName(); + if (!name) return 'linear-gradient(135deg, #6366f1, #8b5cf6)'; + return this.generateGradient(name); + }); + + /** + * Flattened schema fields with current values, filtered and sorted. + * `userProfile().schemas` is already flattened by `flattenUserSchema()` — a flat + * array of field definitions (each with `name`, `type`, `schemaId`, `displayOrder`, etc.), + * NOT nested schema objects with `.attributes`. + */ + visibleFields = computed(() => { + const up = this.authService.userProfile(); + if (!up?.schemas || up.schemas.length === 0) return []; + const flatProfile = (this.authService.flattenedProfile() || {}) as Record; + + return (up.schemas as any[]) + .map((field: any) => ({...field, value: flatProfile[field.name]} as SchemaField)) + .filter((f: SchemaField) => { + if (!f.name) return false; + if (FIELDS_TO_SKIP.includes(f.name)) return false; + if (this.hideFields?.includes(f.name)) return false; + if (this.showFields && this.showFields.length > 0 && !this.showFields.includes(f.name)) return false; + if (!this.editable) { + return f.value !== undefined && f.value !== '' && f.value !== null; + } + return true; + }) + .sort((a: SchemaField, b: SchemaField) => { + const orderA = a.displayOrder ? parseInt(a.displayOrder, 10) : 999; + const orderB = b.displayOrder ? parseInt(b.displayOrder, 10) : 999; + return orderA - orderB; + }); + }); + + /** Fallback flat profile key-value pairs when no schemas available */ + flatProfileEntries = computed(() => { + const profile = (this.authService.flattenedProfile() || this.authService.user()) as Record; + if (!profile) return []; + + const entries: {key: string; value: string}[] = []; + + const flatten = (obj: Record, prefix: string = ''): void => { + for (const [key, value] of Object.entries(obj)) { + const fullKey = prefix ? `${prefix}.${key}` : key; + if (FIELDS_TO_SKIP.includes(fullKey) || FIELDS_TO_SKIP.includes(key)) continue; + if (this.hideFields?.includes(fullKey)) continue; + if (this.showFields && this.showFields.length > 0 && !this.showFields.includes(fullKey)) continue; + if (value === undefined || value === '' || value === null) continue; + + if (Array.isArray(value)) { + const displayVal = value.filter(v => v !== null && v !== undefined && v !== '').join(', '); + if (displayVal) entries.push({key: fullKey, value: displayVal}); + } else if (typeof value === 'object') { + flatten(value, fullKey); + } else { + entries.push({key: fullKey, value: String(value)}); + } + } + }; + + flatten(profile); + return entries.sort((a, b) => a.key.localeCompare(b.key)); + }); + + ngOnChanges(changes: SimpleChanges): void { + if (changes['open'] && !changes['open'].currentValue) { + this.editingFields.set({}); + this.editedValues.set({}); + this.error.set(null); + } + } + + @HostListener('document:keydown.escape') + onEscapeKey(): void { + if (this.mode === 'popup' && this.open) { + this.close(); + } + } + + close(): void { + this.openChange.emit(false); + } + + onOverlayClick(event: Event): void { + if (event.target === event.currentTarget) { + this.close(); + } + } + + isFieldEditing(fieldName: string): boolean { + return this.editingFields()[fieldName] || false; + } + + getEditedValue(fieldName: string): any { + const edited = this.editedValues(); + if (fieldName in edited) return edited[fieldName]; + const profile = (this.authService.flattenedProfile() || {}) as Record; + return profile[fieldName]; + } + + toggleEdit(fieldName: string): void { + const current = this.editingFields(); + this.editingFields.set({...current, [fieldName]: !current[fieldName]}); + } + + onFieldChange(fieldName: string, value: any): void { + this.editedValues.update(v => ({...v, [fieldName]: value})); + } + + cancelEdit(fieldName: string): void { + this.editingFields.update(v => ({...v, [fieldName]: false})); + this.editedValues.update(v => { + const copy = {...v}; + delete copy[fieldName]; + return copy; + }); + } + + async saveField(field: SchemaField): Promise { + if (!field.name) return; + + const fieldName = field.name; + let fieldValue = this.getEditedValue(fieldName) ?? ''; + + if (Array.isArray(fieldValue)) { + fieldValue = fieldValue.filter((v: any) => v !== undefined && v !== null && v !== ''); + } + + let payload: Record = {}; + if (field.schemaId && field.schemaId !== WELL_KNOWN_USER_SCHEMA) { + payload = {[field.schemaId]: {[fieldName]: fieldValue}}; + } else { + this.setNestedValue(payload, fieldName, fieldValue); + } + + this.error.set(null); + try { + const baseUrl = this.authService.getBaseUrl(); + const instanceId = this.authService.getClient().getInstanceId(); + + const response = await updateMeProfile({baseUrl, instanceId, payload}); + + // Update cached user & profile signals from the SCIM response + this.authService.handleProfileUpdate(response); + + this.editingFields.update(v => ({...v, [fieldName]: false})); + this.editedValues.update(v => { + const copy = {...v}; + delete copy[fieldName]; + return copy; + }); + } catch (err: any) { + this.error.set(err?.message || 'Failed to update profile'); + } + } + + isReadonly(field: SchemaField): boolean { + if (field.mutability === 'READ_ONLY') return true; + if (field.name && READONLY_FIELDS.includes(field.name)) return true; + return false; + } + + hasFieldValue(field: SchemaField): boolean { + return field.value !== undefined && field.value !== '' && field.value !== null; + } + + formatFieldValue(field: SchemaField): string { + const val = field.value; + if (val === null || val === undefined) return ''; + if (typeof val === 'boolean') return val ? 'Yes' : 'No'; + if (typeof val === 'object') return JSON.stringify(val); + return String(val); + } + + formatLabel(key: string): string { + return key + .split(/(?=[A-Z])|_|\./) + .map((word: string) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(' '); + } + + private setNestedValue(obj: Record, path: string, value: any): void { + const keys = path.split('.'); + let current = obj; + for (let i = 0; i < keys.length; i++) { + if (i === keys.length - 1) { + current[keys[i]] = value; + } else { + if (!current[keys[i]] || typeof current[keys[i]] !== 'object') { + current[keys[i]] = {}; + } + current = current[keys[i]]; + } + } + } + + private generateGradient(inputString: string): string { + let hash = inputString.split('').reduce((acc: number, char: string) => { + const charCode = char.charCodeAt(0); + return ((acc << 5) - acc + charCode) & 0xffffffff; + }, 0); + const seed = Math.abs(hash); + const hue1 = (seed + seed) % 360; + const hue2 = (hue1 + 60 + (seed % 120)) % 360; + const saturation = 70 + (seed % 20); + const lightness1 = 55 + (seed % 15); + const lightness2 = 60 + ((seed + seed) % 15); + const angle = 45 + (seed % 91); + return `linear-gradient(${angle}deg, hsl(${hue1}, ${saturation}%, ${lightness1}%), hsl(${hue2}, ${saturation}%, ${lightness2}%))`; + } +} diff --git a/packages/angular/src/index.ts b/packages/angular/src/index.ts index ed71dc5b2..9a9680300 100644 --- a/packages/angular/src/index.ts +++ b/packages/angular/src/index.ts @@ -45,6 +45,7 @@ export {AsgardeoLoadingDirective} from './directives/loading.directive'; // --- Components --- export {AsgardeoCallbackComponent} from './components/callback/callback.component'; +export {AsgardeoUserProfileComponent} from './components/user-profile/user-profile.component'; // --- API --- export {default as getAllOrganizations, GetAllOrganizationsConfig} from './api/getAllOrganizations'; diff --git a/packages/angular/src/services/asgardeo-auth.service.ts b/packages/angular/src/services/asgardeo-auth.service.ts index 69887c722..36b3e1ad5 100644 --- a/packages/angular/src/services/asgardeo-auth.service.ts +++ b/packages/angular/src/services/asgardeo-auth.service.ts @@ -33,6 +33,7 @@ import { hasCalledForThisInstanceInUrl, Platform, extractUserClaimsFromIdToken, + generateFlattenedUserProfile, } from '@asgardeo/browser'; import {BehaviorSubject, Observable} from 'rxjs'; import AsgardeoAngularClient from '../AsgardeoAngularClient'; @@ -127,7 +128,7 @@ export class AsgardeoAuthService implements OnDestroy { async initialize(): Promise { try { await this.client.initialize(this.config); - const initializedConfig: AsgardeoAngularConfig = this.client.getConfiguration(); + const initializedConfig: AsgardeoAngularConfig = await this.client.getConfigurationAsync(); this.config = initializedConfig; if (initializedConfig?.platform) { @@ -323,10 +324,37 @@ export class AsgardeoAuthService implements OnDestroy { return this.config; } + /** + * Returns the resolved base URL, including the `/o` suffix for organization logins. + */ + getBaseUrl(): string { + return this._baseUrl(); + } + async reInitialize(config: Partial): Promise { return this.client.reInitialize(config); } + // --- Profile Update --- + + /** + * Updates the cached user and user profile after a successful SCIM2 PATCH. + * Mirrors AsgardeoProvider's handleProfileUpdate from the React SDK. + * + * @param updatedUser - The updated user object returned from the SCIM2 API. + */ + handleProfileUpdate(updatedUser: User): void { + this._user.set(updatedUser); + this._user$.next(updatedUser); + + const currentProfile = this._userProfile(); + this._userProfile.set({ + ...currentProfile, + flattenedProfile: generateFlattenedUserProfile(updatedUser, currentProfile?.schemas), + profile: updatedUser, + } as UserProfile); + } + // --- Internal: Expose client for secondary services --- /** @internal */ @@ -350,7 +378,7 @@ export class AsgardeoAuthService implements OnDestroy { // If there's a `user_org` claim, treat this as an organization login if (decodedToken?.['user_org']) { - resolvedBaseUrl = `${this.client.getConfiguration().baseUrl}/o`; + resolvedBaseUrl = `${(await this.client.getConfigurationAsync()).baseUrl}/o`; this._baseUrl.set(resolvedBaseUrl); } diff --git a/samples/teamspace-angular/src/app/app.component.ts b/samples/teamspace-angular/src/app/app.component.ts index 069fef926..12d455b92 100644 --- a/samples/teamspace-angular/src/app/app.component.ts +++ b/samples/teamspace-angular/src/app/app.component.ts @@ -1,6 +1,5 @@ -import {Component, inject, OnInit} from '@angular/core'; -import {Router, RouterOutlet} from '@angular/router'; -import {AsgardeoAuthService} from '@asgardeo/angular'; +import {Component} from '@angular/core'; +import {RouterOutlet} from '@angular/router'; @Component({ selector: 'app-root', @@ -8,26 +7,4 @@ import {AsgardeoAuthService} from '@asgardeo/angular'; imports: [RouterOutlet], template: '', }) -export class AppComponent implements OnInit { - private authService = inject(AsgardeoAuthService); - private router = inject(Router); - - async ngOnInit(): Promise { - const url = new URL(window.location.href); - - // Workaround: The SDK's APP_INITIALIZER may skip the OAuth code exchange - // because the state param format doesn't match. If we detect OAuth params - // in the URL and we're not signed in, trigger the code exchange manually. - if (url.searchParams.has('code') && !this.authService.isSignedIn()) { - try { - await this.authService.signIn({callOnlyOnRedirect: true}); - } catch { - // signIn may fail if the code has already been consumed - } - // After successful sign-in, clean the URL - if (this.authService.isSignedIn()) { - this.router.navigateByUrl(url.pathname); - } - } - } -} +export class AppComponent {} diff --git a/samples/teamspace-angular/src/app/components/header.component.ts b/samples/teamspace-angular/src/app/components/header.component.ts index f93e15070..3dee92562 100644 --- a/samples/teamspace-angular/src/app/components/header.component.ts +++ b/samples/teamspace-angular/src/app/components/header.component.ts @@ -1,11 +1,11 @@ -import {Component, inject} from '@angular/core'; +import {Component, inject, signal, HostListener, computed} from '@angular/core'; import {RouterLink} from '@angular/router'; -import {AsgardeoAuthService, AsgardeoSignedInDirective, AsgardeoSignedOutDirective} from '@asgardeo/angular'; +import {AsgardeoAuthService, AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoUserProfileComponent} from '@asgardeo/angular'; @Component({ selector: 'app-header', standalone: true, - imports: [RouterLink, AsgardeoSignedInDirective, AsgardeoSignedOutDirective], + imports: [RouterLink, AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoUserProfileComponent], template: `
@@ -31,6 +31,9 @@ import {AsgardeoAuthService, AsgardeoSignedInDirective, AsgardeoSignedOutDirecti Dashboard + Organizations Debug @@ -38,15 +41,88 @@ import {AsgardeoAuthService, AsgardeoSignedInDirective, AsgardeoSignedOutDirecti
- -
- {{ authService.user()?.given_name || 'User' }} + +
+ + @if (dropdownOpen()) { +
+ +
+ @if (getProfileUrl(); as url) { + + } @else { +
+ {{ getInitials() }} +
+ } +
+ {{ getDisplayName() }} + {{ getUserName() }} +
+
+ + +
+ + + + + Dashboard + + + + + + Organizations + + + + + + Debug + + + +
+ + + + + + +
+
+ }
@@ -68,10 +144,215 @@ import {AsgardeoAuthService, AsgardeoSignedInDirective, AsgardeoSignedOutDirecti
+ + + + `, + styles: ` + /* Matches the React SDK's BaseUserDropdown styles */ + .asgardeo-user-dropdown__trigger { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 4px; + background: none; + border: none; + cursor: pointer; + border-radius: 8px; + transition: none; + box-shadow: none; + + &:hover { + background-color: rgba(0, 0, 0, 0.05); + } + + &:focus { + outline: 2px solid #4f46e5; + outline-offset: 2px; + } + } + + .asgardeo-avatar { + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + color: white; + font-weight: 500; + overflow: hidden; + flex-shrink: 0; + } + + .asgardeo-avatar img { + width: 100%; + height: 100%; + object-fit: cover; + } + + .asgardeo-user-dropdown__content { + position: absolute; + right: 0; + margin-top: 5px; + min-width: 250px; + max-width: 600px; + background: #fff; + border-radius: 12px; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + border: 1px solid #e5e7eb; + overflow: hidden; + z-index: 9999; + } + + .asgardeo-user-dropdown__header { + display: flex; + align-items: center; + gap: 8px; + padding: 12px; + border-bottom: 1px solid #e5e7eb; + } + + .asgardeo-user-dropdown__header-info { + display: flex; + flex-direction: column; + gap: 2px; + flex: 1; + min-width: 0; + overflow: hidden; + } + + .asgardeo-user-dropdown__header-name { + font-size: 1rem; + font-weight: 500; + color: #111827; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .asgardeo-user-dropdown__header-email { + font-size: 0.875rem; + color: #6b7280; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .asgardeo-user-dropdown__menu { + display: flex; + flex-direction: column; + width: 100%; + } + + .asgardeo-user-dropdown__menu-item { + display: flex; + align-items: center; + gap: 8px; + padding: 10px 16px; + width: 100%; + color: #111827; + text-decoration: none; + border: none; + background: transparent; + cursor: pointer; + font-size: 0.875rem; + text-align: start; + border-radius: 0; + font-family: inherit; + + &:hover { + background-color: rgba(0, 0, 0, 0.05); + } + } + + .asgardeo-user-dropdown__menu-divider { + margin: 4px 0; + border-bottom: 1px solid #e5e7eb; + } `, }) export class HeaderComponent { authService = inject(AsgardeoAuthService); + dropdownOpen = signal(false); + showProfile = signal(false); + + /** Computed gradient background matching the React SDK Avatar's name-seeded algorithm */ + avatarGradient = computed(() => { + const name = this.getDisplayName(); + if (!name) return 'linear-gradient(135deg, #6366f1, #8b5cf6)'; + return this.generateBackgroundColor(name); + }); + + @HostListener('document:click') + onDocumentClick(): void { + if (this.dropdownOpen()) { + this.dropdownOpen.set(false); + } + } + + toggleDropdown(event: Event): void { + event.stopPropagation(); + this.dropdownOpen.update(v => !v); + } + + closeDropdown(): void { + this.dropdownOpen.set(false); + } + + getProfileUrl(): string | null { + const user = this.authService.user(); + if (!user) return null; + return ( + (user as any)['profile'] || + (user as any)['profileUrl'] || + (user as any)['picture'] || + (user as any)['URL'] || + null + ); + } + + getUserName(): string { + const user = this.authService.user(); + if (!user) return ''; + return (user as any)['userName'] || (user as any)['username'] || (user as any)['user_name'] || ''; + } + + getEmail(): string { + const user = this.authService.user(); + if (!user) return ''; + const emails = (user as any)['emails']; + if (Array.isArray(emails)) return emails[0] || ''; + return (user as any)['email'] || ''; + } + + getDisplayName(): string { + const user = this.authService.user(); + if (!user) return ''; + const firstName = + (user as any)['name']?.['givenName'] || (user as any)['given_name'] || ''; + const lastName = + (user as any)['name']?.['familyName'] || (user as any)['family_name'] || ''; + if (firstName && lastName) return `${firstName} ${lastName}`; + return this.getUserName() || this.getEmail() || (user as any)['name'] || 'User'; + } + + getInitials(): string { + const name = this.getDisplayName(); + return name + .split(' ') + .map((part: string) => part[0]) + .slice(0, 2) + .join('') + .toUpperCase(); + } + + openProfile(): void { + this.closeDropdown(); + this.showProfile.set(true); + } signIn(): void { this.authService.signIn(); @@ -82,6 +363,25 @@ export class HeaderComponent { } signOut(): void { + this.closeDropdown(); this.authService.signOut(); } + + /** Same algorithm as React SDK's Avatar component for name-seeded gradient */ + private generateBackgroundColor(inputString: string): string { + let hash = inputString.split('').reduce((acc: number, char: string) => { + const charCode = char.charCodeAt(0); + return ((acc << 5) - acc + charCode) & 0xffffffff; + }, 0); + + const seed = Math.abs(hash); + const hue1 = (seed + seed) % 360; + const hue2 = (hue1 + 60 + (seed % 120)) % 360; + const saturation = 70 + (seed % 20); + const lightness1 = 55 + (seed % 15); + const lightness2 = 60 + ((seed + seed) % 15); + const angle = 45 + (seed % 91); + + return `linear-gradient(${angle}deg, hsl(${hue1}, ${saturation}%, ${lightness1}%), hsl(${hue2}, ${saturation}%, ${lightness2}%))`; + } } diff --git a/samples/teamspace-angular/src/app/pages/create-org.component.ts b/samples/teamspace-angular/src/app/pages/create-org.component.ts index 2814d2315..553c48c43 100644 --- a/samples/teamspace-angular/src/app/pages/create-org.component.ts +++ b/samples/teamspace-angular/src/app/pages/create-org.component.ts @@ -1,7 +1,7 @@ import {Component, inject, signal} from '@angular/core'; import {Router, RouterLink} from '@angular/router'; import {FormsModule} from '@angular/forms'; -import {AsgardeoOrganizationService} from '@asgardeo/angular'; +import {AsgardeoAuthService, createOrganization} from '@asgardeo/angular'; import {HeaderComponent} from '../components/header.component'; @Component({ @@ -102,7 +102,7 @@ import {HeaderComponent} from '../components/header.component'; `, }) export class CreateOrgComponent { - private orgService = inject(AsgardeoOrganizationService); + private authService = inject(AsgardeoAuthService); private router = inject(Router); orgName = ''; @@ -119,8 +119,16 @@ export class CreateOrgComponent { this.success.set(false); try { - await this.orgService.createOrganization({name: this.orgName.trim(), description: this.orgDescription.trim()}); - await this.orgService.revalidateMyOrganizations(); + await createOrganization({ + baseUrl: import.meta.env['VITE_ASGARDEO_BASE_URL'] || '', + payload: { + name: this.orgName.trim(), + description: this.orgDescription.trim(), + parentId: this.authService.currentOrganization()?.id || '', + type: 'TENANT', + }, + }); + await this.authService.getClient().getMyOrganizations(); this.success.set(true); setTimeout(() => { this.router.navigate(['/organizations']); diff --git a/samples/teamspace-angular/src/app/pages/organizations.component.ts b/samples/teamspace-angular/src/app/pages/organizations.component.ts index 3eca51ead..bae729699 100644 --- a/samples/teamspace-angular/src/app/pages/organizations.component.ts +++ b/samples/teamspace-angular/src/app/pages/organizations.component.ts @@ -1,6 +1,6 @@ -import {Component, inject} from '@angular/core'; +import {Component, inject, signal} from '@angular/core'; import {RouterLink} from '@angular/router'; -import {AsgardeoOrganizationService} from '@asgardeo/angular'; +import {AsgardeoAuthService} from '@asgardeo/angular'; import {HeaderComponent} from '../components/header.component'; @Component({ @@ -37,17 +37,17 @@ import {HeaderComponent} from '../components/header.component'; - @if (orgService.isLoading()) { + @if (isLoading()) {
- } @else if (orgService.error()) { + } @else if (error()) {
-

{{ orgService.error() }}

+

{{ error() }}

} @else { - @if (orgService.currentOrganization(); as currentOrg) { + @if (authService.currentOrganization(); as currentOrg) {
@@ -61,7 +61,7 @@ import {HeaderComponent} from '../components/header.component';
- @if (orgService.myOrganizations().length === 0) { + @if (authService.myOrganizations().length === 0) {
@@ -76,7 +76,7 @@ import {HeaderComponent} from '../components/header.component';
} @else {
    - @for (org of orgService.myOrganizations(); track org.id) { + @for (org of authService.myOrganizations(); track org.id) {
  • @@ -93,7 +93,7 @@ import {HeaderComponent} from '../components/header.component';
    - @if (orgService.currentOrganization()?.id === org.id) { + @if (authService.currentOrganization()?.id === org.id) { Current } @else {
    - @if (userService.isLoading()) { + @if (authService.isLoading()) {
    @@ -51,7 +51,7 @@ import {HeaderComponent} from '../components/header.component';
    - @if (userService.flattenedProfile(); as profile) { + @if (authService.flattenedProfile(); as profile) {

    Basic Information

    @@ -94,7 +94,7 @@ import {HeaderComponent} from '../components/header.component';

    Raw Profile Data

    -
    {{ userService.flattenedProfile() | json }}
    +
    {{ authService.flattenedProfile() | json }}
    @@ -102,7 +102,7 @@ import {HeaderComponent} from '../components/header.component';
    -
    - -
    -
    - } - } @else { + + @if (editable() && !isReadonly(field)) { + + }
- @if (editable && !isReadonly(field)) { - - } -
} } @else { @@ -284,14 +184,89 @@ interface SchemaField { } }
+ + + @if (mode() === 'popup') { + @if (open()) { +
+
+
+

{{ title() || 'Profile' }}

+ +
+ +
+
+ } + } @else { + } `, styles: ` + /* ------------------------------------------------------------------ */ + /* Custom Properties — override these to theme the component. */ + /* */ + /* Usage: */ + /* asgardeo-user-profile { */ + /* --asgardeo-color-primary: #0ea5e9; */ + /* --asgardeo-color-primary-hover: #0284c7; */ + /* } */ + /* ------------------------------------------------------------------ */ + :host { + /* Core palette */ + --asgardeo-color-primary: #4f46e5; + --asgardeo-color-primary-hover: #4338ca; + --asgardeo-color-primary-ring: rgba(99, 102, 241, 0.2); + + /* Text */ + --asgardeo-color-text: #111827; + --asgardeo-color-text-secondary: #6b7280; + --asgardeo-color-text-muted: #9ca3af; + + /* Surfaces & borders */ + --asgardeo-color-surface: #fff; + --asgardeo-color-border: #e5e7eb; + --asgardeo-color-input-border: #d1d5db; + --asgardeo-color-hover: rgba(0, 0, 0, 0.05); + + /* Secondary button */ + --asgardeo-color-secondary: #f3f4f6; + --asgardeo-color-secondary-hover: #e5e7eb; + --asgardeo-color-secondary-text: #374151; + + /* Alert / error */ + --asgardeo-color-error-bg: #fef2f2; + --asgardeo-color-error-border: #fecaca; + --asgardeo-color-error-title: #991b1b; + --asgardeo-color-error-text: #b91c1c; + + /* Overlay */ + --asgardeo-overlay-bg: rgba(0, 0, 0, 0.5); + + /* Border radius */ + --asgardeo-radius-sm: 4px; + --asgardeo-radius-md: 6px; + --asgardeo-radius-lg: 8px; + --asgardeo-radius-xl: 12px; + + /* Font sizes */ + --asgardeo-font-size-xs: 0.8125rem; + --asgardeo-font-size-sm: 0.875rem; + --asgardeo-font-size-md: 1.2rem; + --asgardeo-font-size-lg: 1.5rem; + } + /* Dialog Overlay */ .asgardeo-dialog__overlay { position: fixed; inset: 0; - background: rgba(0, 0, 0, 0.5); + background: var(--asgardeo-overlay-bg); display: flex; align-items: center; justify-content: center; @@ -299,8 +274,8 @@ interface SchemaField { } .asgardeo-dialog__content { - background: #fff; - border-radius: 12px; + background: var(--asgardeo-color-surface); + border-radius: var(--asgardeo-radius-xl); box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15); max-width: 600px; width: 90vw; @@ -316,13 +291,13 @@ interface SchemaField { align-items: center; justify-content: space-between; padding: 1rem 2rem; - border-bottom: 1px solid #e5e7eb; + border-bottom: 1px solid var(--asgardeo-color-border); } .asgardeo-dialog__heading { - font-size: 1.2rem; + font-size: var(--asgardeo-font-size-md); font-weight: 600; - color: #111827; + color: var(--asgardeo-color-text); margin: 0; } @@ -334,13 +309,13 @@ interface SchemaField { height: 32px; background: none; border: none; - border-radius: 6px; + border-radius: var(--asgardeo-radius-md); cursor: pointer; - color: #6b7280; + color: var(--asgardeo-color-text-secondary); &:hover { - background: rgba(0, 0, 0, 0.05); - color: #111827; + background: var(--asgardeo-color-hover); + color: var(--asgardeo-color-text); } } @@ -357,24 +332,24 @@ interface SchemaField { /* Alert */ .asgardeo-alert { padding: 12px 16px; - border-radius: 8px; + border-radius: var(--asgardeo-radius-lg); margin-bottom: 24px; } .asgardeo-alert--error { - background: #fef2f2; - border: 1px solid #fecaca; + background: var(--asgardeo-color-error-bg); + border: 1px solid var(--asgardeo-color-error-border); } .asgardeo-alert__title { - font-size: 0.875rem; + font-size: var(--asgardeo-font-size-sm); font-weight: 600; - color: #991b1b; + color: var(--asgardeo-color-error-title); } .asgardeo-alert__description { - font-size: 0.875rem; - color: #b91c1c; + font-size: var(--asgardeo-font-size-sm); + color: var(--asgardeo-color-error-text); margin-top: 2px; } @@ -412,26 +387,26 @@ interface SchemaField { } .asgardeo-user-profile__summary-name { - font-size: 1.5rem; + font-size: var(--asgardeo-font-size-lg); font-weight: 600; - color: #111827; + color: var(--asgardeo-color-text); margin-top: 8px; } .asgardeo-user-profile__summary-email { - font-size: 0.875rem; - color: #6b7280; + font-size: var(--asgardeo-font-size-sm); + color: var(--asgardeo-color-text-secondary); } /* Divider */ .asgardeo-divider { - border-bottom: 1px solid #e5e7eb; + border-bottom: 1px solid var(--asgardeo-color-border); } - /* Field info row — wraps each field + divider with vertical padding and bottom border */ + /* Field info row */ .asgardeo-user-profile__info { padding: 12px 0; - border-bottom: 1px solid #e5e7eb; + border-bottom: 1px solid var(--asgardeo-color-border); &:last-child { border-bottom: none; @@ -457,16 +432,16 @@ interface SchemaField { .asgardeo-user-profile__field-label { width: 120px; flex-shrink: 0; - font-size: 0.875rem; + font-size: var(--asgardeo-font-size-sm); font-weight: 500; - color: #6b7280; + color: var(--asgardeo-color-text-secondary); line-height: 28px; } .asgardeo-user-profile__field-value { flex: 1; - font-size: 0.875rem; - color: #111827; + font-size: var(--asgardeo-font-size-sm); + color: var(--asgardeo-color-text); min-width: 0; overflow: hidden; text-overflow: ellipsis; @@ -481,7 +456,7 @@ interface SchemaField { opacity: 0.7; cursor: pointer; text-decoration: underline; - font-size: 0.875rem; + font-size: var(--asgardeo-font-size-sm); } .asgardeo-user-profile__field-actions { @@ -496,15 +471,15 @@ interface SchemaField { width: 100%; max-width: 280px; padding: 6px 10px; - font-size: 0.875rem; - border: 1px solid #d1d5db; - border-radius: 6px; + font-size: var(--asgardeo-font-size-sm); + border: 1px solid var(--asgardeo-color-input-border); + border-radius: var(--asgardeo-radius-md); outline: none; font-family: inherit; &:focus { - border-color: #6366f1; - box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2); + border-color: var(--asgardeo-color-primary); + box-shadow: 0 0 0 2px var(--asgardeo-color-primary-ring); } } @@ -528,31 +503,31 @@ interface SchemaField { border: none; cursor: pointer; font-family: inherit; - border-radius: 6px; + border-radius: var(--asgardeo-radius-md); transition: background-color 0.15s; } .asgardeo-btn--sm { padding: 4px 12px; - font-size: 0.8125rem; + font-size: var(--asgardeo-font-size-xs); font-weight: 500; } .asgardeo-btn--primary { - background: #4f46e5; + background: var(--asgardeo-color-primary); color: white; &:hover { - background: #4338ca; + background: var(--asgardeo-color-primary-hover); } } .asgardeo-btn--secondary { - background: #f3f4f6; - color: #374151; + background: var(--asgardeo-color-secondary); + color: var(--asgardeo-color-secondary-text); &:hover { - background: #e5e7eb; + background: var(--asgardeo-color-secondary-hover); } } @@ -561,42 +536,51 @@ interface SchemaField { height: 28px; padding: 0; background: none; - color: #9ca3af; - border-radius: 4px; + color: var(--asgardeo-color-text-muted); + border-radius: var(--asgardeo-radius-sm); &:hover { - background: rgba(0, 0, 0, 0.05); - color: #6b7280; + background: var(--asgardeo-color-hover); + color: var(--asgardeo-color-text-secondary); } } `, }) -export class AsgardeoUserProfileComponent implements OnChanges { +export class AsgardeoUserProfileComponent { /** Display mode: inline (default) or popup dialog */ - @Input() mode: 'inline' | 'popup' = 'inline'; + readonly mode = input<'inline' | 'popup'>('inline'); - /** Whether the popup dialog is open (popup mode only) */ - @Input() open = false; + /** Whether the popup dialog is open (popup mode only). Supports two-way binding via `[(open)]`. */ + readonly open = model(false); /** Dialog title (popup mode only) */ - @Input() title = ''; + readonly title = input(''); /** Whether fields can be edited */ - @Input() editable = true; + readonly editable = input(true); /** Whitelist of field names to show (if set, only these are shown) */ - @Input() showFields?: string[]; + readonly showFields = input(); /** Blacklist of field names to hide */ - @Input() hideFields?: string[]; - - /** Emitted when the popup open state changes */ - @Output() openChange = new EventEmitter(); + readonly hideFields = input(); private authService = inject(AsgardeoAuthService); + private userService = inject(AsgardeoUserService); private editingFields = signal>({}); private editedValues = signal>({}); + constructor() { + // Reset editing state when the popup closes + effect(() => { + if (!this.open()) { + this.editingFields.set({}); + this.editedValues.set({}); + this.error.set(null); + } + }); + } + error = signal(null); schemasAvailable = computed(() => { @@ -662,9 +646,10 @@ export class AsgardeoUserProfileComponent implements OnChanges { .filter((f: SchemaField) => { if (!f.name) return false; if (FIELDS_TO_SKIP.includes(f.name)) return false; - if (this.hideFields?.includes(f.name)) return false; - if (this.showFields && this.showFields.length > 0 && !this.showFields.includes(f.name)) return false; - if (!this.editable) { + if (this.hideFields()?.includes(f.name)) return false; + const sf = this.showFields(); + if (sf && sf.length > 0 && !sf.includes(f.name)) return false; + if (!this.editable()) { return f.value !== undefined && f.value !== '' && f.value !== null; } return true; @@ -687,8 +672,9 @@ export class AsgardeoUserProfileComponent implements OnChanges { for (const [key, value] of Object.entries(obj)) { const fullKey = prefix ? `${prefix}.${key}` : key; if (FIELDS_TO_SKIP.includes(fullKey) || FIELDS_TO_SKIP.includes(key)) continue; - if (this.hideFields?.includes(fullKey)) continue; - if (this.showFields && this.showFields.length > 0 && !this.showFields.includes(fullKey)) continue; + if (this.hideFields()?.includes(fullKey)) continue; + const sf = this.showFields(); + if (sf && sf.length > 0 && !sf.includes(fullKey)) continue; if (value === undefined || value === '' || value === null) continue; if (Array.isArray(value)) { @@ -706,23 +692,15 @@ export class AsgardeoUserProfileComponent implements OnChanges { return entries.sort((a, b) => a.key.localeCompare(b.key)); }); - ngOnChanges(changes: SimpleChanges): void { - if (changes['open'] && !changes['open'].currentValue) { - this.editingFields.set({}); - this.editedValues.set({}); - this.error.set(null); - } - } - @HostListener('document:keydown.escape') onEscapeKey(): void { - if (this.mode === 'popup' && this.open) { + if (this.mode() === 'popup' && this.open()) { this.close(); } } close(): void { - this.openChange.emit(false); + this.open.set(false); } onOverlayClick(event: Event): void { @@ -782,10 +760,7 @@ export class AsgardeoUserProfileComponent implements OnChanges { const baseUrl = this.authService.getBaseUrl(); const instanceId = this.authService.getClient().getInstanceId(); - const response = await updateMeProfile({baseUrl, instanceId, payload}); - - // Update cached user & profile signals from the SCIM response - this.authService.handleProfileUpdate(response); + await this.userService.updateUser({baseUrl, instanceId, payload}); this.editingFields.update(v => ({...v, [fieldName]: false})); this.editedValues.update(v => { diff --git a/packages/angular/src/index.ts b/packages/angular/src/index.ts index 9a9680300..32a2f623e 100644 --- a/packages/angular/src/index.ts +++ b/packages/angular/src/index.ts @@ -16,9 +16,6 @@ * under the License. */ -// --- Client --- -export {default as AsgardeoAngularClient} from './AsgardeoAngularClient'; - // --- Config --- export type {AsgardeoAngularConfig} from './models/config'; diff --git a/packages/angular/src/providers/asgardeo.module.ts b/packages/angular/src/providers/asgardeo.module.ts index 33275230b..265a27419 100644 --- a/packages/angular/src/providers/asgardeo.module.ts +++ b/packages/angular/src/providers/asgardeo.module.ts @@ -19,6 +19,7 @@ import {NgModule, ModuleWithProviders, APP_INITIALIZER} from '@angular/core'; import {ASGARDEO_CONFIG} from './asgardeo-config.token'; import {AsgardeoCallbackComponent} from '../components/callback/callback.component'; +import {AsgardeoUserProfileComponent} from '../components/user-profile/user-profile.component'; import {AsgardeoLoadingDirective} from '../directives/loading.directive'; import {AsgardeoSignedInDirective} from '../directives/signed-in.directive'; import {AsgardeoSignedOutDirective} from '../directives/signed-out.directive'; @@ -48,8 +49,8 @@ import {AsgardeoUserService} from '../services/asgardeo-user.service'; * ``` */ @NgModule({ - exports: [AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoLoadingDirective, AsgardeoCallbackComponent], - imports: [AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoLoadingDirective, AsgardeoCallbackComponent], + exports: [AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoLoadingDirective, AsgardeoCallbackComponent, AsgardeoUserProfileComponent], + imports: [AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoLoadingDirective, AsgardeoCallbackComponent, AsgardeoUserProfileComponent], }) export class AsgardeoModule { static forRoot(config: AsgardeoAngularConfig): ModuleWithProviders { diff --git a/packages/angular/src/services/asgardeo-auth.service.ts b/packages/angular/src/services/asgardeo-auth.service.ts index 36b3e1ad5..15edc1c7b 100644 --- a/packages/angular/src/services/asgardeo-auth.service.ts +++ b/packages/angular/src/services/asgardeo-auth.service.ts @@ -16,7 +16,8 @@ * under the License. */ -import {Injectable, Inject, signal, computed, OnDestroy, Signal, WritableSignal} from '@angular/core'; +import {Injectable, Inject, Injector, signal, computed, OnDestroy, Signal, WritableSignal} from '@angular/core'; +import {toObservable} from '@angular/core/rxjs-interop'; import { AsgardeoRuntimeError, User, @@ -35,7 +36,7 @@ import { extractUserClaimsFromIdToken, generateFlattenedUserProfile, } from '@asgardeo/browser'; -import {BehaviorSubject, Observable} from 'rxjs'; +import {Observable} from 'rxjs'; import AsgardeoAngularClient from '../AsgardeoAngularClient'; import {AsgardeoAngularConfig} from '../models/config'; import {ASGARDEO_CONFIG} from '../providers/asgardeo-config.token'; @@ -44,7 +45,7 @@ import {ASGARDEO_CONFIG} from '../providers/asgardeo-config.token'; * Core authentication service for Asgardeo Angular SDK. * * This service manages the authentication lifecycle and provides reactive state - * via both Angular Signals and RxJS Observables. + * via Angular Signals (primary) with RxJS Observable accessors derived via `toObservable()`. * * It is the Angular equivalent of React's `AsgardeoProvider` + `useAsgardeo()` hook. */ @@ -87,22 +88,14 @@ export class AsgardeoAuthService implements OnDestroy { readonly profile: Signal = computed(() => this._userProfile()?.profile ?? null); - // --- RxJS Observables (for consumers preferring Observable API) --- - private readonly _isLoading$: BehaviorSubject = new BehaviorSubject(true); + // --- RxJS Observables (derived from signals via toObservable) --- + readonly isLoading$: Observable; - private readonly _isSignedIn$: BehaviorSubject = new BehaviorSubject(false); + readonly isSignedIn$: Observable; - private readonly _isInitialized$: BehaviorSubject = new BehaviorSubject(false); + readonly isInitialized$: Observable; - private readonly _user$: BehaviorSubject = new BehaviorSubject(null); - - readonly isLoading$: Observable = this._isLoading$.asObservable(); - - readonly isSignedIn$: Observable = this._isSignedIn$.asObservable(); - - readonly isInitialized$: Observable = this._isInitialized$.asObservable(); - - readonly user$: Observable = this._user$.asObservable(); + readonly user$: Observable; // --- Internal state --- private client: AsgardeoAngularClient; @@ -115,10 +108,19 @@ export class AsgardeoAuthService implements OnDestroy { private isUpdatingSession: boolean = false; - constructor(@Inject(ASGARDEO_CONFIG) config: AsgardeoAngularConfig) { + constructor( + @Inject(ASGARDEO_CONFIG) config: AsgardeoAngularConfig, + injector: Injector, + ) { this.config = {...config}; this.client = new AsgardeoAngularClient(config.instanceId ?? 0); this._baseUrl.set(config.baseUrl || ''); + + // Derive observables from signals within the injection context + this.isLoading$ = toObservable(this.isLoading, {injector}); + this.isSignedIn$ = toObservable(this.isSignedIn, {injector}); + this.isInitialized$ = toObservable(this.isInitialized, {injector}); + this.user$ = toObservable(this.user, {injector}); } /** @@ -139,7 +141,7 @@ export class AsgardeoAuthService implements OnDestroy { this._baseUrl.set(initializedConfig.baseUrl); } - this.syncState('isInitialized', true); + this.setInitializedState(true); // Check if user is already signed in const isAlreadySignedIn: boolean = await this.client.isSignedIn(); @@ -163,7 +165,7 @@ export class AsgardeoAuthService implements OnDestroy { if (hasParams && isForThisInstance) { try { this.isUpdatingSession = true; - this.syncState('isLoading', true); + this.setLoadingState(true); await this.client.signIn({callOnlyOnRedirect: true} as any); @@ -179,16 +181,16 @@ export class AsgardeoAuthService implements OnDestroy { ); } finally { this.isUpdatingSession = false; - this.syncState('isLoading', this.client.isLoading()); + this.setLoadingState(this.client.isLoading()); } } else { - this.syncState('isLoading', false); + this.setLoadingState(false); } this.startSignInPolling(); this.startLoadingStateTracking(); } catch (error) { - this.syncState('isLoading', false); + this.setLoadingState(false); throw error; } } @@ -198,7 +200,7 @@ export class AsgardeoAuthService implements OnDestroy { async signIn(options?: SignInOptions): Promise { try { this.isUpdatingSession = true; - this.syncState('isLoading', true); + this.setLoadingState(true); const response: User = await this.client.signIn(options); @@ -216,14 +218,14 @@ export class AsgardeoAuthService implements OnDestroy { ); } finally { this.isUpdatingSession = false; - this.syncState('isLoading', this.client.isLoading()); + this.setLoadingState(this.client.isLoading()); } } async signInSilently(options?: SignInOptions): Promise { try { this.isUpdatingSession = true; - this.syncState('isLoading', true); + this.setLoadingState(true); const response: User | boolean = await this.client.signInSilently(options); if (await this.client.isSignedIn()) { @@ -240,7 +242,7 @@ export class AsgardeoAuthService implements OnDestroy { ); } finally { this.isUpdatingSession = false; - this.syncState('isLoading', this.client.isLoading()); + this.setLoadingState(this.client.isLoading()); } } @@ -255,7 +257,7 @@ export class AsgardeoAuthService implements OnDestroy { async switchOrganization(organization: Organization): Promise { try { this.isUpdatingSession = true; - this.syncState('isLoading', true); + this.setLoadingState(true); const response: TokenResponse | Response = await this.client.switchOrganization(organization); if (await this.client.isSignedIn()) { @@ -272,7 +274,7 @@ export class AsgardeoAuthService implements OnDestroy { ); } finally { this.isUpdatingSession = false; - this.syncState('isLoading', this.client.isLoading()); + this.setLoadingState(this.client.isLoading()); } } @@ -335,19 +337,27 @@ export class AsgardeoAuthService implements OnDestroy { return this.client.reInitialize(config); } - // --- Profile Update --- + // --- Session Refresh --- + + /** + * Re-fetches user, profile, and organization data from the server. + * Use this to refresh the cached session state without re-initializing the client. + */ + async refreshSession(): Promise { + return this.updateSession(); + } + + // --- State Mutations (for secondary services) --- /** * Updates the cached user and user profile after a successful SCIM2 PATCH. - * Mirrors AsgardeoProvider's handleProfileUpdate from the React SDK. * * @param updatedUser - The updated user object returned from the SCIM2 API. */ handleProfileUpdate(updatedUser: User): void { this._user.set(updatedUser); - this._user$.next(updatedUser); - const currentProfile = this._userProfile(); + const currentProfile: UserProfile | null = this._userProfile(); this._userProfile.set({ ...currentProfile, flattenedProfile: generateFlattenedUserProfile(updatedUser, currentProfile?.schemas), @@ -355,6 +365,15 @@ export class AsgardeoAuthService implements OnDestroy { } as UserProfile); } + /** + * Updates the cached list of the user's organizations. + * + * @param organizations - The updated list of organizations. + */ + setMyOrganizations(organizations: Organization[]): void { + this._myOrganizations.set(organizations); + } + // --- Internal: Expose client for secondary services --- /** @internal */ @@ -371,7 +390,7 @@ export class AsgardeoAuthService implements OnDestroy { private async updateSession(): Promise { try { this.isUpdatingSession = true; - this.syncState('isLoading', true); + this.setLoadingState(true); let resolvedBaseUrl: string = this._baseUrl(); const decodedToken: IdToken = await this.client.getDecodedIdToken(); @@ -385,7 +404,6 @@ export class AsgardeoAuthService implements OnDestroy { if (this.config.platform === Platform.AsgardeoV2) { const claims: Record = extractUserClaimsFromIdToken(decodedToken); this._user.set(claims as User); - this._user$.next(claims as User); this._userProfile.set({ flattenedProfile: claims as User, profile: claims as User, @@ -395,7 +413,6 @@ export class AsgardeoAuthService implements OnDestroy { try { const fetchedUser: User = await this.client.getUser({baseUrl: resolvedBaseUrl}); this._user.set(fetchedUser); - this._user$.next(fetchedUser); } catch { // Silently handle user fetch failure } @@ -424,12 +441,12 @@ export class AsgardeoAuthService implements OnDestroy { // Update sign-in status BEFORE setting loading to false const currentSignInStatus: boolean = await this.client.isSignedIn(); - this.syncState('isSignedIn', currentSignInStatus); + this.setSignedInState(currentSignInStatus); } catch { // Silently handle session update failure } finally { this.isUpdatingSession = false; - this.syncState('isLoading', this.client.isLoading()); + this.setLoadingState(this.client.isLoading()); } } @@ -442,14 +459,14 @@ export class AsgardeoAuthService implements OnDestroy { } this.client.isSignedIn().then((status: boolean) => { - this.syncState('isSignedIn', status); + this.setSignedInState(status); if (!status) { this.signInCheckInterval = setInterval(async () => { const newStatus: boolean = await this.client.isSignedIn(); if (newStatus) { - this.syncState('isSignedIn', true); + this.setSignedInState(true); if (this.signInCheckInterval) { clearInterval(this.signInCheckInterval); this.signInCheckInterval = null; @@ -461,7 +478,7 @@ export class AsgardeoAuthService implements OnDestroy { } /** - * Tracks loading state changes from the client. Mirrors AsgardeoProvider's loading state tracking useEffect. + * Tracks loading state changes from the client. */ private startLoadingStateTracking(): void { this.loadingCheckInterval = setInterval(() => { @@ -479,30 +496,20 @@ export class AsgardeoAuthService implements OnDestroy { } } - this.syncState('isLoading', this.client.isLoading()); + this.setLoadingState(this.client.isLoading()); }, 100); } - /** - * Syncs a state value across both the signal and BehaviorSubject. - */ - private syncState(key: string, value: any): void { - switch (key) { - case 'isLoading': - this._isLoading.set(value); - this._isLoading$.next(value); - break; - case 'isSignedIn': - this._isSignedIn.set(value); - this._isSignedIn$.next(value); - break; - case 'isInitialized': - this._isInitialized.set(value); - this._isInitialized$.next(value); - break; - default: - break; - } + private setLoadingState(value: boolean): void { + this._isLoading.set(value); + } + + private setSignedInState(value: boolean): void { + this._isSignedIn.set(value); + } + + private setInitializedState(value: boolean): void { + this._isInitialized.set(value); } ngOnDestroy(): void { @@ -514,9 +521,5 @@ export class AsgardeoAuthService implements OnDestroy { clearInterval(this.loadingCheckInterval); this.loadingCheckInterval = null; } - this._isLoading$.complete(); - this._isSignedIn$.complete(); - this._isInitialized$.complete(); - this._user$.complete(); } } diff --git a/packages/angular/src/services/asgardeo-organization.service.ts b/packages/angular/src/services/asgardeo-organization.service.ts index 249d2cf0a..607af7e05 100644 --- a/packages/angular/src/services/asgardeo-organization.service.ts +++ b/packages/angular/src/services/asgardeo-organization.service.ts @@ -18,7 +18,6 @@ import {Injectable, Signal, WritableSignal, signal} from '@angular/core'; import {Organization, AllOrganizationsApiResponse, TokenResponse} from '@asgardeo/browser'; -import {BehaviorSubject, Observable} from 'rxjs'; import {AsgardeoAuthService} from './asgardeo-auth.service'; import createOrganization, {CreateOrganizationConfig} from '../api/createOrganization'; @@ -30,22 +29,17 @@ import createOrganization, {CreateOrganizationConfig} from '../api/createOrganiz export class AsgardeoOrganizationService { private readonly _isLoading: WritableSignal = signal(false); - private readonly _error: WritableSignal = signal(null); + private readonly _error: WritableSignal = signal(null); readonly isLoading: Signal = this._isLoading.asReadonly(); - readonly error: Signal = this._error.asReadonly(); + readonly error: Signal = this._error.asReadonly(); /** Delegates to AsgardeoAuthService signals. */ readonly myOrganizations: Signal; readonly currentOrganization: Signal; - // Observable variants - private readonly _isLoading$: BehaviorSubject = new BehaviorSubject(false); - - readonly isLoading$: Observable = this._isLoading$.asObservable(); - constructor(private authService: AsgardeoAuthService) { this.myOrganizations = this.authService.myOrganizations; this.currentOrganization = this.authService.currentOrganization; @@ -56,18 +50,15 @@ export class AsgardeoOrganizationService { */ async getAllOrganizations(): Promise { this._isLoading.set(true); - this._isLoading$.next(true); this._error.set(null); try { return await this.authService.getClient().getAllOrganizations(); } catch (error) { - const errorMessage: string = error instanceof Error ? error.message : 'Failed to fetch organizations'; - this._error.set(errorMessage); + this._error.set(error instanceof Error ? error : new Error('Failed to fetch organizations')); throw error; } finally { this._isLoading.set(false); - this._isLoading$.next(false); } } @@ -79,22 +70,21 @@ export class AsgardeoOrganizationService { } /** - * Re-fetches the user's organizations from the server. + * Re-fetches the user's organizations from the server and updates the cached state. */ async revalidateMyOrganizations(): Promise { this._isLoading.set(true); - this._isLoading$.next(true); this._error.set(null); try { - return await this.authService.getClient().getMyOrganizations(); + const organizations: Organization[] = await this.authService.getClient().getMyOrganizations(); + this.authService.setMyOrganizations(organizations); + return organizations; } catch (error) { - const errorMessage: string = error instanceof Error ? error.message : 'Failed to fetch organizations'; - this._error.set(errorMessage); + this._error.set(error instanceof Error ? error : new Error('Failed to fetch organizations')); throw error; } finally { this._isLoading.set(false); - this._isLoading$.next(false); } } @@ -103,18 +93,15 @@ export class AsgardeoOrganizationService { */ async createOrganization(config: CreateOrganizationConfig): Promise { this._isLoading.set(true); - this._isLoading$.next(true); this._error.set(null); try { return await createOrganization(config); } catch (error) { - const errorMessage: string = error instanceof Error ? error.message : 'Failed to create organization'; - this._error.set(errorMessage); + this._error.set(error instanceof Error ? error : new Error('Failed to create organization')); throw error; } finally { this._isLoading.set(false); - this._isLoading$.next(false); } } } diff --git a/packages/angular/src/services/asgardeo-user.service.ts b/packages/angular/src/services/asgardeo-user.service.ts index c75b3901c..4c00ecdbb 100644 --- a/packages/angular/src/services/asgardeo-user.service.ts +++ b/packages/angular/src/services/asgardeo-user.service.ts @@ -18,7 +18,6 @@ import {Injectable, Signal, WritableSignal, computed, signal} from '@angular/core'; import {User, UserProfile} from '@asgardeo/browser'; -import {BehaviorSubject, Observable} from 'rxjs'; import {AsgardeoAuthService} from './asgardeo-auth.service'; import updateMeProfile, {UpdateMeProfileConfig} from '../api/updateMeProfile'; @@ -45,13 +44,7 @@ export class AsgardeoUserService { readonly schemas: Signal; - // Observable variants - private readonly _isLoading$: BehaviorSubject = new BehaviorSubject(false); - - readonly isLoading$: Observable = this._isLoading$.asObservable(); - constructor(private authService: AsgardeoAuthService) { - // Delegate to auth service's user profile signal this.userProfile = this.authService.userProfile; this.flattenedProfile = this.authService.flattenedProfile; this.profile = this.authService.profile; @@ -63,40 +56,36 @@ export class AsgardeoUserService { */ async refreshUser(): Promise { this._isLoading.set(true); - this._isLoading$.next(true); this._error.set(null); try { - // Re-initialize to trigger updateSession which refreshes the user data - await this.authService.reInitialize({}); + await this.authService.refreshSession(); } catch (error) { this._error.set(error instanceof Error ? error : new Error('Failed to refresh user profile')); } finally { this._isLoading.set(false); - this._isLoading$.next(false); } } /** - * Updates the user profile via the SCIM2 API. + * Updates the user profile via the SCIM2 API and updates the cached state. * * @param config - The update configuration containing operations and baseUrl. * @returns The updated user profile data. */ async updateUser(config: UpdateMeProfileConfig): Promise { this._isLoading.set(true); - this._isLoading$.next(true); this._error.set(null); try { const result: User = await updateMeProfile(config); + this.authService.handleProfileUpdate(result); return result; } catch (error) { this._error.set(error instanceof Error ? error : new Error('Failed to update user profile')); throw error; } finally { this._isLoading.set(false); - this._isLoading$.next(false); } } } diff --git a/samples/teamspace-angular/src/app/components/header.component.ts b/samples/teamspace-angular/src/app/components/header.component.ts index 3dee92562..92e428f98 100644 --- a/samples/teamspace-angular/src/app/components/header.component.ts +++ b/samples/teamspace-angular/src/app/components/header.component.ts @@ -126,20 +126,27 @@ import {AsgardeoAuthService, AsgardeoSignedInDirective, AsgardeoSignedOutDirecti -
- - -
+ @if (!authService.isSignedIn()) { +
+ + +
+ } @@ -148,8 +155,7 @@ import {AsgardeoAuthService, AsgardeoSignedInDirective, AsgardeoSignedOutDirecti `, styles: ` @@ -278,6 +284,7 @@ export class HeaderComponent { authService = inject(AsgardeoAuthService); dropdownOpen = signal(false); showProfile = signal(false); + signingIn = signal(false); /** Computed gradient background matching the React SDK Avatar's name-seeded algorithm */ avatarGradient = computed(() => { @@ -355,6 +362,7 @@ export class HeaderComponent { } signIn(): void { + this.signingIn.set(true); this.authService.signIn(); } diff --git a/samples/teamspace-angular/src/app/pages/landing.component.ts b/samples/teamspace-angular/src/app/pages/landing.component.ts index 55068f249..0c117cd39 100644 --- a/samples/teamspace-angular/src/app/pages/landing.component.ts +++ b/samples/teamspace-angular/src/app/pages/landing.component.ts @@ -1,31 +1,19 @@ -import {Component, inject} from '@angular/core'; +import {Component, inject, signal} from '@angular/core'; import {RouterLink} from '@angular/router'; import { AsgardeoAuthService, AsgardeoSignedInDirective, - AsgardeoSignedOutDirective, - AsgardeoLoadingDirective, } from '@asgardeo/angular'; import {HeaderComponent} from '../components/header.component'; @Component({ selector: 'app-landing', standalone: true, - imports: [RouterLink, HeaderComponent, AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoLoadingDirective], + imports: [RouterLink, HeaderComponent, AsgardeoSignedInDirective], template: `
- -
-
-
-

Loading...

-
-
-
@@ -44,23 +32,32 @@ import {HeaderComponent} from '../components/header.component'; Asgardeo authentication.

-
- - -
+ @if (!authService.isSignedIn()) { +
+ + +
+ }
Date: Sat, 21 Feb 2026 12:51:57 +0530 Subject: [PATCH 5/6] Improve angular SDK archictecture --- package.json | 7 + packages/angular/ng-package.json | 8 + packages/angular/package.json | 29 +- packages/angular/src/AsgardeoAngularClient.ts | 24 +- packages/angular/src/__tests__/index.test.ts | 66 + .../__tests__/setup.ts} | 28 +- .../angular/src/api/createOrganization.ts | 31 +- .../angular/src/api/getAllOrganizations.ts | 30 +- .../angular/src/api/getMeOrganizations.ts | 30 +- packages/angular/src/api/getOrganization.ts | 30 +- packages/angular/src/api/getSchemas.ts | 36 +- packages/angular/src/api/getScim2Me.ts | 36 +- packages/angular/src/api/updateMeProfile.ts | 31 +- .../angular/src/api/updateOrganization.ts | 31 +- .../components/callback/callback.component.ts | 7 +- .../create-organization.component.ts | 641 +++++ .../organization-list.component.ts | 569 ++++ .../organization-profile.component.ts | 687 +++++ .../organization-switcher.component.ts | 411 +++ .../user-profile/user-profile.component.ts | 412 ++- .../src/directives/loading.directive.ts | 6 +- .../src/directives/signed-in.directive.ts | 6 +- .../src/directives/signed-out.directive.ts | 6 +- packages/angular/src/index.ts | 5 + .../src/interceptors/asgardeo.interceptor.ts | 26 + .../angular/src/providers/asgardeo.module.ts | 28 +- .../src/services/asgardeo-auth.service.ts | 108 +- .../services/asgardeo-organization.service.ts | 50 +- .../src/services/asgardeo-user.service.ts | 6 +- packages/angular/src/utils/avatar.ts | 49 + packages/angular/src/utils/fetcher.ts | 46 + packages/angular/tsconfig.json | 4 +- packages/angular/tsconfig.lib.json | 3 + packages/angular/vitest.config.ts | 1 + pnpm-lock.yaml | 2529 +++++++++++------ samples/teamspace-angular/package.json | 24 +- .../teamspace-angular/src/app/app.routes.ts | 21 +- .../src/app/components/header.component.ts | 9 +- .../src/app/guards/auth.guard.ts | 27 +- .../src/app/pages/callback.component.ts | 34 +- .../src/app/pages/create-org.component.ts | 117 +- .../src/app/pages/dashboard.component.ts | 8 +- .../src/app/pages/landing.component.ts | 2 +- .../src/app/pages/organizations.component.ts | 119 +- 44 files changed, 4621 insertions(+), 1757 deletions(-) create mode 100644 packages/angular/ng-package.json create mode 100644 packages/angular/src/__tests__/index.test.ts rename packages/angular/{esbuild.config.mjs => src/__tests__/setup.ts} (53%) create mode 100644 packages/angular/src/components/create-organization/create-organization.component.ts create mode 100644 packages/angular/src/components/organization-list/organization-list.component.ts create mode 100644 packages/angular/src/components/organization-profile/organization-profile.component.ts create mode 100644 packages/angular/src/components/organization-switcher/organization-switcher.component.ts create mode 100644 packages/angular/src/utils/avatar.ts create mode 100644 packages/angular/src/utils/fetcher.ts diff --git a/package.json b/package.json index b23a4ecb9..ac66f762c 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,13 @@ "undici": "^7.21.0" }, "pnpm": { + "packageExtensions": { + "@analogjs/vite-plugin-angular": { + "peerDependencies": { + "typescript": ">=5.5" + } + } + }, "overrides": { "pbkdf2": "3.1.3", "sha.js": "2.4.12", diff --git a/packages/angular/ng-package.json b/packages/angular/ng-package.json new file mode 100644 index 000000000..fe8d7e76e --- /dev/null +++ b/packages/angular/ng-package.json @@ -0,0 +1,8 @@ +{ + "$schema": "node_modules/ng-packagr/ng-package.schema.json", + "dest": "dist", + "allowedNonPeerDependencies": ["@asgardeo/browser", "@asgardeo/i18n", "tslib"], + "lib": { + "entryFile": "src/index.ts" + } +} diff --git a/packages/angular/package.json b/packages/angular/package.json index 896dfefae..12210bac5 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -16,25 +16,30 @@ "author": "WSO2", "license": "Apache-2.0", "type": "module", - "main": "dist/cjs/index.js", - "module": "dist/index.js", + "module": "dist/fesm2022/asgardeo-angular.mjs", + "typings": "dist/types/asgardeo-angular.d.ts", "exports": { - "import": "./dist/index.js", - "require": "./dist/cjs/index.js" + "./package.json": { + "default": "./package.json" + }, + ".": { + "types": "./dist/types/asgardeo-angular.d.ts", + "default": "./dist/fesm2022/asgardeo-angular.mjs" + } }, "files": [ "dist", "README.md", "LICENSE" ], - "types": "dist/index.d.ts", + "sideEffects": false, "repository": { "type": "git", "url": "https://github.com/asgardeo/javascript", "directory": "packages/angular" }, "scripts": { - "build": "pnpm clean && node esbuild.config.mjs && tsc -p tsconfig.lib.json --emitDeclarationOnly --outDir dist", + "build": "pnpm clean && ng-packagr -p ng-package.json", "clean": "rimraf dist", "fix:lint": "eslint . --ext .js,.ts,.cjs,.mjs", "lint": "eslint . --ext .js,.ts,.cjs,.mjs", @@ -42,21 +47,23 @@ "typecheck": "tsc -p tsconfig.lib.json" }, "devDependencies": { + "@angular/compiler": "21.1.5", + "@angular/compiler-cli": "21.1.5", "@types/node": "22.15.3", "@wso2/eslint-plugin": "catalog:", "@wso2/prettier-config": "catalog:", - "esbuild": "0.25.9", "eslint": "8.57.0", "jsdom": "26.1.0", + "ng-packagr": "21.1.0", "prettier": "2.6.2", "rimraf": "6.1.0", - "typescript": "5.7.2", + "typescript": "5.9.3", "vitest": "3.1.3" }, "peerDependencies": { - "@angular/common": ">=17.0.0", - "@angular/core": ">=17.0.0", - "@angular/router": ">=17.0.0", + "@angular/common": ">=18.0.0", + "@angular/core": ">=18.0.0", + "@angular/router": ">=18.0.0", "rxjs": ">=7.0.0" }, "dependencies": { diff --git a/packages/angular/src/AsgardeoAngularClient.ts b/packages/angular/src/AsgardeoAngularClient.ts index 167725865..1afa3f6d5 100644 --- a/packages/angular/src/AsgardeoAngularClient.ts +++ b/packages/angular/src/AsgardeoAngularClient.ts @@ -150,11 +150,11 @@ class AsgardeoAngularClient { - return this.spaClient.getDecodedIdToken(sessionId); + return (await this.spaClient.getDecodedIdToken(sessionId)) as IdToken; } async getIdToken(): Promise { - return this.withLoading(async () => this.spaClient.getIdToken()); + return this.withLoading(async () => (await this.spaClient.getIdToken()) as string); } async getUserProfile(options?: any): Promise { @@ -236,9 +236,9 @@ class AsgardeoAngularClient { const idToken: IdToken = await this.getDecodedIdToken(); return { - id: idToken?.org_id, - name: idToken?.org_name, - orgHandle: idToken?.org_handle, + id: idToken?.org_id || '', + name: idToken?.org_name || '', + orgHandle: idToken?.org_handle || '', }; }); } catch (error) { @@ -298,7 +298,7 @@ class AsgardeoAngularClient { - return this.spaClient.isSignedIn(); + return (await this.spaClient.isSignedIn()) ?? false; } /** @@ -329,7 +329,7 @@ class AsgardeoAngularClient { - return this.spaClient.signInSilently(options as Record); + return (await this.spaClient.signInSilently(options as Record)) as User | boolean; } // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -353,12 +353,12 @@ class AsgardeoAngularClient> { - return this.spaClient.httpRequest(requestConfig); + async request(requestConfig: HttpRequestConfig): Promise> { + return (await this.spaClient.httpRequest(requestConfig)) as HttpResponse; } - async requestAll(requestConfigs?: HttpRequestConfig[]): Promise[]> { - return this.spaClient.httpRequestAll(requestConfigs); + async requestAll(requestConfigs: HttpRequestConfig[]): Promise[]> { + return (await this.spaClient.httpRequestAll(requestConfigs)) as HttpResponse[]; } override async getAccessToken(sessionId?: string): Promise { @@ -374,7 +374,7 @@ class AsgardeoAngularClient>(token: string): Promise { - return this.spaClient.decodeJwtToken(token); + return this.spaClient.decodeJwtToken(token) as Promise; } } diff --git a/packages/angular/src/__tests__/index.test.ts b/packages/angular/src/__tests__/index.test.ts new file mode 100644 index 000000000..38f1da67e --- /dev/null +++ b/packages/angular/src/__tests__/index.test.ts @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {describe, it, expect} from 'vitest'; + +describe('@asgardeo/angular', () => { + it('should export AsgardeoAuthService', async () => { + const {AsgardeoAuthService} = await import('../index'); + expect(AsgardeoAuthService).toBeDefined(); + }); + + it('should export AsgardeoUserService', async () => { + const {AsgardeoUserService} = await import('../index'); + expect(AsgardeoUserService).toBeDefined(); + }); + + it('should export AsgardeoOrganizationService', async () => { + const {AsgardeoOrganizationService} = await import('../index'); + expect(AsgardeoOrganizationService).toBeDefined(); + }); + + it('should export structural directives', async () => { + const {AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoLoadingDirective} = await import('../index'); + expect(AsgardeoSignedInDirective).toBeDefined(); + expect(AsgardeoSignedOutDirective).toBeDefined(); + expect(AsgardeoLoadingDirective).toBeDefined(); + }); + + it('should export organization components', async () => { + const { + AsgardeoOrganizationListComponent, + AsgardeoCreateOrganizationComponent, + AsgardeoOrganizationProfileComponent, + AsgardeoOrganizationSwitcherComponent, + } = await import('../index'); + expect(AsgardeoOrganizationListComponent).toBeDefined(); + expect(AsgardeoCreateOrganizationComponent).toBeDefined(); + expect(AsgardeoOrganizationProfileComponent).toBeDefined(); + expect(AsgardeoOrganizationSwitcherComponent).toBeDefined(); + }); + + it('should export AsgardeoUserProfileComponent', async () => { + const {AsgardeoUserProfileComponent} = await import('../index'); + expect(AsgardeoUserProfileComponent).toBeDefined(); + }); + + it('should export AsgardeoCallbackComponent', async () => { + const {AsgardeoCallbackComponent} = await import('../index'); + expect(AsgardeoCallbackComponent).toBeDefined(); + }); +}); diff --git a/packages/angular/esbuild.config.mjs b/packages/angular/src/__tests__/setup.ts similarity index 53% rename from packages/angular/esbuild.config.mjs rename to packages/angular/src/__tests__/setup.ts index 630e63373..1d407e3fa 100644 --- a/packages/angular/esbuild.config.mjs +++ b/packages/angular/src/__tests__/setup.ts @@ -16,30 +16,4 @@ * under the License. */ -import {readFileSync} from 'fs'; -import {build} from 'esbuild'; - -const pkg = JSON.parse(readFileSync('./package.json', 'utf8')); - -const commonOptions = { - bundle: true, - entryPoints: ['src/index.ts'], - external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})], - metafile: true, - platform: 'browser', - target: ['es2020'], -}; - -await build({ - ...commonOptions, - format: 'esm', - outfile: 'dist/index.js', - sourcemap: true, -}); - -await build({ - ...commonOptions, - format: 'cjs', - outfile: 'dist/cjs/index.js', - sourcemap: true, -}); +import '@angular/compiler'; diff --git a/packages/angular/src/api/createOrganization.ts b/packages/angular/src/api/createOrganization.ts index ab369622f..53d4958ed 100644 --- a/packages/angular/src/api/createOrganization.ts +++ b/packages/angular/src/api/createOrganization.ts @@ -18,13 +18,10 @@ import { Organization, - HttpInstance, - HttpResponse, - AsgardeoSPAClient, - HttpRequestConfig, createOrganization as baseCreateOrganization, CreateOrganizationConfig as BaseCreateOrganizationConfig, } from '@asgardeo/browser'; +import {createDefaultFetcher} from '../utils/fetcher'; /** * Configuration for the createOrganization request (Angular-specific) @@ -96,30 +93,10 @@ const createOrganization = async ({ fetcher, instanceId = 0, ...requestConfig -}: CreateOrganizationConfig): Promise => { - const defaultFetcher = async (url: string, config: RequestInit): Promise => { - const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); - const httpClient: HttpInstance = client.httpRequest.bind(client); - const response: HttpResponse = await httpClient({ - data: config.body ? JSON.parse(config.body as string) : undefined, - headers: config.headers as Record, - method: config.method || 'POST', - url, - } as HttpRequestConfig); - - return { - json: () => Promise.resolve(response.data), - ok: response.status >= 200 && response.status < 300, - status: response.status, - statusText: response.statusText || '', - text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), - } as Response; - }; - - return baseCreateOrganization({ +}: CreateOrganizationConfig): Promise => + baseCreateOrganization({ ...requestConfig, - fetcher: fetcher || defaultFetcher, + fetcher: fetcher || createDefaultFetcher(instanceId), }); -}; export default createOrganization; diff --git a/packages/angular/src/api/getAllOrganizations.ts b/packages/angular/src/api/getAllOrganizations.ts index 1f3aae276..203c1ea1f 100644 --- a/packages/angular/src/api/getAllOrganizations.ts +++ b/packages/angular/src/api/getAllOrganizations.ts @@ -17,14 +17,11 @@ */ import { - HttpInstance, - HttpResponse, - AsgardeoSPAClient, - HttpRequestConfig, getAllOrganizations as baseGetAllOrganizations, GetAllOrganizationsConfig as BaseGetAllOrganizationsConfig, AllOrganizationsApiResponse, } from '@asgardeo/browser'; +import {createDefaultFetcher} from '../utils/fetcher'; /** * Configuration for the getAllOrganizations request (Angular-specific) @@ -88,29 +85,10 @@ const getAllOrganizations = async ({ fetcher, instanceId = 0, ...requestConfig -}: GetAllOrganizationsConfig): Promise => { - const defaultFetcher = async (url: string, config: RequestInit): Promise => { - const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); - const httpClient: HttpInstance = client.httpRequest.bind(client); - const response: HttpResponse = await httpClient({ - headers: config.headers as Record, - method: config.method || 'GET', - url, - } as HttpRequestConfig); - - return { - json: () => Promise.resolve(response.data), - ok: response.status >= 200 && response.status < 300, - status: response.status, - statusText: response.statusText || '', - text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), - } as Response; - }; - - return baseGetAllOrganizations({ +}: GetAllOrganizationsConfig): Promise => + baseGetAllOrganizations({ ...requestConfig, - fetcher: fetcher || defaultFetcher, + fetcher: fetcher || createDefaultFetcher(instanceId), }); -}; export default getAllOrganizations; diff --git a/packages/angular/src/api/getMeOrganizations.ts b/packages/angular/src/api/getMeOrganizations.ts index 40a706944..54e86c194 100644 --- a/packages/angular/src/api/getMeOrganizations.ts +++ b/packages/angular/src/api/getMeOrganizations.ts @@ -18,13 +18,10 @@ import { Organization, - HttpInstance, - HttpResponse, - AsgardeoSPAClient, - HttpRequestConfig, getMeOrganizations as baseGetMeOrganizations, GetMeOrganizationsConfig as BaseGetMeOrganizationsConfig, } from '@asgardeo/browser'; +import {createDefaultFetcher} from '../utils/fetcher'; /** * Configuration for the getMeOrganizations request (Angular-specific) @@ -92,29 +89,10 @@ const getMeOrganizations = async ({ fetcher, instanceId = 0, ...requestConfig -}: GetMeOrganizationsConfig): Promise => { - const defaultFetcher = async (url: string, config: RequestInit): Promise => { - const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); - const httpClient: HttpInstance = client.httpRequest.bind(client); - const response: HttpResponse = await httpClient({ - headers: config.headers as Record, - method: config.method || 'GET', - url, - } as HttpRequestConfig); - - return { - json: () => Promise.resolve(response.data), - ok: response.status >= 200 && response.status < 300, - status: response.status, - statusText: response.statusText || '', - text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), - } as Response; - }; - - return baseGetMeOrganizations({ +}: GetMeOrganizationsConfig): Promise => + baseGetMeOrganizations({ ...requestConfig, - fetcher: fetcher || defaultFetcher, + fetcher: fetcher || createDefaultFetcher(instanceId), }); -}; export default getMeOrganizations; diff --git a/packages/angular/src/api/getOrganization.ts b/packages/angular/src/api/getOrganization.ts index badebe69d..abb322a63 100644 --- a/packages/angular/src/api/getOrganization.ts +++ b/packages/angular/src/api/getOrganization.ts @@ -17,14 +17,11 @@ */ import { - HttpInstance, - HttpResponse, - AsgardeoSPAClient, - HttpRequestConfig, getOrganization as baseGetOrganization, GetOrganizationConfig as BaseGetOrganizationConfig, OrganizationDetails, } from '@asgardeo/browser'; +import {createDefaultFetcher} from '../utils/fetcher'; /** * Configuration for the getOrganization request (Angular-specific) @@ -84,29 +81,10 @@ const getOrganization = async ({ fetcher, instanceId = 0, ...requestConfig -}: GetOrganizationConfig): Promise => { - const defaultFetcher = async (url: string, config: RequestInit): Promise => { - const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); - const httpClient: HttpInstance = client.httpRequest.bind(client); - const response: HttpResponse = await httpClient({ - headers: config.headers as Record, - method: config.method || 'GET', - url, - } as HttpRequestConfig); - - return { - json: () => Promise.resolve(response.data), - ok: response.status >= 200 && response.status < 300, - status: response.status, - statusText: response.statusText || '', - text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), - } as Response; - }; - - return baseGetOrganization({ +}: GetOrganizationConfig): Promise => + baseGetOrganization({ ...requestConfig, - fetcher: fetcher || defaultFetcher, + fetcher: fetcher || createDefaultFetcher(instanceId), }); -}; export default getOrganization; diff --git a/packages/angular/src/api/getSchemas.ts b/packages/angular/src/api/getSchemas.ts index cc16dc115..37ce3003e 100644 --- a/packages/angular/src/api/getSchemas.ts +++ b/packages/angular/src/api/getSchemas.ts @@ -16,15 +16,8 @@ * under the License. */ -import { - Schema, - HttpInstance, - HttpResponse, - AsgardeoSPAClient, - HttpRequestConfig, - getSchemas as baseGetSchemas, - GetSchemasConfig as BaseGetSchemasConfig, -} from '@asgardeo/browser'; +import {Schema, getSchemas as baseGetSchemas, GetSchemasConfig as BaseGetSchemasConfig} from '@asgardeo/browser'; +import {createDefaultFetcher} from '../utils/fetcher'; /** * Configuration for the getSchemas request (Angular-specific) @@ -78,29 +71,10 @@ export interface GetSchemasConfig extends Omit * } * ``` */ -const getSchemas = async ({fetcher, instanceId = 0, ...requestConfig}: GetSchemasConfig): Promise => { - const defaultFetcher = async (url: string, config: RequestInit): Promise => { - const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); - const httpClient: HttpInstance = client.httpRequest.bind(client); - const response: HttpResponse = await httpClient({ - headers: config.headers as Record, - method: config.method || 'GET', - url, - } as HttpRequestConfig); - - return { - json: () => Promise.resolve(response.data), - ok: response.status >= 200 && response.status < 300, - status: response.status, - statusText: response.statusText || '', - text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), - } as Response; - }; - - return baseGetSchemas({ +const getSchemas = async ({fetcher, instanceId = 0, ...requestConfig}: GetSchemasConfig): Promise => + baseGetSchemas({ ...requestConfig, - fetcher: fetcher || defaultFetcher, + fetcher: fetcher || createDefaultFetcher(instanceId), }); -}; export default getSchemas; diff --git a/packages/angular/src/api/getScim2Me.ts b/packages/angular/src/api/getScim2Me.ts index 319cf95a8..3f5e082bb 100644 --- a/packages/angular/src/api/getScim2Me.ts +++ b/packages/angular/src/api/getScim2Me.ts @@ -16,15 +16,8 @@ * under the License. */ -import { - User, - HttpInstance, - HttpResponse, - AsgardeoSPAClient, - HttpRequestConfig, - getScim2Me as baseGetScim2Me, - GetScim2MeConfig as BaseGetScim2MeConfig, -} from '@asgardeo/browser'; +import {User, getScim2Me as baseGetScim2Me, GetScim2MeConfig as BaseGetScim2MeConfig} from '@asgardeo/browser'; +import {createDefaultFetcher} from '../utils/fetcher'; /** * Configuration for the getScim2Me request (Angular-specific) @@ -78,29 +71,10 @@ export interface GetScim2MeConfig extends Omit * } * ``` */ -const getScim2Me = async ({fetcher, instanceId = 0, ...requestConfig}: GetScim2MeConfig): Promise => { - const defaultFetcher = async (url: string, config: RequestInit): Promise => { - const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); - const httpClient: HttpInstance = client.httpRequest.bind(client); - const response: HttpResponse = await httpClient({ - headers: config.headers as Record, - method: config.method || 'GET', - url, - } as HttpRequestConfig); - - return { - json: () => Promise.resolve(response.data), - ok: response.status >= 200 && response.status < 300, - status: response.status, - statusText: response.statusText || '', - text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), - } as Response; - }; - - return baseGetScim2Me({ +const getScim2Me = async ({fetcher, instanceId = 0, ...requestConfig}: GetScim2MeConfig): Promise => + baseGetScim2Me({ ...requestConfig, - fetcher: fetcher || defaultFetcher, + fetcher: fetcher || createDefaultFetcher(instanceId), }); -}; export default getScim2Me; diff --git a/packages/angular/src/api/updateMeProfile.ts b/packages/angular/src/api/updateMeProfile.ts index 122a1b9ae..a5e75cbf4 100644 --- a/packages/angular/src/api/updateMeProfile.ts +++ b/packages/angular/src/api/updateMeProfile.ts @@ -18,13 +18,10 @@ import { User, - HttpInstance, - HttpResponse, - AsgardeoSPAClient, - HttpRequestConfig, updateMeProfile as baseUpdateMeProfile, UpdateMeProfileConfig as BaseUpdateMeProfileConfig, } from '@asgardeo/browser'; +import {createDefaultFetcher} from '../utils/fetcher'; /** * Configuration for the updateMeProfile request (Angular-specific) @@ -66,30 +63,10 @@ export interface UpdateMeProfileConfig extends Omit => { - const defaultFetcher = async (url: string, config: RequestInit): Promise => { - const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); - const httpClient: HttpInstance = client.httpRequest.bind(client); - const response: HttpResponse = await httpClient({ - data: config.body ? JSON.parse(config.body as string) : undefined, - headers: config.headers as Record, - method: config.method || 'PATCH', - url, - } as HttpRequestConfig); - - return { - json: () => Promise.resolve(response.data), - ok: response.status >= 200 && response.status < 300, - status: response.status, - statusText: response.statusText || '', - text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), - } as Response; - }; - - return baseUpdateMeProfile({ +const updateMeProfile = async ({fetcher, instanceId = 0, ...requestConfig}: UpdateMeProfileConfig): Promise => + baseUpdateMeProfile({ ...requestConfig, - fetcher: fetcher || defaultFetcher, + fetcher: fetcher || createDefaultFetcher(instanceId), }); -}; export default updateMeProfile; diff --git a/packages/angular/src/api/updateOrganization.ts b/packages/angular/src/api/updateOrganization.ts index 9a756e41f..e35150e45 100644 --- a/packages/angular/src/api/updateOrganization.ts +++ b/packages/angular/src/api/updateOrganization.ts @@ -17,15 +17,12 @@ */ import { - HttpInstance, - HttpResponse, - AsgardeoSPAClient, - HttpRequestConfig, updateOrganization as baseUpdateOrganization, UpdateOrganizationConfig as BaseUpdateOrganizationConfig, OrganizationDetails, createPatchOperations, } from '@asgardeo/browser'; +import {createDefaultFetcher} from '../utils/fetcher'; /** * Configuration for the updateOrganization request (Angular-specific) @@ -91,31 +88,11 @@ const updateOrganization = async ({ fetcher, instanceId = 0, ...requestConfig -}: UpdateOrganizationConfig): Promise => { - const defaultFetcher = async (url: string, config: RequestInit): Promise => { - const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); - const httpClient: HttpInstance = client.httpRequest.bind(client); - const response: HttpResponse = await httpClient({ - data: config.body ? JSON.parse(config.body as string) : undefined, - headers: config.headers as Record, - method: config.method || 'PATCH', - url, - } as HttpRequestConfig); - - return { - json: () => Promise.resolve(response.data), - ok: response.status >= 200 && response.status < 300, - status: response.status, - statusText: response.statusText || '', - text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), - } as Response; - }; - - return baseUpdateOrganization({ +}: UpdateOrganizationConfig): Promise => + baseUpdateOrganization({ ...requestConfig, - fetcher: fetcher || defaultFetcher, + fetcher: fetcher || createDefaultFetcher(instanceId), }); -}; // Re-export the helper function export {createPatchOperations}; diff --git a/packages/angular/src/components/callback/callback.component.ts b/packages/angular/src/components/callback/callback.component.ts index 6883b9699..6ebd140d2 100644 --- a/packages/angular/src/components/callback/callback.component.ts +++ b/packages/angular/src/components/callback/callback.component.ts @@ -16,7 +16,7 @@ * under the License. */ -import {Component, OnInit, output, inject} from '@angular/core'; +import {Component, ChangeDetectionStrategy, OnInit, output, inject, OutputEmitterRef} from '@angular/core'; import {Router} from '@angular/router'; import {navigate as browserNavigate} from '@asgardeo/browser'; @@ -37,6 +37,7 @@ import {navigate as browserNavigate} from '@asgardeo/browser'; * ``` */ @Component({ + changeDetection: ChangeDetectionStrategy.OnPush, selector: 'asgardeo-callback', standalone: true, template: '', @@ -44,7 +45,7 @@ import {navigate as browserNavigate} from '@asgardeo/browser'; export class AsgardeoCallbackComponent implements OnInit { private router: Router | null = inject(Router, {optional: true}); - readonly error = output(); + readonly error: OutputEmitterRef = output(); ngOnInit(): void { this.processOAuthCallback(); @@ -128,7 +129,7 @@ export class AsgardeoCallbackComponent implements OnInit { } this.navigate(`${returnPath}?${params.toString()}`); - } catch (err) { + } catch (err: unknown) { const errorMessage: string = err instanceof Error ? err.message : 'OAuth callback processing failed'; // eslint-disable-next-line no-console console.error('OAuth callback error:', err); diff --git a/packages/angular/src/components/create-organization/create-organization.component.ts b/packages/angular/src/components/create-organization/create-organization.component.ts new file mode 100644 index 000000000..78b044588 --- /dev/null +++ b/packages/angular/src/components/create-organization/create-organization.component.ts @@ -0,0 +1,641 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {NgTemplateOutlet} from '@angular/common'; +import { + Component, + ChangeDetectionStrategy, + inject, + input, + model, + output, + signal, + effect, + HostListener, + InputSignal, + ModelSignal, + OutputEmitterRef, + WritableSignal, +} from '@angular/core'; +import {Organization} from '@asgardeo/browser'; +import {AsgardeoAuthService} from '../../services/asgardeo-auth.service'; +import {AsgardeoOrganizationService} from '../../services/asgardeo-organization.service'; + +interface CreateOrganizationPayload { + description: string; + name: string; + orgHandle: string; + parentId: string; + type: 'TENANT'; +} + +/** + * Angular Create Organization component matching the React SDK's ``. + * + * Provides a form for creating new organizations with name, handle, and description fields. + * Supports both inline and popup (dialog) modes. + * + * @example + * ```html + * + * + * + * + * + * ``` + */ +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [NgTemplateOutlet], + selector: 'asgardeo-create-organization', + standalone: true, + styles: ` + :host { + /* Core palette */ + --asgardeo-color-primary: #4f46e5; + --asgardeo-color-primary-hover: #4338ca; + --asgardeo-color-primary-ring: rgba(99, 102, 241, 0.2); + + /* Text */ + --asgardeo-color-text: #111827; + --asgardeo-color-text-secondary: #6b7280; + --asgardeo-color-text-muted: #9ca3af; + + /* Surfaces & borders */ + --asgardeo-color-surface: #fff; + --asgardeo-color-border: #e5e7eb; + --asgardeo-color-input-border: #d1d5db; + --asgardeo-color-hover: rgba(0, 0, 0, 0.05); + + /* Secondary button */ + --asgardeo-color-secondary: #f3f4f6; + --asgardeo-color-secondary-hover: #e5e7eb; + --asgardeo-color-secondary-text: #374151; + + /* Alert / error */ + --asgardeo-color-error-bg: #fef2f2; + --asgardeo-color-error-border: #fecaca; + --asgardeo-color-error-title: #991b1b; + --asgardeo-color-error-text: #b91c1c; + + /* Overlay */ + --asgardeo-overlay-bg: rgba(0, 0, 0, 0.5); + + /* Border radius */ + --asgardeo-radius-sm: 4px; + --asgardeo-radius-md: 6px; + --asgardeo-radius-lg: 8px; + --asgardeo-radius-xl: 12px; + + /* Font sizes */ + --asgardeo-font-size-xs: 0.8125rem; + --asgardeo-font-size-sm: 0.875rem; + --asgardeo-font-size-md: 1.2rem; + } + + /* Dialog Overlay */ + .asgardeo-dialog__overlay { + position: fixed; + inset: 0; + background: var(--asgardeo-overlay-bg); + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + } + + .asgardeo-dialog__content { + background: var(--asgardeo-color-surface); + border-radius: var(--asgardeo-radius-xl); + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15); + max-width: 500px; + width: 90vw; + max-height: 85vh; + display: flex; + flex-direction: column; + z-index: 10000; + } + + .asgardeo-dialog__header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 1.5rem; + border-bottom: 1px solid var(--asgardeo-color-border); + } + + .asgardeo-dialog__heading { + font-size: var(--asgardeo-font-size-md); + font-weight: 600; + color: var(--asgardeo-color-text); + margin: 0; + } + + .asgardeo-dialog__close { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + background: none; + border: none; + border-radius: var(--asgardeo-radius-md); + cursor: pointer; + color: var(--asgardeo-color-text-secondary); + + &:hover { + background: var(--asgardeo-color-hover); + color: var(--asgardeo-color-text); + } + } + + .asgardeo-create-organization__popup { + padding: 1.5rem; + overflow-y: auto; + } + + /* Alert */ + .asgardeo-alert { + padding: 12px 16px; + border-radius: var(--asgardeo-radius-lg); + margin-bottom: 16px; + } + + .asgardeo-alert--error { + background: var(--asgardeo-color-error-bg); + border: 1px solid var(--asgardeo-color-error-border); + } + + .asgardeo-alert__title { + font-size: var(--asgardeo-font-size-sm); + font-weight: 600; + color: var(--asgardeo-color-error-title); + } + + .asgardeo-alert__description { + font-size: var(--asgardeo-font-size-sm); + color: var(--asgardeo-color-error-text); + margin-top: 2px; + } + + /* Form */ + .asgardeo-form-group { + margin-bottom: 20px; + } + + .asgardeo-label { + display: block; + font-size: var(--asgardeo-font-size-sm); + font-weight: 500; + color: var(--asgardeo-color-text); + margin-bottom: 6px; + } + + .asgardeo-required { + color: var(--asgardeo-color-error-text); + } + + .asgardeo-text-field { + width: 100%; + padding: 8px 12px; + font-size: var(--asgardeo-font-size-sm); + border: 1px solid var(--asgardeo-color-input-border); + border-radius: var(--asgardeo-radius-md); + outline: none; + font-family: inherit; + box-sizing: border-box; + + &:focus { + border-color: var(--asgardeo-color-primary); + box-shadow: 0 0 0 2px var(--asgardeo-color-primary-ring); + } + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } + } + + .asgardeo-text-field--error { + border-color: var(--asgardeo-color-error-text); + } + + .asgardeo-textarea { + width: 100%; + padding: 8px 12px; + font-size: var(--asgardeo-font-size-sm); + border: 1px solid var(--asgardeo-color-input-border); + border-radius: var(--asgardeo-radius-md); + outline: none; + font-family: inherit; + resize: vertical; + box-sizing: border-box; + + &:focus { + border-color: var(--asgardeo-color-primary); + box-shadow: 0 0 0 2px var(--asgardeo-color-primary-ring); + } + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } + } + + .asgardeo-textarea--error { + border-color: var(--asgardeo-color-error-text); + } + + .asgardeo-form-hint { + display: block; + font-size: var(--asgardeo-font-size-xs); + color: var(--asgardeo-color-text-muted); + margin-top: 4px; + } + + .asgardeo-form-error { + display: block; + font-size: var(--asgardeo-font-size-xs); + color: var(--asgardeo-color-error-text); + margin-top: 4px; + } + + .asgardeo-form-actions { + display: flex; + justify-content: flex-end; + gap: 8px; + margin-top: 24px; + } + + /* Spinner */ + .asgardeo-spinner { + width: 32px; + height: 32px; + border: 3px solid var(--asgardeo-color-border); + border-top-color: var(--asgardeo-color-primary); + border-radius: 50%; + animation: asgardeo-spin 0.6s linear infinite; + } + + .asgardeo-spinner--sm { + width: 16px; + height: 16px; + border-width: 2px; + border-color: rgba(255, 255, 255, 0.3); + border-top-color: white; + margin-right: 6px; + } + + @keyframes asgardeo-spin { + to { transform: rotate(360deg); } + } + + /* Buttons */ + .asgardeo-btn { + display: inline-flex; + align-items: center; + justify-content: center; + border: none; + cursor: pointer; + font-family: inherit; + border-radius: var(--asgardeo-radius-md); + padding: 8px 16px; + font-size: var(--asgardeo-font-size-sm); + font-weight: 500; + transition: background-color 0.15s; + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } + } + + .asgardeo-btn--primary { + background: var(--asgardeo-color-primary); + color: white; + + &:hover:not(:disabled) { + background: var(--asgardeo-color-primary-hover); + } + } + + .asgardeo-btn--secondary { + background: var(--asgardeo-color-secondary); + color: var(--asgardeo-color-secondary-text); + + &:hover:not(:disabled) { + background: var(--asgardeo-color-secondary-hover); + } + } + `, + template: ` + +
+ @if (error()) { +
+
Error
+
{{ error() }}
+
+ } + +
+
+ + + @if (formErrors().name) { + {{ formErrors().name }} + } +
+ +
+ + + Only lowercase letters, numbers, and hyphens are allowed. + @if (formErrors().handle) { + {{ formErrors().handle }} + } +
+ +
+ + + @if (formErrors().description) { + {{ formErrors().description }} + } +
+ +
+ + +
+
+
+
+ + @if (mode() === 'popup') { + @if (open()) { +
+
+
+

{{ title() }}

+ +
+
+ +
+
+
+ } + } @else { + + } + `, +}) +export class AsgardeoCreateOrganizationComponent { + /** Display mode: inline (default) or popup dialog */ + readonly mode: InputSignal<'inline' | 'popup'> = input<'inline' | 'popup'>('inline'); + + /** Whether the popup dialog is open (popup mode only). Supports two-way binding via `[(open)]`. */ + readonly open: ModelSignal = model(false); + + /** Dialog title (popup mode only) */ + readonly title: InputSignal = input('Create Organization'); + + /** Default parent organization ID */ + readonly defaultParentId: InputSignal = input(''); + + /** Initial form values */ + readonly initialValues: InputSignal> = input< + Partial<{description: string; handle: string; name: string}> + >({}); + + /** Emits when the form is submitted (before API call) */ + readonly submitted: OutputEmitterRef = output(); + + /** Emits when the organization is successfully created */ + readonly created: OutputEmitterRef = output(); + + /** Emits when the cancel button is clicked */ + readonly cancelled: OutputEmitterRef = output(); + + private readonly authService: AsgardeoAuthService = inject(AsgardeoAuthService); + + private readonly orgService: AsgardeoOrganizationService = inject(AsgardeoOrganizationService); + + formName: WritableSignal = signal(''); + + formHandle: WritableSignal = signal(''); + + formDescription: WritableSignal = signal(''); + + isSubmitting: WritableSignal = signal(false); + + error: WritableSignal = signal(null); + + formErrors: WritableSignal<{description?: string; handle?: string; name?: string}> = signal<{ + description?: string; + handle?: string; + name?: string; + }>({}); + + private readonly handleManuallyEdited: WritableSignal = signal(false); + + constructor() { + // Reset form when popup closes + effect(() => { + if (!this.open()) { + this.resetForm(); + } + }); + + // Apply initial values + effect(() => { + const iv: Partial<{description: string; handle: string; name: string}> = this.initialValues(); + if (iv.name) this.formName.set(iv.name); + if (iv.handle) this.formHandle.set(iv.handle); + if (iv.description) this.formDescription.set(iv.description); + }); + } + + @HostListener('document:keydown.escape') + onEscapeKey(): void { + if (this.mode() === 'popup' && this.open()) { + this.close(); + } + } + + close(): void { + this.open.set(false); + } + + onOverlayClick(event: Event): void { + if (event.target === event.currentTarget) { + this.close(); + } + } + + onNameInput(value: string): void { + this.formName.set(value); + this.clearFieldError('name'); + if (!this.handleManuallyEdited()) { + this.formHandle.set(AsgardeoCreateOrganizationComponent.generateHandle(value)); + } + } + + onHandleInput(value: string): void { + this.formHandle.set(value); + this.handleManuallyEdited.set(true); + this.clearFieldError('handle'); + } + + onDescriptionInput(value: string): void { + this.formDescription.set(value); + this.clearFieldError('description'); + } + + static generateHandle(name: string): string { + return name + .toLowerCase() + .replace(/[^a-z0-9\s-]/g, '') + .replace(/\s+/g, '-') + .replace(/-+/g, '-') + .replace(/^-|-$/g, ''); + } + + validate(): boolean { + const errors: {description?: string; handle?: string; name?: string} = {}; + if (!this.formName().trim()) errors.name = 'Organization name is required'; + if (!this.formHandle().trim()) { + errors.handle = 'Organization handle is required'; + } else if (!/^[a-z0-9-]+$/.test(this.formHandle())) { + errors.handle = 'Handle can only contain lowercase letters, numbers, and hyphens'; + } + if (!this.formDescription().trim()) errors.description = 'Description is required'; + this.formErrors.set(errors); + return Object.keys(errors).length === 0; + } + + async onSubmit(): Promise { + if (!this.validate() || this.isSubmitting()) return; + + this.isSubmitting.set(true); + this.error.set(null); + + const payload: CreateOrganizationPayload = { + description: this.formDescription().trim(), + name: this.formName().trim(), + orgHandle: this.formHandle().trim(), + parentId: this.defaultParentId() || this.orgService.currentOrganization()?.id || '', + type: 'TENANT' as const, + }; + + this.submitted.emit(payload); + + try { + const baseUrl: string = this.authService.getBaseUrl(); + const instanceId: number = this.authService.getClient().getInstanceId(); + const org: Organization = await this.orgService.createOrganization({baseUrl, instanceId, payload}); + await this.orgService.revalidateMyOrganizations(); + this.created.emit(org); + if (this.mode() === 'popup') { + this.open.set(false); + } + } catch (err: any) { + this.error.set(err?.message || 'Failed to create organization'); + } finally { + this.isSubmitting.set(false); + } + } + + onCancel(): void { + this.cancelled.emit(); + if (this.mode() === 'popup') { + this.open.set(false); + } + } + + private resetForm(): void { + this.formName.set(''); + this.formHandle.set(''); + this.formDescription.set(''); + this.error.set(null); + this.formErrors.set({}); + this.handleManuallyEdited.set(false); + this.isSubmitting.set(false); + } + + private clearFieldError(field: string): void { + this.formErrors.update((v: {description?: string; handle?: string; name?: string}) => { + const copy: {description?: string; handle?: string; name?: string} = {...v}; + delete (copy as any)[field]; + return copy; + }); + } +} diff --git a/packages/angular/src/components/organization-list/organization-list.component.ts b/packages/angular/src/components/organization-list/organization-list.component.ts new file mode 100644 index 000000000..81993bb1e --- /dev/null +++ b/packages/angular/src/components/organization-list/organization-list.component.ts @@ -0,0 +1,569 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {NgTemplateOutlet} from '@angular/common'; +import { + Component, + ChangeDetectionStrategy, + inject, + input, + model, + output, + signal, + computed, + effect, + HostListener, + InputSignal, + ModelSignal, + OutputEmitterRef, + WritableSignal, + Signal, +} from '@angular/core'; +import {Organization, AllOrganizationsApiResponse} from '@asgardeo/browser'; +import {AsgardeoAuthService} from '../../services/asgardeo-auth.service'; +import {AsgardeoOrganizationService} from '../../services/asgardeo-organization.service'; +import {generateGradient, getInitials} from '../../utils/avatar'; + +/** + * Angular Organization List component matching the React SDK's ``. + * + * Displays a paginated list of organizations with "Switch" buttons and "Current" badges. + * Supports both inline and popup (dialog) modes. + * + * @example + * ```html + * + * + * + * + * + * ``` + */ +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [NgTemplateOutlet], + selector: 'asgardeo-organization-list', + standalone: true, + styles: ` + :host { + /* Core palette */ + --asgardeo-color-primary: #4f46e5; + --asgardeo-color-primary-hover: #4338ca; + --asgardeo-color-primary-ring: rgba(99, 102, 241, 0.2); + + /* Text */ + --asgardeo-color-text: #111827; + --asgardeo-color-text-secondary: #6b7280; + --asgardeo-color-text-muted: #9ca3af; + + /* Surfaces & borders */ + --asgardeo-color-surface: #fff; + --asgardeo-color-border: #e5e7eb; + --asgardeo-color-hover: rgba(0, 0, 0, 0.05); + + /* Secondary button */ + --asgardeo-color-secondary: #f3f4f6; + --asgardeo-color-secondary-hover: #e5e7eb; + --asgardeo-color-secondary-text: #374151; + + /* Alert / error */ + --asgardeo-color-error-bg: #fef2f2; + --asgardeo-color-error-border: #fecaca; + --asgardeo-color-error-title: #991b1b; + --asgardeo-color-error-text: #b91c1c; + + /* Status */ + --asgardeo-color-success: #059669; + --asgardeo-color-success-bg: #ecfdf5; + + /* Overlay */ + --asgardeo-overlay-bg: rgba(0, 0, 0, 0.5); + + /* Border radius */ + --asgardeo-radius-sm: 4px; + --asgardeo-radius-md: 6px; + --asgardeo-radius-lg: 8px; + --asgardeo-radius-xl: 12px; + + /* Font sizes */ + --asgardeo-font-size-xs: 0.8125rem; + --asgardeo-font-size-sm: 0.875rem; + --asgardeo-font-size-md: 1.2rem; + --asgardeo-font-size-lg: 1.5rem; + } + + /* Dialog Overlay */ + .asgardeo-dialog__overlay { + position: fixed; + inset: 0; + background: var(--asgardeo-overlay-bg); + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + } + + .asgardeo-dialog__content { + background: var(--asgardeo-color-surface); + border-radius: var(--asgardeo-radius-xl); + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15); + max-width: 600px; + width: 90vw; + max-height: 85vh; + display: flex; + flex-direction: column; + z-index: 10000; + } + + .asgardeo-dialog__header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 1.5rem; + border-bottom: 1px solid var(--asgardeo-color-border); + } + + .asgardeo-dialog__heading { + font-size: var(--asgardeo-font-size-md); + font-weight: 600; + color: var(--asgardeo-color-text); + margin: 0; + } + + .asgardeo-dialog__close { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + background: none; + border: none; + border-radius: var(--asgardeo-radius-md); + cursor: pointer; + color: var(--asgardeo-color-text-secondary); + + &:hover { + background: var(--asgardeo-color-hover); + color: var(--asgardeo-color-text); + } + } + + .asgardeo-organization-list__popup { + padding: 1.5rem; + overflow-y: auto; + } + + /* Alert */ + .asgardeo-alert { + padding: 12px 16px; + border-radius: var(--asgardeo-radius-lg); + margin-bottom: 16px; + } + + .asgardeo-alert--error { + background: var(--asgardeo-color-error-bg); + border: 1px solid var(--asgardeo-color-error-border); + } + + .asgardeo-alert__title { + font-size: var(--asgardeo-font-size-sm); + font-weight: 600; + color: var(--asgardeo-color-error-title); + } + + .asgardeo-alert__description { + font-size: var(--asgardeo-font-size-sm); + color: var(--asgardeo-color-error-text); + margin-top: 2px; + } + + /* Loading */ + .asgardeo-organization-list__loading { + display: flex; + flex-direction: column; + align-items: center; + gap: 12px; + padding: 48px 0; + color: var(--asgardeo-color-text-secondary); + font-size: var(--asgardeo-font-size-sm); + } + + .asgardeo-spinner { + width: 32px; + height: 32px; + border: 3px solid var(--asgardeo-color-border); + border-top-color: var(--asgardeo-color-primary); + border-radius: 50%; + animation: asgardeo-spin 0.6s linear infinite; + } + + .asgardeo-spinner--sm { + width: 16px; + height: 16px; + border-width: 2px; + margin-right: 4px; + } + + @keyframes asgardeo-spin { + to { transform: rotate(360deg); } + } + + /* Empty state */ + .asgardeo-organization-list__empty { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + padding: 48px 0; + color: var(--asgardeo-color-text-muted); + font-size: var(--asgardeo-font-size-sm); + } + + .asgardeo-organization-list__empty-icon { + width: 48px; + height: 48px; + } + + /* Header */ + .asgardeo-organization-list__header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 12px; + } + + .asgardeo-organization-list__count { + font-size: var(--asgardeo-font-size-sm); + color: var(--asgardeo-color-text-secondary); + } + + /* List item */ + .asgardeo-organization-list__item { + display: flex; + align-items: center; + gap: 12px; + padding: 12px; + border-bottom: 1px solid var(--asgardeo-color-border); + + &:last-child { + border-bottom: none; + } + + &:hover { + background: var(--asgardeo-color-hover); + border-radius: var(--asgardeo-radius-lg); + } + } + + .asgardeo-organization-list__item-info { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + gap: 2px; + } + + .asgardeo-organization-list__item-name { + font-size: var(--asgardeo-font-size-sm); + font-weight: 500; + color: var(--asgardeo-color-text); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .asgardeo-organization-list__item-handle { + font-size: var(--asgardeo-font-size-xs); + color: var(--asgardeo-color-text-muted); + } + + .asgardeo-organization-list__item-actions { + flex-shrink: 0; + } + + /* Avatar */ + .asgardeo-avatar { + display: flex; + align-items: center; + justify-content: center; + color: white; + font-weight: 500; + overflow: hidden; + flex-shrink: 0; + } + + .asgardeo-avatar--square { + width: 40px; + height: 40px; + border-radius: var(--asgardeo-radius-lg); + font-size: 14px; + } + + /* Badge */ + .asgardeo-badge { + display: inline-flex; + align-items: center; + padding: 2px 8px; + font-size: 0.75rem; + font-weight: 500; + border-radius: 9999px; + background: var(--asgardeo-color-secondary); + color: var(--asgardeo-color-secondary-text); + } + + .asgardeo-badge--current { + background: var(--asgardeo-color-success-bg); + color: var(--asgardeo-color-success); + } + + .asgardeo-badge--active { + background: var(--asgardeo-color-success-bg); + color: var(--asgardeo-color-success); + } + + /* Buttons */ + .asgardeo-btn { + display: inline-flex; + align-items: center; + justify-content: center; + border: none; + cursor: pointer; + font-family: inherit; + border-radius: var(--asgardeo-radius-md); + transition: background-color 0.15s; + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } + } + + .asgardeo-btn--sm { + padding: 4px 12px; + font-size: var(--asgardeo-font-size-xs); + font-weight: 500; + } + + .asgardeo-btn--primary { + background: var(--asgardeo-color-primary); + color: white; + + &:hover:not(:disabled) { + background: var(--asgardeo-color-primary-hover); + } + } + + .asgardeo-btn--secondary { + background: var(--asgardeo-color-secondary); + color: var(--asgardeo-color-secondary-text); + + &:hover:not(:disabled) { + background: var(--asgardeo-color-secondary-hover); + } + } + `, + template: ` + +
+ @if (error()) { +
+
Error
+
{{ error() }}
+
+ } + + @if (isLoadingAll() && organizationsWithAccess().length === 0) { +
+
+ Loading organizations... +
+ } @else if (!isLoadingAll() && organizationsWithAccess().length === 0 && !error()) { +
+ + + + No organizations found +
+ } @else { +
+ + {{ organizationsWithAccess().length }} organization{{ organizationsWithAccess().length === 1 ? '' : 's' }} + + +
+ + @for (org of organizationsWithAccess(); track org.id) { +
+
+ {{ getInitials(org.name || 'Org') }} +
+
+ {{ org.name || org.id }} + @if (org.orgHandle) { + @{{ org.orgHandle }} + } + @if (showStatus() && org.status) { + + {{ org.status }} + + } +
+
+ @if (org.isCurrent) { + Current + } @else if (org.canSwitch) { + + } +
+
+ } + } +
+
+ + @if (mode() === 'popup') { + @if (open()) { +
+
+
+

{{ title() }}

+ +
+
+ +
+
+
+ } + } @else { + + } + `, +}) +export class AsgardeoOrganizationListComponent { + /** Display mode: inline (default) or popup dialog */ + readonly mode: InputSignal<'inline' | 'popup'> = input<'inline' | 'popup'>('inline'); + + /** Whether the popup dialog is open (popup mode only). Supports two-way binding via `[(open)]`. */ + readonly open: ModelSignal = model(false); + + /** Dialog title (popup mode only) */ + readonly title: InputSignal = input('Organizations'); + + /** Whether to show organization status badges */ + readonly showStatus: InputSignal = input(false); + + /** Emits when an organization is selected for switching */ + readonly organizationSelect: OutputEmitterRef = output(); + + private authService: AsgardeoAuthService = inject(AsgardeoAuthService); + + private orgService: AsgardeoOrganizationService = inject(AsgardeoOrganizationService); + + isLoadingAll: WritableSignal = signal(false); + + error: WritableSignal = signal(null); + + private allOrganizations: WritableSignal = + signal(null); + + organizationsWithAccess: Signal<(Organization & {canSwitch: boolean; isCurrent: boolean})[]> = computed(() => { + const all: AllOrganizationsApiResponse | null = this.allOrganizations(); + const my: Organization[] = this.orgService.myOrganizations(); + const currentId: string | undefined = this.orgService.currentOrganization()?.id; + const myIds: Set = new Set(my.map((o: Organization) => o.id)); + + // If we have allOrganizations response, use it; otherwise fall back to myOrganizations + const orgList: Organization[] = all?.organizations || my; + + return orgList.map((org: Organization) => ({ + ...org, + canSwitch: myIds.has(org.id) && org.id !== currentId, + isCurrent: org.id === currentId, + })); + }); + + constructor() { + this.fetchOrganizations(); + + effect(() => { + if (!this.open()) { + this.error.set(null); + } + }); + } + + @HostListener('document:keydown.escape') + onEscapeKey(): void { + if (this.mode() === 'popup' && this.open()) { + this.close(); + } + } + + close(): void { + this.open.set(false); + } + + onOverlayClick(event: Event): void { + if (event.target === event.currentTarget) { + this.close(); + } + } + + async fetchOrganizations(): Promise { + this.isLoadingAll.set(true); + this.error.set(null); + try { + const result: AllOrganizationsApiResponse = await this.orgService.getAllOrganizations(); + this.allOrganizations.set(result); + } catch (err: any) { + this.error.set(err?.message || 'Failed to fetch organizations'); + } finally { + this.isLoadingAll.set(false); + } + } + + async refresh(): Promise { + await Promise.all([this.fetchOrganizations(), this.orgService.revalidateMyOrganizations()]); + } + + async onSwitch(org: Organization): Promise { + this.organizationSelect.emit(org); + await this.orgService.switchOrganization(org); + } + + readonly getInitials: (name: string) => string = getInitials; + + readonly generateGradient: (inputString: string) => string = generateGradient; +} diff --git a/packages/angular/src/components/organization-profile/organization-profile.component.ts b/packages/angular/src/components/organization-profile/organization-profile.component.ts new file mode 100644 index 000000000..75ed25dcf --- /dev/null +++ b/packages/angular/src/components/organization-profile/organization-profile.component.ts @@ -0,0 +1,687 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {NgTemplateOutlet} from '@angular/common'; +import { + Component, + ChangeDetectionStrategy, + inject, + input, + model, + output, + signal, + computed, + effect, + HostListener, + InputSignal, + ModelSignal, + OutputEmitterRef, + WritableSignal, + Signal, +} from '@angular/core'; +import {OrganizationDetails} from '@asgardeo/browser'; +import {AsgardeoOrganizationService} from '../../services/asgardeo-organization.service'; +import {generateGradient, getInitials} from '../../utils/avatar'; + +interface FieldConfig { + editable: boolean; + format?: (value: any) => string; + key: string; + label: string; +} + +function formatDate(dateString: any): string { + if (!dateString) return '-'; + try { + return new Date(dateString).toLocaleDateString('en-US', {day: 'numeric', month: 'long', year: 'numeric'}); + } catch { + return String(dateString); + } +} + +const DEFAULT_FIELDS: FieldConfig[] = [ + {editable: false, key: 'id', label: 'Organization ID'}, + {editable: true, key: 'name', label: 'Organization Name'}, + {editable: true, key: 'description', label: 'Description'}, + {editable: false, format: formatDate, key: 'created', label: 'Created Date'}, + {editable: false, format: formatDate, key: 'lastModified', label: 'Last Modified'}, +]; + +/** + * Angular Organization Profile component matching the React SDK's ``. + * + * Displays organization details with per-field inline editing. + * Supports both inline and popup (dialog) modes. + * + * @example + * ```html + * + * + * + * + * + * ``` + */ +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [NgTemplateOutlet], + selector: 'asgardeo-organization-profile', + standalone: true, + styles: ` + :host { + /* Core palette */ + --asgardeo-color-primary: #4f46e5; + --asgardeo-color-primary-hover: #4338ca; + --asgardeo-color-primary-ring: rgba(99, 102, 241, 0.2); + + /* Text */ + --asgardeo-color-text: #111827; + --asgardeo-color-text-secondary: #6b7280; + --asgardeo-color-text-muted: #9ca3af; + + /* Surfaces & borders */ + --asgardeo-color-surface: #fff; + --asgardeo-color-border: #e5e7eb; + --asgardeo-color-input-border: #d1d5db; + --asgardeo-color-hover: rgba(0, 0, 0, 0.05); + + /* Secondary button */ + --asgardeo-color-secondary: #f3f4f6; + --asgardeo-color-secondary-hover: #e5e7eb; + --asgardeo-color-secondary-text: #374151; + + /* Alert / error */ + --asgardeo-color-error-bg: #fef2f2; + --asgardeo-color-error-border: #fecaca; + --asgardeo-color-error-title: #991b1b; + --asgardeo-color-error-text: #b91c1c; + + /* Overlay */ + --asgardeo-overlay-bg: rgba(0, 0, 0, 0.5); + + /* Border radius */ + --asgardeo-radius-sm: 4px; + --asgardeo-radius-md: 6px; + --asgardeo-radius-lg: 8px; + --asgardeo-radius-xl: 12px; + + /* Font sizes */ + --asgardeo-font-size-xs: 0.8125rem; + --asgardeo-font-size-sm: 0.875rem; + --asgardeo-font-size-md: 1.2rem; + --asgardeo-font-size-lg: 1.5rem; + } + + /* Dialog Overlay */ + .asgardeo-dialog__overlay { + position: fixed; + inset: 0; + background: var(--asgardeo-overlay-bg); + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + } + + .asgardeo-dialog__content { + background: var(--asgardeo-color-surface); + border-radius: var(--asgardeo-radius-xl); + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15); + max-width: 600px; + width: 90vw; + max-height: 85vh; + display: flex; + flex-direction: column; + z-index: 10000; + } + + .asgardeo-dialog__header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 1.5rem; + border-bottom: 1px solid var(--asgardeo-color-border); + } + + .asgardeo-dialog__heading { + font-size: var(--asgardeo-font-size-md); + font-weight: 600; + color: var(--asgardeo-color-text); + margin: 0; + } + + .asgardeo-dialog__close { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + background: none; + border: none; + border-radius: var(--asgardeo-radius-md); + cursor: pointer; + color: var(--asgardeo-color-text-secondary); + + &:hover { + background: var(--asgardeo-color-hover); + color: var(--asgardeo-color-text); + } + } + + .asgardeo-organization-profile__popup { + padding: 1.5rem; + overflow-y: auto; + } + + /* Loading */ + .asgardeo-organization-profile__loading { + display: flex; + flex-direction: column; + align-items: center; + gap: 12px; + padding: 48px 0; + color: var(--asgardeo-color-text-secondary); + font-size: var(--asgardeo-font-size-sm); + } + + .asgardeo-spinner { + width: 32px; + height: 32px; + border: 3px solid var(--asgardeo-color-border); + border-top-color: var(--asgardeo-color-primary); + border-radius: 50%; + animation: asgardeo-spin 0.6s linear infinite; + } + + @keyframes asgardeo-spin { + to { transform: rotate(360deg); } + } + + /* Empty state */ + .asgardeo-organization-profile__empty { + display: flex; + align-items: center; + justify-content: center; + padding: 48px 0; + color: var(--asgardeo-color-text-muted); + font-size: var(--asgardeo-font-size-sm); + } + + /* Alert */ + .asgardeo-alert { + padding: 12px 16px; + border-radius: var(--asgardeo-radius-lg); + margin-bottom: 16px; + } + + .asgardeo-alert--error { + background: var(--asgardeo-color-error-bg); + border: 1px solid var(--asgardeo-color-error-border); + } + + .asgardeo-alert__title { + font-size: var(--asgardeo-font-size-sm); + font-weight: 600; + color: var(--asgardeo-color-error-title); + } + + .asgardeo-alert__description { + font-size: var(--asgardeo-font-size-sm); + color: var(--asgardeo-color-error-text); + margin-top: 2px; + } + + /* Avatar */ + .asgardeo-avatar { + display: flex; + align-items: center; + justify-content: center; + color: white; + font-weight: 500; + overflow: hidden; + flex-shrink: 0; + } + + .asgardeo-avatar--lg { + width: 70px; + height: 70px; + font-size: 24px; + } + + .asgardeo-avatar--square { + border-radius: var(--asgardeo-radius-lg); + } + + /* Profile Summary */ + .asgardeo-organization-profile__summary { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 4px; + margin-bottom: 12px; + } + + .asgardeo-organization-profile__summary-name { + font-size: var(--asgardeo-font-size-lg); + font-weight: 600; + color: var(--asgardeo-color-text); + margin-top: 8px; + } + + .asgardeo-organization-profile__summary-handle { + font-size: var(--asgardeo-font-size-sm); + color: var(--asgardeo-color-text-secondary); + } + + /* Divider */ + .asgardeo-divider { + border-bottom: 1px solid var(--asgardeo-color-border); + } + + /* Field info row */ + .asgardeo-organization-profile__info { + padding: 12px 0; + border-bottom: 1px solid var(--asgardeo-color-border); + + &:last-child { + border-bottom: none; + } + } + + .asgardeo-organization-profile__field { + display: flex; + align-items: center; + padding: 4px 0; + min-height: 28px; + } + + .asgardeo-organization-profile__field-inner { + flex: 1; + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + } + + .asgardeo-organization-profile__field-label { + width: 140px; + flex-shrink: 0; + font-size: var(--asgardeo-font-size-sm); + font-weight: 500; + color: var(--asgardeo-color-text-secondary); + line-height: 28px; + } + + .asgardeo-organization-profile__field-value { + flex: 1; + font-size: var(--asgardeo-font-size-sm); + color: var(--asgardeo-color-text); + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + max-width: 350px; + line-height: 28px; + word-break: break-word; + } + + .asgardeo-organization-profile__field-placeholder { + font-style: italic; + opacity: 0.7; + cursor: pointer; + text-decoration: underline; + font-size: var(--asgardeo-font-size-sm); + } + + .asgardeo-organization-profile__field-actions { + display: flex; + align-items: center; + gap: 4px; + margin-left: 32px; + } + + /* Text Field */ + .asgardeo-text-field { + width: 100%; + max-width: 280px; + padding: 6px 10px; + font-size: var(--asgardeo-font-size-sm); + border: 1px solid var(--asgardeo-color-input-border); + border-radius: var(--asgardeo-radius-md); + outline: none; + font-family: inherit; + + &:focus { + border-color: var(--asgardeo-color-primary); + box-shadow: 0 0 0 2px var(--asgardeo-color-primary-ring); + } + } + + /* Buttons */ + .asgardeo-btn { + display: inline-flex; + align-items: center; + justify-content: center; + border: none; + cursor: pointer; + font-family: inherit; + border-radius: var(--asgardeo-radius-md); + transition: background-color 0.15s; + } + + .asgardeo-btn--sm { + padding: 4px 12px; + font-size: var(--asgardeo-font-size-xs); + font-weight: 500; + } + + .asgardeo-btn--primary { + background: var(--asgardeo-color-primary); + color: white; + + &:hover { + background: var(--asgardeo-color-primary-hover); + } + } + + .asgardeo-btn--secondary { + background: var(--asgardeo-color-secondary); + color: var(--asgardeo-color-secondary-text); + + &:hover { + background: var(--asgardeo-color-secondary-hover); + } + } + + .asgardeo-btn--icon { + width: 28px; + height: 28px; + padding: 0; + background: none; + color: var(--asgardeo-color-text-muted); + border-radius: var(--asgardeo-radius-sm); + + &:hover { + background: var(--asgardeo-color-hover); + color: var(--asgardeo-color-text-secondary); + } + } + `, + template: ` + +
+ @if (error()) { +
+
Error
+
{{ error() }}
+
+ } + + @if (isLoadingDetails()) { +
+
+ Loading organization... +
+ } @else if (resolvedOrganization(); as org) { + +
+
+ {{ orgInitials() }} +
+
{{ org.name }}
+ @if (org.orgHandle) { +
@{{ org.orgHandle }}
+ } +
+ +
+ + @for (field of fields; track field.key) { + @if (getFieldValue(org, field.key) !== undefined || (editable() && field.editable)) { +
+
+
+
{{ field.label }}
+
+ @if (isFieldEditing(field.key)) { + + } @else { + @if (getFieldValue(org, field.key) != null && getFieldValue(org, field.key) !== '') { + {{ field.format ? field.format(getFieldValue(org, field.key)) : getFieldValue(org, field.key) }} + } @else if (editable() && field.editable) { + + Add {{ field.label.toLowerCase() }} + + } @else { + - + } + } +
+
+ @if (editable() && field.editable) { +
+ @if (isFieldEditing(field.key)) { + + + } @else if (getFieldValue(org, field.key) != null && getFieldValue(org, field.key) !== '') { + + } +
+ } +
+
+ } + } + } @else if (!isLoadingDetails()) { +
No organization data available
+ } +
+
+ + @if (mode() === 'popup') { + @if (open()) { +
+
+
+

{{ title() }}

+ +
+
+ +
+
+
+ } + } @else { + + } + `, +}) +export class AsgardeoOrganizationProfileComponent { + /** Display mode: inline (default) or popup dialog */ + readonly mode: InputSignal<'inline' | 'popup'> = input<'inline' | 'popup'>('inline'); + + /** Whether the popup dialog is open (popup mode only). Supports two-way binding via `[(open)]`. */ + readonly open: ModelSignal = model(false); + + /** Dialog title (popup mode only) */ + readonly title: InputSignal = input('Organization Profile'); + + /** Whether fields can be edited */ + readonly editable: InputSignal = input(true); + + /** Organization ID to fetch details for */ + readonly organizationId: InputSignal = input(); + + /** Organization data to display directly (alternative to organizationId) */ + readonly organization: InputSignal = input(); + + /** Emits when the organization is updated */ + readonly updated: OutputEmitterRef = output(); + + private orgService: AsgardeoOrganizationService = inject(AsgardeoOrganizationService); + + private fetchedOrganization: WritableSignal = signal(null); + + private editingFields: WritableSignal> = signal>({}); + + private editedValues: WritableSignal> = signal>({}); + + error: WritableSignal = signal(null); + + isLoadingDetails: WritableSignal = signal(false); + + readonly fields: FieldConfig[] = DEFAULT_FIELDS; + + resolvedOrganization: Signal = computed( + () => this.organization() || this.fetchedOrganization(), + ); + + orgInitials: Signal = computed(() => { + const name: string | undefined = this.resolvedOrganization()?.name; + if (!name) return 'ORG'; + return getInitials(name); + }); + + avatarGradient: Signal = computed(() => { + const name: string = this.resolvedOrganization()?.name || 'Organization'; + return generateGradient(name); + }); + + constructor() { + // Fetch organization when organizationId changes + effect(() => { + const id: string | undefined = this.organizationId(); + if (id) { + this.fetchOrganization(id); + } + }); + + // Reset editing state when popup closes + effect(() => { + if (!this.open()) { + this.editingFields.set({}); + this.editedValues.set({}); + this.error.set(null); + } + }); + } + + @HostListener('document:keydown.escape') + onEscapeKey(): void { + if (this.mode() === 'popup' && this.open()) { + this.close(); + } + } + + close(): void { + this.open.set(false); + } + + onOverlayClick(event: Event): void { + if (event.target === event.currentTarget) { + this.close(); + } + } + + async fetchOrganization(id: string): Promise { + this.isLoadingDetails.set(true); + this.error.set(null); + try { + const result: OrganizationDetails = await this.orgService.getOrganization(id); + this.fetchedOrganization.set(result); + } catch (err: any) { + this.error.set(err?.message || 'Failed to load organization'); + } finally { + this.isLoadingDetails.set(false); + } + } + + // eslint-disable-next-line class-methods-use-this + getFieldValue(org: OrganizationDetails, key: string): any { + return (org as Record)[key]; + } + + isFieldEditing(fieldKey: string): boolean { + return this.editingFields()[fieldKey] || false; + } + + getEditedValue(fieldKey: string): any { + const edited: Record = this.editedValues(); + if (fieldKey in edited) return edited[fieldKey]; + const org: OrganizationDetails | null = this.resolvedOrganization(); + return org ? this.getFieldValue(org, fieldKey) : ''; + } + + toggleEdit(fieldKey: string): void { + this.editingFields.update((v: Record) => ({...v, [fieldKey]: !v[fieldKey]})); + } + + onFieldChange(fieldKey: string, value: any): void { + this.editedValues.update((v: Record) => ({...v, [fieldKey]: value})); + } + + cancelEdit(fieldKey: string): void { + this.editingFields.update((v: Record) => ({...v, [fieldKey]: false})); + this.editedValues.update((v: Record) => { + const copy: Record = {...v}; + delete copy[fieldKey]; + return copy; + }); + } + + async saveField(field: FieldConfig): Promise { + const org: OrganizationDetails | null = this.resolvedOrganization(); + if (!org) return; + + const value: any = this.getEditedValue(field.key); + this.error.set(null); + + try { + const updated: OrganizationDetails = await this.orgService.updateOrganization(org.id, {[field.key]: value}); + this.fetchedOrganization.set(updated); + this.editingFields.update((v: Record) => ({...v, [field.key]: false})); + this.editedValues.update((v: Record) => { + const copy: Record = {...v}; + delete copy[field.key]; + return copy; + }); + this.updated.emit(updated); + } catch (err: any) { + this.error.set(err?.message || 'Failed to update organization'); + } + } +} diff --git a/packages/angular/src/components/organization-switcher/organization-switcher.component.ts b/packages/angular/src/components/organization-switcher/organization-switcher.component.ts new file mode 100644 index 000000000..4629093f5 --- /dev/null +++ b/packages/angular/src/components/organization-switcher/organization-switcher.component.ts @@ -0,0 +1,411 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + ChangeDetectionStrategy, + Component, + HostListener, + InputSignal, + OutputEmitterRef, + Signal, + WritableSignal, + computed, + inject, + input, + output, + signal, +} from '@angular/core'; +import {Organization} from '@asgardeo/browser'; +import {AsgardeoOrganizationService} from '../../services/asgardeo-organization.service'; +import {generateGradient, getInitials} from '../../utils/avatar'; + +/** + * Angular Organization Switcher component matching the React SDK's ``. + * + * A trigger button with dropdown for switching between organizations. + * Uses CSS absolute positioning (no floating-ui dependency). + * + * @example + * ```html + * + * + * + * + * ``` + */ +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'asgardeo-organization-switcher', + standalone: true, + styles: ` + :host { + /* Core palette */ + --asgardeo-color-primary: #4f46e5; + --asgardeo-color-primary-hover: #4338ca; + + /* Text */ + --asgardeo-color-text: #111827; + --asgardeo-color-text-secondary: #6b7280; + --asgardeo-color-text-muted: #9ca3af; + + /* Surfaces & borders */ + --asgardeo-color-surface: #fff; + --asgardeo-color-border: #e5e7eb; + --asgardeo-color-hover: rgba(0, 0, 0, 0.05); + + /* Border radius */ + --asgardeo-radius-md: 6px; + --asgardeo-radius-lg: 8px; + --asgardeo-radius-xl: 12px; + + /* Font sizes */ + --asgardeo-font-size-xs: 0.8125rem; + --asgardeo-font-size-sm: 0.875rem; + + display: inline-block; + } + + .asgardeo-org-switcher { + position: relative; + display: inline-block; + } + + /* Trigger */ + .asgardeo-org-switcher__trigger { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 6px 10px; + background: none; + border: 1px solid var(--asgardeo-color-border); + border-radius: var(--asgardeo-radius-lg); + cursor: pointer; + font-family: inherit; + transition: background-color 0.15s; + + &:hover { + background-color: var(--asgardeo-color-hover); + } + + &:focus { + outline: 2px solid var(--asgardeo-color-primary); + outline-offset: 2px; + } + } + + .asgardeo-org-switcher__trigger-label { + font-size: var(--asgardeo-font-size-sm); + font-weight: 500; + color: var(--asgardeo-color-text); + max-width: 150px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .asgardeo-org-switcher__trigger-icon { + color: var(--asgardeo-color-text-secondary); + } + + .asgardeo-org-switcher__chevron { + color: var(--asgardeo-color-text-muted); + transition: transform 0.2s; + flex-shrink: 0; + } + + .asgardeo-org-switcher__chevron--open { + transform: rotate(180deg); + } + + /* Dropdown content */ + .asgardeo-org-switcher__content { + position: absolute; + top: calc(100% + 5px); + right: 0; + min-width: 250px; + max-width: 350px; + background: var(--asgardeo-color-surface); + border-radius: var(--asgardeo-radius-xl); + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + border: 1px solid var(--asgardeo-color-border); + overflow: hidden; + z-index: 9999; + } + + /* Header */ + .asgardeo-org-switcher__header { + display: flex; + align-items: center; + gap: 10px; + padding: 12px 16px; + border-bottom: 1px solid var(--asgardeo-color-border); + } + + .asgardeo-org-switcher__header-info { + display: flex; + flex-direction: column; + gap: 1px; + flex: 1; + min-width: 0; + overflow: hidden; + } + + .asgardeo-org-switcher__header-name { + font-size: var(--asgardeo-font-size-sm); + font-weight: 600; + color: var(--asgardeo-color-text); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .asgardeo-org-switcher__header-handle { + font-size: var(--asgardeo-font-size-xs); + color: var(--asgardeo-color-text-muted); + } + + /* Section header */ + .asgardeo-org-switcher__section-header { + padding: 8px 16px 4px; + font-size: 0.75rem; + font-weight: 600; + color: var(--asgardeo-color-text-muted); + text-transform: uppercase; + letter-spacing: 0.05em; + } + + /* Menu items */ + .asgardeo-org-switcher__menu { + display: flex; + flex-direction: column; + padding: 4px 0; + } + + .asgardeo-org-switcher__menu-item { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 16px; + width: 100%; + color: var(--asgardeo-color-text); + text-decoration: none; + border: none; + background: transparent; + cursor: pointer; + font-size: var(--asgardeo-font-size-sm); + text-align: start; + font-family: inherit; + + &:hover { + background-color: var(--asgardeo-color-hover); + } + } + + /* Empty state */ + .asgardeo-org-switcher__empty { + padding: 16px; + text-align: center; + font-size: var(--asgardeo-font-size-xs); + color: var(--asgardeo-color-text-muted); + } + + /* Avatar */ + .asgardeo-avatar { + display: flex; + align-items: center; + justify-content: center; + color: white; + font-weight: 500; + overflow: hidden; + flex-shrink: 0; + } + + .asgardeo-avatar--square { + border-radius: var(--asgardeo-radius-md); + } + + .asgardeo-avatar--sm { + width: 24px; + height: 24px; + font-size: 10px; + } + `, + template: ` +
+ + + + + @if (isOpen()) { +
+ + @if (resolvedCurrentOrg(); as org) { +
+
+ {{ currentOrgInitials() }} +
+
+ {{ org.name || org.id }} + @if (org.orgHandle) { + @{{ org.orgHandle }} + } +
+
+ } + + + @if (switchableOrganizations().length > 0) { +
Switch organization
+
+ @for (org of switchableOrganizations(); track org.id) { + + } +
+ } @else { +
No other organizations available
+ } + + + +
+ } +
+ `, +}) +export class AsgardeoOrganizationSwitcherComponent { + /** Whether to show the organization name next to the avatar in the trigger */ + readonly showTriggerLabel: InputSignal = input(true); + + /** Avatar size in pixels */ + readonly avatarSize: InputSignal = input(24); + + /** Override the list of organizations (defaults to orgService.myOrganizations) */ + readonly organizations: InputSignal = input(); + + /** Override the current organization (defaults to orgService.currentOrganization) */ + readonly currentOrganization: InputSignal = input(); + + /** Emits when an organization is selected for switching */ + readonly organizationSwitch: OutputEmitterRef = output(); + + private orgService: AsgardeoOrganizationService = inject(AsgardeoOrganizationService); + + isOpen: WritableSignal = signal(false); + + resolvedCurrentOrg: Signal = computed( + () => this.currentOrganization() || this.orgService.currentOrganization() || undefined, + ); + + switchableOrganizations: Signal = computed(() => { + const orgs: Organization[] = this.organizations() || this.orgService.myOrganizations(); + const currentId: string | undefined = this.resolvedCurrentOrg()?.id; + return orgs.filter((o: Organization) => o.id !== currentId); + }); + + currentOrgInitials: Signal = computed(() => { + const name: string | undefined = this.resolvedCurrentOrg()?.name; + if (!name) return 'O'; + return getInitials(name); + }); + + currentOrgGradient: Signal = computed(() => { + const name: string = this.resolvedCurrentOrg()?.name || 'Organization'; + return generateGradient(name); + }); + + @HostListener('document:click') + onDocumentClick(): void { + if (this.isOpen()) { + this.isOpen.set(false); + } + } + + toggle(event: Event): void { + event.stopPropagation(); + this.isOpen.update((v: boolean) => !v); + } + + async switchTo(org: Organization): Promise { + this.isOpen.set(false); + this.organizationSwitch.emit(org); + await this.orgService.switchOrganization(org); + } + + readonly getInitials: (name: string) => string = getInitials; + + readonly generateGradient: (name: string) => string = generateGradient; +} diff --git a/packages/angular/src/components/user-profile/user-profile.component.ts b/packages/angular/src/components/user-profile/user-profile.component.ts index 3e82afd48..32c927d01 100644 --- a/packages/angular/src/components/user-profile/user-profile.component.ts +++ b/packages/angular/src/components/user-profile/user-profile.component.ts @@ -16,8 +16,10 @@ * under the License. */ +import {NgTemplateOutlet} from '@angular/common'; import { Component, + ChangeDetectionStrategy, inject, input, model, @@ -25,10 +27,14 @@ import { computed, effect, HostListener, + InputSignal, + ModelSignal, + WritableSignal, + Signal, } from '@angular/core'; -import {NgTemplateOutlet} from '@angular/common'; import {AsgardeoAuthService} from '../../services/asgardeo-auth.service'; import {AsgardeoUserService} from '../../services/asgardeo-user.service'; +import {generateGradient, getInitials} from '../../utils/avatar'; /** Fields that should never be displayed in the profile fields list. * Matches React SDK's BaseUserProfile.fieldsToSkip. */ @@ -56,7 +62,7 @@ const FIELDS_TO_SKIP: string[] = [ const READONLY_FIELDS: string[] = ['username', 'userName', 'user_name']; /** Well-known SCIM2 schema IDs */ -const WELL_KNOWN_USER_SCHEMA = 'urn:ietf:params:scim:schemas:core:2.0:User'; +const WELL_KNOWN_USER_SCHEMA: string = 'urn:ietf:params:scim:schemas:core:2.0:User'; interface SchemaField { caseExact?: boolean; @@ -66,14 +72,14 @@ interface SchemaField { multiValued?: boolean; mutability?: string; name?: string; + path?: string; required?: boolean; returned?: string; + schemaId?: string; subAttributes?: SchemaField[]; type?: string; uniqueness?: string; value?: any; - path?: string; - schemaId?: string; } /** @@ -96,118 +102,10 @@ interface SchemaField { * ``` */ @Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [NgTemplateOutlet], selector: 'asgardeo-user-profile', standalone: true, - imports: [NgTemplateOutlet], - template: ` - - - - - @if (mode() === 'popup') { - @if (open()) { -
-
-
-

{{ title() || 'Profile' }}

- -
- -
-
- } - } @else { - - } - `, styles: ` /* ------------------------------------------------------------------ */ /* Custom Properties — override these to theme the component. */ @@ -545,30 +443,142 @@ interface SchemaField { } } `, + template: ` + + + + + @if (mode() === 'popup') { + @if (open()) { +
+
+
+

{{ title() || 'Profile' }}

+ +
+ +
+
+ } + } @else { + + } + `, }) export class AsgardeoUserProfileComponent { /** Display mode: inline (default) or popup dialog */ - readonly mode = input<'inline' | 'popup'>('inline'); + readonly mode: InputSignal<'inline' | 'popup'> = input<'inline' | 'popup'>('inline'); /** Whether the popup dialog is open (popup mode only). Supports two-way binding via `[(open)]`. */ - readonly open = model(false); + readonly open: ModelSignal = model(false); /** Dialog title (popup mode only) */ - readonly title = input(''); + readonly title: InputSignal = input(''); /** Whether fields can be edited */ - readonly editable = input(true); + readonly editable: InputSignal = input(true); /** Whitelist of field names to show (if set, only these are shown) */ - readonly showFields = input(); + readonly showFields: InputSignal = input(); /** Blacklist of field names to hide */ - readonly hideFields = input(); + readonly hideFields: InputSignal = input(); + + private authService: AsgardeoAuthService = inject(AsgardeoAuthService); - private authService = inject(AsgardeoAuthService); - private userService = inject(AsgardeoUserService); - private editingFields = signal>({}); - private editedValues = signal>({}); + private userService: AsgardeoUserService = inject(AsgardeoUserService); + + private editingFields: WritableSignal> = signal>({}); + + private editedValues: WritableSignal> = signal>({}); constructor() { // Reset editing state when the popup closes @@ -581,53 +591,45 @@ export class AsgardeoUserProfileComponent { }); } - error = signal(null); + error: WritableSignal = signal(null); - schemasAvailable = computed(() => { - const up = this.authService.userProfile(); - return up?.schemas && up.schemas.length > 0; + schemasAvailable: Signal = computed(() => { + const up: Record | null = this.authService.userProfile(); + return up?.['schemas'] && up['schemas'].length > 0; }); - displayName = computed(() => { - const user = this.authService.flattenedProfile() || this.authService.user(); + displayName: Signal = computed(() => { + const user: Record | null = this.authService.flattenedProfile() || this.authService.user(); if (!user) return 'User'; - const u = user as Record; - const firstName = u['name']?.['givenName'] || u['given_name'] || ''; - const lastName = u['name']?.['familyName'] || u['family_name'] || ''; + const u: Record = user as Record; + const firstName: string = u['name']?.['givenName'] || u['given_name'] || ''; + const lastName: string = u['name']?.['familyName'] || u['family_name'] || ''; if (firstName && lastName) return `${firstName} ${lastName}`; return u['userName'] || u['username'] || u['email'] || 'User'; }); - emailValue = computed(() => { - const user = this.authService.flattenedProfile() || this.authService.user(); + emailValue: Signal = computed(() => { + const user: Record | null = this.authService.flattenedProfile() || this.authService.user(); if (!user) return ''; - const u = user as Record; - const emails = u['emails']; + const u: Record = user as Record; + const {emails}: {emails: any} = u as {emails: any}; if (Array.isArray(emails)) return emails[0] || ''; return u['email'] || ''; }); - profileImageUrl = computed(() => { - const user = this.authService.flattenedProfile() || this.authService.user(); + profileImageUrl: Signal = computed(() => { + const user: Record | null = this.authService.flattenedProfile() || this.authService.user(); if (!user) return null; - const u = user as Record; + const u: Record = user as Record; return u['profile'] || u['profileUrl'] || u['picture'] || u['URL'] || null; }); - initials = computed(() => { - const name = this.displayName(); - return name - .split(' ') - .map((p: string) => p[0]) - .slice(0, 2) - .join('') - .toUpperCase(); - }); + initials: Signal = computed(() => getInitials(this.displayName())); - avatarGradient = computed(() => { - const name = this.displayName(); + avatarGradient: Signal = computed(() => { + const name: string = this.displayName(); if (!name) return 'linear-gradient(135deg, #6366f1, #8b5cf6)'; - return this.generateGradient(name); + return generateGradient(name); }); /** @@ -636,18 +638,18 @@ export class AsgardeoUserProfileComponent { * array of field definitions (each with `name`, `type`, `schemaId`, `displayOrder`, etc.), * NOT nested schema objects with `.attributes`. */ - visibleFields = computed(() => { - const up = this.authService.userProfile(); - if (!up?.schemas || up.schemas.length === 0) return []; - const flatProfile = (this.authService.flattenedProfile() || {}) as Record; + visibleFields: Signal = computed(() => { + const up: Record | null = this.authService.userProfile(); + if (!up?.['schemas'] || up['schemas'].length === 0) return []; + const flatProfile: Record = (this.authService.flattenedProfile() || {}) as Record; - return (up.schemas as any[]) + return (up['schemas'] as any[]) .map((field: any) => ({...field, value: flatProfile[field.name]} as SchemaField)) .filter((f: SchemaField) => { if (!f.name) return false; if (FIELDS_TO_SKIP.includes(f.name)) return false; if (this.hideFields()?.includes(f.name)) return false; - const sf = this.showFields(); + const sf: string[] | undefined = this.showFields(); if (sf && sf.length > 0 && !sf.includes(f.name)) return false; if (!this.editable()) { return f.value !== undefined && f.value !== '' && f.value !== null; @@ -655,41 +657,48 @@ export class AsgardeoUserProfileComponent { return true; }) .sort((a: SchemaField, b: SchemaField) => { - const orderA = a.displayOrder ? parseInt(a.displayOrder, 10) : 999; - const orderB = b.displayOrder ? parseInt(b.displayOrder, 10) : 999; + const orderA: number = a.displayOrder ? parseInt(a.displayOrder, 10) : 999; + const orderB: number = b.displayOrder ? parseInt(b.displayOrder, 10) : 999; return orderA - orderB; }); }); /** Fallback flat profile key-value pairs when no schemas available */ - flatProfileEntries = computed(() => { - const profile = (this.authService.flattenedProfile() || this.authService.user()) as Record; + flatProfileEntries: Signal<{key: string; value: string}[]> = computed(() => { + const profile: Record = (this.authService.flattenedProfile() || this.authService.user()) as Record< + string, + any + >; if (!profile) return []; const entries: {key: string; value: string}[] = []; const flatten = (obj: Record, prefix: string = ''): void => { - for (const [key, value] of Object.entries(obj)) { - const fullKey = prefix ? `${prefix}.${key}` : key; - if (FIELDS_TO_SKIP.includes(fullKey) || FIELDS_TO_SKIP.includes(key)) continue; - if (this.hideFields()?.includes(fullKey)) continue; - const sf = this.showFields(); - if (sf && sf.length > 0 && !sf.includes(fullKey)) continue; - if (value === undefined || value === '' || value === null) continue; + Object.entries(obj).forEach((entry: [string, any]) => { + const key: string = entry[0]; + const value: any = entry[1]; + const fullKey: string = prefix ? `${prefix}.${key}` : key; + if (FIELDS_TO_SKIP.includes(fullKey) || FIELDS_TO_SKIP.includes(key)) return; + if (this.hideFields()?.includes(fullKey)) return; + const sf: string[] | undefined = this.showFields(); + if (sf && sf.length > 0 && !sf.includes(fullKey)) return; + if (value === undefined || value === '' || value === null) return; if (Array.isArray(value)) { - const displayVal = value.filter(v => v !== null && v !== undefined && v !== '').join(', '); + const displayVal: string = value.filter((v: any) => v !== null && v !== undefined && v !== '').join(', '); if (displayVal) entries.push({key: fullKey, value: displayVal}); } else if (typeof value === 'object') { flatten(value, fullKey); } else { entries.push({key: fullKey, value: String(value)}); } - } + }); }; flatten(profile); - return entries.sort((a, b) => a.key.localeCompare(b.key)); + return entries.sort((a: {key: string; value: string}, b: {key: string; value: string}) => + a.key.localeCompare(b.key), + ); }); @HostListener('document:keydown.escape') @@ -714,25 +723,25 @@ export class AsgardeoUserProfileComponent { } getEditedValue(fieldName: string): any { - const edited = this.editedValues(); + const edited: Record = this.editedValues(); if (fieldName in edited) return edited[fieldName]; - const profile = (this.authService.flattenedProfile() || {}) as Record; + const profile: Record = (this.authService.flattenedProfile() || {}) as Record; return profile[fieldName]; } toggleEdit(fieldName: string): void { - const current = this.editingFields(); + const current: Record = this.editingFields(); this.editingFields.set({...current, [fieldName]: !current[fieldName]}); } onFieldChange(fieldName: string, value: any): void { - this.editedValues.update(v => ({...v, [fieldName]: value})); + this.editedValues.update((v: Record) => ({...v, [fieldName]: value})); } cancelEdit(fieldName: string): void { - this.editingFields.update(v => ({...v, [fieldName]: false})); - this.editedValues.update(v => { - const copy = {...v}; + this.editingFields.update((v: Record) => ({...v, [fieldName]: false})); + this.editedValues.update((v: Record) => { + const copy: Record = {...v}; delete copy[fieldName]; return copy; }); @@ -741,8 +750,8 @@ export class AsgardeoUserProfileComponent { async saveField(field: SchemaField): Promise { if (!field.name) return; - const fieldName = field.name; - let fieldValue = this.getEditedValue(fieldName) ?? ''; + const fieldName: string = field.name; + let fieldValue: any = this.getEditedValue(fieldName) ?? ''; if (Array.isArray(fieldValue)) { fieldValue = fieldValue.filter((v: any) => v !== undefined && v !== null && v !== ''); @@ -752,19 +761,19 @@ export class AsgardeoUserProfileComponent { if (field.schemaId && field.schemaId !== WELL_KNOWN_USER_SCHEMA) { payload = {[field.schemaId]: {[fieldName]: fieldValue}}; } else { - this.setNestedValue(payload, fieldName, fieldValue); + AsgardeoUserProfileComponent.setNestedValue(payload, fieldName, fieldValue); } this.error.set(null); try { - const baseUrl = this.authService.getBaseUrl(); - const instanceId = this.authService.getClient().getInstanceId(); + const baseUrl: string = this.authService.getBaseUrl(); + const instanceId: number = this.authService.getClient().getInstanceId(); await this.userService.updateUser({baseUrl, instanceId, payload}); - this.editingFields.update(v => ({...v, [fieldName]: false})); - this.editedValues.update(v => { - const copy = {...v}; + this.editingFields.update((v: Record) => ({...v, [fieldName]: false})); + this.editedValues.update((v: Record) => { + const copy: Record = {...v}; delete copy[fieldName]; return copy; }); @@ -773,24 +782,28 @@ export class AsgardeoUserProfileComponent { } } + // eslint-disable-next-line class-methods-use-this isReadonly(field: SchemaField): boolean { if (field.mutability === 'READ_ONLY') return true; if (field.name && READONLY_FIELDS.includes(field.name)) return true; return false; } + // eslint-disable-next-line class-methods-use-this hasFieldValue(field: SchemaField): boolean { return field.value !== undefined && field.value !== '' && field.value !== null; } + // eslint-disable-next-line class-methods-use-this formatFieldValue(field: SchemaField): string { - const val = field.value; + const val: any = field.value; if (val === null || val === undefined) return ''; if (typeof val === 'boolean') return val ? 'Yes' : 'No'; if (typeof val === 'object') return JSON.stringify(val); return String(val); } + // eslint-disable-next-line class-methods-use-this formatLabel(key: string): string { return key .split(/(?=[A-Z])|_|\./) @@ -798,10 +811,10 @@ export class AsgardeoUserProfileComponent { .join(' '); } - private setNestedValue(obj: Record, path: string, value: any): void { - const keys = path.split('.'); - let current = obj; - for (let i = 0; i < keys.length; i++) { + private static setNestedValue(obj: Record, path: string, value: any): void { + const keys: string[] = path.split('.'); + let current: Record = obj; + for (let i: number = 0; i < keys.length; i += 1) { if (i === keys.length - 1) { current[keys[i]] = value; } else { @@ -812,19 +825,4 @@ export class AsgardeoUserProfileComponent { } } } - - private generateGradient(inputString: string): string { - let hash = inputString.split('').reduce((acc: number, char: string) => { - const charCode = char.charCodeAt(0); - return ((acc << 5) - acc + charCode) & 0xffffffff; - }, 0); - const seed = Math.abs(hash); - const hue1 = (seed + seed) % 360; - const hue2 = (hue1 + 60 + (seed % 120)) % 360; - const saturation = 70 + (seed % 20); - const lightness1 = 55 + (seed % 15); - const lightness2 = 60 + ((seed + seed) % 15); - const angle = 45 + (seed % 91); - return `linear-gradient(${angle}deg, hsl(${hue1}, ${saturation}%, ${lightness1}%), hsl(${hue2}, ${saturation}%, ${lightness2}%))`; - } } diff --git a/packages/angular/src/directives/loading.directive.ts b/packages/angular/src/directives/loading.directive.ts index 25f496f68..8e25fd288 100644 --- a/packages/angular/src/directives/loading.directive.ts +++ b/packages/angular/src/directives/loading.directive.ts @@ -35,11 +35,11 @@ import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; standalone: true, }) export class AsgardeoLoadingDirective { - private authService: AsgardeoAuthService = inject(AsgardeoAuthService); + private readonly authService: AsgardeoAuthService = inject(AsgardeoAuthService); - private templateRef: TemplateRef = inject(TemplateRef); + private readonly templateRef: TemplateRef = inject(TemplateRef); - private viewContainer: ViewContainerRef = inject(ViewContainerRef); + private readonly viewContainer: ViewContainerRef = inject(ViewContainerRef); private hasView: boolean = false; diff --git a/packages/angular/src/directives/signed-in.directive.ts b/packages/angular/src/directives/signed-in.directive.ts index 682ea7fcb..c277f265e 100644 --- a/packages/angular/src/directives/signed-in.directive.ts +++ b/packages/angular/src/directives/signed-in.directive.ts @@ -35,11 +35,11 @@ import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; standalone: true, }) export class AsgardeoSignedInDirective { - private authService: AsgardeoAuthService = inject(AsgardeoAuthService); + private readonly authService: AsgardeoAuthService = inject(AsgardeoAuthService); - private templateRef: TemplateRef = inject(TemplateRef); + private readonly templateRef: TemplateRef = inject(TemplateRef); - private viewContainer: ViewContainerRef = inject(ViewContainerRef); + private readonly viewContainer: ViewContainerRef = inject(ViewContainerRef); private hasView: boolean = false; diff --git a/packages/angular/src/directives/signed-out.directive.ts b/packages/angular/src/directives/signed-out.directive.ts index 30d866729..cbfdfc18e 100644 --- a/packages/angular/src/directives/signed-out.directive.ts +++ b/packages/angular/src/directives/signed-out.directive.ts @@ -36,11 +36,11 @@ import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; standalone: true, }) export class AsgardeoSignedOutDirective { - private authService: AsgardeoAuthService = inject(AsgardeoAuthService); + private readonly authService: AsgardeoAuthService = inject(AsgardeoAuthService); - private templateRef: TemplateRef = inject(TemplateRef); + private readonly templateRef: TemplateRef = inject(TemplateRef); - private viewContainer: ViewContainerRef = inject(ViewContainerRef); + private readonly viewContainer: ViewContainerRef = inject(ViewContainerRef); private hasView: boolean = false; diff --git a/packages/angular/src/index.ts b/packages/angular/src/index.ts index 32a2f623e..5b9799060 100644 --- a/packages/angular/src/index.ts +++ b/packages/angular/src/index.ts @@ -43,6 +43,10 @@ export {AsgardeoLoadingDirective} from './directives/loading.directive'; // --- Components --- export {AsgardeoCallbackComponent} from './components/callback/callback.component'; export {AsgardeoUserProfileComponent} from './components/user-profile/user-profile.component'; +export {AsgardeoOrganizationListComponent} from './components/organization-list/organization-list.component'; +export {AsgardeoCreateOrganizationComponent} from './components/create-organization/create-organization.component'; +export {AsgardeoOrganizationProfileComponent} from './components/organization-profile/organization-profile.component'; +export {AsgardeoOrganizationSwitcherComponent} from './components/organization-switcher/organization-switcher.component'; // --- API --- export {default as getAllOrganizations, GetAllOrganizationsConfig} from './api/getAllOrganizations'; @@ -63,6 +67,7 @@ export { type User, type UserProfile, type Organization, + type OrganizationDetails, type IdToken, type TokenResponse, type HttpRequestConfig, diff --git a/packages/angular/src/interceptors/asgardeo.interceptor.ts b/packages/angular/src/interceptors/asgardeo.interceptor.ts index 03f7b7574..f428d7f3d 100644 --- a/packages/angular/src/interceptors/asgardeo.interceptor.ts +++ b/packages/angular/src/interceptors/asgardeo.interceptor.ts @@ -21,6 +21,25 @@ import {inject} from '@angular/core'; import {from, switchMap} from 'rxjs'; import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; +/** + * Checks whether the request URL belongs to the same origin as the configured base URL. + * Only attaches tokens to requests targeting the Asgardeo/IS server to prevent leaking + * credentials to third-party APIs. + */ +function isAllowedUrl(requestUrl: string, baseUrl: string): boolean { + if (!baseUrl) { + return false; + } + + try { + const reqOrigin: string = new URL(requestUrl).origin; + const baseOrigin: string = new URL(baseUrl).origin; + return reqOrigin === baseOrigin; + } catch { + return false; + } +} + /** * Functional HTTP interceptor that automatically attaches the access token * to outgoing HTTP requests as a Bearer token in the Authorization header. @@ -28,6 +47,7 @@ import {AsgardeoAuthService} from '../services/asgardeo-auth.service'; * Skips token attachment if: * - The request already has an Authorization header * - The user is not signed in + * - The request URL does not match the configured base URL origin * * @example * ```typescript @@ -56,6 +76,12 @@ export const asgardeoInterceptor: HttpInterceptorFn = (req: HttpRequest return next(req); } + // Only attach token to requests targeting the configured base URL origin + const baseUrl: string = authService.getBaseUrl(); + if (!isAllowedUrl(req.url, baseUrl)) { + return next(req); + } + return from(authService.getAccessToken()).pipe( switchMap((token: string) => { if (token) { diff --git a/packages/angular/src/providers/asgardeo.module.ts b/packages/angular/src/providers/asgardeo.module.ts index 265a27419..795e5efcb 100644 --- a/packages/angular/src/providers/asgardeo.module.ts +++ b/packages/angular/src/providers/asgardeo.module.ts @@ -19,6 +19,10 @@ import {NgModule, ModuleWithProviders, APP_INITIALIZER} from '@angular/core'; import {ASGARDEO_CONFIG} from './asgardeo-config.token'; import {AsgardeoCallbackComponent} from '../components/callback/callback.component'; +import {AsgardeoCreateOrganizationComponent} from '../components/create-organization/create-organization.component'; +import {AsgardeoOrganizationListComponent} from '../components/organization-list/organization-list.component'; +import {AsgardeoOrganizationProfileComponent} from '../components/organization-profile/organization-profile.component'; +import {AsgardeoOrganizationSwitcherComponent} from '../components/organization-switcher/organization-switcher.component'; import {AsgardeoUserProfileComponent} from '../components/user-profile/user-profile.component'; import {AsgardeoLoadingDirective} from '../directives/loading.directive'; import {AsgardeoSignedInDirective} from '../directives/signed-in.directive'; @@ -49,8 +53,28 @@ import {AsgardeoUserService} from '../services/asgardeo-user.service'; * ``` */ @NgModule({ - exports: [AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoLoadingDirective, AsgardeoCallbackComponent, AsgardeoUserProfileComponent], - imports: [AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoLoadingDirective, AsgardeoCallbackComponent, AsgardeoUserProfileComponent], + exports: [ + AsgardeoSignedInDirective, + AsgardeoSignedOutDirective, + AsgardeoLoadingDirective, + AsgardeoCallbackComponent, + AsgardeoUserProfileComponent, + AsgardeoOrganizationListComponent, + AsgardeoCreateOrganizationComponent, + AsgardeoOrganizationProfileComponent, + AsgardeoOrganizationSwitcherComponent, + ], + imports: [ + AsgardeoSignedInDirective, + AsgardeoSignedOutDirective, + AsgardeoLoadingDirective, + AsgardeoCallbackComponent, + AsgardeoUserProfileComponent, + AsgardeoOrganizationListComponent, + AsgardeoCreateOrganizationComponent, + AsgardeoOrganizationProfileComponent, + AsgardeoOrganizationSwitcherComponent, + ], }) export class AsgardeoModule { static forRoot(config: AsgardeoAngularConfig): ModuleWithProviders { diff --git a/packages/angular/src/services/asgardeo-auth.service.ts b/packages/angular/src/services/asgardeo-auth.service.ts index 15edc1c7b..75b4d6382 100644 --- a/packages/angular/src/services/asgardeo-auth.service.ts +++ b/packages/angular/src/services/asgardeo-auth.service.ts @@ -16,10 +16,11 @@ * under the License. */ -import {Injectable, Inject, Injector, signal, computed, OnDestroy, Signal, WritableSignal} from '@angular/core'; +import {Injectable, Injector, inject, signal, computed, OnDestroy, Signal, WritableSignal} from '@angular/core'; import {toObservable} from '@angular/core/rxjs-interop'; import { AsgardeoRuntimeError, + AsgardeoSPAClient, User, UserProfile, Organization, @@ -30,6 +31,7 @@ import { HttpRequestConfig, HttpResponse, TokenExchangeRequestConfig, + Hooks, hasAuthParamsInUrl, hasCalledForThisInstanceInUrl, Platform, @@ -88,39 +90,52 @@ export class AsgardeoAuthService implements OnDestroy { readonly profile: Signal = computed(() => this._userProfile()?.profile ?? null); - // --- RxJS Observables (derived from signals via toObservable) --- - readonly isLoading$: Observable; + // --- RxJS Observables (lazily derived from signals via toObservable) --- + // These are lazy because toObservable() requires ChangeDetectionScheduler, + // which is not available during APP_INITIALIZER when this service is constructed. + private _isLoading$: Observable | null = null; - readonly isSignedIn$: Observable; + private _isSignedIn$: Observable | null = null; - readonly isInitialized$: Observable; + private _isInitialized$: Observable | null = null; - readonly user$: Observable; + private _user$: Observable | null = null; + + get isLoading$(): Observable { + if (!this._isLoading$) this._isLoading$ = toObservable(this.isLoading, {injector: this.injector}); + return this._isLoading$; + } + + get isSignedIn$(): Observable { + if (!this._isSignedIn$) this._isSignedIn$ = toObservable(this.isSignedIn, {injector: this.injector}); + return this._isSignedIn$; + } + + get isInitialized$(): Observable { + if (!this._isInitialized$) this._isInitialized$ = toObservable(this.isInitialized, {injector: this.injector}); + return this._isInitialized$; + } + + get user$(): Observable { + if (!this._user$) this._user$ = toObservable(this.user, {injector: this.injector}); + return this._user$; + } // --- Internal state --- - private client: AsgardeoAngularClient; + private readonly injector: Injector = inject(Injector); - private config: AsgardeoAngularConfig; + private config: AsgardeoAngularConfig = {...inject(ASGARDEO_CONFIG)}; - private signInCheckInterval: ReturnType | null = null; + private client: AsgardeoAngularClient = new AsgardeoAngularClient(this.config.instanceId ?? 0); + + private signInHookRegistered: boolean = false; private loadingCheckInterval: ReturnType | null = null; private isUpdatingSession: boolean = false; - constructor( - @Inject(ASGARDEO_CONFIG) config: AsgardeoAngularConfig, - injector: Injector, - ) { - this.config = {...config}; - this.client = new AsgardeoAngularClient(config.instanceId ?? 0); - this._baseUrl.set(config.baseUrl || ''); - - // Derive observables from signals within the injection context - this.isLoading$ = toObservable(this.isLoading, {injector}); - this.isSignedIn$ = toObservable(this.isSignedIn, {injector}); - this.isInitialized$ = toObservable(this.isInitialized, {injector}); - this.user$ = toObservable(this.user, {injector}); + constructor() { + this._baseUrl.set(this.config.baseUrl || ''); } /** @@ -302,11 +317,11 @@ export class AsgardeoAuthService implements OnDestroy { // --- HTTP --- - async request(requestConfig?: HttpRequestConfig): Promise> { + async request(requestConfig: HttpRequestConfig): Promise> { return this.client.request(requestConfig); } - async requestAll(requestConfigs?: HttpRequestConfig[]): Promise[]> { + async requestAll(requestConfigs: HttpRequestConfig[]): Promise[]> { return this.client.requestAll(requestConfigs); } @@ -360,7 +375,7 @@ export class AsgardeoAuthService implements OnDestroy { const currentProfile: UserProfile | null = this._userProfile(); this._userProfile.set({ ...currentProfile, - flattenedProfile: generateFlattenedUserProfile(updatedUser, currentProfile?.schemas), + flattenedProfile: generateFlattenedUserProfile(updatedUser, currentProfile?.schemas ?? []), profile: updatedUser, } as UserProfile); } @@ -425,7 +440,7 @@ export class AsgardeoAuthService implements OnDestroy { } try { - const fetchedOrganization: Organization = await this.client.getCurrentOrganization(); + const fetchedOrganization: Organization | null = await this.client.getCurrentOrganization(); this._currentOrganization.set(fetchedOrganization); } catch { // Silently handle organization fetch failure @@ -451,10 +466,11 @@ export class AsgardeoAuthService implements OnDestroy { } /** - * Polls for sign-in status changes. Mirrors AsgardeoProvider's sign-in status polling useEffect. + * Registers a hook to be notified when sign-in completes, + * instead of polling with setInterval. */ private startSignInPolling(): void { - if (this.signInCheckInterval) { + if (this.signInHookRegistered) { return; } @@ -462,36 +478,36 @@ export class AsgardeoAuthService implements OnDestroy { this.setSignedInState(status); if (!status) { - this.signInCheckInterval = setInterval(async () => { - const newStatus: boolean = await this.client.isSignedIn(); - - if (newStatus) { - this.setSignedInState(true); - if (this.signInCheckInterval) { - clearInterval(this.signInCheckInterval); - this.signInCheckInterval = null; - } - } - }, 1000); + this.signInHookRegistered = true; + AsgardeoSPAClient.getInstance(this.config.instanceId ?? 0).on(Hooks.SignIn, () => { + this.setSignedInState(true); + }); } }); } /** * Tracks loading state changes from the client. + * Caches the afterSignInUrl path to avoid repeated URL parsing on every tick. */ private startLoadingStateTracking(): void { + const afterSignInUrl: string = this.config.afterSignInUrl || window.location.origin; + let cachedAfterSignInPath: string; + try { + const parsed: URL = new URL(afterSignInUrl); + cachedAfterSignInPath = new URL(parsed.origin + parsed.pathname).toString(); + } catch { + cachedAfterSignInPath = afterSignInUrl; + } + this.loadingCheckInterval = setInterval(() => { if (this.isUpdatingSession) { return; } - const currentUrl: URL = new URL(window.location.href); - const afterSignInUrl: string = this.config.afterSignInUrl || window.location.origin; if (!this._isSignedIn() && hasAuthParamsInUrl()) { - const currentPathUrl: string = new URL(currentUrl.origin + currentUrl.pathname).toString(); - const afterSignInPathUrl: string = new URL(afterSignInUrl).toString(); - if (currentPathUrl === afterSignInPathUrl) { + const currentPathUrl: string = window.location.origin + window.location.pathname; + if (currentPathUrl === cachedAfterSignInPath) { return; } } @@ -513,10 +529,6 @@ export class AsgardeoAuthService implements OnDestroy { } ngOnDestroy(): void { - if (this.signInCheckInterval) { - clearInterval(this.signInCheckInterval); - this.signInCheckInterval = null; - } if (this.loadingCheckInterval) { clearInterval(this.loadingCheckInterval); this.loadingCheckInterval = null; diff --git a/packages/angular/src/services/asgardeo-organization.service.ts b/packages/angular/src/services/asgardeo-organization.service.ts index 607af7e05..346f0f7ef 100644 --- a/packages/angular/src/services/asgardeo-organization.service.ts +++ b/packages/angular/src/services/asgardeo-organization.service.ts @@ -16,10 +16,12 @@ * under the License. */ -import {Injectable, Signal, WritableSignal, signal} from '@angular/core'; -import {Organization, AllOrganizationsApiResponse, TokenResponse} from '@asgardeo/browser'; +import {Injectable, Signal, WritableSignal, inject, signal} from '@angular/core'; +import {Organization, AllOrganizationsApiResponse, TokenResponse, OrganizationDetails} from '@asgardeo/browser'; import {AsgardeoAuthService} from './asgardeo-auth.service'; import createOrganization, {CreateOrganizationConfig} from '../api/createOrganization'; +import getOrganizationApi from '../api/getOrganization'; +import updateOrganizationApi, {createPatchOperations} from '../api/updateOrganization'; /** * Service for managing organizations. @@ -40,7 +42,9 @@ export class AsgardeoOrganizationService { readonly currentOrganization: Signal; - constructor(private authService: AsgardeoAuthService) { + private readonly authService: AsgardeoAuthService = inject(AsgardeoAuthService); + + constructor() { this.myOrganizations = this.authService.myOrganizations; this.currentOrganization = this.authService.currentOrganization; } @@ -104,4 +108,44 @@ export class AsgardeoOrganizationService { this._isLoading.set(false); } } + + /** + * Fetches detailed information for a specific organization. + */ + async getOrganization(organizationId: string): Promise { + this._isLoading.set(true); + this._error.set(null); + + try { + const baseUrl: string = this.authService.getBaseUrl(); + const instanceId: number = this.authService.getClient().getInstanceId(); + return await getOrganizationApi({baseUrl, instanceId, organizationId}); + } catch (error) { + this._error.set(error instanceof Error ? error : new Error('Failed to fetch organization')); + throw error; + } finally { + this._isLoading.set(false); + } + } + + /** + * Updates an organization using PATCH operations. + */ + async updateOrganization(organizationId: string, data: Record): Promise { + this._isLoading.set(true); + this._error.set(null); + + try { + const baseUrl: string = this.authService.getBaseUrl(); + const instanceId: number = this.authService.getClient().getInstanceId(); + const operations: Array<{operation: 'REPLACE' | 'REMOVE'; path: string; value?: any}> = + createPatchOperations(data); + return await updateOrganizationApi({baseUrl, instanceId, operations, organizationId}); + } catch (error) { + this._error.set(error instanceof Error ? error : new Error('Failed to update organization')); + throw error; + } finally { + this._isLoading.set(false); + } + } } diff --git a/packages/angular/src/services/asgardeo-user.service.ts b/packages/angular/src/services/asgardeo-user.service.ts index 4c00ecdbb..1167f9719 100644 --- a/packages/angular/src/services/asgardeo-user.service.ts +++ b/packages/angular/src/services/asgardeo-user.service.ts @@ -16,7 +16,7 @@ * under the License. */ -import {Injectable, Signal, WritableSignal, computed, signal} from '@angular/core'; +import {Injectable, Signal, WritableSignal, computed, inject, signal} from '@angular/core'; import {User, UserProfile} from '@asgardeo/browser'; import {AsgardeoAuthService} from './asgardeo-auth.service'; import updateMeProfile, {UpdateMeProfileConfig} from '../api/updateMeProfile'; @@ -44,7 +44,9 @@ export class AsgardeoUserService { readonly schemas: Signal; - constructor(private authService: AsgardeoAuthService) { + private readonly authService: AsgardeoAuthService = inject(AsgardeoAuthService); + + constructor() { this.userProfile = this.authService.userProfile; this.flattenedProfile = this.authService.flattenedProfile; this.profile = this.authService.profile; diff --git a/packages/angular/src/utils/avatar.ts b/packages/angular/src/utils/avatar.ts new file mode 100644 index 000000000..0c39e3f96 --- /dev/null +++ b/packages/angular/src/utils/avatar.ts @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Generates a deterministic gradient background CSS value from a string (e.g. a name). + * Uses the same algorithm as the React SDK's Avatar component. + */ +export function generateGradient(inputString: string): string { + const hash: number = inputString.split('').reduce((acc: number, char: string) => { + const charCode: number = char.charCodeAt(0); + // eslint-disable-next-line no-bitwise + return ((acc << 5) - acc + charCode) & 0xffffffff; + }, 0); + const seed: number = Math.abs(hash); + const hue1: number = (seed + seed) % 360; + const hue2: number = (hue1 + 60 + (seed % 120)) % 360; + const saturation: number = 70 + (seed % 20); + const lightness1: number = 55 + (seed % 15); + const lightness2: number = 60 + ((seed + seed) % 15); + const angle: number = 45 + (seed % 91); + return `linear-gradient(${angle}deg, hsl(${hue1}, ${saturation}%, ${lightness1}%), hsl(${hue2}, ${saturation}%, ${lightness2}%))`; +} + +/** + * Extracts initials from a name string (up to 2 characters). + */ +export function getInitials(name: string): string { + return name + .split(' ') + .map((w: string) => w[0]) + .slice(0, 2) + .join('') + .toUpperCase(); +} diff --git a/packages/angular/src/utils/fetcher.ts b/packages/angular/src/utils/fetcher.ts new file mode 100644 index 000000000..8bad61adc --- /dev/null +++ b/packages/angular/src/utils/fetcher.ts @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {HttpResponse, AsgardeoSPAClient, HttpRequestConfig} from '@asgardeo/browser'; + +/** + * Creates a default fetcher function that bridges the Fetch API interface expected + * by `@asgardeo/browser` API functions with the Axios-based AsgardeoSPAClient HTTP layer. + * + * @param instanceId - The Asgardeo client instance ID (for multi-instance support). + * @returns A Fetch API-compatible function. + */ +export function createDefaultFetcher(instanceId: number): (url: string, config: RequestInit) => Promise { + return async (url: string, config: RequestInit): Promise => { + const client: AsgardeoSPAClient = AsgardeoSPAClient.getInstance(instanceId); + const response: HttpResponse = (await client.httpRequest({ + data: config.body ? JSON.parse(config.body as string) : undefined, + headers: config.headers as Record, + method: (config.method as string) || 'GET', + url, + } as HttpRequestConfig)) as HttpResponse; + + return { + json: () => Promise.resolve(response.data), + ok: response.status >= 200 && response.status < 300, + status: response.status, + statusText: response.statusText || '', + text: () => Promise.resolve(typeof response.data === 'string' ? response.data : JSON.stringify(response.data)), + } as Response; + }; +} diff --git a/packages/angular/tsconfig.json b/packages/angular/tsconfig.json index b405f5dd6..1fec4399e 100644 --- a/packages/angular/tsconfig.json +++ b/packages/angular/tsconfig.json @@ -3,9 +3,7 @@ "compileOnSave": false, "compilerOptions": { "declaration": false, - "emitDecoratorMetadata": true, "esModuleInterop": true, - "experimentalDecorators": true, "importHelpers": true, "lib": ["ESNext", "DOM"], "module": "ESNext", @@ -15,7 +13,7 @@ "sourceMap": true, "target": "ESNext", "forceConsistentCasingInFileNames": true, - "strict": false, + "strict": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, diff --git a/packages/angular/tsconfig.lib.json b/packages/angular/tsconfig.lib.json index 6a51b0159..639af85aa 100644 --- a/packages/angular/tsconfig.lib.json +++ b/packages/angular/tsconfig.lib.json @@ -6,6 +6,9 @@ "declarationDir": "dist", "types": ["node"] }, + "angularCompilerOptions": { + "compilationMode": "partial" + }, "exclude": [ "**/*.spec.ts", "**/*.test.ts" diff --git a/packages/angular/vitest.config.ts b/packages/angular/vitest.config.ts index 8d3773a21..1b3ce2a34 100644 --- a/packages/angular/vitest.config.ts +++ b/packages/angular/vitest.config.ts @@ -22,5 +22,6 @@ import {defineConfig} from 'vitest/config'; export default defineConfig({ test: { environment: 'jsdom', + setupFiles: ['./src/__tests__/setup.ts'], }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 66d9f2e69..2a2b188b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,6 +46,8 @@ overrides: '@wso2/eslint-plugin>@typescript-eslint/type-utils': 6.21.0 '@wso2/eslint-plugin>@typescript-eslint/utils': 6.21.0 +packageExtensionsChecksum: sha256-EMtoZD9TYQcjWtR0A05GjB9G1mp66W1Smh7cSozHxjs= + importers: .: @@ -87,14 +89,14 @@ importers: packages/angular: dependencies: '@angular/common': - specifier: '>=17.0.0' - version: 21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) + specifier: '>=18.0.0' + version: 21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) '@angular/core': - specifier: '>=17.0.0' - version: 21.1.5(rxjs@7.8.2)(zone.js@0.15.0) + specifier: '>=18.0.0' + version: 21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1) '@angular/router': - specifier: '>=17.0.0' - version: 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2) + specifier: '>=18.0.0' + version: 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2) '@asgardeo/browser': specifier: workspace:* version: link:../browser @@ -108,24 +110,30 @@ importers: specifier: 2.8.1 version: 2.8.1 devDependencies: + '@angular/compiler': + specifier: 21.1.5 + version: 21.1.5 + '@angular/compiler-cli': + specifier: 21.1.5 + version: 21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3) '@types/node': specifier: 22.15.3 version: 22.15.3 '@wso2/eslint-plugin': specifier: 'catalog:' - version: https://codeload.github.com/brionmario/wso2-ui-configs/tar.gz/d3041825a4f8f235c8f9fa36b55cf29d54e791c8#path:packages/eslint-plugin(eslint@8.57.0)(typescript@5.7.2) + version: https://codeload.github.com/brionmario/wso2-ui-configs/tar.gz/d3041825a4f8f235c8f9fa36b55cf29d54e791c8#path:packages/eslint-plugin(eslint@8.57.0)(typescript@5.9.3) '@wso2/prettier-config': specifier: 'catalog:' - version: https://codeload.github.com/brionmario/wso2-ui-configs/tar.gz/d3041825a4f8f235c8f9fa36b55cf29d54e791c8#path:packages/prettier-config(prettier@2.6.2)(typescript@5.7.2) - esbuild: - specifier: 0.25.9 - version: 0.25.9 + version: https://codeload.github.com/brionmario/wso2-ui-configs/tar.gz/d3041825a4f8f235c8f9fa36b55cf29d54e791c8#path:packages/prettier-config(prettier@2.6.2)(typescript@5.9.3) eslint: specifier: 8.57.0 version: 8.57.0 jsdom: specifier: 26.1.0 version: 26.1.0 + ng-packagr: + specifier: 21.1.0 + version: 21.1.0(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(tailwindcss@4.1.8)(tslib@2.8.1)(typescript@5.9.3) prettier: specifier: 2.6.2 version: 2.6.2 @@ -133,11 +141,11 @@ importers: specifier: 6.1.0 version: 6.1.0 typescript: - specifier: 5.7.2 - version: 5.7.2 + specifier: 5.9.3 + version: 5.9.3 vitest: specifier: 3.1.3 - version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@26.1.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@26.1.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) packages/browser: dependencies: @@ -189,7 +197,7 @@ importers: version: 22.15.3 '@vitest/browser': specifier: 3.1.3 - version: 3.1.3(playwright@1.55.1)(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3) + version: 3.1.3(playwright@1.55.1)(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3) '@wso2/eslint-plugin': specifier: 'catalog:' version: https://codeload.github.com/brionmario/wso2-ui-configs/tar.gz/d3041825a4f8f235c8f9fa36b55cf29d54e791c8#path:packages/eslint-plugin(eslint@8.57.0)(typescript@5.7.2) @@ -225,7 +233,7 @@ importers: version: 5.7.2 vitest: specifier: 3.1.3 - version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) packages/express: dependencies: @@ -265,7 +273,7 @@ importers: version: 5.7.2 vitest: specifier: 3.1.3 - version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) packages/i18n: dependencies: @@ -299,7 +307,7 @@ importers: version: 5.7.2 vitest: specifier: 3.1.3 - version: 3.1.3(@types/node@22.15.30)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 3.1.3(@types/node@22.15.30)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) packages/javascript: dependencies: @@ -336,7 +344,7 @@ importers: version: 5.7.2 vitest: specifier: 3.1.3 - version: 3.1.3(@types/node@22.15.30)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 3.1.3(@types/node@22.15.30)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) packages/nextjs: dependencies: @@ -376,7 +384,7 @@ importers: version: 8.57.0 next: specifier: 15.5.12 - version: 15.5.12(@playwright/test@1.58.2)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)(sass@1.92.1) + version: 15.5.12(@playwright/test@1.58.2)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)(sass@1.97.1) prettier: specifier: 2.6.2 version: 2.6.2 @@ -391,7 +399,7 @@ importers: version: 5.7.2 vitest: specifier: 3.1.3 - version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) packages/node: dependencies: @@ -449,7 +457,7 @@ importers: version: 5.7.2 vitest: specifier: 3.1.3 - version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) packages/react: dependencies: @@ -519,7 +527,7 @@ importers: version: 5.7.2 vitest: specifier: 3.1.3 - version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@26.1.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@26.1.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) packages/react-router: dependencies: @@ -568,7 +576,7 @@ importers: version: 5.7.2 vitest: specifier: 3.1.3 - version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) packages/tanstack-router: dependencies: @@ -620,7 +628,7 @@ importers: version: 5.7.2 vitest: specifier: 3.1.3 - version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) packages/vue: dependencies: @@ -632,7 +640,7 @@ importers: version: 0.1.3 '@vitejs/plugin-vue': specifier: 5.2.4 - version: 5.2.4(vite@7.1.12(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vue@3.5.13(typescript@5.1.6)) + version: 5.2.4(vite@7.1.12(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vue@3.5.13(typescript@5.1.6)) base64url: specifier: 3.0.1 version: 3.0.1 @@ -672,10 +680,10 @@ importers: version: 20.12.7 '@vitest/coverage-v8': specifier: 3.0.8 - version: 3.0.8(vitest@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + version: 3.0.8(vitest@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitest/web-worker': specifier: 3.0.8 - version: 3.0.8(vitest@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + version: 3.0.8(vitest@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vue/eslint-config-prettier': specifier: 8.0.0 version: 8.0.0(eslint@8.57.0)(prettier@2.6.2) @@ -726,10 +734,10 @@ importers: version: 5.1.6 vite: specifier: 7.1.12 - version: 7.1.12(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 7.1.12(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) vitest: specifier: 3.0.8 - version: 3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) vue-tsc: specifier: 2.2.2 version: 2.2.2(typescript@5.1.6) @@ -763,10 +771,10 @@ importers: version: 19.1.5(@types/react@19.1.5) '@vitejs/plugin-basic-ssl': specifier: 2.0.0 - version: 2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + version: 2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitejs/plugin-react': specifier: 4.4.1 - version: 4.4.1(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + version: 4.4.1(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) eslint: specifier: 9.25.0 version: 9.25.0(jiti@2.6.0) @@ -787,28 +795,28 @@ importers: version: 8.30.1(eslint@9.25.0(jiti@2.6.0))(typescript@5.8.3) vite: specifier: 6.4.1 - version: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) samples/teamspace-angular: dependencies: '@angular/common': - specifier: 19.2.4 - version: 19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1) + specifier: 21.1.5 + version: 21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1) '@angular/core': - specifier: 19.2.4 - version: 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) + specifier: 21.1.5 + version: 21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1) '@angular/forms': - specifier: 19.2.4 - version: 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1) + specifier: 21.1.5 + version: 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)))(rxjs@7.8.1) '@angular/platform-browser': - specifier: 19.2.4 - version: 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)) + specifier: 21.1.5 + version: 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)) '@angular/platform-browser-dynamic': - specifier: 19.2.4 - version: 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/compiler@19.2.4)(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))) + specifier: 21.1.5 + version: 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/compiler@21.1.5)(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))) '@angular/router': - specifier: 19.2.4 - version: 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1) + specifier: 21.1.5 + version: 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)))(rxjs@7.8.1) '@asgardeo/angular': specifier: workspace:* version: link:../../packages/angular @@ -819,36 +827,36 @@ importers: specifier: 2.8.1 version: 2.8.1 zone.js: - specifier: 0.15.0 - version: 0.15.0 + specifier: 0.16.1 + version: 0.16.1 devDependencies: '@analogjs/vite-plugin-angular': - specifier: 1.16.2 - version: 1.16.2(@angular/build@19.2.4(@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3))(@angular/compiler@19.2.4)(@types/node@24.0.3)(chokidar@4.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.0)) + specifier: 2.2.3 + version: 2.2.3(@angular/build@21.1.4(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(@angular/compiler@21.1.5)(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)))(@types/node@24.0.3)(chokidar@5.0.0)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(ng-packagr@21.1.0(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(tailwindcss@4.1.8)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.0))(typescript@5.9.3) '@angular/build': - specifier: 19.2.4 - version: 19.2.4(@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3))(@angular/compiler@19.2.4)(@types/node@24.0.3)(chokidar@4.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.0) + specifier: 21.1.4 + version: 21.1.4(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(@angular/compiler@21.1.5)(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)))(@types/node@24.0.3)(chokidar@5.0.0)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(ng-packagr@21.1.0(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(tailwindcss@4.1.8)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.0) '@angular/compiler': - specifier: 19.2.4 - version: 19.2.4 + specifier: 21.1.5 + version: 21.1.5 '@angular/compiler-cli': - specifier: 19.2.4 - version: 19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3) + specifier: 21.1.5 + version: 21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3) '@tailwindcss/vite': specifier: 4.1.8 - version: 4.1.8(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + version: 4.1.8(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitejs/plugin-basic-ssl': specifier: 2.0.0 - version: 2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + version: 2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) tailwindcss: specifier: 4.1.8 version: 4.1.8 typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 5.9.3 + version: 5.9.3 vite: specifier: 6.4.1 - version: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) samples/teamspace-react: dependencies: @@ -900,7 +908,7 @@ importers: version: 9.25.0 '@tailwindcss/vite': specifier: 4.1.8 - version: 4.1.8(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + version: 4.1.8(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@types/react': specifier: 19.1.5 version: 19.1.5 @@ -909,10 +917,10 @@ importers: version: 19.1.5(@types/react@19.1.5) '@vitejs/plugin-basic-ssl': specifier: 2.0.0 - version: 2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + version: 2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitejs/plugin-react': specifier: 4.4.1 - version: 4.4.1(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + version: 4.4.1(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) autoprefixer: specifier: 10.4.16 version: 10.4.16(postcss@8.4.31) @@ -945,7 +953,7 @@ importers: version: 8.30.1(eslint@9.25.0(jiti@2.6.0))(typescript@5.8.3) vite: specifier: 6.4.1 - version: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + version: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) packages: @@ -956,49 +964,59 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@analogjs/vite-plugin-angular@1.16.2': - resolution: {integrity: sha512-2dHwp11/oyUnxXXU5vXgRdyN7nrwEZWGYAfOEYMkk2bHfOohH6BAPpR3+eiHbLVAxt7kt+igBcOCrvRFUkJ30A==} + '@analogjs/vite-plugin-angular@2.2.3': + resolution: {integrity: sha512-OqVfiJsaHdHMxzvK0heVvp8MenSXh+xib6/p+v3d44kJ3J7ooD4gRx/jKC350zkgRKwcZc3a0ybGUnG6LEF7mg==} peerDependencies: - '@angular-devkit/build-angular': ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@angular/build': ^18.0.0 || ^19.0.0 + '@angular-devkit/build-angular': ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 + '@angular/build': ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 + typescript: '>=5.5' peerDependenciesMeta: '@angular-devkit/build-angular': optional: true '@angular/build': optional: true - '@angular-devkit/architect@0.1902.4': - resolution: {integrity: sha512-YTLiJ7uVItZTAxRuSgASP0M5qILESWH8xGmfR+YWR1JiJem09DWEOpWeLdha1BFzUui5L+6j1btzh4FUHJOtAg==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@angular-devkit/architect@0.2101.4': + resolution: {integrity: sha512-3yyebORk+ovtO+LfDjIGbGCZhCMDAsyn9vkCljARj3sSshS4blOQBar0g+V3kYAweLT5Gf+rTKbN5jneOkBAFQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + hasBin: true - '@angular-devkit/core@19.2.4': - resolution: {integrity: sha512-dL6AmCQsKh+CFVvO/jxX8qZpamVwt9r4iIo7fYcAI2+mTSDGxxBGWbS+onIfdPFuRp2HgKa+AT6WiHmRqu63AA==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@angular-devkit/core@21.1.4': + resolution: {integrity: sha512-ObPTI5gYCB1jGxTRhcqZ6oQVUBFVJ8GH4LksVuAiz0nFX7xxpzARWvlhq943EtnlovVlUd9I8fM3RQqjfGVVAQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: - chokidar: ^4.0.0 + chokidar: ^5.0.0 peerDependenciesMeta: chokidar: optional: true - '@angular/build@19.2.4': - resolution: {integrity: sha512-poCXvmwKri3snWa9zVJ2sW7wyJatZjkwnH6GUBdJrM2dXRQ+LYLk/oXqEjlSRBYNna7P1ZcKNqBbzu0/SnnngA==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@angular/build@21.1.4': + resolution: {integrity: sha512-7CAAQPWFMMqod40ox5MOVB/CnoBXFDehyQhs0hls6lu7bOy/M0EDy0v6bERkyNGRz1mihWWBiCV8XzEinrlq1A==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: - '@angular/compiler': ^19.0.0 || ^19.2.0-next.0 - '@angular/compiler-cli': ^19.0.0 || ^19.2.0-next.0 - '@angular/localize': ^19.0.0 || ^19.2.0-next.0 - '@angular/platform-server': ^19.0.0 || ^19.2.0-next.0 - '@angular/service-worker': ^19.0.0 || ^19.2.0-next.0 - '@angular/ssr': ^19.2.4 + '@angular/compiler': ^21.0.0 + '@angular/compiler-cli': ^21.0.0 + '@angular/core': ^21.0.0 + '@angular/localize': ^21.0.0 + '@angular/platform-browser': ^21.0.0 + '@angular/platform-server': ^21.0.0 + '@angular/service-worker': ^21.0.0 + '@angular/ssr': ^21.1.4 karma: ^6.4.0 less: ^4.2.0 - ng-packagr: ^19.0.0 || ^19.2.0-next.0 + ng-packagr: ^21.0.0 postcss: ^8.4.0 tailwindcss: ^2.0.0 || ^3.0.0 || ^4.0.0 - typescript: '>=5.5 <5.9' + tslib: ^2.3.0 + typescript: '>=5.9 <6.0' + vitest: ^4.0.8 peerDependenciesMeta: + '@angular/core': + optional: true '@angular/localize': optional: true + '@angular/platform-browser': + optional: true '@angular/platform-server': optional: true '@angular/service-worker': @@ -1015,13 +1033,8 @@ packages: optional: true tailwindcss: optional: true - - '@angular/common@19.2.4': - resolution: {integrity: sha512-5iBerI1hkY8rAt0gZQgOlfzR69jj5j25JyfkDOhdZhezE0pqhDc69OnbkUM20LTau4bFRYOj015eiKWzE2DOzQ==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} - peerDependencies: - '@angular/core': 19.2.4 - rxjs: ^6.5.3 || ^7.4.0 + vitest: + optional: true '@angular/common@21.1.5': resolution: {integrity: sha512-olO2F0b+H8YBfsuQFEwo9Hjf+B714xGcttDW37+4jnY2IRS2uYeMu2RGIpY7ps+0uZ017c4iK3CCgSPBgmbTcA==} @@ -1030,24 +1043,20 @@ packages: '@angular/core': 21.1.5 rxjs: ^6.5.3 || ^7.4.0 - '@angular/compiler-cli@19.2.4': - resolution: {integrity: sha512-zIWWJm0L+OGMGoRJ73WW96+LDSmZsWqNpwYYXBAEzzoMtPMsWg8uiOIxxjF9ZUWQ1Y5ODUSADnBJwt5vtiLbzA==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/compiler-cli@21.1.5': + resolution: {integrity: sha512-i2r2bQuWdjjFGTd2TA7FtCWNx5yJ3BMoyTGUC9lzSfmxWAfcH/NWR+6OdaEVwv6Zap3IXYYxs8S+REkx954EwA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} hasBin: true peerDependencies: - '@angular/compiler': 19.2.4 - typescript: '>=5.5 <5.9' - - '@angular/compiler@19.2.4': - resolution: {integrity: sha512-HxUwmkoXMlj9EiSmRMRTI4vR3d5hSxiIZazq7OWtlEm8uKedzLzf72dF+hdc3yF6JCdF87vWiQN22bcGeTxYZw==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/compiler': 21.1.5 + typescript: '>=5.9 <6.0' + peerDependenciesMeta: + typescript: + optional: true - '@angular/core@19.2.4': - resolution: {integrity: sha512-ZuSMg+LWG0ADLEvMzSqU+D6M5KcQtxBssEFq4UskGIYuvNGqC91hAl4sbnXDQ5C7GgFcLY6ouaemS6dBOIfc/g==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} - peerDependencies: - rxjs: ^6.5.3 || ^7.4.0 - zone.js: ~0.15.0 + '@angular/compiler@21.1.5': + resolution: {integrity: sha512-yRUdWlL+AWcTL4d7zD0jkNqsjvxXpWEihvOfD2gc65DO0+E80DsWIpHq9A8yWeLukbfLcmBGI2QbfW9+SXAlvg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} '@angular/core@21.1.5': resolution: {integrity: sha512-m61YHiyE+SIvS8UXcFLjYCucv6ShJJCwz9xxEk7ysYW9wOtHdfIf9tgyOsucZDAvrvpSyQLRj5jGBCGm1VIvXA==} @@ -1062,34 +1071,23 @@ packages: zone.js: optional: true - '@angular/forms@19.2.4': - resolution: {integrity: sha512-XzFVmy2BduohtV6E304VCiCvayqV6hiYfPDvkzQnPiFfnQqRCGOTKSDOqxBDsSoDoZW7vZNHe3HmNMdyPg3Rog==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/forms@21.1.5': + resolution: {integrity: sha512-Z8Vcgz5KYlCobRxLjyGGUBv0mA4nusuiD36GqYRn3sR780TLDcPFVwTCwVEWLdwID64oiHXG+x9jjU/Z3HzR6A==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 19.2.4 - '@angular/core': 19.2.4 - '@angular/platform-browser': 19.2.4 + '@angular/common': 21.1.5 + '@angular/core': 21.1.5 + '@angular/platform-browser': 21.1.5 rxjs: ^6.5.3 || ^7.4.0 - '@angular/platform-browser-dynamic@19.2.4': - resolution: {integrity: sha512-KEVf5YTVBFrFAAW7nOVARy+A/xFJ56iDaeoqn63XB3VF5btEGpqoAxKbQGWRRB9G68uZBFXalJ9wXjS6v2T4ng==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} - peerDependencies: - '@angular/common': 19.2.4 - '@angular/compiler': 19.2.4 - '@angular/core': 19.2.4 - '@angular/platform-browser': 19.2.4 - - '@angular/platform-browser@19.2.4': - resolution: {integrity: sha512-skP+Oq9hxh0hkLcs2bXgnt7Z+KKP5xZYzaHPEToLtPat6l6kSPjT0CJ+DE/8ce443hItAcCbn+JrKGC29nd2pw==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} + '@angular/platform-browser-dynamic@21.1.5': + resolution: {integrity: sha512-Pd8nPbJSIONnze1WS9wLBAtaFw4TYIH+ZGjKHS9G1E9l09tDWtHWyB7dY82Sc//Nc8iR4V7dcsbUmFjOJHThww==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/animations': 19.2.4 - '@angular/common': 19.2.4 - '@angular/core': 19.2.4 - peerDependenciesMeta: - '@angular/animations': - optional: true + '@angular/common': 21.1.5 + '@angular/compiler': 21.1.5 + '@angular/core': 21.1.5 + '@angular/platform-browser': 21.1.5 '@angular/platform-browser@21.1.5': resolution: {integrity: sha512-rAN0cu05Pg7HHe9JMRd3g5JyyVCeFW8QiB/jG6klUrOTF4QzyCbmwlm7MX0uTx3CWAZraWCGbdahUkLyYtuqFA==} @@ -1102,15 +1100,6 @@ packages: '@angular/animations': optional: true - '@angular/router@19.2.4': - resolution: {integrity: sha512-pnQX6gk8Z+YQFtnuqRDPEv+d9Up2oP1ZJk9/i/vnYS53PguSEtKgCBuiy6FQmn7SdrYFJ3+ZoV6ow9jhv00eqA==} - engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0} - peerDependencies: - '@angular/common': 19.2.4 - '@angular/core': 19.2.4 - '@angular/platform-browser': 19.2.4 - rxjs: ^6.5.3 || ^7.4.0 - '@angular/router@21.1.5': resolution: {integrity: sha512-OjFn6Nw51CU712CMbl2U9TxlCkzOmjMLYPAfnV4+RdG7o+/eOS2nV0oapJ88RNCw7Yl04PA1amc3ql3agDFd4A==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -1145,22 +1134,22 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.27.2': - resolution: {integrity: sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.26.10': - resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} - '@babel/core@7.26.9': - resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} + '@babel/compat-data@7.27.2': + resolution: {integrity: sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==} engines: {node: '>=6.9.0'} '@babel/core@7.27.1': resolution: {integrity: sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==} engines: {node: '>=6.9.0'} + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} + engines: {node: '>=6.9.0'} + '@babel/eslint-parser@7.28.5': resolution: {integrity: sha512-fcdRcWahONYo+JRnJg1/AekOacGvKx12Gu0qXJXFi2WBqQA1i7+O5PaxRB7kxE/Op94dExnCiiar6T09pvdHpA==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} @@ -1172,24 +1161,42 @@ packages: resolution: {integrity: sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==} engines: {node: '>=6.9.0'} - '@babel/helper-annotate-as-pure@7.25.9': - resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.27.2': resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.27.1': resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-transforms@7.27.1': resolution: {integrity: sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/helper-plugin-utils@7.27.1': resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} @@ -1206,6 +1213,10 @@ packages: resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.27.1': resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} @@ -1214,16 +1225,19 @@ packages: resolution: {integrity: sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==} engines: {node: '>=6.9.0'} + '@babel/helpers@7.28.6': + resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} + engines: {node: '>=6.9.0'} + '@babel/parser@7.27.2': resolution: {integrity: sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-syntax-import-attributes@7.26.0': - resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/parser@7.29.0': + resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + engines: {node: '>=6.0.0'} + hasBin: true '@babel/plugin-transform-react-jsx-self@7.27.1': resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} @@ -1245,14 +1259,26 @@ packages: resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.27.1': resolution: {integrity: sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + '@babel/types@7.27.1': resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} engines: {node: '>=6.9.0'} + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@1.0.2': resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} @@ -1379,6 +1405,9 @@ packages: '@emnapi/core@1.4.3': resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} + '@emnapi/core@1.8.1': + resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} + '@emnapi/runtime@1.4.3': resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} @@ -1388,6 +1417,9 @@ packages: '@emnapi/wasi-threads@1.0.2': resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + '@emotion/babel-plugin@11.13.5': resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} @@ -1418,14 +1450,14 @@ packages: '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@esbuild/aix-ppc64@0.25.1': - resolution: {integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==} + '@esbuild/aix-ppc64@0.25.9': + resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.25.9': - resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==} + '@esbuild/aix-ppc64@0.27.2': + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -1436,14 +1468,14 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.1': - resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==} + '@esbuild/android-arm64@0.25.9': + resolution: {integrity: sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.25.9': - resolution: {integrity: sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==} + '@esbuild/android-arm64@0.27.2': + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -1454,14 +1486,14 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.1': - resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==} + '@esbuild/android-arm@0.25.9': + resolution: {integrity: sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-arm@0.25.9': - resolution: {integrity: sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==} + '@esbuild/android-arm@0.27.2': + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -1472,14 +1504,14 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.1': - resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==} + '@esbuild/android-x64@0.25.9': + resolution: {integrity: sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/android-x64@0.25.9': - resolution: {integrity: sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==} + '@esbuild/android-x64@0.27.2': + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -1490,14 +1522,14 @@ packages: cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.1': - resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==} + '@esbuild/darwin-arm64@0.25.9': + resolution: {integrity: sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.25.9': - resolution: {integrity: sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==} + '@esbuild/darwin-arm64@0.27.2': + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -1508,14 +1540,14 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.1': - resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==} + '@esbuild/darwin-x64@0.25.9': + resolution: {integrity: sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.25.9': - resolution: {integrity: sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==} + '@esbuild/darwin-x64@0.27.2': + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -1526,14 +1558,14 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.1': - resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==} + '@esbuild/freebsd-arm64@0.25.9': + resolution: {integrity: sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.25.9': - resolution: {integrity: sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==} + '@esbuild/freebsd-arm64@0.27.2': + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -1544,14 +1576,14 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.1': - resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==} + '@esbuild/freebsd-x64@0.25.9': + resolution: {integrity: sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.9': - resolution: {integrity: sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==} + '@esbuild/freebsd-x64@0.27.2': + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -1562,14 +1594,14 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.1': - resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==} + '@esbuild/linux-arm64@0.25.9': + resolution: {integrity: sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.25.9': - resolution: {integrity: sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==} + '@esbuild/linux-arm64@0.27.2': + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -1580,14 +1612,14 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.1': - resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==} + '@esbuild/linux-arm@0.25.9': + resolution: {integrity: sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.25.9': - resolution: {integrity: sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==} + '@esbuild/linux-arm@0.27.2': + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -1598,14 +1630,14 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.1': - resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==} + '@esbuild/linux-ia32@0.25.9': + resolution: {integrity: sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.25.9': - resolution: {integrity: sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==} + '@esbuild/linux-ia32@0.27.2': + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -1616,14 +1648,14 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.1': - resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==} + '@esbuild/linux-loong64@0.25.9': + resolution: {integrity: sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.25.9': - resolution: {integrity: sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==} + '@esbuild/linux-loong64@0.27.2': + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -1634,14 +1666,14 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.1': - resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==} + '@esbuild/linux-mips64el@0.25.9': + resolution: {integrity: sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.25.9': - resolution: {integrity: sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==} + '@esbuild/linux-mips64el@0.27.2': + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -1652,14 +1684,14 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.1': - resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==} + '@esbuild/linux-ppc64@0.25.9': + resolution: {integrity: sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.25.9': - resolution: {integrity: sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==} + '@esbuild/linux-ppc64@0.27.2': + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -1670,14 +1702,14 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.1': - resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==} + '@esbuild/linux-riscv64@0.25.9': + resolution: {integrity: sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.25.9': - resolution: {integrity: sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==} + '@esbuild/linux-riscv64@0.27.2': + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -1688,14 +1720,14 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.1': - resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==} + '@esbuild/linux-s390x@0.25.9': + resolution: {integrity: sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.25.9': - resolution: {integrity: sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==} + '@esbuild/linux-s390x@0.27.2': + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -1706,14 +1738,14 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.1': - resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==} + '@esbuild/linux-x64@0.25.9': + resolution: {integrity: sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.25.9': - resolution: {integrity: sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==} + '@esbuild/linux-x64@0.27.2': + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} engines: {node: '>=18'} cpu: [x64] os: [linux] @@ -1724,14 +1756,14 @@ packages: cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.1': - resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==} + '@esbuild/netbsd-arm64@0.25.9': + resolution: {integrity: sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.25.9': - resolution: {integrity: sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==} + '@esbuild/netbsd-arm64@0.27.2': + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -1742,14 +1774,14 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.1': - resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==} + '@esbuild/netbsd-x64@0.25.9': + resolution: {integrity: sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.9': - resolution: {integrity: sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==} + '@esbuild/netbsd-x64@0.27.2': + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] @@ -1760,14 +1792,14 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.1': - resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==} + '@esbuild/openbsd-arm64@0.25.9': + resolution: {integrity: sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.25.9': - resolution: {integrity: sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==} + '@esbuild/openbsd-arm64@0.27.2': + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -1778,14 +1810,14 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.1': - resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==} + '@esbuild/openbsd-x64@0.25.9': + resolution: {integrity: sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.9': - resolution: {integrity: sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==} + '@esbuild/openbsd-x64@0.27.2': + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -1802,20 +1834,26 @@ packages: cpu: [arm64] os: [openharmony] + '@esbuild/openharmony-arm64@0.27.2': + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/openharmony-arm64@0.27.3': resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.25.1': - resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==} + '@esbuild/sunos-x64@0.25.9': + resolution: {integrity: sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.25.9': - resolution: {integrity: sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==} + '@esbuild/sunos-x64@0.27.2': + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -1826,14 +1864,14 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.1': - resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==} + '@esbuild/win32-arm64@0.25.9': + resolution: {integrity: sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.25.9': - resolution: {integrity: sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==} + '@esbuild/win32-arm64@0.27.2': + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -1844,14 +1882,14 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.1': - resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==} + '@esbuild/win32-ia32@0.25.9': + resolution: {integrity: sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.25.9': - resolution: {integrity: sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==} + '@esbuild/win32-ia32@0.27.2': + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -1862,14 +1900,14 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.1': - resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==} + '@esbuild/win32-x64@0.25.9': + resolution: {integrity: sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.25.9': - resolution: {integrity: sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==} + '@esbuild/win32-x64@0.27.2': + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -2146,8 +2184,8 @@ packages: resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} engines: {node: '>=18'} - '@inquirer/confirm@5.1.6': - resolution: {integrity: sha512-6ZXYK3M1XmaVBZX6FCfChgtponnL0R6I7k8Nu+kaoNkT828FVZTcca1MqmWQipaW2oNREQl5AaPCUOOCVNdRMw==} + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2217,6 +2255,9 @@ packages: resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -2243,33 +2284,38 @@ packages: '@jspm/core@2.1.0': resolution: {integrity: sha512-3sRl+pkyFY/kLmHl0cgHiFp2xEqErA8N3ECjMs7serSUBmoJ70lBa0PG5t0IM6WJgdZNyyI0R8YFfi5wM8+mzg==} - '@lmdb/lmdb-darwin-arm64@3.2.6': - resolution: {integrity: sha512-yF/ih9EJJZc72psFQbwnn8mExIWfTnzWJg+N02hnpXtDPETYLmQswIMBn7+V88lfCaFrMozJsUvcEQIkEPU0Gg==} + '@lmdb/lmdb-darwin-arm64@3.4.4': + resolution: {integrity: sha512-XaKL705gDWd6XVls3ATDj13ZdML/LqSIxwgnYpG8xTzH2ifArx8fMMDdvqGE/Emd+W6R90W2fveZcJ0AyS8Y0w==} cpu: [arm64] os: [darwin] - '@lmdb/lmdb-darwin-x64@3.2.6': - resolution: {integrity: sha512-5BbCumsFLbCi586Bb1lTWQFkekdQUw8/t8cy++Uq251cl3hbDIGEwD9HAwh8H6IS2F6QA9KdKmO136LmipRNkg==} + '@lmdb/lmdb-darwin-x64@3.4.4': + resolution: {integrity: sha512-GPHGEVcwJlkD01GmIr7B4kvbIcUDS2+kBadVEd7lU4can1RZaZQLDDBJRrrNfS2Kavvl0VLI/cMv7UASAXGrww==} cpu: [x64] os: [darwin] - '@lmdb/lmdb-linux-arm64@3.2.6': - resolution: {integrity: sha512-l5VmJamJ3nyMmeD1ANBQCQqy7do1ESaJQfKPSm2IG9/ADZryptTyCj8N6QaYgIWewqNUrcbdMkJajRQAt5Qjfg==} + '@lmdb/lmdb-linux-arm64@3.4.4': + resolution: {integrity: sha512-mALqr7DE42HsiwVTKpQWxacjHoJk+e9p00RWIJqTACh/hpucxp/0lK/XMh5XzWnU/TDCZLukq1+vNqnNumTP/Q==} cpu: [arm64] os: [linux] - '@lmdb/lmdb-linux-arm@3.2.6': - resolution: {integrity: sha512-+6XgLpMb7HBoWxXj+bLbiiB4s0mRRcDPElnRS3LpWRzdYSe+gFk5MT/4RrVNqd2MESUDmb53NUXw1+BP69bjiQ==} + '@lmdb/lmdb-linux-arm@3.4.4': + resolution: {integrity: sha512-cmev5/dZr5ACKri9f6GU6lZCXTjMhV72xujlbOhFCgFXrt4W0TxGsmY8kA1BITvH60JBKE50cSxsiulybAbrrw==} cpu: [arm] os: [linux] - '@lmdb/lmdb-linux-x64@3.2.6': - resolution: {integrity: sha512-nDYT8qN9si5+onHYYaI4DiauDMx24OAiuZAUsEqrDy+ja/3EbpXPX/VAkMV8AEaQhy3xc4dRC+KcYIvOFefJ4Q==} + '@lmdb/lmdb-linux-x64@3.4.4': + resolution: {integrity: sha512-QjLs8OcmCNcraAcLoZyFlo0atzBJniQLLwhtR+ymQqS5kLYpV5RqwriL87BW+ZiR9ZiGgZx3evrz5vnWPtJ1fQ==} cpu: [x64] os: [linux] - '@lmdb/lmdb-win32-x64@3.2.6': - resolution: {integrity: sha512-XlqVtILonQnG+9fH2N3Aytria7P/1fwDgDhl29rde96uH2sLB8CHORIf2PfuLVzFQJ7Uqp8py9AYwr3ZUCFfWg==} + '@lmdb/lmdb-win32-arm64@3.4.4': + resolution: {integrity: sha512-tr/pwHDlZ33forLGAr0tI04cRmP4SgF93yHbb+2zvZiDEyln5yMHhbKDySxY66aUOkhvBvTuHq9q/3YmTj6ZHQ==} + cpu: [arm64] + os: [win32] + + '@lmdb/lmdb-win32-x64@3.4.4': + resolution: {integrity: sha512-KRzfocJzB/mgoTCqnMawuLSKheHRVTqWfSmouIgYpFs6Hx4zvZSvsZKSCEb5gHmICy7qsx9l06jk3MFTtiFVAQ==} cpu: [x64] os: [win32] @@ -2431,6 +2477,9 @@ packages: '@napi-rs/wasm-runtime@0.2.4': resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} + '@napi-rs/wasm-runtime@1.1.1': + resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} + '@next/env@15.5.12': resolution: {integrity: sha512-pUvdJN1on574wQHjaBfNGDt9Mz5utDSZFsIIQkMzPgNS8ZvT4H2mwOrOIClwsQOb6EGx5M76/CZr6G8i6pSpLg==} @@ -2571,6 +2620,9 @@ packages: '@one-ini/wasm@0.1.1': resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + '@oxc-project/types@0.106.0': + resolution: {integrity: sha512-QdsH3rZq480VnOHSHgPYOhjL8O8LBdcnSjM408BpPCCUc0JYYZPG9Gafl9i3OcGk/7137o+gweb4cCv3WAUykg==} + '@parcel/watcher-android-arm64@2.5.1': resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} engines: {node: '>= 10.0.0'} @@ -2719,6 +2771,90 @@ packages: '@types/react': optional: true + '@rolldown/binding-android-arm64@1.0.0-beta.58': + resolution: {integrity: sha512-mWj5eE4Qc8TbPdGGaaLvBb9XfDPvE1EmZkJQgiGKwchkWH4oAJcRAKMTw7ZHnb1L+t7Ah41sBkAecaIsuUgsug==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-beta.58': + resolution: {integrity: sha512-wFxUymI/5R8bH8qZFYDfAxAN9CyISEIYke+95oZPiv6EWo88aa5rskjVcCpKA532R+klFmdqjbbaD56GNmTF4Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-beta.58': + resolution: {integrity: sha512-ybp3MkPj23VDV9PhtRwdU5qrGhlViWRV5BjKwO6epaSlUD5lW0WyY+roN3ZAzbma/9RrMTgZ/a/gtQq8YXOcqw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-beta.58': + resolution: {integrity: sha512-Evxj3yh7FWvyklUYZa0qTVT9N2zX9TPDqGF056hl8hlCZ9/ndQ2xMv6uw9PD1VlLpukbsqL+/C6M0qwipL0QMg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.58': + resolution: {integrity: sha512-tYeXprDOrEgVHUbPXH6MPso4cM/c6RTkmJNICMQlYdki4hGMh92aj3yU6CKs+4X5gfG0yj5kVUw/L4M685SYag==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.58': + resolution: {integrity: sha512-N78vmZzP6zG967Ohr+MasCjmKtis0geZ1SOVmxrA0/bklTQSzH5kHEjW5Qn+i1taFno6GEre1E40v0wuWsNOQw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.58': + resolution: {integrity: sha512-l+p4QVtG72C7wI2SIkNQw/KQtSjuYwS3rV6AKcWrRBF62ClsFUcif5vLaZIEbPrCXu5OFRXigXFJnxYsVVZqdQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.58': + resolution: {integrity: sha512-urzJX0HrXxIh0FfxwWRjfPCMeInU9qsImLQxHBgLp5ivji1EEUnOfux8KxPPnRQthJyneBrN2LeqUix9DYrNaQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.58': + resolution: {integrity: sha512-7ijfVK3GISnXIwq/1FZo+KyAUJjL3kWPJ7rViAL6MWeEBhEgRzJ0yEd9I8N9aut8Y8ab+EKFJyRNMWZuUBwQ0A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.58': + resolution: {integrity: sha512-/m7sKZCS+cUULbzyJTIlv8JbjNohxbpAOA6cM+lgWgqVzPee3U6jpwydrib328JFN/gF9A99IZEnuGYqEDJdww==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.58': + resolution: {integrity: sha512-6SZk7zMgv+y3wFFQ9qE5P9NnRHcRsptL1ypmudD26PDY+PvFCvfHRkJNfclWnvacVGxjowr7JOL3a9fd1wWhUw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.58': + resolution: {integrity: sha512-sFqfYPnBZ6xBhMkadB7UD0yjEDRvs7ipR3nCggblN+N4ODCXY6qhg/bKL39+W+dgQybL7ErD4EGERVbW9DAWvg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.58': + resolution: {integrity: sha512-AnFWJdAqB8+IDPcGrATYs67Kik/6tnndNJV2jGRmwlbeNiQQ8GhRJU8ETRlINfII0pqi9k4WWLnb00p1QCxw/Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-beta.58': + resolution: {integrity: sha512-qWhDs6yFGR5xDfdrwiSa3CWGIHxD597uGE/A9xGqytBjANvh4rLCTTkq7szhMV4+Ygh+PMS90KVJ8xWG/TkX4w==} + '@rollup/plugin-commonjs@25.0.7': resolution: {integrity: sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==} engines: {node: '>=14.0.0'} @@ -2746,17 +2882,26 @@ packages: rollup: optional: true - '@rollup/plugin-node-resolve@15.2.3': - resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} + '@rollup/plugin-json@6.1.0': + resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 peerDependenciesMeta: rollup: optional: true - '@rollup/plugin-typescript@11.1.6': - resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} + '@rollup/plugin-node-resolve@15.2.3': + resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-typescript@11.1.6': + resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^2.14.0||^3.0.0||^4.0.0 @@ -2786,11 +2931,6 @@ packages: cpu: [arm] os: [android] - '@rollup/rollup-android-arm-eabi@4.34.8': - resolution: {integrity: sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==} - cpu: [arm] - os: [android] - '@rollup/rollup-android-arm-eabi@4.50.0': resolution: {integrity: sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==} cpu: [arm] @@ -2801,11 +2941,6 @@ packages: cpu: [arm64] os: [android] - '@rollup/rollup-android-arm64@4.34.8': - resolution: {integrity: sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==} - cpu: [arm64] - os: [android] - '@rollup/rollup-android-arm64@4.50.0': resolution: {integrity: sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==} cpu: [arm64] @@ -2816,11 +2951,6 @@ packages: cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-arm64@4.34.8': - resolution: {integrity: sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==} - cpu: [arm64] - os: [darwin] - '@rollup/rollup-darwin-arm64@4.50.0': resolution: {integrity: sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==} cpu: [arm64] @@ -2831,11 +2961,6 @@ packages: cpu: [x64] os: [darwin] - '@rollup/rollup-darwin-x64@4.34.8': - resolution: {integrity: sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==} - cpu: [x64] - os: [darwin] - '@rollup/rollup-darwin-x64@4.50.0': resolution: {integrity: sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==} cpu: [x64] @@ -2846,11 +2971,6 @@ packages: cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-arm64@4.34.8': - resolution: {integrity: sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==} - cpu: [arm64] - os: [freebsd] - '@rollup/rollup-freebsd-arm64@4.50.0': resolution: {integrity: sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==} cpu: [arm64] @@ -2861,11 +2981,6 @@ packages: cpu: [x64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.34.8': - resolution: {integrity: sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==} - cpu: [x64] - os: [freebsd] - '@rollup/rollup-freebsd-x64@4.50.0': resolution: {integrity: sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==} cpu: [x64] @@ -2877,12 +2992,6 @@ packages: os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm-gnueabihf@4.34.8': - resolution: {integrity: sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==} - cpu: [arm] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-arm-gnueabihf@4.50.0': resolution: {integrity: sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==} cpu: [arm] @@ -2895,12 +3004,6 @@ packages: os: [linux] libc: [musl] - '@rollup/rollup-linux-arm-musleabihf@4.34.8': - resolution: {integrity: sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==} - cpu: [arm] - os: [linux] - libc: [musl] - '@rollup/rollup-linux-arm-musleabihf@4.50.0': resolution: {integrity: sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==} cpu: [arm] @@ -2913,12 +3016,6 @@ packages: os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-gnu@4.34.8': - resolution: {integrity: sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==} - cpu: [arm64] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-arm64-gnu@4.50.0': resolution: {integrity: sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==} cpu: [arm64] @@ -2931,12 +3028,6 @@ packages: os: [linux] libc: [musl] - '@rollup/rollup-linux-arm64-musl@4.34.8': - resolution: {integrity: sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==} - cpu: [arm64] - os: [linux] - libc: [musl] - '@rollup/rollup-linux-arm64-musl@4.50.0': resolution: {integrity: sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==} cpu: [arm64] @@ -2949,12 +3040,6 @@ packages: os: [linux] libc: [glibc] - '@rollup/rollup-linux-loongarch64-gnu@4.34.8': - resolution: {integrity: sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==} - cpu: [loong64] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-loongarch64-gnu@4.50.0': resolution: {integrity: sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==} cpu: [loong64] @@ -2967,12 +3052,6 @@ packages: os: [linux] libc: [glibc] - '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': - resolution: {integrity: sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-ppc64-gnu@4.50.0': resolution: {integrity: sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==} cpu: [ppc64] @@ -2985,12 +3064,6 @@ packages: os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-gnu@4.34.8': - resolution: {integrity: sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-riscv64-gnu@4.50.0': resolution: {integrity: sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==} cpu: [riscv64] @@ -3009,12 +3082,6 @@ packages: os: [linux] libc: [glibc] - '@rollup/rollup-linux-s390x-gnu@4.34.8': - resolution: {integrity: sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==} - cpu: [s390x] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-s390x-gnu@4.50.0': resolution: {integrity: sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==} cpu: [s390x] @@ -3027,12 +3094,6 @@ packages: os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.34.8': - resolution: {integrity: sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==} - cpu: [x64] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.50.0': resolution: {integrity: sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==} cpu: [x64] @@ -3045,12 +3106,6 @@ packages: os: [linux] libc: [musl] - '@rollup/rollup-linux-x64-musl@4.34.8': - resolution: {integrity: sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==} - cpu: [x64] - os: [linux] - libc: [musl] - '@rollup/rollup-linux-x64-musl@4.50.0': resolution: {integrity: sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==} cpu: [x64] @@ -3067,11 +3122,6 @@ packages: cpu: [arm64] os: [win32] - '@rollup/rollup-win32-arm64-msvc@4.34.8': - resolution: {integrity: sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==} - cpu: [arm64] - os: [win32] - '@rollup/rollup-win32-arm64-msvc@4.50.0': resolution: {integrity: sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==} cpu: [arm64] @@ -3082,11 +3132,6 @@ packages: cpu: [ia32] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.34.8': - resolution: {integrity: sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==} - cpu: [ia32] - os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.50.0': resolution: {integrity: sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==} cpu: [ia32] @@ -3097,22 +3142,25 @@ packages: cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.34.8': - resolution: {integrity: sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==} - cpu: [x64] - os: [win32] - '@rollup/rollup-win32-x64-msvc@4.50.0': resolution: {integrity: sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==} cpu: [x64] os: [win32] + '@rollup/wasm-node@4.58.0': + resolution: {integrity: sha512-G4YrvWabOgRPfRSYEM95ZZGESbzVGUS+uvO/gVPNs3P93z8lBLTDpRwoo6zeEg6AqK9AdIshWbvDGOehZOikMw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} @@ -3281,6 +3329,9 @@ packages: '@ts-morph/common@0.22.0': resolution: {integrity: sha512-HqNBuV/oIlMKdkLshXd1zKBqNQCsuPEsgQOkfFQ/eUKjRlwndXW1AjN9LVkBEIukm00gGXSRmfkl0Wv5VXLnlw==} + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} @@ -3360,9 +3411,6 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@types/unist@3.0.3': - resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@typescript-eslint/eslint-plugin@6.21.0': resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} engines: {node: ^16.0.0 || >=18.0.0} @@ -3504,18 +3552,18 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - '@vitejs/plugin-basic-ssl@1.2.0': - resolution: {integrity: sha512-mkQnxTkcldAzIsomk1UuLfAu9n+kpQ3JbHcpCp7d2Oo6ITtji8pHS3QToOWjhPFvNQSnhlkAjmGbhv2QvwO/7Q==} - engines: {node: '>=14.21.3'} - peerDependencies: - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 - '@vitejs/plugin-basic-ssl@2.0.0': resolution: {integrity: sha512-gc9Tjg8bUxBVSTzeWT3Njc0Cl3PakHFKdNfABnZWiUgbxqmHDEn7uECv3fHVylxoYgNzAcmU7ZrILz+BwSo3sA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} peerDependencies: vite: ^6.0.0 + '@vitejs/plugin-basic-ssl@2.1.0': + resolution: {integrity: sha512-dOxxrhgyDIEUADhb/8OlV9JIqYLgos03YorAueTIeOUskLJSEsfwCByjbu98ctXitUN3znXKp0bYD/WHSudCeA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + peerDependencies: + vite: ^6.0.0 || ^7.0.0 + '@vitejs/plugin-react@4.4.1': resolution: {integrity: sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==} engines: {node: ^14.18.0 || >=16.0.0} @@ -3922,8 +3970,13 @@ packages: resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==} engines: {node: '>=6.0.0'} - beasties@0.2.0: - resolution: {integrity: sha512-Ljqskqx/tbZagIglYoJIMzH5zgssyp+in9+9sAyh15N22AornBeIDnb8EZ6Rk+6ShfMxd92uO3gfpT0NtZbpow==} + baseline-browser-mapping@2.10.0: + resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==} + engines: {node: '>=6.0.0'} + hasBin: true + + beasties@0.3.5: + resolution: {integrity: sha512-NaWu+f4YrJxEttJSm16AzMIFtVldCvaJ68b1L098KpqXmxt9xOLtKoLkKxb8ekhOrLqEJAbvT6n6SEvB/sac7A==} engines: {node: '>=14.0.0'} better-path-resolve@1.0.0: @@ -3985,6 +4038,11 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + buffer-builder@0.2.0: resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==} @@ -4042,6 +4100,9 @@ packages: caniuse-lite@1.0.30001718: resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==} + caniuse-lite@1.0.30001770: + resolution: {integrity: sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==} + chai@5.2.0: resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} engines: {node: '>=12'} @@ -4050,6 +4111,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} @@ -4065,6 +4130,10 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + chownr@3.0.0: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} @@ -4092,9 +4161,13 @@ packages: resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} engines: {node: '>=6'} - cli-truncate@4.0.0: - resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} - engines: {node: '>=18'} + cli-spinners@3.4.0: + resolution: {integrity: sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==} + engines: {node: '>=18.20'} + + cli-truncate@5.1.1: + resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==} + engines: {node: '>=20'} cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} @@ -4107,6 +4180,10 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} + cliui@9.0.1: + resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} + engines: {node: '>=20'} + clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} @@ -4142,6 +4219,10 @@ packages: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} + engines: {node: '>=20'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -4149,6 +4230,9 @@ packages: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} + common-path-prefix@3.0.0: + resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} @@ -4193,6 +4277,9 @@ packages: resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} engines: {node: '>=18'} + copy-anything@2.0.6: + resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + core-js@3.42.0: resolution: {integrity: sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==} @@ -4248,8 +4335,8 @@ packages: css-select@4.3.0: resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} - css-select@5.2.2: - resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + css-select@6.0.0: + resolution: {integrity: sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==} css-tree@1.1.3: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} @@ -4267,6 +4354,10 @@ packages: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} + css-what@7.0.0: + resolution: {integrity: sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==} + engines: {node: '>= 6'} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -4409,6 +4500,10 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} + dependency-graph@1.0.0: + resolution: {integrity: sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==} + engines: {node: '>=4'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -4510,6 +4605,9 @@ packages: electron-to-chromium@1.5.155: resolution: {integrity: sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==} + electron-to-chromium@1.5.302: + resolution: {integrity: sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==} + elliptic@6.6.1: resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} @@ -4552,10 +4650,18 @@ packages: resolution: {integrity: sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==} engines: {node: '>=0.12'} + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + environment@1.1.0: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} engines: {node: '>=18'} + errno@0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -4614,13 +4720,13 @@ packages: peerDependencies: esbuild: '>=0.14.0 <=0.25.x' - esbuild@0.25.1: - resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==} + esbuild@0.25.9: + resolution: {integrity: sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==} engines: {node: '>=18'} hasBin: true - esbuild@0.25.9: - resolution: {integrity: sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==} + esbuild@0.27.2: + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} engines: {node: '>=18'} hasBin: true @@ -5004,9 +5110,17 @@ packages: resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} engines: {node: '>=8'} + find-cache-directory@6.0.0: + resolution: {integrity: sha512-CvFd5ivA6HcSHbD+59P7CyzINHXzwhuQK8RY7CxJZtgDSAtRlHiCaQpZQ2lMR/WRyUIEmzUvL6G2AGurMfegZA==} + engines: {node: '>=20'} + find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + find-up-simple@1.0.1: + resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} + engines: {node: '>=18'} + find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -5295,8 +5409,8 @@ packages: resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} engines: {node: '>=8'} - htmlparser2@9.1.0: - resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} + htmlparser2@10.1.0: + resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} @@ -5339,6 +5453,11 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} + image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + immutable@4.3.7: resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} @@ -5374,6 +5493,9 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + injection-js@2.6.1: + resolution: {integrity: sha512-dbR5bdhi7TWDoCye9cByZqeg/gAfamm8Vu3G1KZOTYkOif8WkuM8CD0oeDPtZYMzT5YH76JAFB7bkmyY9OJi2A==} + internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} @@ -5442,10 +5564,6 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-fullwidth-code-point@4.0.0: - resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} - engines: {node: '>=12'} - is-fullwidth-code-point@5.1.0: resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} engines: {node: '>=18'} @@ -5462,6 +5580,10 @@ packages: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -5534,6 +5656,10 @@ packages: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} @@ -5546,6 +5672,9 @@ packages: resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} engines: {node: '>= 0.4'} + is-what@3.14.1: + resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} + is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -5724,6 +5853,11 @@ packages: resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} engines: {node: '>=0.10'} + less@4.5.1: + resolution: {integrity: sha512-UKgI3/KON4u6ngSsnDADsUERqhZknsVZbnuzlRZXLQCmfC/MDld42fTydUE9B+Mla1AL6SJ/Pp6SlEFi/AVGfw==} + engines: {node: '>=14'} + hasBin: true + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -5807,12 +5941,12 @@ packages: resolution: {integrity: sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - listr2@8.2.5: - resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} - engines: {node: '>=18.0.0'} + listr2@9.0.5: + resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} + engines: {node: '>=20.0.0'} - lmdb@3.2.6: - resolution: {integrity: sha512-SuHqzPl7mYStna8WRotY8XX/EUZBjjv3QyKIByeCLFfC9uXT/OIHByEcA07PzbMfQAM0KYJtLgtpMRlIe5dErQ==} + lmdb@3.4.4: + resolution: {integrity: sha512-+Y2DqovevLkb6DrSQ6SXTYLEd6kvlRbhsxzgJrk7BUfOVA/mt21ak6pFDZDKxiAczHMWxrb02kXBTSTIA0O94A==} hasBin: true local-pkg@1.1.1: @@ -5852,6 +5986,10 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + log-symbols@7.0.1: + resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==} + engines: {node: '>=18'} + log-update@6.1.0: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} @@ -5889,9 +6027,16 @@ packages: magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magicast@0.3.5: resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -5970,6 +6115,11 @@ packages: resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} engines: {node: '>= 0.6'} + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -6077,6 +6227,11 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + needle@3.3.1: + resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==} + engines: {node: '>= 4.4.x'} + hasBin: true + negotiator@1.0.0: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} @@ -6102,6 +6257,19 @@ packages: sass: optional: true + ng-packagr@21.1.0: + resolution: {integrity: sha512-UlQOhH8DRlaYsBGQMjOYvg70J70hD4i/55NV9vAsYvsxEskmp86xjUtZgEeVKeoLq8tYMjMXDgaYjYde153sZQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@angular/compiler-cli': ^21.0.0 || ^21.1.0-next + tailwindcss: ^2.0.0 || ^3.0.0 || ^4.0.0 + tslib: ^2.3.0 + typescript: '>=5.9 <6.0' + peerDependenciesMeta: + tailwindcss: + optional: true + node-addon-api@6.1.0: resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} @@ -6127,6 +6295,9 @@ packages: node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + nopt@7.2.1: resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -6232,6 +6403,10 @@ packages: resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} engines: {node: '>=10'} + ora@9.3.0: + resolution: {integrity: sha512-lBX72MWFduWEf7v7uWf5DHp9Jn5BI8bNPGuFgtXMmr2uDz2Gz2749y3am3agSDdkhHPHYmmxEGSKH85ZLGzgXw==} + engines: {node: '>=20'} + ordered-binary@1.6.1: resolution: {integrity: sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==} @@ -6300,11 +6475,15 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} - parse5-html-rewriting-stream@7.0.0: - resolution: {integrity: sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==} + parse-node-version@1.0.1: + resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} + engines: {node: '>= 0.10'} + + parse5-html-rewriting-stream@8.0.0: + resolution: {integrity: sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==} - parse5-sax-parser@7.0.0: - resolution: {integrity: sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==} + parse5-sax-parser@8.0.0: + resolution: {integrity: sha512-/dQ8UzHZwnrzs3EvDj6IkKrD/jIZyTlB+8XrHJvcjNgRdmWruNdN9i9RK/JtxakmlUdPwKubKPTCqvbTgzGhrw==} parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} @@ -6368,21 +6547,26 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - picomatch@4.0.2: - resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} - engines: {node: '>=12'} - picomatch@4.0.3: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} - piscina@4.8.0: - resolution: {integrity: sha512-EZJb+ZxDrQf3dihsUL7p42pjNyrNIFJCrRHPMgxu/svsj+P3xS3fuEWp7k2+rfsavfl1N0G29b1HGs7J0m8rZA==} + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + piscina@5.1.4: + resolution: {integrity: sha512-7uU4ZnKeQq22t9AsmHGD2w4OYQGonwFnTypDypaWi7Qr2EvQIFVtG8J5D/3bE7W123Wdc9+v4CZDu5hJXVCtBg==} + engines: {node: '>=20.x'} pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} + pkg-dir@8.0.0: + resolution: {integrity: sha512-4peoBq4Wks0riS0z8741NVv+/8IiTvqnZAr8QGgtdifrtpdXbNw/FxRS1l6NFqm4EMzuS0EDqNNx4XGaz8cuyQ==} + engines: {node: '>=18'} + pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -6684,6 +6868,9 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + prr@1.0.1: + resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + public-encrypt@4.0.3: resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} @@ -6782,6 +6969,10 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -6872,6 +7063,11 @@ packages: resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} engines: {node: '>= 0.8'} + rolldown@1.0.0-beta.58: + resolution: {integrity: sha512-v1FCjMZCan7f+xGAHBi+mqiE4MlH7I+SXEHSQSJoMOGNNB2UYtvMiejsq9YuUOiZjNeUeV/a21nSFbrUR+4ZCQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + rollup-plugin-dts@6.1.0: resolution: {integrity: sha512-ijSCPICkRMDKDLBK9torss07+8dl9UpY9z1N/zTeA1cIqdzMlpkV3MOOC7zukyvQfDyxa1s3Dl2+DeiP/G6DOw==} engines: {node: '>=16'} @@ -6879,6 +7075,13 @@ packages: rollup: ^3.29.4 || ^4 typescript: ^4.5 || ^5.0 + rollup-plugin-dts@6.3.0: + resolution: {integrity: sha512-d0UrqxYd8KyZ6i3M2Nx7WOMy708qsV/7fTHMHxCMCBOAe3V/U7OMPu5GkX8hC+cmkHhzGnfeYongl1IgiooddA==} + engines: {node: '>=16'} + peerDependencies: + rollup: ^3.29.4 || ^4 + typescript: ^4.5 || ^5.0 + rollup-plugin-polyfill-node@0.13.0: resolution: {integrity: sha512-FYEvpCaD5jGtyBuBFcQImEGmTxDTPbiHjJdrYIp+mFIwgXiXabxvKUK7ZT9P31ozu2Tqm9llYQMRWsfvTMTAOw==} peerDependencies: @@ -6895,11 +7098,6 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - rollup@4.34.8: - resolution: {integrity: sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - rollup@4.50.0: resolution: {integrity: sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -7064,16 +7262,20 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - sass@1.85.0: - resolution: {integrity: sha512-3ToiC1xZ1Y8aU7+CkgCI/tqyuPXEmYGJXO7H4uqp0xkLXUqp88rQQ4j1HmP37xSJLbCJPaIiv+cT1y+grssrww==} + sass@1.92.1: + resolution: {integrity: sha512-ffmsdbwqb3XeyR8jJR6KelIXARM9bFQe8A6Q3W4Klmwy5Ckd5gz7jgUNHo4UOqutU5Sk1DtKLbpDP0nLCg1xqQ==} engines: {node: '>=14.0.0'} hasBin: true - sass@1.92.1: - resolution: {integrity: sha512-ffmsdbwqb3XeyR8jJR6KelIXARM9bFQe8A6Q3W4Klmwy5Ckd5gz7jgUNHo4UOqutU5Sk1DtKLbpDP0nLCg1xqQ==} + sass@1.97.1: + resolution: {integrity: sha512-uf6HoO8fy6ClsrShvMgaKUn14f2EHQLQRtpsZZLeU/Mv0Q1K5P0+x2uvH6Cub39TVVbWNSrraUhDAoFph6vh0A==} engines: {node: '>=14.0.0'} hasBin: true + sax@1.4.4: + resolution: {integrity: sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==} + engines: {node: '>=11.0.0'} + saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} @@ -7097,11 +7299,6 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.7.1: - resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} - engines: {node: '>=10'} - hasBin: true - semver@7.7.2: resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} engines: {node: '>=10'} @@ -7203,10 +7400,6 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} - slice-ansi@5.0.0: - resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} - engines: {node: '>=12'} - slice-ansi@7.1.2: resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} engines: {node: '>=18'} @@ -7226,9 +7419,9 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} spawndamnit@3.0.1: resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} @@ -7267,6 +7460,10 @@ packages: std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + stdin-discarder@0.3.1: + resolution: {integrity: sha512-reExS1kSGoElkextOcPkel4NE99S0BWxjUHQeDFnR8S993JxpPX7KU4MNmO19NXhlJp+8dmdCbKQVNgLJh2teA==} + engines: {node: '>=18'} + stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -7290,6 +7487,10 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string-width@8.2.0: + resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} + engines: {node: '>=20'} + string.prototype.includes@2.0.1: resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} engines: {node: '>= 0.4'} @@ -7678,6 +7879,11 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + ufo@1.6.1: resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} @@ -7694,13 +7900,14 @@ packages: undici-types@7.8.0: resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + undici@7.20.0: + resolution: {integrity: sha512-MJZrkjyd7DeC+uPZh+5/YaMDxFiiEEaDgbUSVMXayofAkDWF1088CDo+2RPg7B1BuS1qf1vgNE7xqwPxE0DuSQ==} + engines: {node: '>=20.18.1'} + undici@7.21.0: resolution: {integrity: sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg==} engines: {node: '>=20.18.1'} - unist-util-stringify-position@4.0.0: - resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} - universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -7719,6 +7926,12 @@ packages: peerDependencies: browserslist: '>= 4.21.0' + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -7747,12 +7960,6 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - vfile-message@4.0.3: - resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} - - vfile@6.0.3: - resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite-node@3.0.8: resolution: {integrity: sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -7763,8 +7970,8 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true - vite@6.2.0: - resolution: {integrity: sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==} + vite@6.4.1: + resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -7803,19 +8010,19 @@ packages: yaml: 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.1.12: + resolution: {integrity: sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==} + 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 @@ -7843,8 +8050,8 @@ packages: yaml: optional: true - vite@7.1.12: - resolution: {integrity: sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==} + vite@7.3.0: + resolution: {integrity: sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -7975,8 +8182,8 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} - watchpack@2.4.2: - resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} + watchpack@2.5.0: + resolution: {integrity: sha512-e6vZvY6xboSwLz2GD36c16+O/2Z6fKvIf4pOXptw2rY9MVwE/TXc6RGqxD3I3x0a28lwBY7DE+76uTPSsBrrCA==} engines: {node: '>=10.13.0'} wcwidth@1.0.1: @@ -8143,10 +8350,18 @@ packages: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yargs@18.0.0: + resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -8155,8 +8370,12 @@ packages: resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} engines: {node: '>=18'} - zone.js@0.15.0: - resolution: {integrity: sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA==} + yoctocolors@2.1.2: + resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + engines: {node: '>=18'} + + zone.js@0.16.1: + resolution: {integrity: sha512-dpvY17vxYIW3+bNrP0ClUlaiY0CiIRK3tnoLaGoQsQcY9/I/NpzIWQ7tQNhbV7LacQMpCII6wVzuL3tuWOyfuA==} snapshots: @@ -8167,64 +8386,70 @@ snapshots: '@jridgewell/gen-mapping': 0.3.12 '@jridgewell/trace-mapping': 0.3.29 - '@analogjs/vite-plugin-angular@1.16.2(@angular/build@19.2.4(@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3))(@angular/compiler@19.2.4)(@types/node@24.0.3)(chokidar@4.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.0))': + '@analogjs/vite-plugin-angular@2.2.3(@angular/build@21.1.4(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(@angular/compiler@21.1.5)(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)))(@types/node@24.0.3)(chokidar@5.0.0)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(ng-packagr@21.1.0(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(tailwindcss@4.1.8)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.0))(typescript@5.9.3)': dependencies: ts-morph: 21.0.1 - vfile: 6.0.3 + typescript: 5.9.3 optionalDependencies: - '@angular/build': 19.2.4(@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3))(@angular/compiler@19.2.4)(@types/node@24.0.3)(chokidar@4.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.0) + '@angular/build': 21.1.4(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(@angular/compiler@21.1.5)(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)))(@types/node@24.0.3)(chokidar@5.0.0)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(ng-packagr@21.1.0(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(tailwindcss@4.1.8)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.0) - '@angular-devkit/architect@0.1902.4(chokidar@4.0.3)': + '@angular-devkit/architect@0.2101.4(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 19.2.4(chokidar@4.0.3) - rxjs: 7.8.1 + '@angular-devkit/core': 21.1.4(chokidar@5.0.0) + rxjs: 7.8.2 transitivePeerDependencies: - chokidar - '@angular-devkit/core@19.2.4(chokidar@4.0.3)': + '@angular-devkit/core@21.1.4(chokidar@5.0.0)': dependencies: ajv: 8.17.1 ajv-formats: 3.0.1(ajv@8.17.1) jsonc-parser: 3.3.1 - picomatch: 4.0.2 - rxjs: 7.8.1 - source-map: 0.7.4 + picomatch: 4.0.3 + rxjs: 7.8.2 + source-map: 0.7.6 optionalDependencies: - chokidar: 4.0.3 + chokidar: 5.0.0 - '@angular/build@19.2.4(@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3))(@angular/compiler@19.2.4)(@types/node@24.0.3)(chokidar@4.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(yaml@2.8.0)': + '@angular/build@21.1.4(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(@angular/compiler@21.1.5)(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)))(@types/node@24.0.3)(chokidar@5.0.0)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(ng-packagr@21.1.0(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(tailwindcss@4.1.8)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.6)(sass-embedded@1.92.1)(tailwindcss@4.1.8)(terser@5.39.2)(tslib@2.8.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.0)': dependencies: '@ampproject/remapping': 2.3.0 - '@angular-devkit/architect': 0.1902.4(chokidar@4.0.3) - '@angular/compiler': 19.2.4 - '@angular/compiler-cli': 19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3) - '@babel/core': 7.26.10 - '@babel/helper-annotate-as-pure': 7.25.9 + '@angular-devkit/architect': 0.2101.4(chokidar@5.0.0) + '@angular/compiler': 21.1.5 + '@angular/compiler-cli': 21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3) + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-split-export-declaration': 7.24.7 - '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.10) - '@inquirer/confirm': 5.1.6(@types/node@24.0.3) - '@vitejs/plugin-basic-ssl': 1.2.0(vite@6.2.0(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) - beasties: 0.2.0 - browserslist: 4.24.5 - esbuild: 0.25.1 - fast-glob: 3.3.3 + '@inquirer/confirm': 5.1.21(@types/node@24.0.3) + '@vitejs/plugin-basic-ssl': 2.1.0(vite@7.3.0(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + beasties: 0.3.5 + browserslist: 4.28.1 + esbuild: 0.27.2 https-proxy-agent: 7.0.6 istanbul-lib-instrument: 6.0.3 - listr2: 8.2.5 - magic-string: 0.30.17 + jsonc-parser: 3.3.1 + listr2: 9.0.5 + magic-string: 0.30.21 mrmime: 2.0.1 - parse5-html-rewriting-stream: 7.0.0 - picomatch: 4.0.2 - piscina: 4.8.0 - rollup: 4.34.8 - sass: 1.85.0 - semver: 7.7.1 + parse5-html-rewriting-stream: 8.0.0 + picomatch: 4.0.3 + piscina: 5.1.4 + rolldown: 1.0.0-beta.58 + sass: 1.97.1 + semver: 7.7.3 source-map-support: 0.5.21 - typescript: 5.8.3 - vite: 6.2.0(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) - watchpack: 2.4.2 + tinyglobby: 0.2.15 + tslib: 2.8.1 + typescript: 5.9.3 + undici: 7.20.0 + vite: 7.3.0(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + watchpack: 2.5.0 optionalDependencies: - lmdb: 3.2.6 + '@angular/core': 21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1) + '@angular/platform-browser': 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)) + less: 4.5.1 + lmdb: 3.4.4 + ng-packagr: 21.1.0(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(tailwindcss@4.1.8)(tslib@2.8.1)(typescript@5.9.3) postcss: 8.5.6 tailwindcss: 4.1.8 transitivePeerDependencies: @@ -8240,91 +8465,96 @@ snapshots: - tsx - yaml - '@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)': + '@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1)': dependencies: - '@angular/core': 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) + '@angular/core': 21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1) rxjs: 7.8.1 tslib: 2.8.1 - '@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)': + '@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2)': dependencies: - '@angular/core': 21.1.5(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/core': 21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/compiler-cli@19.2.4(@angular/compiler@19.2.4)(typescript@5.8.3)': + '@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3)': dependencies: - '@angular/compiler': 19.2.4 - '@babel/core': 7.26.9 + '@angular/compiler': 21.1.5 + '@babel/core': 7.28.5 '@jridgewell/sourcemap-codec': 1.5.5 - chokidar: 4.0.3 + chokidar: 5.0.0 convert-source-map: 1.9.0 reflect-metadata: 0.2.2 semver: 7.7.3 tslib: 2.8.1 - typescript: 5.8.3 - yargs: 17.7.2 + yargs: 18.0.0 + optionalDependencies: + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@angular/compiler@19.2.4': + '@angular/compiler@21.1.5': dependencies: tslib: 2.8.1 - '@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)': + '@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)': dependencies: rxjs: 7.8.1 tslib: 2.8.1 - zone.js: 0.15.0 + optionalDependencies: + '@angular/compiler': 21.1.5 + zone.js: 0.16.1 - '@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0)': + '@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1)': dependencies: rxjs: 7.8.2 tslib: 2.8.1 optionalDependencies: - zone.js: 0.15.0 + '@angular/compiler': 21.1.5 + zone.js: 0.16.1 - '@angular/forms@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)': + '@angular/forms@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)))(rxjs@7.8.1)': dependencies: - '@angular/common': 19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1) - '@angular/core': 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) - '@angular/platform-browser': 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)) + '@angular/common': 21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1) + '@angular/core': 21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1) + '@angular/platform-browser': 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)) + '@standard-schema/spec': 1.1.0 rxjs: 7.8.1 tslib: 2.8.1 - '@angular/platform-browser-dynamic@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/compiler@19.2.4)(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)))': + '@angular/platform-browser-dynamic@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/compiler@21.1.5)(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)))': dependencies: - '@angular/common': 19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1) - '@angular/compiler': 19.2.4 - '@angular/core': 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) - '@angular/platform-browser': 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)) + '@angular/common': 21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1) + '@angular/compiler': 21.1.5 + '@angular/core': 21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1) + '@angular/platform-browser': 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)) tslib: 2.8.1 - '@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))': + '@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))': dependencies: - '@angular/common': 19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1) - '@angular/core': 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) + '@angular/common': 21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1) + '@angular/core': 21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1) tslib: 2.8.1 - '@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))': + '@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))': dependencies: - '@angular/common': 21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) - '@angular/core': 21.1.5(rxjs@7.8.2)(zone.js@0.15.0) + '@angular/common': 21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/core': 21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1) tslib: 2.8.1 - '@angular/router@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)': + '@angular/router@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)))(rxjs@7.8.1)': dependencies: - '@angular/common': 19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1) - '@angular/core': 19.2.4(rxjs@7.8.1)(zone.js@0.15.0) - '@angular/platform-browser': 19.2.4(@angular/common@19.2.4(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.2.4(rxjs@7.8.1)(zone.js@0.15.0)) + '@angular/common': 21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1) + '@angular/core': 21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1) + '@angular/platform-browser': 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1))(rxjs@7.8.1))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.1)(zone.js@0.16.1)) rxjs: 7.8.1 tslib: 2.8.1 - '@angular/router@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2)': + '@angular/router@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(@angular/platform-browser@21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1)))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2) - '@angular/core': 21.1.5(rxjs@7.8.2)(zone.js@0.15.0) - '@angular/platform-browser': 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@21.1.5(rxjs@7.8.2)(zone.js@0.15.0)) + '@angular/common': 21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2) + '@angular/core': 21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1) + '@angular/platform-browser': 21.1.5(@angular/common@21.1.5(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1))(rxjs@7.8.2))(@angular/core@21.1.5(@angular/compiler@21.1.5)(rxjs@7.8.2)(zone.js@0.16.1)) rxjs: 7.8.2 tslib: 2.8.1 @@ -8382,40 +8612,46 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/compat-data@7.27.2': {} - '@babel/core@7.26.10': + '@babel/core@7.27.1': dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.27.1 '@babel/generator': 7.27.1 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.27.1(@babel/core@7.26.10) + '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) '@babel/helpers': 7.27.1 '@babel/parser': 7.27.2 '@babel/template': 7.27.2 '@babel/traverse': 7.27.1 '@babel/types': 7.27.1 convert-source-map: 2.0.0 - debug: 4.4.3 + debug: 4.4.1 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/core@7.26.9': + '@babel/core@7.28.5': dependencies: - '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.1 + '@babel/generator': 7.29.1 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.27.1(@babel/core@7.26.9) - '@babel/helpers': 7.27.1 - '@babel/parser': 7.27.2 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.5) + '@babel/helpers': 7.28.6 + '@babel/parser': 7.29.0 '@babel/template': 7.27.2 - '@babel/traverse': 7.27.1 - '@babel/types': 7.27.1 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 gensync: 1.0.0-beta.2 @@ -8424,26 +8660,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/core@7.27.1': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.1 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) - '@babel/helpers': 7.27.1 - '@babel/parser': 7.27.2 - '@babel/template': 7.27.2 - '@babel/traverse': 7.27.1 - '@babel/types': 7.27.1 - convert-source-map: 2.0.0 - debug: 4.4.1 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - '@babel/eslint-parser@7.28.5(@babel/core@7.27.1)(eslint@8.57.0)': dependencies: '@babel/core': 7.27.1 @@ -8460,9 +8676,17 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 - '@babel/helper-annotate-as-pure@7.25.9': + '@babel/generator@7.29.1': dependencies: - '@babel/types': 7.27.1 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.29.0 '@babel/helper-compilation-targets@7.27.2': dependencies: @@ -8472,6 +8696,8 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-globals@7.28.0': {} + '@babel/helper-module-imports@7.27.1': dependencies: '@babel/traverse': 7.27.1 @@ -8479,30 +8705,28 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.27.1(@babel/core@7.26.10)': + '@babel/helper-module-imports@7.28.6': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.27.1 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.27.1(@babel/core@7.26.9)': + '@babel/helper-module-transforms@7.27.1(@babel/core@7.27.1)': dependencies: - '@babel/core': 7.26.9 + '@babel/core': 7.27.1 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 '@babel/traverse': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.27.1(@babel/core@7.27.1)': + '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.27.1 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -8516,6 +8740,8 @@ snapshots: '@babel/helper-validator-identifier@7.27.1': {} + '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-option@7.27.1': {} '@babel/helpers@7.27.1': @@ -8523,14 +8749,18 @@ snapshots: '@babel/template': 7.27.2 '@babel/types': 7.27.1 + '@babel/helpers@7.28.6': + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + '@babel/parser@7.27.2': dependencies: '@babel/types': 7.27.1 - '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.10)': + '@babel/parser@7.29.0': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/types': 7.29.0 '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.27.1)': dependencies: @@ -8550,6 +8780,12 @@ snapshots: '@babel/parser': 7.27.2 '@babel/types': 7.27.1 + '@babel/template@7.28.6': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@babel/traverse@7.27.1': dependencies: '@babel/code-frame': 7.27.1 @@ -8562,11 +8798,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.0 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + '@babel/types@7.27.1': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@bcoe/v8-coverage@1.0.2': {} '@bufbuild/protobuf@2.7.0': @@ -8773,6 +9026,12 @@ snapshots: '@emnapi/wasi-threads': 1.0.2 tslib: 2.8.1 + '@emnapi/core@1.8.1': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.4.3': dependencies: tslib: 2.8.1 @@ -8786,6 +9045,11 @@ snapshots: dependencies: tslib: 2.8.1 + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + optional: true + '@emotion/babel-plugin@11.13.5': dependencies: '@babel/helper-module-imports': 7.27.1 @@ -8840,190 +9104,190 @@ snapshots: '@emotion/weak-memoize@0.4.0': {} - '@esbuild/aix-ppc64@0.25.1': + '@esbuild/aix-ppc64@0.25.9': optional: true - '@esbuild/aix-ppc64@0.25.9': + '@esbuild/aix-ppc64@0.27.2': optional: true '@esbuild/aix-ppc64@0.27.3': optional: true - '@esbuild/android-arm64@0.25.1': + '@esbuild/android-arm64@0.25.9': optional: true - '@esbuild/android-arm64@0.25.9': + '@esbuild/android-arm64@0.27.2': optional: true '@esbuild/android-arm64@0.27.3': optional: true - '@esbuild/android-arm@0.25.1': + '@esbuild/android-arm@0.25.9': optional: true - '@esbuild/android-arm@0.25.9': + '@esbuild/android-arm@0.27.2': optional: true '@esbuild/android-arm@0.27.3': optional: true - '@esbuild/android-x64@0.25.1': + '@esbuild/android-x64@0.25.9': optional: true - '@esbuild/android-x64@0.25.9': + '@esbuild/android-x64@0.27.2': optional: true '@esbuild/android-x64@0.27.3': optional: true - '@esbuild/darwin-arm64@0.25.1': + '@esbuild/darwin-arm64@0.25.9': optional: true - '@esbuild/darwin-arm64@0.25.9': + '@esbuild/darwin-arm64@0.27.2': optional: true '@esbuild/darwin-arm64@0.27.3': optional: true - '@esbuild/darwin-x64@0.25.1': + '@esbuild/darwin-x64@0.25.9': optional: true - '@esbuild/darwin-x64@0.25.9': + '@esbuild/darwin-x64@0.27.2': optional: true '@esbuild/darwin-x64@0.27.3': optional: true - '@esbuild/freebsd-arm64@0.25.1': + '@esbuild/freebsd-arm64@0.25.9': optional: true - '@esbuild/freebsd-arm64@0.25.9': + '@esbuild/freebsd-arm64@0.27.2': optional: true '@esbuild/freebsd-arm64@0.27.3': optional: true - '@esbuild/freebsd-x64@0.25.1': + '@esbuild/freebsd-x64@0.25.9': optional: true - '@esbuild/freebsd-x64@0.25.9': + '@esbuild/freebsd-x64@0.27.2': optional: true '@esbuild/freebsd-x64@0.27.3': optional: true - '@esbuild/linux-arm64@0.25.1': + '@esbuild/linux-arm64@0.25.9': optional: true - '@esbuild/linux-arm64@0.25.9': + '@esbuild/linux-arm64@0.27.2': optional: true '@esbuild/linux-arm64@0.27.3': optional: true - '@esbuild/linux-arm@0.25.1': + '@esbuild/linux-arm@0.25.9': optional: true - '@esbuild/linux-arm@0.25.9': + '@esbuild/linux-arm@0.27.2': optional: true '@esbuild/linux-arm@0.27.3': optional: true - '@esbuild/linux-ia32@0.25.1': + '@esbuild/linux-ia32@0.25.9': optional: true - '@esbuild/linux-ia32@0.25.9': + '@esbuild/linux-ia32@0.27.2': optional: true '@esbuild/linux-ia32@0.27.3': optional: true - '@esbuild/linux-loong64@0.25.1': + '@esbuild/linux-loong64@0.25.9': optional: true - '@esbuild/linux-loong64@0.25.9': + '@esbuild/linux-loong64@0.27.2': optional: true '@esbuild/linux-loong64@0.27.3': optional: true - '@esbuild/linux-mips64el@0.25.1': + '@esbuild/linux-mips64el@0.25.9': optional: true - '@esbuild/linux-mips64el@0.25.9': + '@esbuild/linux-mips64el@0.27.2': optional: true '@esbuild/linux-mips64el@0.27.3': optional: true - '@esbuild/linux-ppc64@0.25.1': + '@esbuild/linux-ppc64@0.25.9': optional: true - '@esbuild/linux-ppc64@0.25.9': + '@esbuild/linux-ppc64@0.27.2': optional: true '@esbuild/linux-ppc64@0.27.3': optional: true - '@esbuild/linux-riscv64@0.25.1': + '@esbuild/linux-riscv64@0.25.9': optional: true - '@esbuild/linux-riscv64@0.25.9': + '@esbuild/linux-riscv64@0.27.2': optional: true '@esbuild/linux-riscv64@0.27.3': optional: true - '@esbuild/linux-s390x@0.25.1': + '@esbuild/linux-s390x@0.25.9': optional: true - '@esbuild/linux-s390x@0.25.9': + '@esbuild/linux-s390x@0.27.2': optional: true '@esbuild/linux-s390x@0.27.3': optional: true - '@esbuild/linux-x64@0.25.1': + '@esbuild/linux-x64@0.25.9': optional: true - '@esbuild/linux-x64@0.25.9': + '@esbuild/linux-x64@0.27.2': optional: true '@esbuild/linux-x64@0.27.3': optional: true - '@esbuild/netbsd-arm64@0.25.1': + '@esbuild/netbsd-arm64@0.25.9': optional: true - '@esbuild/netbsd-arm64@0.25.9': + '@esbuild/netbsd-arm64@0.27.2': optional: true '@esbuild/netbsd-arm64@0.27.3': optional: true - '@esbuild/netbsd-x64@0.25.1': + '@esbuild/netbsd-x64@0.25.9': optional: true - '@esbuild/netbsd-x64@0.25.9': + '@esbuild/netbsd-x64@0.27.2': optional: true '@esbuild/netbsd-x64@0.27.3': optional: true - '@esbuild/openbsd-arm64@0.25.1': + '@esbuild/openbsd-arm64@0.25.9': optional: true - '@esbuild/openbsd-arm64@0.25.9': + '@esbuild/openbsd-arm64@0.27.2': optional: true '@esbuild/openbsd-arm64@0.27.3': optional: true - '@esbuild/openbsd-x64@0.25.1': + '@esbuild/openbsd-x64@0.25.9': optional: true - '@esbuild/openbsd-x64@0.25.9': + '@esbuild/openbsd-x64@0.27.2': optional: true '@esbuild/openbsd-x64@0.27.3': @@ -9032,42 +9296,45 @@ snapshots: '@esbuild/openharmony-arm64@0.25.9': optional: true - '@esbuild/openharmony-arm64@0.27.3': + '@esbuild/openharmony-arm64@0.27.2': optional: true - '@esbuild/sunos-x64@0.25.1': + '@esbuild/openharmony-arm64@0.27.3': optional: true '@esbuild/sunos-x64@0.25.9': optional: true - '@esbuild/sunos-x64@0.27.3': + '@esbuild/sunos-x64@0.27.2': optional: true - '@esbuild/win32-arm64@0.25.1': + '@esbuild/sunos-x64@0.27.3': optional: true '@esbuild/win32-arm64@0.25.9': optional: true - '@esbuild/win32-arm64@0.27.3': + '@esbuild/win32-arm64@0.27.2': optional: true - '@esbuild/win32-ia32@0.25.1': + '@esbuild/win32-arm64@0.27.3': optional: true '@esbuild/win32-ia32@0.25.9': optional: true - '@esbuild/win32-ia32@0.27.3': + '@esbuild/win32-ia32@0.27.2': optional: true - '@esbuild/win32-x64@0.25.1': + '@esbuild/win32-ia32@0.27.3': optional: true '@esbuild/win32-x64@0.25.9': optional: true + '@esbuild/win32-x64@0.27.2': + optional: true + '@esbuild/win32-x64@0.27.3': optional: true @@ -9289,7 +9556,7 @@ snapshots: '@inquirer/ansi@1.0.2': {} - '@inquirer/confirm@5.1.6(@types/node@24.0.3)': + '@inquirer/confirm@5.1.21(@types/node@24.0.3)': dependencies: '@inquirer/core': 10.3.2(@types/node@24.0.3) '@inquirer/type': 3.0.10(@types/node@24.0.3) @@ -9358,6 +9625,11 @@ snapshots: '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/set-array@1.2.1': {} @@ -9384,22 +9656,25 @@ snapshots: '@jspm/core@2.1.0': {} - '@lmdb/lmdb-darwin-arm64@3.2.6': + '@lmdb/lmdb-darwin-arm64@3.4.4': optional: true - '@lmdb/lmdb-darwin-x64@3.2.6': + '@lmdb/lmdb-darwin-x64@3.4.4': optional: true - '@lmdb/lmdb-linux-arm64@3.2.6': + '@lmdb/lmdb-linux-arm64@3.4.4': optional: true - '@lmdb/lmdb-linux-arm@3.2.6': + '@lmdb/lmdb-linux-arm@3.4.4': optional: true - '@lmdb/lmdb-linux-x64@3.2.6': + '@lmdb/lmdb-linux-x64@3.4.4': optional: true - '@lmdb/lmdb-win32-x64@3.2.6': + '@lmdb/lmdb-win32-arm64@3.4.4': + optional: true + + '@lmdb/lmdb-win32-x64@3.4.4': optional: true '@manypkg/find-root@1.1.0': @@ -9523,6 +9798,13 @@ snapshots: '@emnapi/runtime': 1.4.3 '@tybys/wasm-util': 0.9.0 + '@napi-rs/wasm-runtime@1.1.1': + dependencies: + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 + '@tybys/wasm-util': 0.10.1 + optional: true + '@next/env@15.5.12': {} '@next/eslint-plugin-next@13.5.11': @@ -9601,6 +9883,8 @@ snapshots: '@one-ini/wasm@0.1.1': {} + '@oxc-project/types@0.106.0': {} + '@parcel/watcher-android-arm64@2.5.1': optional: true @@ -9704,6 +9988,49 @@ snapshots: optionalDependencies: '@types/react': 19.1.5 + '@rolldown/binding-android-arm64@1.0.0-beta.58': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-beta.58': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-beta.58': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-beta.58': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.58': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.58': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.58': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.58': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.58': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.58': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.58': + dependencies: + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.58': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.58': + optional: true + + '@rolldown/pluginutils@1.0.0-beta.58': {} + '@rollup/plugin-commonjs@25.0.7(rollup@4.32.0)': dependencies: '@rollup/pluginutils': 5.1.4(rollup@4.32.0) @@ -9730,6 +10057,12 @@ snapshots: optionalDependencies: rollup: 4.32.0 + '@rollup/plugin-json@6.1.0(rollup@4.32.0)': + dependencies: + '@rollup/pluginutils': 5.1.4(rollup@4.32.0) + optionalDependencies: + rollup: 4.32.0 + '@rollup/plugin-node-resolve@15.2.3(rollup@4.32.0)': dependencies: '@rollup/pluginutils': 5.1.4(rollup@4.32.0) @@ -9766,117 +10099,78 @@ snapshots: '@rollup/rollup-android-arm-eabi@4.32.0': optional: true - '@rollup/rollup-android-arm-eabi@4.34.8': - optional: true - '@rollup/rollup-android-arm-eabi@4.50.0': optional: true '@rollup/rollup-android-arm64@4.32.0': optional: true - '@rollup/rollup-android-arm64@4.34.8': - optional: true - '@rollup/rollup-android-arm64@4.50.0': optional: true '@rollup/rollup-darwin-arm64@4.32.0': optional: true - '@rollup/rollup-darwin-arm64@4.34.8': - optional: true - '@rollup/rollup-darwin-arm64@4.50.0': optional: true '@rollup/rollup-darwin-x64@4.32.0': optional: true - '@rollup/rollup-darwin-x64@4.34.8': - optional: true - '@rollup/rollup-darwin-x64@4.50.0': optional: true '@rollup/rollup-freebsd-arm64@4.32.0': optional: true - '@rollup/rollup-freebsd-arm64@4.34.8': - optional: true - '@rollup/rollup-freebsd-arm64@4.50.0': optional: true '@rollup/rollup-freebsd-x64@4.32.0': optional: true - '@rollup/rollup-freebsd-x64@4.34.8': - optional: true - '@rollup/rollup-freebsd-x64@4.50.0': optional: true '@rollup/rollup-linux-arm-gnueabihf@4.32.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.34.8': - optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.50.0': optional: true '@rollup/rollup-linux-arm-musleabihf@4.32.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.34.8': - optional: true - '@rollup/rollup-linux-arm-musleabihf@4.50.0': optional: true '@rollup/rollup-linux-arm64-gnu@4.32.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.34.8': - optional: true - '@rollup/rollup-linux-arm64-gnu@4.50.0': optional: true '@rollup/rollup-linux-arm64-musl@4.32.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.34.8': - optional: true - '@rollup/rollup-linux-arm64-musl@4.50.0': optional: true '@rollup/rollup-linux-loongarch64-gnu@4.32.0': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.34.8': - optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.50.0': optional: true '@rollup/rollup-linux-powerpc64le-gnu@4.32.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': - optional: true - '@rollup/rollup-linux-ppc64-gnu@4.50.0': optional: true '@rollup/rollup-linux-riscv64-gnu@4.32.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.34.8': - optional: true - '@rollup/rollup-linux-riscv64-gnu@4.50.0': optional: true @@ -9886,27 +10180,18 @@ snapshots: '@rollup/rollup-linux-s390x-gnu@4.32.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.34.8': - optional: true - '@rollup/rollup-linux-s390x-gnu@4.50.0': optional: true '@rollup/rollup-linux-x64-gnu@4.32.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.34.8': - optional: true - '@rollup/rollup-linux-x64-gnu@4.50.0': optional: true '@rollup/rollup-linux-x64-musl@4.32.0': optional: true - '@rollup/rollup-linux-x64-musl@4.34.8': - optional: true - '@rollup/rollup-linux-x64-musl@4.50.0': optional: true @@ -9916,34 +10201,33 @@ snapshots: '@rollup/rollup-win32-arm64-msvc@4.32.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.34.8': - optional: true - '@rollup/rollup-win32-arm64-msvc@4.50.0': optional: true '@rollup/rollup-win32-ia32-msvc@4.32.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.34.8': - optional: true - '@rollup/rollup-win32-ia32-msvc@4.50.0': optional: true '@rollup/rollup-win32-x64-msvc@4.32.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.34.8': - optional: true - '@rollup/rollup-win32-x64-msvc@4.50.0': optional: true + '@rollup/wasm-node@4.58.0': + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + '@rtsao/scc@1.1.0': {} '@sinclair/typebox@0.27.8': {} + '@standard-schema/spec@1.1.0': {} + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -10012,19 +10296,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.8 '@tailwindcss/oxide-win32-x64-msvc': 4.1.8 - '@tailwindcss/vite@4.1.8(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + '@tailwindcss/vite@4.1.8(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': dependencies: '@tailwindcss/node': 4.1.8 '@tailwindcss/oxide': 4.1.8 tailwindcss: 4.1.8 - vite: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) - - '@tailwindcss/vite@4.1.8(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': - dependencies: - '@tailwindcss/node': 4.1.8 - '@tailwindcss/oxide': 4.1.8 - tailwindcss: 4.1.8 - vite: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) '@tanstack/history@1.154.7': {} @@ -10102,6 +10379,11 @@ snapshots: mkdirp: 3.0.1 path-browserify: 1.0.1 + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + '@tybys/wasm-util@0.9.0': dependencies: tslib: 2.8.1 @@ -10187,8 +10469,6 @@ snapshots: '@types/trusted-types@2.0.7': optional: true - '@types/unist@3.0.3': {} - '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -10229,6 +10509,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.0)(typescript@5.9.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.4.3 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + semver: 7.7.3 + ts-api-utils: 1.4.3(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.25.0(jiti@2.6.0))(typescript@5.8.3))(eslint@9.25.0(jiti@2.6.0))(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -10262,6 +10562,14 @@ snapshots: - supports-color - typescript + '@typescript-eslint/experimental-utils@5.62.0(eslint@8.57.0)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.9.3) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6)': dependencies: '@typescript-eslint/scope-manager': 6.21.0 @@ -10288,6 +10596,19 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.4.3 + eslint: 8.57.0 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@8.30.1(eslint@9.25.0(jiti@2.6.0))(typescript@5.8.3)': dependencies: '@typescript-eslint/scope-manager': 8.30.1 @@ -10339,6 +10660,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@6.21.0(eslint@8.57.0)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.9.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.9.3) + debug: 4.4.3 + eslint: 8.57.0 + ts-api-utils: 1.4.3(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/type-utils@8.30.1(eslint@9.25.0(jiti@2.6.0))(typescript@5.8.3)': dependencies: '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) @@ -10384,6 +10717,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + debug: 4.4.3 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.7.3 + tsutils: 3.21.0(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/typescript-estree@6.21.0(typescript@5.1.6)': dependencies: '@typescript-eslint/types': 6.21.0 @@ -10414,6 +10761,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@6.21.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.4.3 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.7.3 + ts-api-utils: 1.4.3(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/typescript-estree@8.30.1(typescript@5.8.3)': dependencies: '@typescript-eslint/types': 8.30.1 @@ -10458,6 +10820,21 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.7.0 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.9.3) + eslint: 8.57.0 + eslint-scope: 5.1.1 + semver: 7.7.3 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.1.6)': dependencies: '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0) @@ -10486,6 +10863,20 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.7.0 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.9.3) + eslint: 8.57.0 + semver: 7.7.3 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/utils@8.30.1(eslint@9.25.0(jiti@2.6.0))(typescript@5.8.3)': dependencies: '@eslint-community/eslint-utils': 4.8.0(eslint@9.25.0(jiti@2.6.0)) @@ -10514,44 +10905,40 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@vitejs/plugin-basic-ssl@1.2.0(vite@6.2.0(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': - dependencies: - vite: 6.2.0(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) - - '@vitejs/plugin-basic-ssl@2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + '@vitejs/plugin-basic-ssl@2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': dependencies: - vite: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) - '@vitejs/plugin-basic-ssl@2.0.0(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + '@vitejs/plugin-basic-ssl@2.1.0(vite@7.3.0(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': dependencies: - vite: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 7.3.0(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) - '@vitejs/plugin-react@4.4.1(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + '@vitejs/plugin-react@4.4.1(vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': dependencies: '@babel/core': 7.27.1 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.1) '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.27.1) '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@5.2.4(vite@7.1.12(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vue@3.5.13(typescript@5.1.6))': + '@vitejs/plugin-vue@5.2.4(vite@7.1.12(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vue@3.5.13(typescript@5.1.6))': dependencies: - vite: 7.1.12(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 7.1.12(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) vue: 3.5.13(typescript@5.1.6) - '@vitest/browser@3.1.3(playwright@1.55.1)(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3)': + '@vitest/browser@3.1.3(playwright@1.55.1)(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3)': dependencies: '@testing-library/dom': 10.4.0 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) - '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitest/utils': 3.1.3 magic-string: 0.30.17 sirv: 3.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vitest: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) ws: 8.18.2 optionalDependencies: playwright: 1.55.1 @@ -10561,16 +10948,16 @@ snapshots: - utf-8-validate - vite - '@vitest/browser@3.1.3(playwright@1.58.2)(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3)': + '@vitest/browser@3.1.3(playwright@1.58.2)(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3)': dependencies: '@testing-library/dom': 10.4.0 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) - '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitest/utils': 3.1.3 magic-string: 0.30.17 sirv: 3.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@26.1.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vitest: 3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@26.1.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) ws: 8.18.2 optionalDependencies: playwright: 1.58.2 @@ -10581,16 +10968,16 @@ snapshots: - vite optional: true - '@vitest/browser@3.1.3(playwright@1.58.2)(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3)': + '@vitest/browser@3.1.3(playwright@1.58.2)(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3)': dependencies: '@testing-library/dom': 10.4.0 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) - '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitest/utils': 3.1.3 magic-string: 0.30.17 sirv: 3.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.3(@types/node@22.15.30)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vitest: 3.1.3(@types/node@22.15.30)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) ws: 8.18.2 optionalDependencies: playwright: 1.58.2 @@ -10601,7 +10988,7 @@ snapshots: - vite optional: true - '@vitest/coverage-v8@3.0.8(vitest@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + '@vitest/coverage-v8@3.0.8(vitest@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -10615,7 +11002,7 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vitest: 3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) transitivePeerDependencies: - supports-color @@ -10633,29 +11020,29 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.0.8(vite@6.4.1(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + '@vitest/mocker@3.0.8(vite@6.4.1(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': dependencies: '@vitest/spy': 3.0.8 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.4.1(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) - '@vitest/mocker@3.1.3(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + '@vitest/mocker@3.1.3(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': dependencies: '@vitest/spy': 3.1.3 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) - '@vitest/mocker@3.1.3(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + '@vitest/mocker@3.1.3(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': dependencies: '@vitest/spy': 3.1.3 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.4.1(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@22.15.30)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) '@vitest/pretty-format@3.0.8': dependencies: @@ -10707,10 +11094,10 @@ snapshots: loupe: 3.1.3 tinyrainbow: 2.0.0 - '@vitest/web-worker@3.0.8(vitest@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': + '@vitest/web-worker@3.0.8(vitest@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))': dependencies: debug: 4.4.1 - vitest: 3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vitest: 3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) transitivePeerDependencies: - supports-color @@ -10894,13 +11281,47 @@ snapshots: eslint-plugin-prettier: 4.2.5(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.6.2) eslint-plugin-react: 7.37.5(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) - eslint-plugin-testing-library: 5.11.1(eslint@8.57.0)(typescript@5.7.2) + eslint-plugin-testing-library: 5.11.1(eslint@8.57.0)(typescript@5.7.2) + eslint-plugin-tsdoc: 0.2.17 + eslint-plugin-typescript-sort-keys: 2.3.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2) + prettier: 2.6.2 + requireindex: 1.2.0 + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - jest + - supports-color + + '@wso2/eslint-plugin@https://codeload.github.com/brionmario/wso2-ui-configs/tar.gz/d3041825a4f8f235c8f9fa36b55cf29d54e791c8#path:packages/eslint-plugin(eslint@8.57.0)(typescript@5.9.3)': + dependencies: + '@babel/core': 7.27.1 + '@babel/eslint-parser': 7.28.5(@babel/core@7.27.1)(eslint@8.57.0) + '@next/eslint-plugin-next': 13.5.11 + '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3) + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.9.3) + eslint: 8.57.0 + eslint-config-airbnb: 19.0.4(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.0))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.37.5(eslint@8.57.0))(eslint@8.57.0) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0))(eslint@8.57.0) + eslint-config-airbnb-typescript: 17.1.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0))(eslint@8.57.0) + eslint-config-prettier: 8.10.0(eslint@8.57.0) + eslint-plugin-eslint-plugin: 5.5.1(eslint@8.57.0) + eslint-plugin-header: 3.1.1(eslint@8.57.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0) + eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3) + eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.0) + eslint-plugin-node: 11.1.0(eslint@8.57.0) + eslint-plugin-prettier: 4.2.5(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.6.2) + eslint-plugin-react: 7.37.5(eslint@8.57.0) + eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) + eslint-plugin-testing-library: 5.11.1(eslint@8.57.0)(typescript@5.9.3) eslint-plugin-tsdoc: 0.2.17 - eslint-plugin-typescript-sort-keys: 2.3.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0)(typescript@5.7.2) + eslint-plugin-typescript-sort-keys: 2.3.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3) prettier: 2.6.2 requireindex: 1.2.0 optionalDependencies: - typescript: 5.7.2 + typescript: 5.9.3 transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -10919,6 +11340,12 @@ snapshots: optionalDependencies: typescript: 5.7.2 + '@wso2/prettier-config@https://codeload.github.com/brionmario/wso2-ui-configs/tar.gz/d3041825a4f8f235c8f9fa36b55cf29d54e791c8#path:packages/prettier-config(prettier@2.6.2)(typescript@5.9.3)': + dependencies: + prettier: 2.6.2 + optionalDependencies: + typescript: 5.9.3 + '@wso2/stylelint-config@https://codeload.github.com/brionmario/wso2-ui-configs/tar.gz/d3041825a4f8f235c8f9fa36b55cf29d54e791c8#path:packages/stylelint-config(postcss@8.5.6)(stylelint@15.1.0(typescript@5.1.6))(typescript@5.1.6)': dependencies: postcss-scss: 4.0.9(postcss@8.5.6) @@ -11135,13 +11562,15 @@ snapshots: base64url@3.0.1: {} - beasties@0.2.0: + baseline-browser-mapping@2.10.0: {} + + beasties@0.3.5: dependencies: - css-select: 5.2.2 - css-what: 6.1.0 + css-select: 6.0.0 + css-what: 7.0.0 dom-serializer: 2.0.0 domhandler: 5.0.3 - htmlparser2: 9.1.0 + htmlparser2: 10.1.0 picocolors: 1.1.1 postcss: 8.5.6 postcss-media-query-parser: 0.2.3 @@ -11240,6 +11669,14 @@ snapshots: node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.5) + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.10.0 + caniuse-lite: 1.0.30001770 + electron-to-chromium: 1.5.302 + node-releases: 2.0.27 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + buffer-builder@0.2.0: optional: true @@ -11299,6 +11736,8 @@ snapshots: caniuse-lite@1.0.30001718: {} + caniuse-lite@1.0.30001770: {} + chai@5.2.0: dependencies: assertion-error: 2.0.1 @@ -11312,6 +11751,8 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chalk@5.6.2: {} + chardet@2.1.1: {} check-error@2.1.1: {} @@ -11332,6 +11773,10 @@ snapshots: dependencies: readdirp: 4.1.2 + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + chownr@3.0.0: {} ci-info@3.9.0: {} @@ -11355,10 +11800,12 @@ snapshots: cli-spinners@2.6.1: {} - cli-truncate@4.0.0: + cli-spinners@3.4.0: {} + + cli-truncate@5.1.1: dependencies: - slice-ansi: 5.0.0 - string-width: 7.2.0 + slice-ansi: 7.1.2 + string-width: 8.2.0 cli-width@4.1.0: {} @@ -11370,6 +11817,12 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + cliui@9.0.1: + dependencies: + string-width: 7.2.0 + strip-ansi: 7.1.2 + wrap-ansi: 9.0.2 + clone@1.0.4: {} clsx@2.1.1: {} @@ -11395,11 +11848,15 @@ snapshots: commander@10.0.1: {} + commander@14.0.3: {} + commander@2.20.3: optional: true commander@7.2.0: {} + common-path-prefix@3.0.0: {} + commondir@1.0.1: {} confbox@0.1.8: {} @@ -11431,6 +11888,10 @@ snapshots: cookie@1.0.2: {} + copy-anything@2.0.6: + dependencies: + is-what: 3.14.1 + core-js@3.42.0: {} core-util-is@1.0.3: {} @@ -11522,10 +11983,10 @@ snapshots: domutils: 2.8.0 nth-check: 2.1.1 - css-select@5.2.2: + css-select@6.0.0: dependencies: boolbase: 1.0.0 - css-what: 6.1.0 + css-what: 7.0.0 domhandler: 5.0.3 domutils: 3.2.2 nth-check: 2.1.1 @@ -11547,6 +12008,8 @@ snapshots: css-what@6.1.0: {} + css-what@7.0.0: {} + cssesc@3.0.0: {} cssnano-preset-default@5.2.14(postcss@8.4.31): @@ -11696,6 +12159,8 @@ snapshots: depd@2.0.0: {} + dependency-graph@1.0.0: {} + dequal@2.0.3: {} des.js@1.1.0: @@ -11799,6 +12264,8 @@ snapshots: electron-to-chromium@1.5.155: {} + electron-to-chromium@1.5.302: {} + elliptic@6.6.1: dependencies: bn.js: 4.12.2 @@ -11841,8 +12308,15 @@ snapshots: entities@6.0.0: {} + entities@7.0.1: {} + environment@1.1.0: {} + errno@0.1.8: + dependencies: + prr: 1.0.1 + optional: true + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -11972,34 +12446,6 @@ snapshots: local-pkg: 1.1.1 resolve.exports: 2.0.3 - esbuild@0.25.1: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.1 - '@esbuild/android-arm': 0.25.1 - '@esbuild/android-arm64': 0.25.1 - '@esbuild/android-x64': 0.25.1 - '@esbuild/darwin-arm64': 0.25.1 - '@esbuild/darwin-x64': 0.25.1 - '@esbuild/freebsd-arm64': 0.25.1 - '@esbuild/freebsd-x64': 0.25.1 - '@esbuild/linux-arm': 0.25.1 - '@esbuild/linux-arm64': 0.25.1 - '@esbuild/linux-ia32': 0.25.1 - '@esbuild/linux-loong64': 0.25.1 - '@esbuild/linux-mips64el': 0.25.1 - '@esbuild/linux-ppc64': 0.25.1 - '@esbuild/linux-riscv64': 0.25.1 - '@esbuild/linux-s390x': 0.25.1 - '@esbuild/linux-x64': 0.25.1 - '@esbuild/netbsd-arm64': 0.25.1 - '@esbuild/netbsd-x64': 0.25.1 - '@esbuild/openbsd-arm64': 0.25.1 - '@esbuild/openbsd-x64': 0.25.1 - '@esbuild/sunos-x64': 0.25.1 - '@esbuild/win32-arm64': 0.25.1 - '@esbuild/win32-ia32': 0.25.1 - '@esbuild/win32-x64': 0.25.1 - esbuild@0.25.9: optionalDependencies: '@esbuild/aix-ppc64': 0.25.9 @@ -12029,6 +12475,35 @@ snapshots: '@esbuild/win32-ia32': 0.25.9 '@esbuild/win32-x64': 0.25.9 + 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 + esbuild@0.27.3: optionalDependencies: '@esbuild/aix-ppc64': 0.27.3 @@ -12084,6 +12559,15 @@ snapshots: object.entries: 1.1.9 semver: 6.3.1 + eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0))(eslint@8.57.0): + dependencies: + confusing-browser-globals: 1.0.11 + eslint: 8.57.0 + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0) + object.assign: 4.1.7 + object.entries: 1.1.9 + semver: 6.3.1 + eslint-config-airbnb-typescript@17.1.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6))(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0))(eslint@8.57.0): dependencies: '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6) @@ -12100,6 +12584,14 @@ snapshots: eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint@8.57.0) + eslint-config-airbnb-typescript@17.1.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3))(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0))(eslint@8.57.0): + dependencies: + '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3) + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.9.3) + eslint: 8.57.0 + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0) + eslint-config-airbnb@19.0.4(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.0))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.37.5(eslint@8.57.0))(eslint@8.57.0): dependencies: eslint: 8.57.0 @@ -12122,6 +12614,17 @@ snapshots: object.assign: 4.1.7 object.entries: 1.1.9 + eslint-config-airbnb@19.0.4(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.0))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.37.5(eslint@8.57.0))(eslint@8.57.0): + dependencies: + eslint: 8.57.0 + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0) + eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.0) + eslint-plugin-react: 7.37.5(eslint@8.57.0) + eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) + object.assign: 4.1.7 + object.entries: 1.1.9 + eslint-config-prettier@8.10.0(eslint@8.57.0): dependencies: eslint: 8.57.0 @@ -12154,6 +12657,16 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.9.3) + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + eslint-plugin-es@3.0.1(eslint@8.57.0): dependencies: eslint: 8.57.0 @@ -12228,6 +12741,35 @@ snapshots: - eslint-import-resolver-webpack - supports-color + eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.9.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6))(eslint@8.57.0)(typescript@5.1.6): dependencies: '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.1.6) @@ -12248,6 +12790,16 @@ snapshots: - supports-color - typescript + eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3): + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.9.3) + eslint: 8.57.0 + optionalDependencies: + '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3) + transitivePeerDependencies: + - supports-color + - typescript + eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.0): dependencies: aria-query: 5.3.2 @@ -12344,6 +12896,14 @@ snapshots: - supports-color - typescript + eslint-plugin-testing-library@5.11.1(eslint@8.57.0)(typescript@5.9.3): + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.9.3) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + eslint-plugin-tsdoc@0.2.17: dependencies: '@microsoft/tsdoc': 0.14.2 @@ -12371,6 +12931,17 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-plugin-typescript-sort-keys@2.3.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.9.3))(eslint@8.57.0)(typescript@5.9.3): + dependencies: + '@typescript-eslint/experimental-utils': 5.62.0(eslint@8.57.0)(typescript@5.9.3) + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.9.3) + eslint: 8.57.0 + json-schema: 0.4.0 + natural-compare-lite: 1.4.0 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + eslint-plugin-vue@10.1.0(eslint@8.57.0)(vue-eslint-parser@10.1.3(eslint@8.57.0)): dependencies: '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0) @@ -12646,8 +13217,15 @@ snapshots: make-dir: 3.1.0 pkg-dir: 4.2.0 + find-cache-directory@6.0.0: + dependencies: + common-path-prefix: 3.0.0 + pkg-dir: 8.0.0 + find-root@1.1.0: {} + find-up-simple@1.0.1: {} + find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -12957,12 +13535,12 @@ snapshots: html-tags@3.3.1: {} - htmlparser2@9.1.0: + htmlparser2@10.1.0: dependencies: domelementtype: 2.3.0 domhandler: 5.0.3 domutils: 3.2.2 - entities: 4.5.0 + entities: 7.0.1 http-errors@2.0.0: dependencies: @@ -13012,6 +13590,9 @@ snapshots: ignore@5.3.2: {} + image-size@0.5.5: + optional: true + immutable@4.3.7: {} immutable@5.1.2: {} @@ -13038,6 +13619,10 @@ snapshots: ini@1.3.8: {} + injection-js@2.6.1: + dependencies: + tslib: 2.8.1 + internal-slot@1.1.0: dependencies: es-errors: 1.3.0 @@ -13106,8 +13691,6 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-fullwidth-code-point@4.0.0: {} - is-fullwidth-code-point@5.1.0: dependencies: get-east-asian-width: 1.5.0 @@ -13126,6 +13709,8 @@ snapshots: is-interactive@1.0.0: {} + is-interactive@2.0.0: {} + is-map@2.0.3: {} is-module@1.0.0: {} @@ -13187,6 +13772,8 @@ snapshots: is-unicode-supported@0.1.0: {} + is-unicode-supported@2.1.0: {} + is-weakmap@2.0.2: {} is-weakref@1.1.1: @@ -13198,6 +13785,8 @@ snapshots: call-bound: 1.0.4 get-intrinsic: 1.3.0 + is-what@3.14.1: {} + is-windows@1.0.2: {} is-wsl@2.2.0: @@ -13216,7 +13805,7 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: - '@babel/core': 7.27.1 + '@babel/core': 7.28.5 '@babel/parser': 7.27.2 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 @@ -13409,6 +13998,20 @@ snapshots: dependencies: language-subtag-registry: 0.3.23 + less@4.5.1: + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.8.1 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + image-size: 0.5.5 + make-dir: 2.1.0 + mime: 1.6.0 + needle: 3.3.1 + source-map: 0.6.1 + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -13465,16 +14068,16 @@ snapshots: lines-and-columns@2.0.3: {} - listr2@8.2.5: + listr2@9.0.5: dependencies: - cli-truncate: 4.0.0 + cli-truncate: 5.1.1 colorette: 2.0.20 eventemitter3: 5.0.4 log-update: 6.1.0 rfdc: 1.4.1 wrap-ansi: 9.0.2 - lmdb@3.2.6: + lmdb@3.4.4: dependencies: msgpackr: 1.11.8 node-addon-api: 6.1.0 @@ -13482,12 +14085,13 @@ snapshots: ordered-binary: 1.6.1 weak-lru-cache: 1.2.2 optionalDependencies: - '@lmdb/lmdb-darwin-arm64': 3.2.6 - '@lmdb/lmdb-darwin-x64': 3.2.6 - '@lmdb/lmdb-linux-arm': 3.2.6 - '@lmdb/lmdb-linux-arm64': 3.2.6 - '@lmdb/lmdb-linux-x64': 3.2.6 - '@lmdb/lmdb-win32-x64': 3.2.6 + '@lmdb/lmdb-darwin-arm64': 3.4.4 + '@lmdb/lmdb-darwin-x64': 3.4.4 + '@lmdb/lmdb-linux-arm': 3.4.4 + '@lmdb/lmdb-linux-arm64': 3.4.4 + '@lmdb/lmdb-linux-x64': 3.4.4 + '@lmdb/lmdb-win32-arm64': 3.4.4 + '@lmdb/lmdb-win32-x64': 3.4.4 optional: true local-pkg@1.1.1: @@ -13523,6 +14127,11 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 + log-symbols@7.0.1: + dependencies: + is-unicode-supported: 2.1.0 + yoctocolors: 2.1.2 + log-update@6.1.0: dependencies: ansi-escapes: 7.3.0 @@ -13559,12 +14168,22 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + magicast@0.3.5: dependencies: '@babel/parser': 7.27.2 '@babel/types': 7.27.1 source-map-js: 1.2.1 + make-dir@2.1.0: + dependencies: + pify: 4.0.1 + semver: 5.7.2 + optional: true + make-dir@3.1.0: dependencies: semver: 6.3.1 @@ -13638,6 +14257,9 @@ snapshots: dependencies: mime-db: 1.54.0 + mime@1.6.0: + optional: true + mimic-fn@2.1.0: {} mimic-function@5.0.1: {} @@ -13734,9 +14356,15 @@ snapshots: natural-compare@1.4.0: {} + needle@3.3.1: + dependencies: + iconv-lite: 0.6.3 + sax: 1.4.4 + optional: true + negotiator@1.0.0: {} - next@15.5.12(@playwright/test@1.58.2)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)(sass@1.92.1): + next@15.5.12(@playwright/test@1.58.2)(react-dom@19.1.4(react@19.1.4))(react@19.1.4)(sass@1.97.1): dependencies: '@next/env': 15.5.12 '@swc/helpers': 0.5.15 @@ -13755,12 +14383,42 @@ snapshots: '@next/swc-win32-arm64-msvc': 15.5.12 '@next/swc-win32-x64-msvc': 15.5.12 '@playwright/test': 1.58.2 - sass: 1.92.1 + sass: 1.97.1 sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros + ng-packagr@21.1.0(@angular/compiler-cli@21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3))(tailwindcss@4.1.8)(tslib@2.8.1)(typescript@5.9.3): + dependencies: + '@ampproject/remapping': 2.3.0 + '@angular/compiler-cli': 21.1.5(@angular/compiler@21.1.5)(typescript@5.9.3) + '@rollup/plugin-json': 6.1.0(rollup@4.32.0) + '@rollup/wasm-node': 4.58.0 + ajv: 8.17.1 + ansi-colors: 4.1.3 + browserslist: 4.28.1 + chokidar: 5.0.0 + commander: 14.0.3 + dependency-graph: 1.0.0 + esbuild: 0.27.3 + find-cache-directory: 6.0.0 + injection-js: 2.6.1 + jsonc-parser: 3.3.1 + less: 4.5.1 + ora: 9.3.0 + piscina: 5.1.4 + postcss: 8.5.6 + rollup-plugin-dts: 6.3.0(rollup@4.32.0)(typescript@5.9.3) + rxjs: 7.8.1 + sass: 1.92.1 + tinyglobby: 0.2.15 + tslib: 2.8.1 + typescript: 5.9.3 + optionalDependencies: + rollup: 4.32.0 + tailwindcss: 4.1.8 + node-addon-api@6.1.0: optional: true @@ -13780,6 +14438,8 @@ snapshots: node-releases@2.0.19: {} + node-releases@2.0.27: {} + nopt@7.2.1: dependencies: abbrev: 2.0.0 @@ -13948,6 +14608,17 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 + ora@9.3.0: + dependencies: + chalk: 5.6.2 + cli-cursor: 5.0.0 + cli-spinners: 3.4.0 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 7.0.1 + stdin-discarder: 0.3.1 + string-width: 8.2.0 + ordered-binary@1.6.1: optional: true @@ -14020,15 +14691,17 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - parse5-html-rewriting-stream@7.0.0: + parse-node-version@1.0.1: {} + + parse5-html-rewriting-stream@8.0.0: dependencies: - entities: 4.5.0 - parse5: 7.3.0 - parse5-sax-parser: 7.0.0 + entities: 6.0.0 + parse5: 8.0.0 + parse5-sax-parser: 8.0.0 - parse5-sax-parser@7.0.0: + parse5-sax-parser@8.0.0: dependencies: - parse5: 7.3.0 + parse5: 8.0.0 parse5@7.3.0: dependencies: @@ -14081,11 +14754,12 @@ snapshots: picomatch@2.3.1: {} - picomatch@4.0.2: {} - picomatch@4.0.3: {} - piscina@4.8.0: + pify@4.0.1: + optional: true + + piscina@5.1.4: optionalDependencies: '@napi-rs/nice': 1.1.1 @@ -14093,6 +14767,10 @@ snapshots: dependencies: find-up: 4.1.0 + pkg-dir@8.0.0: + dependencies: + find-up-simple: 1.0.1 + pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -14379,6 +15057,9 @@ snapshots: proxy-from-env@1.1.0: {} + prr@1.0.1: + optional: true + public-encrypt@4.0.3: dependencies: bn.js: 4.12.2 @@ -14488,6 +15169,8 @@ snapshots: readdirp@4.1.2: {} + readdirp@5.0.0: {} + redent@3.0.0: dependencies: indent-string: 4.0.0 @@ -14581,6 +15264,25 @@ snapshots: hash-base: 3.1.2 inherits: 2.0.4 + rolldown@1.0.0-beta.58: + dependencies: + '@oxc-project/types': 0.106.0 + '@rolldown/pluginutils': 1.0.0-beta.58 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-beta.58 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.58 + '@rolldown/binding-darwin-x64': 1.0.0-beta.58 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.58 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.58 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.58 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.58 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.58 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.58 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.58 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.58 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.58 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.58 + rollup-plugin-dts@6.1.0(rollup@4.32.0)(typescript@5.1.6): dependencies: magic-string: 0.30.17 @@ -14589,6 +15291,14 @@ snapshots: optionalDependencies: '@babel/code-frame': 7.27.1 + rollup-plugin-dts@6.3.0(rollup@4.32.0)(typescript@5.9.3): + dependencies: + magic-string: 0.30.21 + rollup: 4.32.0 + typescript: 5.9.3 + optionalDependencies: + '@babel/code-frame': 7.27.1 + rollup-plugin-polyfill-node@0.13.0(rollup@4.32.0): dependencies: '@rollup/plugin-inject': 5.0.5(rollup@4.32.0) @@ -14641,31 +15351,6 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.32.0 fsevents: 2.3.3 - rollup@4.34.8: - dependencies: - '@types/estree': 1.0.6 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.34.8 - '@rollup/rollup-android-arm64': 4.34.8 - '@rollup/rollup-darwin-arm64': 4.34.8 - '@rollup/rollup-darwin-x64': 4.34.8 - '@rollup/rollup-freebsd-arm64': 4.34.8 - '@rollup/rollup-freebsd-x64': 4.34.8 - '@rollup/rollup-linux-arm-gnueabihf': 4.34.8 - '@rollup/rollup-linux-arm-musleabihf': 4.34.8 - '@rollup/rollup-linux-arm64-gnu': 4.34.8 - '@rollup/rollup-linux-arm64-musl': 4.34.8 - '@rollup/rollup-linux-loongarch64-gnu': 4.34.8 - '@rollup/rollup-linux-powerpc64le-gnu': 4.34.8 - '@rollup/rollup-linux-riscv64-gnu': 4.34.8 - '@rollup/rollup-linux-s390x-gnu': 4.34.8 - '@rollup/rollup-linux-x64-gnu': 4.34.8 - '@rollup/rollup-linux-x64-musl': 4.34.8 - '@rollup/rollup-win32-arm64-msvc': 4.34.8 - '@rollup/rollup-win32-ia32-msvc': 4.34.8 - '@rollup/rollup-win32-x64-msvc': 4.34.8 - fsevents: 2.3.3 - rollup@4.50.0: dependencies: '@types/estree': 1.0.8 @@ -14837,7 +15522,7 @@ snapshots: immutable: 4.3.7 source-map-js: 1.2.1 - sass@1.85.0: + sass@1.92.1: dependencies: chokidar: 4.0.3 immutable: 5.1.2 @@ -14845,13 +15530,15 @@ snapshots: optionalDependencies: '@parcel/watcher': 2.5.1 - sass@1.92.1: + sass@1.97.1: dependencies: chokidar: 4.0.3 immutable: 5.1.2 source-map-js: 1.2.1 optionalDependencies: '@parcel/watcher': 2.5.1 + + sax@1.4.4: optional: true saxes@6.0.0: @@ -14872,8 +15559,6 @@ snapshots: semver@6.3.1: {} - semver@7.7.1: {} - semver@7.7.2: {} semver@7.7.3: {} @@ -15027,11 +15712,6 @@ snapshots: astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - slice-ansi@5.0.0: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 4.0.0 - slice-ansi@7.1.2: dependencies: ansi-styles: 6.2.3 @@ -15048,7 +15728,7 @@ snapshots: source-map@0.6.1: {} - source-map@0.7.4: {} + source-map@0.7.6: {} spawndamnit@3.0.1: dependencies: @@ -15081,6 +15761,8 @@ snapshots: std-env@3.9.0: {} + stdin-discarder@0.3.1: {} + stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -15111,6 +15793,11 @@ snapshots: get-east-asian-width: 1.5.0 strip-ansi: 7.1.2 + string-width@8.2.0: + dependencies: + get-east-asian-width: 1.5.0 + strip-ansi: 7.1.2 + string.prototype.includes@2.0.1: dependencies: call-bind: 1.0.8 @@ -15451,6 +16138,10 @@ snapshots: dependencies: typescript: 5.7.2 + ts-api-utils@1.4.3(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + ts-api-utils@2.1.0(typescript@5.8.3): dependencies: typescript: 5.8.3 @@ -15489,6 +16180,11 @@ snapshots: tslib: 1.14.1 typescript: 5.7.2 + tsutils@3.21.0(typescript@5.9.3): + dependencies: + tslib: 1.14.1 + typescript: 5.9.3 + tsx@4.21.0: dependencies: esbuild: 0.27.3 @@ -15565,6 +16261,8 @@ snapshots: typescript@5.8.3: {} + typescript@5.9.3: {} + ufo@1.6.1: {} unbox-primitive@1.1.0: @@ -15581,11 +16279,9 @@ snapshots: undici-types@7.8.0: optional: true - undici@7.21.0: {} + undici@7.20.0: {} - unist-util-stringify-position@4.0.0: - dependencies: - '@types/unist': 3.0.3 + undici@7.21.0: {} universalify@0.1.2: {} @@ -15599,6 +16295,12 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 + update-browserslist-db@1.2.3(browserslist@4.28.1): + dependencies: + browserslist: 4.28.1 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -15623,23 +16325,13 @@ snapshots: vary@1.1.2: {} - vfile-message@4.0.3: - dependencies: - '@types/unist': 3.0.3 - unist-util-stringify-position: 4.0.0 - - vfile@6.0.3: - dependencies: - '@types/unist': 3.0.3 - vfile-message: 4.0.3 - - vite-node@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vite-node@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: cac: 6.7.14 debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.4.1(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - jiti @@ -15654,13 +16346,13 @@ snapshots: - tsx - yaml - vite-node@3.1.3(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vite-node@3.1.3(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): 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@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - jiti @@ -15675,13 +16367,13 @@ snapshots: - tsx - yaml - vite-node@3.1.3(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vite-node@3.1.3(@types/node@22.15.30)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): 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@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@22.15.30)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - jiti @@ -15696,23 +16388,7 @@ snapshots: - tsx - yaml - vite@6.2.0(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): - dependencies: - esbuild: 0.25.9 - postcss: 8.5.6 - rollup: 4.32.0 - optionalDependencies: - '@types/node': 24.0.3 - fsevents: 2.3.3 - jiti: 2.6.0 - lightningcss: 1.30.1 - sass: 1.85.0 - sass-embedded: 1.92.1 - terser: 5.39.2 - tsx: 4.21.0 - yaml: 2.8.0 - - vite@6.4.1(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vite@6.4.1(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: esbuild: 0.25.9 fdir: 6.5.0(picomatch@4.0.3) @@ -15724,6 +16400,7 @@ snapshots: '@types/node': 20.12.7 fsevents: 2.3.3 jiti: 2.6.0 + less: 4.5.1 lightningcss: 1.30.1 sass: 1.75.0 sass-embedded: 1.92.1 @@ -15731,7 +16408,7 @@ snapshots: tsx: 4.21.0 yaml: 2.8.0 - vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: esbuild: 0.25.9 fdir: 6.5.0(picomatch@4.0.3) @@ -15743,14 +16420,15 @@ snapshots: '@types/node': 22.15.3 fsevents: 2.3.3 jiti: 2.6.0 + less: 4.5.1 lightningcss: 1.30.1 - sass: 1.92.1 + sass: 1.97.1 sass-embedded: 1.92.1 terser: 5.39.2 tsx: 4.21.0 yaml: 2.8.0 - vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: esbuild: 0.25.9 fdir: 6.5.0(picomatch@4.0.3) @@ -15762,14 +16440,15 @@ snapshots: '@types/node': 22.15.30 fsevents: 2.3.3 jiti: 2.6.0 + less: 4.5.1 lightningcss: 1.30.1 - sass: 1.92.1 + sass: 1.97.1 sass-embedded: 1.92.1 terser: 5.39.2 tsx: 4.21.0 yaml: 2.8.0 - vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.85.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: esbuild: 0.25.9 fdir: 6.5.0(picomatch@4.0.3) @@ -15781,14 +16460,15 @@ snapshots: '@types/node': 24.0.3 fsevents: 2.3.3 jiti: 2.6.0 + less: 4.5.1 lightningcss: 1.30.1 - sass: 1.85.0 + sass: 1.97.1 sass-embedded: 1.92.1 terser: 5.39.2 tsx: 4.21.0 yaml: 2.8.0 - vite@6.4.1(@types/node@24.0.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vite@7.1.12(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: esbuild: 0.25.9 fdir: 6.5.0(picomatch@4.0.3) @@ -15797,39 +16477,41 @@ snapshots: rollup: 4.50.0 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.0.3 + '@types/node': 20.12.7 fsevents: 2.3.3 jiti: 2.6.0 + less: 4.5.1 lightningcss: 1.30.1 - sass: 1.92.1 + sass: 1.75.0 sass-embedded: 1.92.1 terser: 5.39.2 tsx: 4.21.0 yaml: 2.8.0 - vite@7.1.12(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vite@7.3.0(@types/node@24.0.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: - esbuild: 0.25.9 + esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 rollup: 4.50.0 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 20.12.7 + '@types/node': 24.0.3 fsevents: 2.3.3 jiti: 2.6.0 + less: 4.5.1 lightningcss: 1.30.1 - sass: 1.75.0 + sass: 1.97.1 sass-embedded: 1.92.1 terser: 5.39.2 tsx: 4.21.0 yaml: 2.8.0 - vitest@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vitest@3.0.8(@types/node@20.12.7)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: '@vitest/expect': 3.0.8 - '@vitest/mocker': 3.0.8(vite@6.4.1(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + '@vitest/mocker': 3.0.8(vite@6.4.1(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitest/pretty-format': 3.1.3 '@vitest/runner': 3.0.8 '@vitest/snapshot': 3.0.8 @@ -15845,8 +16527,8 @@ snapshots: tinyexec: 0.3.2 tinypool: 1.0.2 tinyrainbow: 2.0.0 - vite: 6.4.1(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) - vite-node: 3.0.8(@types/node@20.12.7)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite-node: 3.0.8(@types/node@20.12.7)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.75.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.12.7 @@ -15865,10 +16547,10 @@ snapshots: - tsx - yaml - vitest@3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@26.1.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vitest@3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@26.1.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: '@vitest/expect': 3.1.3 - '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitest/pretty-format': 3.1.3 '@vitest/runner': 3.1.3 '@vitest/snapshot': 3.1.3 @@ -15885,12 +16567,12 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.0.2 tinyrainbow: 2.0.0 - vite: 6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) - vite-node: 3.1.3(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite-node: 3.1.3(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.15.3 - '@vitest/browser': 3.1.3(playwright@1.58.2)(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3) + '@vitest/browser': 3.1.3(playwright@1.58.2)(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3) jsdom: 26.1.0 transitivePeerDependencies: - jiti @@ -15906,10 +16588,10 @@ snapshots: - tsx - yaml - vitest@3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vitest@3.1.3(@types/node@22.15.3)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: '@vitest/expect': 3.1.3 - '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitest/pretty-format': 3.1.3 '@vitest/runner': 3.1.3 '@vitest/snapshot': 3.1.3 @@ -15926,12 +16608,12 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.0.2 tinyrainbow: 2.0.0 - vite: 6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) - vite-node: 3.1.3(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite-node: 3.1.3(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.15.3 - '@vitest/browser': 3.1.3(playwright@1.55.1)(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3) + '@vitest/browser': 3.1.3(playwright@1.55.1)(vite@6.4.1(@types/node@22.15.3)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3) jsdom: 27.4.0 transitivePeerDependencies: - jiti @@ -15947,10 +16629,10 @@ snapshots: - tsx - yaml - vitest@3.1.3(@types/node@22.15.30)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): + vitest@3.1.3(@types/node@22.15.30)(@vitest/browser@3.1.3)(jiti@2.6.0)(jsdom@27.4.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0): dependencies: '@vitest/expect': 3.1.3 - '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) + '@vitest/mocker': 3.1.3(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitest/pretty-format': 3.1.3 '@vitest/runner': 3.1.3 '@vitest/snapshot': 3.1.3 @@ -15967,12 +16649,12 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.0.2 tinyrainbow: 2.0.0 - vite: 6.4.1(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) - vite-node: 3.1.3(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite: 6.4.1(@types/node@22.15.30)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) + vite-node: 3.1.3(@types/node@22.15.30)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.15.30 - '@vitest/browser': 3.1.3(playwright@1.58.2)(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.92.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3) + '@vitest/browser': 3.1.3(playwright@1.58.2)(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.0)(less@4.5.1)(lightningcss@1.30.1)(sass-embedded@1.92.1)(sass@1.97.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.0))(vitest@3.1.3) jsdom: 27.4.0 transitivePeerDependencies: - jiti @@ -16038,7 +16720,7 @@ snapshots: dependencies: xml-name-validator: 5.0.0 - watchpack@2.4.2: + watchpack@2.5.0: dependencies: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 @@ -16192,6 +16874,8 @@ snapshots: yargs-parser@21.1.1: {} + yargs-parser@22.0.0: {} + yargs@17.7.2: dependencies: cliui: 8.0.1 @@ -16202,8 +16886,19 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yargs@18.0.0: + dependencies: + cliui: 9.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + string-width: 7.2.0 + y18n: 5.0.8 + yargs-parser: 22.0.0 + yocto-queue@0.1.0: {} yoctocolors-cjs@2.1.3: {} - zone.js@0.15.0: {} + yoctocolors@2.1.2: {} + + zone.js@0.16.1: {} diff --git a/samples/teamspace-angular/package.json b/samples/teamspace-angular/package.json index 321d765e4..4f496c25c 100644 --- a/samples/teamspace-angular/package.json +++ b/samples/teamspace-angular/package.json @@ -10,25 +10,25 @@ }, "dependencies": { "@asgardeo/angular": "workspace:*", - "@angular/common": "19.2.4", - "@angular/core": "19.2.4", - "@angular/forms": "19.2.4", - "@angular/platform-browser": "19.2.4", - "@angular/platform-browser-dynamic": "19.2.4", - "@angular/router": "19.2.4", + "@angular/common": "21.1.5", + "@angular/core": "21.1.5", + "@angular/forms": "21.1.5", + "@angular/platform-browser": "21.1.5", + "@angular/platform-browser-dynamic": "21.1.5", + "@angular/router": "21.1.5", "rxjs": "7.8.1", "tslib": "2.8.1", - "zone.js": "0.15.0" + "zone.js": "0.16.1" }, "devDependencies": { - "@analogjs/vite-plugin-angular": "1.16.2", - "@angular/build": "19.2.4", - "@angular/compiler": "19.2.4", - "@angular/compiler-cli": "19.2.4", + "@analogjs/vite-plugin-angular": "2.2.3", + "@angular/build": "21.1.4", + "@angular/compiler": "21.1.5", + "@angular/compiler-cli": "21.1.5", "@tailwindcss/vite": "4.1.8", "@vitejs/plugin-basic-ssl": "2.0.0", "tailwindcss": "4.1.8", - "typescript": "5.8.3", + "typescript": "5.9.3", "vite": "6.4.1" } } diff --git a/samples/teamspace-angular/src/app/app.routes.ts b/samples/teamspace-angular/src/app/app.routes.ts index 7359ba492..c29ca5272 100644 --- a/samples/teamspace-angular/src/app/app.routes.ts +++ b/samples/teamspace-angular/src/app/app.routes.ts @@ -1,20 +1,13 @@ import {Routes} from '@angular/router'; -import {LandingComponent} from './pages/landing.component'; -import {CallbackPageComponent} from './pages/callback.component'; -import {DashboardComponent} from './pages/dashboard.component'; -import {ProfileComponent} from './pages/profile.component'; -import {OrganizationsComponent} from './pages/organizations.component'; -import {CreateOrgComponent} from './pages/create-org.component'; -import {DebugComponent} from './pages/debug.component'; import {authGuard} from './guards/auth.guard'; export const routes: Routes = [ - {path: '', component: LandingComponent}, - {path: 'callback', component: CallbackPageComponent}, - {path: 'dashboard', component: DashboardComponent, canActivate: [authGuard]}, - {path: 'profile', component: ProfileComponent, canActivate: [authGuard]}, - {path: 'organizations', component: OrganizationsComponent, canActivate: [authGuard]}, - {path: 'organizations/new', component: CreateOrgComponent, canActivate: [authGuard]}, - {path: 'debug', component: DebugComponent, canActivate: [authGuard]}, + {path: '', loadComponent: () => import('./pages/landing.component').then(m => m.LandingComponent)}, + {path: 'callback', loadComponent: () => import('./pages/callback.component').then(m => m.CallbackPageComponent)}, + {path: 'dashboard', loadComponent: () => import('./pages/dashboard.component').then(m => m.DashboardComponent), canActivate: [authGuard]}, + {path: 'profile', loadComponent: () => import('./pages/profile.component').then(m => m.ProfileComponent), canActivate: [authGuard]}, + {path: 'organizations', loadComponent: () => import('./pages/organizations.component').then(m => m.OrganizationsComponent), canActivate: [authGuard]}, + {path: 'organizations/new', loadComponent: () => import('./pages/create-org.component').then(m => m.CreateOrgComponent), canActivate: [authGuard]}, + {path: 'debug', loadComponent: () => import('./pages/debug.component').then(m => m.DebugComponent), canActivate: [authGuard]}, {path: '**', redirectTo: ''}, ]; diff --git a/samples/teamspace-angular/src/app/components/header.component.ts b/samples/teamspace-angular/src/app/components/header.component.ts index 92e428f98..5f25b0a18 100644 --- a/samples/teamspace-angular/src/app/components/header.component.ts +++ b/samples/teamspace-angular/src/app/components/header.component.ts @@ -1,11 +1,11 @@ import {Component, inject, signal, HostListener, computed} from '@angular/core'; import {RouterLink} from '@angular/router'; -import {AsgardeoAuthService, AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoUserProfileComponent} from '@asgardeo/angular'; +import {AsgardeoAuthService, AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoUserProfileComponent, AsgardeoOrganizationSwitcherComponent} from '@asgardeo/angular'; @Component({ selector: 'app-header', standalone: true, - imports: [RouterLink, AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoUserProfileComponent], + imports: [RouterLink, AsgardeoSignedInDirective, AsgardeoSignedOutDirective, AsgardeoUserProfileComponent, AsgardeoOrganizationSwitcherComponent], template: `
@@ -41,6 +41,11 @@ import {AsgardeoAuthService, AsgardeoSignedInDirective, AsgardeoSignedOutDirecti
+ +
+ +
+
`, }) -export class CallbackPageComponent implements OnInit { +export class CallbackPageComponent { private authService = inject(AsgardeoAuthService); private router = inject(Router); - async ngOnInit(): Promise { - // The SDK's APP_INITIALIZER processes the OAuth code on this page - // (because afterSignInUrl points here). Wait for it to finish. - await this.waitForAuth(); + constructor() { + effect(() => { + const loading = this.authService.isLoading(); + if (loading) return; - if (this.authService.isSignedIn()) { - this.router.navigate(['/dashboard']); - } else { - this.router.navigate(['/']); - } - } - - private waitForAuth(): Promise { - return new Promise((resolve) => { - if (!this.authService.isLoading()) { - resolve(); - return; + if (this.authService.isSignedIn()) { + this.router.navigate(['/dashboard']); + } else { + this.router.navigate(['/']); } - const interval = setInterval(() => { - if (!this.authService.isLoading()) { - clearInterval(interval); - resolve(); - } - }, 50); }); } } diff --git a/samples/teamspace-angular/src/app/pages/create-org.component.ts b/samples/teamspace-angular/src/app/pages/create-org.component.ts index 553c48c43..0c3e04fb9 100644 --- a/samples/teamspace-angular/src/app/pages/create-org.component.ts +++ b/samples/teamspace-angular/src/app/pages/create-org.component.ts @@ -1,13 +1,12 @@ -import {Component, inject, signal} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {Router, RouterLink} from '@angular/router'; -import {FormsModule} from '@angular/forms'; -import {AsgardeoAuthService, createOrganization} from '@asgardeo/angular'; +import {AsgardeoCreateOrganizationComponent} from '@asgardeo/angular'; import {HeaderComponent} from '../components/header.component'; @Component({ selector: 'app-create-org', standalone: true, - imports: [RouterLink, FormsModule, HeaderComponent], + imports: [RouterLink, HeaderComponent, AsgardeoCreateOrganizationComponent], template: `
@@ -27,116 +26,24 @@ import {HeaderComponent} from '../components/header.component';

-
`, }) export class CreateOrgComponent { - private authService = inject(AsgardeoAuthService); private router = inject(Router); - orgName = ''; - orgDescription = ''; - isSubmitting = signal(false); - error = signal(null); - success = signal(false); - - async onCreate(): Promise { - if (!this.orgName.trim()) return; - - this.isSubmitting.set(true); - this.error.set(null); - this.success.set(false); + onCreated(): void { + this.router.navigate(['/organizations']); + } - try { - await createOrganization({ - baseUrl: import.meta.env['VITE_ASGARDEO_BASE_URL'] || '', - payload: { - name: this.orgName.trim(), - description: this.orgDescription.trim(), - parentId: this.authService.currentOrganization()?.id || '', - type: 'TENANT', - }, - }); - await this.authService.getClient().getMyOrganizations(); - this.success.set(true); - setTimeout(() => { - this.router.navigate(['/organizations']); - }, 1500); - } catch (err: any) { - this.error.set(err?.message || 'Failed to create organization'); - } finally { - this.isSubmitting.set(false); - } + onCancel(): void { + this.router.navigate(['/organizations']); } } diff --git a/samples/teamspace-angular/src/app/pages/dashboard.component.ts b/samples/teamspace-angular/src/app/pages/dashboard.component.ts index a01166166..5121e9a29 100644 --- a/samples/teamspace-angular/src/app/pages/dashboard.component.ts +++ b/samples/teamspace-angular/src/app/pages/dashboard.component.ts @@ -1,4 +1,4 @@ -import {Component, inject} from '@angular/core'; +import {Component, computed, inject} from '@angular/core'; import {RouterLink} from '@angular/router'; import {AsgardeoAuthService} from '@asgardeo/angular'; import {HeaderComponent} from '../components/header.component'; @@ -15,7 +15,7 @@ import {HeaderComponent} from '../components/header.component';

- Welcome back {{ getUserFullName() }}! + Welcome back {{ userFullName() }}!

@if (authService.currentOrganization(); as org) {

@@ -204,11 +204,11 @@ export class DashboardComponent { {id: 3, title: 'Client presentation prep', dueDate: 'Friday, 2:00 PM', priority: 'high', project: 'Client Work'}, ]; - getUserFullName(): string { + userFullName = computed(() => { const user = this.authService.user(); if (!user) return ''; const givenName = (user as any)['givenName'] || (user as any)['name']?.['givenName'] || (user as any)['given_name'] || ''; const familyName = (user as any)['name']?.['familyName'] || (user as any)['familyName'] || (user as any)['family_name'] || ''; return [givenName, familyName].filter(Boolean).join(' '); - } + }); } diff --git a/samples/teamspace-angular/src/app/pages/landing.component.ts b/samples/teamspace-angular/src/app/pages/landing.component.ts index 0c117cd39..bf48855c1 100644 --- a/samples/teamspace-angular/src/app/pages/landing.component.ts +++ b/samples/teamspace-angular/src/app/pages/landing.component.ts @@ -242,7 +242,7 @@ import {HeaderComponent} from '../components/header.component'; Teamspace

- Built with Angular 19 and @asgardeo/angular SDK. A sample application for demonstration purposes. + Built with Angular 21 and @asgardeo/angular SDK. A sample application for demonstration purposes.

diff --git a/samples/teamspace-angular/src/app/pages/organizations.component.ts b/samples/teamspace-angular/src/app/pages/organizations.component.ts index bae729699..7c60a3ec9 100644 --- a/samples/teamspace-angular/src/app/pages/organizations.component.ts +++ b/samples/teamspace-angular/src/app/pages/organizations.component.ts @@ -1,12 +1,12 @@ -import {Component, inject, signal} from '@angular/core'; +import {Component} from '@angular/core'; import {RouterLink} from '@angular/router'; -import {AsgardeoAuthService} from '@asgardeo/angular'; +import {AsgardeoOrganizationListComponent} from '@asgardeo/angular'; import {HeaderComponent} from '../components/header.component'; @Component({ selector: 'app-organizations', standalone: true, - imports: [RouterLink, HeaderComponent], + imports: [RouterLink, HeaderComponent, AsgardeoOrganizationListComponent], template: `
@@ -37,116 +37,11 @@ import {HeaderComponent} from '../components/header.component';
- @if (isLoading()) { -
-
-
- } @else if (error()) { -
-

{{ error() }}

-
- } @else { - - @if (authService.currentOrganization(); as currentOrg) { -
-
-
-

Current Organization

-

{{ currentOrg.name || currentOrg.id }}

-
-
Active
-
-
- } - - -
- @if (authService.myOrganizations().length === 0) { -
- - - -

No organizations found

- - Create your first organization - -
- } @else { -
    - @for (org of authService.myOrganizations(); track org.id) { -
  • -
    -
    -
    - - - -
    -
    -

    {{ org.name || org.id }}

    - @if (org.id) { -

    {{ org.id }}

    - } -
    -
    -
    - @if (authService.currentOrganization()?.id === org.id) { - Current - } @else { - - } -
    -
    -
  • - } -
- } -
- - -
- -
- } +
+ +
`, }) -export class OrganizationsComponent { - authService = inject(AsgardeoAuthService); - isLoading = signal(false); - error = signal(null); - - async switchTo(org: any): Promise { - await this.authService.switchOrganization(org); - } - - async revalidate(): Promise { - this.isLoading.set(true); - this.error.set(null); - try { - await this.authService.getClient().getMyOrganizations(); - } catch (err: any) { - this.error.set(err?.message || 'Failed to fetch organizations'); - } finally { - this.isLoading.set(false); - } - } -} +export class OrganizationsComponent {} From 6b774a6ad606d0d59cdf26040f4f5817923bc59a Mon Sep 17 00:00:00 2001 From: DonOmalVindula Date: Sat, 21 Feb 2026 17:06:51 +0530 Subject: [PATCH 6/6] Fix e2e failures --- e2e/docker-compose.yml | 3 ++- e2e/playwright-report-embedded/index.html | 2 +- e2e/setup/is/app-registration.ts | 2 +- e2e/setup/thunder/app-registration.ts | 28 +++++++------------- e2e/setup/thunder/constants.ts | 2 +- e2e/thunder-bootstrap/02-sample-resources.sh | 4 +-- e2e/thunder-config/deployment.yaml | 8 +++++- e2e/thunder-config/gate-config.js | 18 +++++++++++++ 8 files changed, 42 insertions(+), 25 deletions(-) create mode 100644 e2e/thunder-config/gate-config.js diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index 9e1356873..a78465b23 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -60,10 +60,11 @@ services: thunder-setup: condition: service_completed_successfully ports: - - "8090:8090" + - "9090:8090" volumes: - thunder-db:/opt/thunder/repository/database - ./thunder-config/deployment.yaml:/opt/thunder/repository/conf/deployment.yaml:ro + - ./thunder-config/gate-config.js:/opt/thunder/apps/gate/config.js:ro healthcheck: test: ["CMD", "curl", "-k", "-f", "https://localhost:8090/health/readiness"] interval: 10s diff --git a/e2e/playwright-report-embedded/index.html b/e2e/playwright-report-embedded/index.html index 5a1660df4..5c7bc631f 100644 --- a/e2e/playwright-report-embedded/index.html +++ b/e2e/playwright-report-embedded/index.html @@ -82,4 +82,4 @@
- \ No newline at end of file + \ No newline at end of file diff --git a/e2e/setup/is/app-registration.ts b/e2e/setup/is/app-registration.ts index cb2bff02c..ed6cef641 100644 --- a/e2e/setup/is/app-registration.ts +++ b/e2e/setup/is/app-registration.ts @@ -137,7 +137,7 @@ export async function registerIsApp(): Promise<{clientId: string; clientSecret: }; // Remove read-only fields that can't be sent in PUT - delete updatedConfig.state; + delete (updatedConfig as Record).state; const oidcPutResponse = await fetch(oidcUrl, { method: 'PUT', diff --git a/e2e/setup/thunder/app-registration.ts b/e2e/setup/thunder/app-registration.ts index 0f6b0d15c..3926595d0 100644 --- a/e2e/setup/thunder/app-registration.ts +++ b/e2e/setup/thunder/app-registration.ts @@ -34,7 +34,7 @@ export async function getThunderAppClientId(): Promise<{clientId: string; applic let applicationId: string | undefined; try { - const result = thunderSqlite("SELECT APP_ID FROM SP_APP WHERE APP_NAME='React SDK Sample'"); + const result = thunderSqlite("SELECT APP_ID FROM APPLICATION WHERE APP_NAME='React SDK Sample'"); if (result) { applicationId = result; @@ -44,15 +44,13 @@ export async function getThunderAppClientId(): Promise<{clientId: string; applic console.warn('[E2E] Could not retrieve Thunder application ID from database'); } - // Patch the pre-configured app's OAuth config: - // 1. Add the callback URL to redirect_uris (bootstrap only has / and /dashboard) - // 2. Fix the token issuer to match the OIDC discovery issuer (baseUrl, not baseUrl/oauth2/token) + // Patch the pre-configured app's OAuth config to add the callback URL + // to redirect_uris (bootstrap only has / and /dashboard). const callbackUrl = `${SAMPLE_APP.url}${SAMPLE_APP.afterSignInPath}`; - const correctIssuer = THUNDER_CONFIG.baseUrl; try { const configJson = thunderSqlite( - `SELECT OAUTH_CONFIG_JSON FROM IDN_OAUTH_CONSUMER_APPS WHERE CONSUMER_KEY='${clientId}'`, + `SELECT OAUTH_CONFIG_JSON FROM APP_OAUTH_INBOUND_CONFIG WHERE CLIENT_ID='${clientId}'`, ); if (configJson) { @@ -68,25 +66,19 @@ export async function getThunderAppClientId(): Promise<{clientId: string; applic needsUpdate = true; } - // Fix token issuer to match OIDC discovery (required for ID token validation) - if (config.token?.issuer !== correctIssuer) { - config.token.issuer = correctIssuer; - needsUpdate = true; - } - if (needsUpdate) { const updatedJson = JSON.stringify(config); // Write JSON to a temp file inside the container to avoid shell escaping issues, // then use readfile() in the SQLite UPDATE. - execSync( - `docker exec -i ${CONTAINER} sh -c 'cat > /tmp/oauth_config.json'`, - {input: updatedJson, encoding: 'utf-8'}, - ); + execSync(`docker exec -i ${CONTAINER} sh -c 'cat > /tmp/oauth_config.json'`, { + input: updatedJson, + encoding: 'utf-8', + }); thunderSqlite( - `UPDATE IDN_OAUTH_CONSUMER_APPS SET OAUTH_CONFIG_JSON=readfile('/tmp/oauth_config.json') WHERE CONSUMER_KEY='${clientId}'`, + `UPDATE APP_OAUTH_INBOUND_CONFIG SET OAUTH_CONFIG_JSON=readfile('/tmp/oauth_config.json') WHERE CLIENT_ID='${clientId}'`, ); - console.log(`[E2E] Thunder app OAuth config updated (redirect_uris, token issuer)`); + console.log(`[E2E] Thunder app OAuth config updated (redirect_uris)`); } } } catch (err) { diff --git a/e2e/setup/thunder/constants.ts b/e2e/setup/thunder/constants.ts index df7acca67..93fe25af3 100644 --- a/e2e/setup/thunder/constants.ts +++ b/e2e/setup/thunder/constants.ts @@ -3,7 +3,7 @@ */ export const THUNDER_CONFIG = { - baseUrl: process.env.THUNDER_BASE_URL ?? 'https://localhost:8090', + baseUrl: process.env.THUNDER_BASE_URL ?? 'https://localhost:9090', healthCheckPath: '/health/readiness', adminUsername: 'admin', adminPassword: 'admin', diff --git a/e2e/thunder-bootstrap/02-sample-resources.sh b/e2e/thunder-bootstrap/02-sample-resources.sh index 28f4100fd..cbad4e8fa 100755 --- a/e2e/thunder-bootstrap/02-sample-resources.sh +++ b/e2e/thunder-bootstrap/02-sample-resources.sh @@ -188,7 +188,7 @@ RESPONSE=$(thunder_api_call POST "/applications" "{ \"registration_flow_graph_id\": \"${REG_FLOW_ID}\", \"is_registration_flow_enabled\": true, \"user_attributes\": [\"given_name\",\"family_name\",\"email\",\"groups\",\"name\"], - \"allowed_user_types\": [\"Customer\"], + \"allowed_user_types\": [\"Customer\",\"Person\"], \"inbound_auth_config\": [{ \"type\": \"oauth2\", \"config\": { @@ -201,7 +201,7 @@ RESPONSE=$(thunder_api_call POST "/applications" "{ \"pkce_required\": true, \"public_client\": true, \"token\": { - \"issuer\": \"${PUBLIC_URL}/oauth2/token\", + \"issuer\": \"${PUBLIC_URL}\", \"access_token\": { \"validity_period\": 3600, \"user_attributes\": [\"given_name\",\"family_name\",\"email\",\"groups\",\"name\"] diff --git a/e2e/thunder-config/deployment.yaml b/e2e/thunder-config/deployment.yaml index dfa5bf6b8..03c0b77a3 100644 --- a/e2e/thunder-config/deployment.yaml +++ b/e2e/thunder-config/deployment.yaml @@ -1,8 +1,14 @@ server: hostname: "0.0.0.0" - public_url: "https://localhost:8090" + public_url: "https://localhost:9090" port: 8090 +gate_client: + hostname: "localhost" + port: 9090 + scheme: "https" + path: "/gate" + tls: min_version: "1.3" cert_file: "repository/resources/security/server.cert" diff --git a/e2e/thunder-config/gate-config.js b/e2e/thunder-config/gate-config.js new file mode 100644 index 000000000..a710761e9 --- /dev/null +++ b/e2e/thunder-config/gate-config.js @@ -0,0 +1,18 @@ +/** + * Custom Gate runtime config for e2e tests. + * + * Points the Gate's API calls at the Docker Thunder container + * on port 9090 (mapped from 8090 to avoid conflicts with any + * local Thunder dev server). + */ + +/* eslint-disable no-underscore-dangle */ + +window.__THUNDER_RUNTIME_CONFIG__ = { + client: { + base: '/gate', + }, + server: { + public_url: 'https://localhost:9090', + }, +};