From 0f46109c234c2ae17bcc420758d066f827bf4c82 Mon Sep 17 00:00:00 2001 From: Brion Date: Tue, 5 May 2026 23:05:56 +0530 Subject: [PATCH 1/2] Remove `legacy` code --- .../client.ts => AsgardeoSPAClient.ts} | 16 +- .../crypto-utils.ts => DefaultCrypto.ts} | 0 .../browser/src/__legacy__/clients/index.ts | 20 - .../browser/src/__legacy__/constants/index.ts | 24 - .../browser/src/__legacy__/helpers/index.ts | 21 - .../browser/src/__legacy__/models/index.ts | 28 - .../browser/src/__legacy__/stores/index.ts | 21 - .../browser/src/__legacy__/utils/index.ts | 20 - .../browser/src/__legacy__/worker/index.ts | 20 - packages/browser/src/clients/index.ts | 2 + .../mainThreadClient.ts} | 15 +- .../webWorkerClient.ts} | 11 +- .../src/{__legacy__ => }/constants/errors.ts | 0 .../src/{__legacy__ => }/constants/hooks.ts | 0 packages/browser/src/constants/index.ts | 6 + .../message-types.ts} | 0 .../{__legacy__ => }/constants/parameters.ts | 0 .../constants/session-management.ts | 0 .../src/{__legacy__ => }/constants/storage.ts | 0 .../helpers/authentication-helper.ts | 8 +- packages/browser/src/helpers/index.ts | 3 + .../helpers/session-management-helper.ts | 6 +- .../{__legacy__ => }/helpers/spa-helper.ts | 8 +- packages/browser/src/index.ts | 22 +- .../storage.ts => models/browser-storage.ts} | 0 .../{__legacy__ => }/models/http-client.ts | 0 packages/browser/src/models/index.ts | 9 + .../src/{__legacy__ => }/models/message.ts | 0 .../models/request-custom-grant.ts | 0 .../models/session-management-helper.ts | 0 .../src/{__legacy__ => }/models/sign-in.ts | 0 .../{__legacy__ => }/models/sign-out-error.ts | 0 .../spa-client-config.ts} | 2 +- .../client.ts => models/thread-client.ts} | 0 .../src/{__legacy__ => }/models/web-worker.ts | 0 .../local-store.ts => stores/LocalStore.ts} | 0 .../memory-store.ts => stores/MemoryStore.ts} | 0 .../SessionStore.ts} | 0 packages/browser/src/stores/index.ts | 3 + .../MessageUtils.ts} | 0 .../utils/spa-utils.ts => utils/SPAUtils.ts} | 10 +- packages/browser/src/utils/http.ts | 2 +- packages/browser/src/utils/index.ts | 2 + packages/browser/src/web.worker.ts | 10 +- packages/browser/src/worker/index.ts | 2 + .../worker-core.ts => worker/workerCore.ts} | 11 +- .../workerReceiver.ts} | 6 +- ...ient.ts => LegacyAsgardeoExpressClient.ts} | 11 +- .../express/src/__legacy__/constants/index.ts | 20 - .../__legacy__/middleware/authentication.ts | 101 -- .../src/__legacy__/middleware/index.ts | 20 - .../src/__legacy__/utils/express-utils.ts | 16 - .../constants/default-options.ts | 12 +- .../stores => express/src/constants}/index.ts | 3 +- .../constants/logger-config.ts | 18 +- packages/express/src/index.ts | 7 +- .../express/src/middleware/authentication.ts | 94 ++ .../core => express/src/middleware}/index.ts | 1 + .../middleware/protect-route.ts | 5 +- .../src/{__legacy__ => }/models/data.ts | 2 +- .../express-client-config.ts} | 0 .../utils => express/src/models}/index.ts | 7 +- .../{__legacy__ => }/models/protect-route.ts | 2 +- .../models/index.ts => utils/ExpressUtils.ts} | 10 +- .../src/AsgardeoJavaScriptClient.ts | 496 +++++-- packages/javascript/src/StorageManager.ts | 2 +- packages/javascript/src/__legacy__/client.ts | 1189 ----------------- .../helpers/authentication-helper.ts | 336 ----- .../javascript/src/__legacy__/models/index.ts | 19 - packages/javascript/src/api/exchangeToken.ts | 115 ++ .../javascript/src/api/handleTokenResponse.ts | 63 + .../api/loadOpenIDProviderConfiguration.ts | 100 ++ .../javascript/src/api/refreshAccessToken.ts | 93 ++ .../javascript/src/api/requestAccessToken.ts | 124 ++ .../javascript/src/api/revokeAccessToken.ts | 83 ++ .../javascript/src/api/validateIdToken.ts | 82 ++ packages/javascript/src/index.ts | 3 +- .../auth-client-config.ts} | 39 +- .../index.ts => utils/clearSession.ts} | 7 +- .../src/utils/getAuthenticatedUserInfo.ts | 37 + .../utils/replaceCustomGrantTemplateTags.ts | 72 + .../javascript/src/utils/resolveEndpoints.ts | 39 + .../src/utils/resolveEndpointsByBaseURL.ts | 73 + .../src/utils/resolveEndpointsExplicitly.ts | 75 ++ .../authentication.ts => AsgardeoNodeCore.ts} | 19 +- .../crypto-utils.ts => DefaultCrypto.ts} | 0 .../client.ts => LegacyAsgardeoNodeClient.ts} | 6 +- .../src/{__legacy__ => }/constants/index.ts | 0 .../constants/logger-config.ts | 0 .../{__legacy__ => }/constants/uuid-config.ts | 0 packages/node/src/index.ts | 6 +- .../node/src/{__legacy__ => }/models/index.ts | 0 .../{__legacy__ => }/models/session-data.ts | 0 .../{__legacy__ => }/models/url-callback.ts | 0 .../MemoryCacheStore.ts} | 0 packages/node/src/stores/index.ts | 1 + .../logger-utils.ts => utils/NodeLogger.ts} | 0 .../SessionUtils.ts} | 0 packages/node/src/utils/index.ts | 2 + 99 files changed, 1623 insertions(+), 2095 deletions(-) rename packages/browser/src/{__legacy__/client.ts => AsgardeoSPAClient.ts} (98%) rename packages/browser/src/{__legacy__/utils/crypto-utils.ts => DefaultCrypto.ts} (100%) delete mode 100644 packages/browser/src/__legacy__/clients/index.ts delete mode 100644 packages/browser/src/__legacy__/constants/index.ts delete mode 100644 packages/browser/src/__legacy__/helpers/index.ts delete mode 100644 packages/browser/src/__legacy__/models/index.ts delete mode 100644 packages/browser/src/__legacy__/stores/index.ts delete mode 100644 packages/browser/src/__legacy__/utils/index.ts delete mode 100644 packages/browser/src/__legacy__/worker/index.ts create mode 100644 packages/browser/src/clients/index.ts rename packages/browser/src/{__legacy__/clients/main-thread-client.ts => clients/mainThreadClient.ts} (97%) rename packages/browser/src/{__legacy__/clients/web-worker-client.ts => clients/webWorkerClient.ts} (98%) rename packages/browser/src/{__legacy__ => }/constants/errors.ts (100%) rename packages/browser/src/{__legacy__ => }/constants/hooks.ts (100%) create mode 100644 packages/browser/src/constants/index.ts rename packages/browser/src/{__legacy__/constants/messages-types.ts => constants/message-types.ts} (100%) rename packages/browser/src/{__legacy__ => }/constants/parameters.ts (100%) rename packages/browser/src/{__legacy__ => }/constants/session-management.ts (100%) rename packages/browser/src/{__legacy__ => }/constants/storage.ts (100%) rename packages/browser/src/{__legacy__ => }/helpers/authentication-helper.ts (99%) create mode 100644 packages/browser/src/helpers/index.ts rename packages/browser/src/{__legacy__ => }/helpers/session-management-helper.ts (97%) rename packages/browser/src/{__legacy__ => }/helpers/spa-helper.ts (93%) rename packages/browser/src/{__legacy__/models/storage.ts => models/browser-storage.ts} (100%) rename packages/browser/src/{__legacy__ => }/models/http-client.ts (100%) create mode 100644 packages/browser/src/models/index.ts rename packages/browser/src/{__legacy__ => }/models/message.ts (100%) rename packages/browser/src/{__legacy__ => }/models/request-custom-grant.ts (100%) rename packages/browser/src/{__legacy__ => }/models/session-management-helper.ts (100%) rename packages/browser/src/{__legacy__ => }/models/sign-in.ts (100%) rename packages/browser/src/{__legacy__ => }/models/sign-out-error.ts (100%) rename packages/browser/src/{__legacy__/models/client-config.ts => models/spa-client-config.ts} (97%) rename packages/browser/src/{__legacy__/models/client.ts => models/thread-client.ts} (100%) rename packages/browser/src/{__legacy__ => }/models/web-worker.ts (100%) rename packages/browser/src/{__legacy__/stores/local-store.ts => stores/LocalStore.ts} (100%) rename packages/browser/src/{__legacy__/stores/memory-store.ts => stores/MemoryStore.ts} (100%) rename packages/browser/src/{__legacy__/stores/session-store.ts => stores/SessionStore.ts} (100%) create mode 100644 packages/browser/src/stores/index.ts rename packages/browser/src/{__legacy__/utils/message-utils.ts => utils/MessageUtils.ts} (100%) rename packages/browser/src/{__legacy__/utils/spa-utils.ts => utils/SPAUtils.ts} (95%) create mode 100644 packages/browser/src/utils/index.ts create mode 100644 packages/browser/src/worker/index.ts rename packages/browser/src/{__legacy__/worker/worker-core.ts => worker/workerCore.ts} (95%) rename packages/browser/src/{__legacy__/worker/worker-receiver.ts => worker/workerReceiver.ts} (97%) rename packages/express/src/{__legacy__/client.ts => LegacyAsgardeoExpressClient.ts} (93%) delete mode 100644 packages/express/src/__legacy__/constants/index.ts delete mode 100644 packages/express/src/__legacy__/middleware/authentication.ts delete mode 100644 packages/express/src/__legacy__/middleware/index.ts delete mode 100644 packages/express/src/__legacy__/utils/express-utils.ts rename packages/express/src/{__legacy__ => }/constants/default-options.ts (77%) rename packages/{node/src/__legacy__/stores => express/src/constants}/index.ts (90%) rename packages/express/src/{__legacy__ => }/constants/logger-config.ts (78%) create mode 100644 packages/express/src/middleware/authentication.ts rename packages/{node/src/__legacy__/core => express/src/middleware}/index.ts (95%) rename packages/express/src/{__legacy__ => }/middleware/protect-route.ts (95%) rename packages/express/src/{__legacy__ => }/models/data.ts (97%) rename packages/express/src/{__legacy__/models/client-config.ts => models/express-client-config.ts} (100%) rename packages/{node/src/__legacy__/utils => express/src/models}/index.ts (84%) rename packages/express/src/{__legacy__ => }/models/protect-route.ts (96%) rename packages/express/src/{__legacy__/models/index.ts => utils/ExpressUtils.ts} (76%) delete mode 100644 packages/javascript/src/__legacy__/client.ts delete mode 100644 packages/javascript/src/__legacy__/helpers/authentication-helper.ts delete mode 100644 packages/javascript/src/__legacy__/models/index.ts create mode 100644 packages/javascript/src/api/exchangeToken.ts create mode 100644 packages/javascript/src/api/handleTokenResponse.ts create mode 100644 packages/javascript/src/api/loadOpenIDProviderConfiguration.ts create mode 100644 packages/javascript/src/api/refreshAccessToken.ts create mode 100644 packages/javascript/src/api/requestAccessToken.ts create mode 100644 packages/javascript/src/api/revokeAccessToken.ts create mode 100644 packages/javascript/src/api/validateIdToken.ts rename packages/javascript/src/{__legacy__/models/client-config.ts => models/auth-client-config.ts} (62%) rename packages/javascript/src/{__legacy__/helpers/index.ts => utils/clearSession.ts} (71%) create mode 100644 packages/javascript/src/utils/getAuthenticatedUserInfo.ts create mode 100644 packages/javascript/src/utils/replaceCustomGrantTemplateTags.ts create mode 100644 packages/javascript/src/utils/resolveEndpoints.ts create mode 100644 packages/javascript/src/utils/resolveEndpointsByBaseURL.ts create mode 100644 packages/javascript/src/utils/resolveEndpointsExplicitly.ts rename packages/node/src/{__legacy__/core/authentication.ts => AsgardeoNodeCore.ts} (94%) rename packages/node/src/{__legacy__/utils/crypto-utils.ts => DefaultCrypto.ts} (100%) rename packages/node/src/{__legacy__/client.ts => LegacyAsgardeoNodeClient.ts} (99%) rename packages/node/src/{__legacy__ => }/constants/index.ts (100%) rename packages/node/src/{__legacy__ => }/constants/logger-config.ts (100%) rename packages/node/src/{__legacy__ => }/constants/uuid-config.ts (100%) rename packages/node/src/{__legacy__ => }/models/index.ts (100%) rename packages/node/src/{__legacy__ => }/models/session-data.ts (100%) rename packages/node/src/{__legacy__ => }/models/url-callback.ts (100%) rename packages/node/src/{__legacy__/stores/memory-cache-store.ts => stores/MemoryCacheStore.ts} (100%) create mode 100644 packages/node/src/stores/index.ts rename packages/node/src/{__legacy__/utils/logger-utils.ts => utils/NodeLogger.ts} (100%) rename packages/node/src/{__legacy__/utils/session-utils.ts => utils/SessionUtils.ts} (100%) create mode 100644 packages/node/src/utils/index.ts diff --git a/packages/browser/src/__legacy__/client.ts b/packages/browser/src/AsgardeoSPAClient.ts similarity index 98% rename from packages/browser/src/__legacy__/client.ts rename to packages/browser/src/AsgardeoSPAClient.ts index fc5d1186c..940a9c9c6 100755 --- a/packages/browser/src/__legacy__/client.ts +++ b/packages/browser/src/AsgardeoSPAClient.ts @@ -17,7 +17,7 @@ */ import { - AsgardeoAuthClient, + AsgardeoJavaScriptClient, AsgardeoAuthException, AuthClientConfig, IsomorphicCrypto, @@ -28,7 +28,7 @@ import { User, createPackageComponentLogger, } from '@asgardeo/javascript'; -import WorkerFile from '../web.worker'; +import WorkerFile from './web.worker'; import {MainThreadClient, WebWorkerClient} from './clients'; import {Hooks, REFRESH_ACCESS_TOKEN_ERR0R} from './constants'; import {AuthenticationHelper, SPAHelper} from './helpers'; @@ -45,7 +45,7 @@ import { WebWorkerClientConfig, WebWorkerClientInterface, } from './models'; -import {BrowserStorage} from './models/storage'; +import {BrowserStorage} from './models/browser-storage'; import {SPAUtils} from './utils'; const logger: ReturnType = createPackageComponentLogger( @@ -366,7 +366,7 @@ export class AsgardeoSPAClient { this._client = await MainThreadClient( this._instanceId, mergedConfig, - (authClient: AsgardeoAuthClient, spaHelper: SPAHelper) => { + (authClient: AsgardeoJavaScriptClient, spaHelper: SPAHelper) => { return new this._authHelper(authClient, spaHelper); }, ); @@ -405,7 +405,7 @@ export class AsgardeoSPAClient { ...webWorkerClientConfig, }, this._worker, - (authClient: AsgardeoAuthClient, spaHelper: SPAHelper) => { + (authClient: AsgardeoJavaScriptClient, spaHelper: SPAHelper) => { return new this._authHelper(authClient, spaHelper); }, )) as WebWorkerClientInterface; @@ -914,7 +914,7 @@ export class AsgardeoSPAClient { * * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getIdToken * - * @memberof AsgardeoAuthClient + * @memberof AsgardeoJavaScriptClient * * @preserve */ @@ -1276,7 +1276,7 @@ export class AsgardeoSPAClient { * ``` * @link https://github.com/asgardeo/asgardeo-auth-spa-sdk/tree/master/lib#reInitialize * - * @memberof AsgardeoAuthClient + * @memberof AsgardeoJavaScriptClient * * @preserve */ @@ -1298,6 +1298,6 @@ export class AsgardeoSPAClient { * @param sessionId - The session ID of the session to be cleared. If not provided, the current session will be cleared. */ public clearSession(sessionId?: string): void { - AsgardeoAuthClient.clearSession(sessionId); + AsgardeoJavaScriptClient.clearSession(sessionId); } } diff --git a/packages/browser/src/__legacy__/utils/crypto-utils.ts b/packages/browser/src/DefaultCrypto.ts similarity index 100% rename from packages/browser/src/__legacy__/utils/crypto-utils.ts rename to packages/browser/src/DefaultCrypto.ts diff --git a/packages/browser/src/__legacy__/clients/index.ts b/packages/browser/src/__legacy__/clients/index.ts deleted file mode 100644 index 6148f41d4..000000000 --- a/packages/browser/src/__legacy__/clients/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** -* Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -* -* WSO2 Inc. 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. -*/ - -export * from "./main-thread-client"; -export * from "./web-worker-client"; diff --git a/packages/browser/src/__legacy__/constants/index.ts b/packages/browser/src/__legacy__/constants/index.ts deleted file mode 100644 index 67b72880a..000000000 --- a/packages/browser/src/__legacy__/constants/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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. - */ - -export * from "./messages-types"; -export * from "./storage"; -export * from "./hooks"; -export * from "./session-management"; -export * from "./parameters"; -export * from "./errors"; diff --git a/packages/browser/src/__legacy__/helpers/index.ts b/packages/browser/src/__legacy__/helpers/index.ts deleted file mode 100644 index 03b8ee07a..000000000 --- a/packages/browser/src/__legacy__/helpers/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** -* Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -* -* WSO2 Inc. 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. -*/ - -export * from "./authentication-helper"; -export * from "./spa-helper"; -export * from "./session-management-helper"; diff --git a/packages/browser/src/__legacy__/models/index.ts b/packages/browser/src/__legacy__/models/index.ts deleted file mode 100644 index 0ae035f78..000000000 --- a/packages/browser/src/__legacy__/models/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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. - */ - -export * from './client'; -export * from './message'; -export * from './http-client'; -export * from './web-worker'; -export * from './session-management-helper'; -export * from './sign-in'; -export * from './sign-out-error'; - -export {Config as LegacyConfig} from './client-config'; -export {SPAConfig, MainThreadClientConfig, WebWorkerClientConfig, AuthSPAClientConfig} from './client-config'; diff --git a/packages/browser/src/__legacy__/stores/index.ts b/packages/browser/src/__legacy__/stores/index.ts deleted file mode 100644 index 4c1a1f2cd..000000000 --- a/packages/browser/src/__legacy__/stores/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** -* Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -* -* WSO2 Inc. 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. -*/ - -export * from "./local-store"; -export * from "./memory-store"; -export * from "./session-store"; diff --git a/packages/browser/src/__legacy__/utils/index.ts b/packages/browser/src/__legacy__/utils/index.ts deleted file mode 100644 index ca1d41288..000000000 --- a/packages/browser/src/__legacy__/utils/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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. - */ - -export * from "./message-utils"; -export * from "./spa-utils"; diff --git a/packages/browser/src/__legacy__/worker/index.ts b/packages/browser/src/__legacy__/worker/index.ts deleted file mode 100644 index 2bef373ce..000000000 --- a/packages/browser/src/__legacy__/worker/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** -* Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -* -* WSO2 Inc. 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. -*/ - -export * from "./worker-receiver"; -export * from "./worker-core"; diff --git a/packages/browser/src/clients/index.ts b/packages/browser/src/clients/index.ts new file mode 100644 index 000000000..9e28cbb30 --- /dev/null +++ b/packages/browser/src/clients/index.ts @@ -0,0 +1,2 @@ +export * from './mainThreadClient'; +export * from './webWorkerClient'; diff --git a/packages/browser/src/__legacy__/clients/main-thread-client.ts b/packages/browser/src/clients/mainThreadClient.ts similarity index 97% rename from packages/browser/src/__legacy__/clients/main-thread-client.ts rename to packages/browser/src/clients/mainThreadClient.ts index 1b43d85d4..d78eb6e0a 100755 --- a/packages/browser/src/__legacy__/clients/main-thread-client.ts +++ b/packages/browser/src/clients/mainThreadClient.ts @@ -17,7 +17,7 @@ */ import { - AsgardeoAuthClient, + AsgardeoJavaScriptClient, AuthClientConfig, User, IsomorphicCrypto, @@ -35,13 +35,13 @@ import {SILENT_SIGN_IN_STATE, TOKEN_REQUEST_CONFIG_KEY} from '../constants'; import {AuthenticationHelper} from '../helpers/authentication-helper'; import {SessionManagementHelper} from '../helpers/session-management-helper'; import {SPAHelper} from '../helpers/spa-helper'; -import {FetchHttpClient} from '../../FetchHttpClient'; +import {FetchHttpClient} from '../FetchHttpClient'; import {HttpError, HttpRequestConfig, HttpResponse, MainThreadClientConfig, MainThreadClientInterface} from '../models'; import {SPACustomGrantConfig} from '../models/request-custom-grant'; -import {BrowserStorage} from '../models/storage'; +import {BrowserStorage} from '../models/browser-storage'; import {LocalStore, MemoryStore, SessionStore} from '../stores'; import {SPAUtils} from '../utils'; -import {SPACryptoUtils} from '../utils/crypto-utils'; +import {SPACryptoUtils} from '../DefaultCrypto'; const initiateStore = (store: BrowserStorage | undefined): Storage => { switch (store) { @@ -60,15 +60,14 @@ export const MainThreadClient = async ( instanceId: number, config: AuthClientConfig, getAuthHelper: ( - authClient: AsgardeoAuthClient, + authClient: AsgardeoJavaScriptClient, spaHelper: SPAHelper, ) => AuthenticationHelper, ): Promise => { const _store: Storage = initiateStore(config.storage as BrowserStorage); const _cryptoUtils: SPACryptoUtils = new SPACryptoUtils(); - const _authenticationClient = new AsgardeoAuthClient(); - await _authenticationClient.initialize(config, _store, _cryptoUtils, instanceId); - + const _authenticationClient = new AsgardeoJavaScriptClient(config, _store, _cryptoUtils, instanceId); + const _spaHelper = new SPAHelper(_authenticationClient); const _dataLayer = _authenticationClient.getStorageManager(); const _sessionManagementHelper = await SessionManagementHelper( diff --git a/packages/browser/src/__legacy__/clients/web-worker-client.ts b/packages/browser/src/clients/webWorkerClient.ts similarity index 98% rename from packages/browser/src/__legacy__/clients/web-worker-client.ts rename to packages/browser/src/clients/webWorkerClient.ts index be70b1f34..79a96c479 100755 --- a/packages/browser/src/__legacy__/clients/web-worker-client.ts +++ b/packages/browser/src/clients/webWorkerClient.ts @@ -17,7 +17,7 @@ */ import { - AsgardeoAuthClient, + AsgardeoJavaScriptClient, AsgardeoAuthException, AuthClientConfig, User, @@ -79,10 +79,10 @@ interface HttpClientCallbacks { requestFinishCallback: () => void; } import {SPACustomGrantConfig} from '../models/request-custom-grant'; -import {BrowserStorage} from '../models/storage'; +import {BrowserStorage} from '../models/browser-storage'; import {LocalStore, MemoryStore, SessionStore} from '../stores'; import {SPAUtils} from '../utils'; -import {SPACryptoUtils} from '../utils/crypto-utils'; +import {SPACryptoUtils} from '../DefaultCrypto'; const initiateStore = (store: BrowserStorage | undefined): Storage => { switch (store) { @@ -102,7 +102,7 @@ export const WebWorkerClient = async ( config: AuthClientConfig, webWorker: new () => Worker, getAuthHelper: ( - authClient: AsgardeoAuthClient, + authClient: AsgardeoJavaScriptClient, spaHelper: SPAHelper, ) => AuthenticationHelper, ): Promise => { @@ -119,8 +119,7 @@ export const WebWorkerClient = async ( const _store: Storage = initiateStore(config.storage as BrowserStorage); const _cryptoUtils: SPACryptoUtils = new SPACryptoUtils(); - const _authenticationClient = new AsgardeoAuthClient(); - await _authenticationClient.initialize(config, _store, _cryptoUtils, instanceId); + const _authenticationClient = new AsgardeoJavaScriptClient(config, _store, _cryptoUtils, instanceId); const _spaHelper = new SPAHelper(_authenticationClient); const _sessionManagementHelper = await SessionManagementHelper( diff --git a/packages/browser/src/__legacy__/constants/errors.ts b/packages/browser/src/constants/errors.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/errors.ts rename to packages/browser/src/constants/errors.ts diff --git a/packages/browser/src/__legacy__/constants/hooks.ts b/packages/browser/src/constants/hooks.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/hooks.ts rename to packages/browser/src/constants/hooks.ts diff --git a/packages/browser/src/constants/index.ts b/packages/browser/src/constants/index.ts new file mode 100644 index 000000000..4c95adf6c --- /dev/null +++ b/packages/browser/src/constants/index.ts @@ -0,0 +1,6 @@ +export * from './message-types'; +export * from './storage'; +export * from './hooks'; +export * from './session-management'; +export * from './parameters'; +export * from './errors'; diff --git a/packages/browser/src/__legacy__/constants/messages-types.ts b/packages/browser/src/constants/message-types.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/messages-types.ts rename to packages/browser/src/constants/message-types.ts diff --git a/packages/browser/src/__legacy__/constants/parameters.ts b/packages/browser/src/constants/parameters.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/parameters.ts rename to packages/browser/src/constants/parameters.ts diff --git a/packages/browser/src/__legacy__/constants/session-management.ts b/packages/browser/src/constants/session-management.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/session-management.ts rename to packages/browser/src/constants/session-management.ts diff --git a/packages/browser/src/__legacy__/constants/storage.ts b/packages/browser/src/constants/storage.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/storage.ts rename to packages/browser/src/constants/storage.ts diff --git a/packages/browser/src/__legacy__/helpers/authentication-helper.ts b/packages/browser/src/helpers/authentication-helper.ts similarity index 99% rename from packages/browser/src/__legacy__/helpers/authentication-helper.ts rename to packages/browser/src/helpers/authentication-helper.ts index 867db398b..4c3c174f6 100644 --- a/packages/browser/src/__legacy__/helpers/authentication-helper.ts +++ b/packages/browser/src/helpers/authentication-helper.ts @@ -17,7 +17,7 @@ */ import { - AsgardeoAuthClient, + AsgardeoJavaScriptClient, AsgardeoAuthException, AuthClientConfig, User, @@ -56,17 +56,17 @@ import { WebWorkerClientConfig, } from '../models'; import {SPACustomGrantConfig} from '../models/request-custom-grant'; -import {BrowserStorage} from '../models/storage'; +import {BrowserStorage} from '../models/browser-storage'; import {SPAUtils} from '../utils'; export class AuthenticationHelper { - protected _authenticationClient: AsgardeoAuthClient; + protected _authenticationClient: AsgardeoJavaScriptClient; protected _storageManager: StorageManager; protected _spaHelper: SPAHelper; protected _instanceId: number; protected _isTokenRefreshing: boolean; - public constructor(authClient: AsgardeoAuthClient, spaHelper: SPAHelper) { + public constructor(authClient: AsgardeoJavaScriptClient, spaHelper: SPAHelper) { this._authenticationClient = authClient; this._storageManager = this._authenticationClient.getStorageManager(); this._spaHelper = spaHelper; diff --git a/packages/browser/src/helpers/index.ts b/packages/browser/src/helpers/index.ts new file mode 100644 index 000000000..7c9d05783 --- /dev/null +++ b/packages/browser/src/helpers/index.ts @@ -0,0 +1,3 @@ +export * from './authentication-helper'; +export * from './spa-helper'; +export * from './session-management-helper'; diff --git a/packages/browser/src/__legacy__/helpers/session-management-helper.ts b/packages/browser/src/helpers/session-management-helper.ts similarity index 97% rename from packages/browser/src/__legacy__/helpers/session-management-helper.ts rename to packages/browser/src/helpers/session-management-helper.ts index 184245c92..6ed31f52a 100644 --- a/packages/browser/src/__legacy__/helpers/session-management-helper.ts +++ b/packages/browser/src/helpers/session-management-helper.ts @@ -16,7 +16,7 @@ * under the License. */ -import {AsgardeoAuthClient, ExtendedAuthorizeRequestUrlParams, OIDCRequestConstants} from '@asgardeo/javascript'; +import {AsgardeoJavaScriptClient, ExtendedAuthorizeRequestUrlParams, OIDCRequestConstants} from '@asgardeo/javascript'; import { CHECK_SESSION_SIGNED_IN, CHECK_SESSION_SIGNED_OUT, @@ -30,7 +30,7 @@ import { STATE_QUERY, } from '../constants'; import {AuthorizationInfo, Message, SessionManagementHelperInterface} from '../models'; -import {BrowserStorage} from '../models/storage'; +import {BrowserStorage} from '../models/browser-storage'; import {SPAUtils} from '../utils'; export const SessionManagementHelper = (() => { @@ -242,7 +242,7 @@ export const SessionManagementHelper = (() => { const signOutURL = await _signOut(); // Clearing user session data before redirecting to the signOutURL because user has been already logged // out by the initial logout request in the single logout flow. - await AsgardeoAuthClient.clearSession(); + await AsgardeoJavaScriptClient.clearSession(); parent.location.href = signOutURL; window.location.href = 'about:blank'; diff --git a/packages/browser/src/__legacy__/helpers/spa-helper.ts b/packages/browser/src/helpers/spa-helper.ts similarity index 93% rename from packages/browser/src/__legacy__/helpers/spa-helper.ts rename to packages/browser/src/helpers/spa-helper.ts index e4c63e0a4..1e761c36f 100644 --- a/packages/browser/src/__legacy__/helpers/spa-helper.ts +++ b/packages/browser/src/helpers/spa-helper.ts @@ -16,17 +16,17 @@ * under the License. */ -import {AsgardeoAuthClient, StorageManager, TokenConstants} from '@asgardeo/javascript'; +import {AsgardeoJavaScriptClient, StorageManager, TokenConstants} from '@asgardeo/javascript'; import {AuthenticationHelper} from '../helpers/authentication-helper'; -import {MainThreadClientConfig, WebWorkerClientConfig} from '../models/client-config'; +import {MainThreadClientConfig, WebWorkerClientConfig} from '../models/spa-client-config'; export class SPAHelper { - private _authenticationClient: AsgardeoAuthClient; + private _authenticationClient: AsgardeoJavaScriptClient; private _storageManager: StorageManager; private _isTokenRefreshLoading: boolean = false; - public constructor(authClient: AsgardeoAuthClient) { + public constructor(authClient: AsgardeoJavaScriptClient) { this._authenticationClient = authClient; this._storageManager = this._authenticationClient.getStorageManager(); } diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index 915425028..5bdb81930 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -20,31 +20,31 @@ * Entry point for all public APIs of this SDK. */ // eslint-disable-next-line import/no-cycle -export * from './__legacy__/client'; +export * from './AsgardeoSPAClient'; // eslint-disable-next-line import/no-cycle -export * from './__legacy__/models'; +export * from './models'; // Utils // eslint-disable-next-line import/no-cycle -export * from './__legacy__/utils/spa-utils'; +export * from './utils/SPAUtils'; // Constants -export * from './__legacy__/constants/storage'; -export * from './__legacy__/constants/hooks'; +export * from './constants/storage'; +export * from './constants/hooks'; // clients -export * from './__legacy__/clients/main-thread-client'; -export * from './__legacy__/clients/web-worker-client'; +export * from './clients/mainThreadClient'; +export * from './clients/webWorkerClient'; // models -export * from './__legacy__/models/request-custom-grant'; +export * from './models/request-custom-grant'; // helpers -export * from './__legacy__/helpers/authentication-helper'; -export * from './__legacy__/helpers/spa-helper'; +export * from './helpers/authentication-helper'; +export * from './helpers/spa-helper'; // worker receiver -export * from './__legacy__/worker/worker-receiver'; +export * from './worker/workerReceiver'; export {AsgardeoBrowserConfig} from './models/config'; diff --git a/packages/browser/src/__legacy__/models/storage.ts b/packages/browser/src/models/browser-storage.ts similarity index 100% rename from packages/browser/src/__legacy__/models/storage.ts rename to packages/browser/src/models/browser-storage.ts diff --git a/packages/browser/src/__legacy__/models/http-client.ts b/packages/browser/src/models/http-client.ts similarity index 100% rename from packages/browser/src/__legacy__/models/http-client.ts rename to packages/browser/src/models/http-client.ts diff --git a/packages/browser/src/models/index.ts b/packages/browser/src/models/index.ts new file mode 100644 index 000000000..39fdafa0c --- /dev/null +++ b/packages/browser/src/models/index.ts @@ -0,0 +1,9 @@ +export * from './thread-client'; +export * from './message'; +export * from './http-client'; +export * from './web-worker'; +export * from './session-management-helper'; +export * from './sign-in'; +export * from './sign-out-error'; +export {Config as LegacyConfig} from './spa-client-config'; +export {SPAConfig, MainThreadClientConfig, WebWorkerClientConfig, AuthSPAClientConfig} from './spa-client-config'; diff --git a/packages/browser/src/__legacy__/models/message.ts b/packages/browser/src/models/message.ts similarity index 100% rename from packages/browser/src/__legacy__/models/message.ts rename to packages/browser/src/models/message.ts diff --git a/packages/browser/src/__legacy__/models/request-custom-grant.ts b/packages/browser/src/models/request-custom-grant.ts similarity index 100% rename from packages/browser/src/__legacy__/models/request-custom-grant.ts rename to packages/browser/src/models/request-custom-grant.ts diff --git a/packages/browser/src/__legacy__/models/session-management-helper.ts b/packages/browser/src/models/session-management-helper.ts similarity index 100% rename from packages/browser/src/__legacy__/models/session-management-helper.ts rename to packages/browser/src/models/session-management-helper.ts diff --git a/packages/browser/src/__legacy__/models/sign-in.ts b/packages/browser/src/models/sign-in.ts similarity index 100% rename from packages/browser/src/__legacy__/models/sign-in.ts rename to packages/browser/src/models/sign-in.ts diff --git a/packages/browser/src/__legacy__/models/sign-out-error.ts b/packages/browser/src/models/sign-out-error.ts similarity index 100% rename from packages/browser/src/__legacy__/models/sign-out-error.ts rename to packages/browser/src/models/sign-out-error.ts diff --git a/packages/browser/src/__legacy__/models/client-config.ts b/packages/browser/src/models/spa-client-config.ts similarity index 97% rename from packages/browser/src/__legacy__/models/client-config.ts rename to packages/browser/src/models/spa-client-config.ts index d4e5e9c90..3f1b3c4a7 100644 --- a/packages/browser/src/__legacy__/models/client-config.ts +++ b/packages/browser/src/models/spa-client-config.ts @@ -17,7 +17,7 @@ */ import {AuthClientConfig} from '@asgardeo/javascript'; -import {BrowserStorage} from './storage'; +import {BrowserStorage} from './browser-storage'; export interface SPAConfig { /** diff --git a/packages/browser/src/__legacy__/models/client.ts b/packages/browser/src/models/thread-client.ts similarity index 100% rename from packages/browser/src/__legacy__/models/client.ts rename to packages/browser/src/models/thread-client.ts diff --git a/packages/browser/src/__legacy__/models/web-worker.ts b/packages/browser/src/models/web-worker.ts similarity index 100% rename from packages/browser/src/__legacy__/models/web-worker.ts rename to packages/browser/src/models/web-worker.ts diff --git a/packages/browser/src/__legacy__/stores/local-store.ts b/packages/browser/src/stores/LocalStore.ts similarity index 100% rename from packages/browser/src/__legacy__/stores/local-store.ts rename to packages/browser/src/stores/LocalStore.ts diff --git a/packages/browser/src/__legacy__/stores/memory-store.ts b/packages/browser/src/stores/MemoryStore.ts similarity index 100% rename from packages/browser/src/__legacy__/stores/memory-store.ts rename to packages/browser/src/stores/MemoryStore.ts diff --git a/packages/browser/src/__legacy__/stores/session-store.ts b/packages/browser/src/stores/SessionStore.ts similarity index 100% rename from packages/browser/src/__legacy__/stores/session-store.ts rename to packages/browser/src/stores/SessionStore.ts diff --git a/packages/browser/src/stores/index.ts b/packages/browser/src/stores/index.ts new file mode 100644 index 000000000..6f6cc033d --- /dev/null +++ b/packages/browser/src/stores/index.ts @@ -0,0 +1,3 @@ +export * from './LocalStore'; +export * from './MemoryStore'; +export * from './SessionStore'; diff --git a/packages/browser/src/__legacy__/utils/message-utils.ts b/packages/browser/src/utils/MessageUtils.ts similarity index 100% rename from packages/browser/src/__legacy__/utils/message-utils.ts rename to packages/browser/src/utils/MessageUtils.ts diff --git a/packages/browser/src/__legacy__/utils/spa-utils.ts b/packages/browser/src/utils/SPAUtils.ts similarity index 95% rename from packages/browser/src/__legacy__/utils/spa-utils.ts rename to packages/browser/src/utils/SPAUtils.ts index 7122a09cc..05eff86c0 100644 --- a/packages/browser/src/__legacy__/utils/spa-utils.ts +++ b/packages/browser/src/utils/SPAUtils.ts @@ -16,8 +16,8 @@ * under the License. */ -import {AsgardeoAuthClient, OIDCRequestConstants} from '@asgardeo/javascript'; -import {SignOutError} from '../..'; +import {AsgardeoJavaScriptClient, OIDCRequestConstants} from '@asgardeo/javascript'; +import {SignOutError} from '../models/sign-out-error'; import { ERROR, ERROR_DESCRIPTION, @@ -116,11 +116,11 @@ export class SPAUtils { } public static async isSignOutSuccessful(): Promise { - if (AsgardeoAuthClient.isSignOutSuccessful(window.location.href)) { + if (AsgardeoJavaScriptClient.isSignOutSuccessful(window.location.href)) { const newUrl = window.location.href.split('?')[0]; history.pushState({}, document.title, newUrl); - await AsgardeoAuthClient.clearSession(); + await AsgardeoJavaScriptClient.clearSession(); return true; } @@ -128,7 +128,7 @@ export class SPAUtils { } public static didSignOutFail(): boolean | SignOutError { - if (AsgardeoAuthClient.didSignOutFail(window.location.href)) { + if (AsgardeoJavaScriptClient.didSignOutFail(window.location.href)) { const url: URL = new URL(window.location.href); const error: string | null = url.searchParams.get(ERROR); const description: string | null = url.searchParams.get(ERROR_DESCRIPTION); diff --git a/packages/browser/src/utils/http.ts b/packages/browser/src/utils/http.ts index a69932708..7d9a8f9e0 100644 --- a/packages/browser/src/utils/http.ts +++ b/packages/browser/src/utils/http.ts @@ -17,7 +17,7 @@ */ // eslint-disable-next-line import/no-cycle -import {AsgardeoSPAClient} from '../__legacy__/client'; +import {AsgardeoSPAClient} from '../AsgardeoSPAClient'; /** * Creates an HTTP utility for making requests using a specific AsgardeoSPAClient instance. diff --git a/packages/browser/src/utils/index.ts b/packages/browser/src/utils/index.ts new file mode 100644 index 000000000..345526184 --- /dev/null +++ b/packages/browser/src/utils/index.ts @@ -0,0 +1,2 @@ +export * from './SPAUtils'; +export * from './MessageUtils'; diff --git a/packages/browser/src/web.worker.ts b/packages/browser/src/web.worker.ts index f4981ba9c..e43d989de 100644 --- a/packages/browser/src/web.worker.ts +++ b/packages/browser/src/web.worker.ts @@ -16,12 +16,12 @@ * under the License. */ -import {AsgardeoAuthClient} from '@asgardeo/javascript'; +import {AsgardeoJavaScriptClient} from '@asgardeo/javascript'; import {Buffer} from 'buffer/'; // eslint-disable-next-line import/no-cycle -import {AuthenticationHelper, SPAHelper} from './__legacy__/helpers'; -import {WebWorkerClientConfig} from './__legacy__/models'; -import {workerReceiver} from './__legacy__/worker/worker-receiver'; +import {AuthenticationHelper, SPAHelper} from './helpers'; +import {WebWorkerClientConfig} from './models'; +import {workerReceiver} from './worker/workerReceiver'; /* eslint-disable no-restricted-globals */ // Set up global polyfills @@ -39,7 +39,7 @@ if (typeof self !== 'undefined') { /* eslint-enable no-restricted-globals */ workerReceiver( - (authClient: AsgardeoAuthClient, spaHelper: SPAHelper) => + (authClient: AsgardeoJavaScriptClient, spaHelper: SPAHelper) => new AuthenticationHelper(authClient, spaHelper), ); diff --git a/packages/browser/src/worker/index.ts b/packages/browser/src/worker/index.ts new file mode 100644 index 000000000..34c1d2e08 --- /dev/null +++ b/packages/browser/src/worker/index.ts @@ -0,0 +1,2 @@ +export * from './workerReceiver'; +export * from './workerCore'; diff --git a/packages/browser/src/__legacy__/worker/worker-core.ts b/packages/browser/src/worker/workerCore.ts similarity index 95% rename from packages/browser/src/__legacy__/worker/worker-core.ts rename to packages/browser/src/worker/workerCore.ts index e33d79471..67573e141 100755 --- a/packages/browser/src/__legacy__/worker/worker-core.ts +++ b/packages/browser/src/worker/workerCore.ts @@ -17,7 +17,7 @@ */ import { - AsgardeoAuthClient, + AsgardeoJavaScriptClient, AuthClientConfig, AuthorizeRequestUrlParams, User, @@ -30,7 +30,7 @@ import { Storage, } from '@asgardeo/javascript'; import {AuthenticationHelper, SPAHelper} from '../helpers'; -import {FetchHttpClient} from '../../FetchHttpClient'; +import {FetchHttpClient} from '../FetchHttpClient'; import { AuthorizationResponse, HttpRequestConfig, @@ -39,20 +39,19 @@ import { WebWorkerCoreInterface, } from '../models'; import {MemoryStore} from '../stores'; -import {SPACryptoUtils} from '../utils/crypto-utils'; +import {SPACryptoUtils} from '../DefaultCrypto'; export const WebWorkerCore = async ( instanceId: number, config: AuthClientConfig, getAuthHelper: ( - authClient: AsgardeoAuthClient, + authClient: AsgardeoJavaScriptClient, spaHelper: SPAHelper, ) => AuthenticationHelper, ): Promise => { const _store: Storage = new MemoryStore(); const _cryptoUtils: SPACryptoUtils = new SPACryptoUtils(); - const _authenticationClient = new AsgardeoAuthClient(); - await _authenticationClient.initialize(config, _store, _cryptoUtils, instanceId); + const _authenticationClient = new AsgardeoJavaScriptClient(config, _store, _cryptoUtils, instanceId); const _spaHelper = new SPAHelper(_authenticationClient); diff --git a/packages/browser/src/__legacy__/worker/worker-receiver.ts b/packages/browser/src/worker/workerReceiver.ts similarity index 97% rename from packages/browser/src/__legacy__/worker/worker-receiver.ts rename to packages/browser/src/worker/workerReceiver.ts index 074e815ce..f2b2f8176 100644 --- a/packages/browser/src/__legacy__/worker/worker-receiver.ts +++ b/packages/browser/src/worker/workerReceiver.ts @@ -16,8 +16,8 @@ * under the License. */ -import {AsgardeoAuthClient, AsgardeoAuthException, AuthClientConfig, User} from '@asgardeo/javascript'; -import {WebWorkerCore} from './worker-core'; +import {AsgardeoJavaScriptClient, AsgardeoAuthException, AuthClientConfig, User} from '@asgardeo/javascript'; +import {WebWorkerCore} from './workerCore'; import { DISABLE_HTTP_HANDLER, ENABLE_HTTP_HANDLER, @@ -57,7 +57,7 @@ import {MessageUtils} from '../utils'; export const workerReceiver = ( getAuthHelper: ( - authClient: AsgardeoAuthClient, + authClient: AsgardeoJavaScriptClient, spaHelper: SPAHelper, ) => AuthenticationHelper, ) => { diff --git a/packages/express/src/__legacy__/client.ts b/packages/express/src/LegacyAsgardeoExpressClient.ts similarity index 93% rename from packages/express/src/__legacy__/client.ts rename to packages/express/src/LegacyAsgardeoExpressClient.ts index fc196dace..044c8da8d 100644 --- a/packages/express/src/__legacy__/client.ts +++ b/packages/express/src/LegacyAsgardeoExpressClient.ts @@ -34,7 +34,7 @@ import {ExpressClientConfig, UnauthenticatedCallback} from './models'; import express from 'express'; import {v4 as uuidv4} from 'uuid'; import {asgardeoExpressAuth, protectRoute} from './middleware'; -import {ExpressUtils} from './utils/express-utils'; +import {ExpressUtils} from './utils/ExpressUtils'; export class AsgardeoExpressClient { private _authClient: LegacyAsgardeoNodeClient; @@ -44,24 +44,19 @@ export class AsgardeoExpressClient { private static _instance: AsgardeoExpressClient; private constructor(config: ExpressClientConfig, storage?: Storage) { - //Set the client config AsgardeoExpressClient._clientConfig = {...config}; - //Add the afterSignInUrl and afterSignOutUrl - //Add custom paths if the user has already declared any or else use the defaults const nodeClientConfig: AuthClientConfig = { ...config, afterSignInUrl: config.appURL + (config.loginPath || DEFAULT_LOGIN_PATH), afterSignOutUrl: config.appURL + (config.logoutPath || DEFAULT_LOGOUT_PATH), }; - //Initialize the user provided storage if there is any if (storage) { Logger.debug('Initializing user provided storage'); this._storage = storage; } - //Initialize the Auth Client this._authClient = new LegacyAsgardeoNodeClient(); this._authClient.initialize(nodeClientConfig, this._storage); } @@ -69,7 +64,6 @@ export class AsgardeoExpressClient { public static getInstance(config: ExpressClientConfig, storage?: Storage): AsgardeoExpressClient; public static getInstance(): AsgardeoExpressClient; public static getInstance(config?: ExpressClientConfig, storage?: Storage): AsgardeoExpressClient { - //Create a new instance if its not instantiated already if (!AsgardeoExpressClient._instance && config) { AsgardeoExpressClient._instance = new AsgardeoExpressClient(config, storage); Logger.debug('Initialized AsgardeoExpressClient successfully'); @@ -104,16 +98,13 @@ export class AsgardeoExpressClient { ); } - //Check if the user has a valid user ID and if not create one let userId = req.cookies.ASGARDEO_SESSION_ID; if (!userId) { userId = uuidv4(); } - //Handle signIn() callback const authRedirectCallback = (url: string) => { if (url) { - //DEBUG Logger.debug('Redirecting to: ' + url); res.cookie('ASGARDEO_SESSION_ID', userId, { maxAge: AsgardeoExpressClient._clientConfig.cookieConfig?.maxAge diff --git a/packages/express/src/__legacy__/constants/index.ts b/packages/express/src/__legacy__/constants/index.ts deleted file mode 100644 index 565d702c6..000000000 --- a/packages/express/src/__legacy__/constants/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.com) All Rights Reserved. - * - * WSO2 Inc. 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. - */ - -export * from "./default-options"; -export * from "./logger-config"; diff --git a/packages/express/src/__legacy__/middleware/authentication.ts b/packages/express/src/__legacy__/middleware/authentication.ts deleted file mode 100644 index cc4b7be88..000000000 --- a/packages/express/src/__legacy__/middleware/authentication.ts +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.com) All Rights Reserved. - * - * WSO2 Inc. 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 { AsgardeoAuthException, Storage, TokenResponse, Logger } from "@asgardeo/node"; -import express from "express"; -import { AsgardeoExpressClient } from "../client"; -import { DEFAULT_LOGIN_PATH, DEFAULT_LOGOUT_PATH } from "../constants"; -import { ExpressClientConfig } from "../models"; - -export const asgardeoExpressAuth = ( - asgardeoExpressClient: AsgardeoExpressClient, - config: ExpressClientConfig, - onSignIn: (res: express.Response, tokenResponse: TokenResponse) => void, - onSignOut: (res: express.Response) => void, - onError: (res: express.Response, exception: AsgardeoAuthException) => void -): any => { - //Create the router - const router = new express.Router(); - - //Patch AuthClient to the request and the response - router.use(async (req: express.Request, res: express.Response, next: express.nextFunction): Promise => { - req.asgardeoAuth = asgardeoExpressClient; - res.asgardeoAuth = asgardeoExpressClient; - next(); - }); - - //Patch in '/login' route - router.get( - config.loginPath || DEFAULT_LOGIN_PATH, - async (req: express.Request, res: express.Response, next: express.nextFunction): Promise => { - try { - const response: TokenResponse = await asgardeoExpressClient.signIn(req, res, next, config.signInConfig); - if (response.accessToken || response.idToken) { - onSignIn(res, response); - } - } catch (e: any) { - Logger.error(e.message); - onError(res, e); - } - } - ); - - //Patch in '/logout' route - router.get( - config.logoutPath || DEFAULT_LOGOUT_PATH, - async (req: express.Request, res: express.Response, next: express.nextFunction): Promise => { - //Check if it is a logout success response - if (req.query.state === "sign_out_success") { - onSignOut(res); - - return; - } - - //Check if the cookie exists - if (req.cookies.ASGARDEO_SESSION_ID === undefined) { - onError( - res, - new AsgardeoAuthException( - "EXPRESS-AUTH_MW-LOGOUT-NF01", - "No cookie found in the request", - "No cookie was sent with the request. The user may not have signed in yet." - ) - ); - - return; - } else { - //Get the signout URL - try { - const signOutURL = await req.asgardeoAuth.signOut(req.cookies.ASGARDEO_SESSION_ID); - if (signOutURL) { - res.cookie("ASGARDEO_SESSION_ID", null, { maxAge: 0 }); - res.redirect(signOutURL); - - return; - } - } catch (e: any) { - onError(res, e); - - return; - } - } - } - ); - - return router; -}; diff --git a/packages/express/src/__legacy__/middleware/index.ts b/packages/express/src/__legacy__/middleware/index.ts deleted file mode 100644 index d86cb6bc2..000000000 --- a/packages/express/src/__legacy__/middleware/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.com) All Rights Reserved. - * - * WSO2 Inc. 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. - */ - -export * from "./protect-route"; -export * from "./authentication"; diff --git a/packages/express/src/__legacy__/utils/express-utils.ts b/packages/express/src/__legacy__/utils/express-utils.ts deleted file mode 100644 index a129d9de2..000000000 --- a/packages/express/src/__legacy__/utils/express-utils.ts +++ /dev/null @@ -1,16 +0,0 @@ -export class ExpressUtils { - - private static readonly AUTH_CODE_REGEXP: RegExp = /[?&]error=[^&]+/; - - /** - * Util function to check if the URL contains an error. - * - * @param url - URL to be checked. - * - * @returns {boolean} - True if the URL contains an error. - */ - public static hasErrorInURL(url: string): boolean { - - return this.AUTH_CODE_REGEXP.test(url); - } -} diff --git a/packages/express/src/__legacy__/constants/default-options.ts b/packages/express/src/constants/default-options.ts similarity index 77% rename from packages/express/src/__legacy__/constants/default-options.ts rename to packages/express/src/constants/default-options.ts index 799cb25b7..e1668331e 100644 --- a/packages/express/src/__legacy__/constants/default-options.ts +++ b/packages/express/src/constants/default-options.ts @@ -17,12 +17,12 @@ */ export enum CookieConfig { - defaultMaxAge = 90000, - defaultHttpOnly = 'true', - defaultSameSite = 'lax', - defaultSecure = 'false' + defaultMaxAge = 90000, + defaultHttpOnly = 'true', + defaultSameSite = 'lax', + defaultSecure = 'false', } -export const DEFAULT_LOGIN_PATH = "/login"; +export const DEFAULT_LOGIN_PATH = '/login'; -export const DEFAULT_LOGOUT_PATH = "/logout"; +export const DEFAULT_LOGOUT_PATH = '/logout'; diff --git a/packages/node/src/__legacy__/stores/index.ts b/packages/express/src/constants/index.ts similarity index 90% rename from packages/node/src/__legacy__/stores/index.ts rename to packages/express/src/constants/index.ts index 110552c24..ef733110f 100644 --- a/packages/node/src/__legacy__/stores/index.ts +++ b/packages/express/src/constants/index.ts @@ -16,4 +16,5 @@ * under the License. */ -export * from './memory-cache-store'; +export * from './default-options'; +export * from './logger-config'; diff --git a/packages/express/src/__legacy__/constants/logger-config.ts b/packages/express/src/constants/logger-config.ts similarity index 78% rename from packages/express/src/__legacy__/constants/logger-config.ts rename to packages/express/src/constants/logger-config.ts index 62f6ad262..445233a45 100644 --- a/packages/express/src/__legacy__/constants/logger-config.ts +++ b/packages/express/src/constants/logger-config.ts @@ -17,12 +17,12 @@ */ export const LOGGER_CONFIG = { - bgGreen: "\x1b[42m", - bgRed: "\x1b[41m", - bgYellow: "\x1b[43m", - fgBlack: "\x1b[30m", - fgGreen: "\x1b[32m", - fgRed: "\x1b[31m", - fgYellow: "\x1b[33m", - reset: "\x1b[0m" -} + bgGreen: '\x1b[42m', + bgRed: '\x1b[41m', + bgYellow: '\x1b[43m', + fgBlack: '\x1b[30m', + fgGreen: '\x1b[32m', + fgRed: '\x1b[31m', + fgYellow: '\x1b[33m', + reset: '\x1b[0m', +}; diff --git a/packages/express/src/index.ts b/packages/express/src/index.ts index 376006554..8f7becdac 100644 --- a/packages/express/src/index.ts +++ b/packages/express/src/index.ts @@ -16,7 +16,10 @@ * under the License. */ -export * from './__legacy__/models'; -export * from './__legacy__/client'; +export * from './models'; + +export {AsgardeoExpressClient as LegacyAsgardeoExpressClient} from './LegacyAsgardeoExpressClient'; + +export {default as AsgardeoExpressClient} from './AsgardeoExpressClient'; export * from '@asgardeo/node'; diff --git a/packages/express/src/middleware/authentication.ts b/packages/express/src/middleware/authentication.ts new file mode 100644 index 000000000..4ef3ae1f6 --- /dev/null +++ b/packages/express/src/middleware/authentication.ts @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.com) All Rights Reserved. + * + * WSO2 Inc. 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 {AsgardeoAuthException, Logger, TokenResponse} from '@asgardeo/node'; +import express from 'express'; +import {AsgardeoExpressClient} from '../LegacyAsgardeoExpressClient'; +import {DEFAULT_LOGIN_PATH, DEFAULT_LOGOUT_PATH} from '../constants'; +import {ExpressClientConfig} from '../models'; + +export const asgardeoExpressAuth = ( + asgardeoExpressClient: AsgardeoExpressClient, + config: ExpressClientConfig, + onSignIn: (res: express.Response, tokenResponse: TokenResponse) => void, + onSignOut: (res: express.Response) => void, + onError: (res: express.Response, exception: AsgardeoAuthException) => void, +): any => { + const router = new express.Router(); + + router.use(async (req: express.Request, res: express.Response, next: express.nextFunction): Promise => { + req.asgardeoAuth = asgardeoExpressClient; + res.asgardeoAuth = asgardeoExpressClient; + next(); + }); + + router.get( + config.loginPath || DEFAULT_LOGIN_PATH, + async (req: express.Request, res: express.Response, next: express.nextFunction): Promise => { + try { + const response: TokenResponse = await asgardeoExpressClient.signIn(req, res, next, config.signInConfig); + if (response.accessToken || response.idToken) { + onSignIn(res, response); + } + } catch (e: any) { + Logger.error(e.message); + onError(res, e); + } + }, + ); + + router.get( + config.logoutPath || DEFAULT_LOGOUT_PATH, + async (req: express.Request, res: express.Response, next: express.nextFunction): Promise => { + if (req.query.state === 'sign_out_success') { + onSignOut(res); + + return; + } + + if (req.cookies.ASGARDEO_SESSION_ID === undefined) { + onError( + res, + new AsgardeoAuthException( + 'EXPRESS-AUTH_MW-LOGOUT-NF01', + 'No cookie found in the request', + 'No cookie was sent with the request. The user may not have signed in yet.', + ), + ); + + return; + } else { + try { + const signOutURL = await req.asgardeoAuth.signOut(req.cookies.ASGARDEO_SESSION_ID); + if (signOutURL) { + res.cookie('ASGARDEO_SESSION_ID', null, {maxAge: 0}); + res.redirect(signOutURL); + + return; + } + } catch (e: any) { + onError(res, e); + + return; + } + } + }, + ); + + return router; +}; diff --git a/packages/node/src/__legacy__/core/index.ts b/packages/express/src/middleware/index.ts similarity index 95% rename from packages/node/src/__legacy__/core/index.ts rename to packages/express/src/middleware/index.ts index 5ee2f2525..e16a05611 100644 --- a/packages/node/src/__legacy__/core/index.ts +++ b/packages/express/src/middleware/index.ts @@ -17,3 +17,4 @@ */ export * from './authentication'; +export * from './protect-route'; diff --git a/packages/express/src/__legacy__/middleware/protect-route.ts b/packages/express/src/middleware/protect-route.ts similarity index 95% rename from packages/express/src/__legacy__/middleware/protect-route.ts rename to packages/express/src/middleware/protect-route.ts index 545e0d598..fe738339a 100644 --- a/packages/express/src/__legacy__/middleware/protect-route.ts +++ b/packages/express/src/middleware/protect-route.ts @@ -16,10 +16,10 @@ * under the License. */ +import {Logger} from '@asgardeo/node'; import express from 'express'; -import {AsgardeoExpressClient} from '../client'; +import {AsgardeoExpressClient} from '../LegacyAsgardeoExpressClient'; import {UnauthenticatedCallback} from '../models'; -import {Logger} from '@asgardeo/node'; export const protectRoute = ( asgardeoExpressClient: AsgardeoExpressClient, @@ -35,7 +35,6 @@ export const protectRoute = ( return next(); } else { - //validate the cookie const isCookieValid = await asgardeoExpressClient.isSignedIn(req.cookies.ASGARDEO_SESSION_ID); if (isCookieValid) { return next(); diff --git a/packages/express/src/__legacy__/models/data.ts b/packages/express/src/models/data.ts similarity index 97% rename from packages/express/src/__legacy__/models/data.ts rename to packages/express/src/models/data.ts index 8b071cec8..77b41c4c3 100644 --- a/packages/express/src/__legacy__/models/data.ts +++ b/packages/express/src/models/data.ts @@ -17,5 +17,5 @@ */ export interface AuthURL { - url: string + url: string; } diff --git a/packages/express/src/__legacy__/models/client-config.ts b/packages/express/src/models/express-client-config.ts similarity index 100% rename from packages/express/src/__legacy__/models/client-config.ts rename to packages/express/src/models/express-client-config.ts diff --git a/packages/node/src/__legacy__/utils/index.ts b/packages/express/src/models/index.ts similarity index 84% rename from packages/node/src/__legacy__/utils/index.ts rename to packages/express/src/models/index.ts index 8445b7090..e580f271a 100644 --- a/packages/node/src/__legacy__/utils/index.ts +++ b/packages/express/src/models/index.ts @@ -16,6 +16,7 @@ * under the License. */ -// eslint-disable-next-line import/no-cycle -export * from './session-utils'; -export * from './logger-utils'; +export * from './config'; +export * from './data'; +export * from './express-client-config'; +export * from './protect-route'; diff --git a/packages/express/src/__legacy__/models/protect-route.ts b/packages/express/src/models/protect-route.ts similarity index 96% rename from packages/express/src/__legacy__/models/protect-route.ts rename to packages/express/src/models/protect-route.ts index 789c6031f..8e5a4c7e1 100644 --- a/packages/express/src/__legacy__/models/protect-route.ts +++ b/packages/express/src/models/protect-route.ts @@ -16,6 +16,6 @@ * under the License. */ -import express from "express"; +import express from 'express'; export type UnauthenticatedCallback = (res: express.Response, error: string) => boolean; diff --git a/packages/express/src/__legacy__/models/index.ts b/packages/express/src/utils/ExpressUtils.ts similarity index 76% rename from packages/express/src/__legacy__/models/index.ts rename to packages/express/src/utils/ExpressUtils.ts index ba80e6572..ee994369d 100644 --- a/packages/express/src/__legacy__/models/index.ts +++ b/packages/express/src/utils/ExpressUtils.ts @@ -16,6 +16,10 @@ * under the License. */ -export * from './data'; -export * from "./client-config"; -export * from "./protect-route"; +export class ExpressUtils { + private static readonly AUTH_CODE_REGEXP: RegExp = /[?&]error=[^&]+/; + + public static hasErrorInURL(url: string): boolean { + return this.AUTH_CODE_REGEXP.test(url); + } +} diff --git a/packages/javascript/src/AsgardeoJavaScriptClient.ts b/packages/javascript/src/AsgardeoJavaScriptClient.ts index 2998b15ab..e57527ca8 100644 --- a/packages/javascript/src/AsgardeoJavaScriptClient.ts +++ b/packages/javascript/src/AsgardeoJavaScriptClient.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2025-2026, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2025, 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 @@ -16,17 +16,28 @@ * under the License. */ -import {AsgardeoAuthClient} from './__legacy__/client'; -import {AuthClientConfig} from './__legacy__/models/client-config'; +import exchangeToken from './api/exchangeToken'; import executeEmbeddedSignInFlow from './api/executeEmbeddedSignInFlow'; import initializeEmbeddedSignInFlow from './api/initializeEmbeddedSignInFlow'; +import loadOpenIDProviderConfiguration from './api/loadOpenIDProviderConfiguration'; +import refreshAccessToken from './api/refreshAccessToken'; +import requestAccessToken from './api/requestAccessToken'; +import revokeAccessToken from './api/revokeAccessToken'; +import OIDCDiscoveryConstants from './constants/OIDCDiscoveryConstants'; +import OIDCDiscoveryConstantsV2 from './constants/v2/OIDCDiscoveryConstants'; +import OIDCRequestConstants from './constants/OIDCRequestConstants'; +import PKCEConstants from './constants/PKCEConstants'; import {DefaultCacheStore} from './DefaultCacheStore'; import {DefaultCrypto} from './DefaultCrypto'; +import {AsgardeoAuthException} from './errors/exception'; +import {IsomorphicCrypto} from './IsomorphicCrypto'; import {AgentConfig} from './models/agent'; import {AuthCodeResponse} from './models/auth-code-response'; +import {AuthClientConfig, StrictAuthClientConfig} from './models/auth-client-config'; import {AsgardeoClient} from './models/client'; import {Config, SignInOptions, SignOutOptions, SignUpOptions} from './models/config'; import {Crypto} from './models/crypto'; +import {ExtendedAuthorizeRequestUrlParams} from './models/oauth-request'; import { EmbeddedFlowExecuteRequestConfig, EmbeddedFlowExecuteRequestPayload, @@ -39,34 +50,117 @@ import { EmbeddedSignInFlowStatus, } from './models/embedded-signin-flow'; import {OIDCDiscoveryApiResponse} from './models/oidc-discovery'; +import {OIDCEndpoints} from './models/oidc-endpoints'; +import {Platform} from './models/platforms'; +import {SessionData, UserSession} from './models/session'; import {AllOrganizationsApiResponse, Organization} from './models/organization'; -import {Storage} from './models/store'; -import {TokenExchangeRequestConfig, TokenResponse} from './models/token'; +import {Storage, TemporaryStore} from './models/store'; +import {TokenExchangeRequestConfig, TokenResponse, IdToken} from './models/token'; import {User, UserProfile} from './models/user'; import StorageManager from './StorageManager'; +import clearSession from './utils/clearSession'; +import deepMerge from './utils/deepMerge'; +import extractPkceStorageKeyFromState from './utils/extractPkceStorageKeyFromState'; +import generatePkceStorageKey from './utils/generatePkceStorageKey'; +import getAuthenticatedUserInfo from './utils/getAuthenticatedUserInfo'; +import getAuthorizeRequestUrlParams from './utils/getAuthorizeRequestUrlParams'; +import processOpenIDScopes from './utils/processOpenIDScopes'; + +const DefaultOIDCConfig: Partial> = { + enablePKCE: true, + responseMode: 'query', + sendCookiesInRequests: true, + tokenValidation: { + idToken: { + clockTolerance: 300, + validate: true, + validateIssuer: true, + }, + }, +}; class AsgardeoJavaScriptClient implements AsgardeoClient { - private cacheStore: Storage; + private storageManager!: StorageManager; private cryptoUtils: Crypto; - private auth: AsgardeoAuthClient; + private cryptoHelper: IsomorphicCrypto; - private storageManager: StorageManager; + private instanceIdValue: number; private baseURL: string; - constructor(config?: AuthClientConfig, cacheStore?: Storage, cryptoUtils?: Crypto) { - this.cacheStore = cacheStore ?? new DefaultCacheStore(); + static _storageManager: StorageManager; + + constructor(config?: AuthClientConfig, store?: Storage, cryptoUtils?: Crypto, instanceId?: number) { + const cacheStore: Storage = store ?? new DefaultCacheStore(); + this.cryptoUtils = cryptoUtils ?? new DefaultCrypto(); - this.auth = new AsgardeoAuthClient(); + this.cryptoHelper = new IsomorphicCrypto(this.cryptoUtils); + this.instanceIdValue = instanceId ?? 0; + this.baseURL = config?.baseUrl ?? ''; if (config) { - this.auth.initialize(config, this.cacheStore, this.cryptoUtils); - this.storageManager = this.auth.getStorageManager(); + this._initStorage(config, cacheStore); } + } - this.baseURL = config?.baseUrl ?? ''; + public async initialize(config: T, storage?: Storage): Promise { + const store: Storage = storage ?? new DefaultCacheStore(); + + this.baseURL = (config as any)?.baseUrl ?? ''; + await this._initStorage(config as unknown as AuthClientConfig, store); + + return true; + } + + private async _initStorage(config: AuthClientConfig, store: Storage): Promise { + const {clientId} = config; + + if (!clientId) { + this.storageManager = new StorageManager(`instance_${this.instanceIdValue}`, store); + } else { + this.storageManager = new StorageManager(`instance_${this.instanceIdValue}-${clientId}`, store); + } + + AsgardeoJavaScriptClient._storageManager = this.storageManager; + + const {applicationId, platform, endpoints} = config; + let resolvedApplicationId: string | undefined = applicationId; + + if (applicationId) { + await this.storageManager.setPersistedData({applicationId}); + } else { + const persistedData: TemporaryStore = await this.storageManager.getPersistedData(); + + if (persistedData['applicationId']) { + resolvedApplicationId = persistedData['applicationId'] as string; + } + } + + const resolvedEndpoints: Partial = endpoints || {}; + + if (platform === Platform.AsgardeoV2) { + if (!resolvedEndpoints['wellKnown']) { + resolvedEndpoints['wellKnown'] = OIDCDiscoveryConstantsV2.Endpoints.WELL_KNOWN; + } + } + + await this.storageManager.setConfigData({ + ...DefaultOIDCConfig, + ...config, + applicationId: resolvedApplicationId, + endpoints: resolvedEndpoints, + scope: processOpenIDScopes(config.scopes), + }); + } + + public getStorageManager(): StorageManager { + return this.storageManager; + } + + public getInstanceId(): number { + return this.instanceIdValue; } public async getDiscoveryResponse(): Promise { @@ -77,112 +171,292 @@ class AsgardeoJavaScriptClient implements AsgardeoClient { return this.storageManager.loadOpenIDProviderConfiguration(); } - /* eslint-disable class-methods-use-this, @typescript-eslint/no-unused-vars */ - switchOrganization(_organization: Organization, _sessionId?: string): Promise { - throw new Error('Method not implemented.'); - } + public async getSignInUrl(requestConfig?: ExtendedAuthorizeRequestUrlParams, userId?: string): Promise { + const authRequestConfig: ExtendedAuthorizeRequestUrlParams = {...requestConfig}; + + delete authRequestConfig?.forceInit; + + const buildSignInUrl = async (): Promise => { + const authorizeEndpoint: string = (await this.storageManager.getOIDCProviderMetaDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.AUTHORIZATION as keyof OIDCDiscoveryApiResponse, + )) as string; + + if (!authorizeEndpoint || authorizeEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GAU-NF01', + 'No authorization endpoint found.', + 'No authorization endpoint was found in the OIDC provider meta data from the well-known endpoint ' + + 'or the authorization endpoint passed to the SDK is empty.', + ); + } + + const authorizeRequest: URL = new URL(authorizeEndpoint); + const configData: StrictAuthClientConfig = await this.storageManager.getConfigData(); + const tempStore: TemporaryStore = await this.storageManager.getTemporaryData(userId); + const pkceKey: string = await generatePkceStorageKey(tempStore); + + let codeVerifier: string | undefined; + let codeChallenge: string | undefined; + + if (configData.enablePKCE) { + codeVerifier = this.cryptoHelper?.getCodeVerifier(); + codeChallenge = await this.cryptoHelper?.getCodeChallenge(codeVerifier); + await this.storageManager.setTemporaryDataParameter(pkceKey, codeVerifier, userId); + } + + if (authRequestConfig['client_secret']) { + authRequestConfig['client_secret'] = configData.clientSecret; + } + + const authorizeRequestParams: Map = getAuthorizeRequestUrlParams( + { + clientId: configData.clientId, + codeChallenge, + codeChallengeMethod: PKCEConstants.DEFAULT_CODE_CHALLENGE_METHOD, + instanceId: this.getInstanceId().toString(), + prompt: configData.prompt, + redirectUri: configData.afterSignInUrl, + responseMode: configData.responseMode, + scopes: processOpenIDScopes(configData.scopes), + }, + {key: pkceKey}, + authRequestConfig, + ); - initialize(_config: T, _storage?: Storage): Promise { - throw new Error('Method not implemented.'); + Array.from(authorizeRequestParams.entries()).forEach(([paramKey, paramValue]: [string, string]) => { + authorizeRequest.searchParams.append(paramKey, paramValue); + }); + + return authorizeRequest.toString(); + }; + + if ( + await this.storageManager.getTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + ) + ) { + return buildSignInUrl(); + } + + return loadOpenIDProviderConfiguration(this.storageManager, requestConfig?.forceInit as boolean).then(() => + buildSignInUrl(), + ); } - reInitialize(_config: Partial): Promise { - throw new Error('Method not implemented.'); + public async requestAccessToken( + authorizationCode: string, + sessionState: string, + state: string, + userId?: string, + tokenRequestConfig?: {params: Record}, + ): Promise { + return requestAccessToken( + this.storageManager, + this.cryptoHelper, + authorizationCode, + sessionState, + state, + userId, + tokenRequestConfig, + ); } - getUser(_options?: any): Promise { - throw new Error('Method not implemented.'); + public async loadOpenIDProviderConfiguration(forceInit: boolean): Promise { + return loadOpenIDProviderConfiguration(this.storageManager, forceInit); } - getAllOrganizations(_options?: any, _sessionId?: string): Promise { - throw new Error('Method not implemented.'); + public async getSignOutUrl(userId?: string): Promise { + const logoutEndpoint: string | undefined = (await this.storageManager.loadOpenIDProviderConfiguration()) + ?.end_session_endpoint; + const configData: StrictAuthClientConfig = await this.storageManager.getConfigData(); + + if (!logoutEndpoint || logoutEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GSOU-NF01', + 'Sign-out endpoint not found.', + 'No sign-out endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + + 'or the sign-out endpoint passed to the SDK is empty.', + ); + } + + const callbackURL: string = configData?.afterSignOutUrl ?? configData?.afterSignInUrl; + + if (!callbackURL || callbackURL.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GSOU-NF03', + 'No sign-out redirect URL found.', + 'The sign-out redirect URL cannot be found or the URL passed to the SDK is empty. ' + + 'No sign-in redirect URL has been found either. ', + ); + } + + const queryParams: URLSearchParams = new URLSearchParams(); + + queryParams.set('post_logout_redirect_uri', callbackURL); + + if (configData.sendIdTokenInLogoutRequest) { + const idToken: string = (await this.storageManager.getSessionData(userId))?.id_token; + + if (!idToken || idToken.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GSOU-NF02', + 'ID token not found.', + 'No ID token could be found. Either the session information is lost or you have not signed in.', + ); + } + queryParams.set('id_token_hint', idToken); + } else { + queryParams.set('client_id', configData.clientId); + } + + queryParams.set('state', OIDCRequestConstants.Params.SIGN_OUT_SUCCESS); + + return `${logoutEndpoint}?${queryParams.toString()}`; } - getMyOrganizations(_options?: any, _sessionId?: string): Promise { - throw new Error('Method not implemented.'); + public async getOpenIDProviderEndpoints(): Promise> { + const oidcProviderMetaData: OIDCDiscoveryApiResponse = await this.storageManager.loadOpenIDProviderConfiguration(); + + return { + authorizationEndpoint: oidcProviderMetaData.authorization_endpoint ?? '', + checkSessionIframe: oidcProviderMetaData.check_session_iframe ?? '', + endSessionEndpoint: oidcProviderMetaData.end_session_endpoint ?? '', + introspectionEndpoint: oidcProviderMetaData.introspection_endpoint ?? '', + issuer: oidcProviderMetaData.issuer ?? '', + jwksUri: oidcProviderMetaData.jwks_uri ?? '', + registrationEndpoint: oidcProviderMetaData.registration_endpoint ?? '', + revocationEndpoint: oidcProviderMetaData.revocation_endpoint ?? '', + tokenEndpoint: oidcProviderMetaData.token_endpoint ?? '', + userinfoEndpoint: oidcProviderMetaData.userinfo_endpoint ?? '', + }; } - getCurrentOrganization(_sessionId?: string): Promise { - throw new Error('Method not implemented.'); + public async decodeJwtToken>(token: string): Promise { + return this.cryptoHelper.decodeJwtToken(token); } - getUserProfile(_options?: any): Promise { - throw new Error('Method not implemented.'); + public async getDecodedIdToken(userId?: string, idToken?: string): Promise { + const storedIdToken: string = (await this.storageManager.getSessionData(userId)).id_token; + + return this.cryptoHelper.decodeJwtToken(storedIdToken ?? idToken); } - isLoading(): boolean { - throw new Error('Method not implemented.'); + public async getIdToken(userId?: string): Promise { + return (await this.storageManager.getSessionData(userId)).id_token; } - isSignedIn(): Promise { - throw new Error('Method not implemented.'); + public async getUser(userId?: string): Promise { + const sessionData: SessionData = await this.storageManager.getSessionData(userId); + const authenticatedUser: User = getAuthenticatedUserInfo(this.cryptoHelper, sessionData?.id_token); + + Object.keys(authenticatedUser).forEach((key: string) => { + if (authenticatedUser[key] === undefined || authenticatedUser[key] === '' || authenticatedUser[key] === null) { + delete authenticatedUser[key]; + } + }); + + return authenticatedUser; } - updateUserProfile(_payload: any, _userId?: string): Promise { - throw new Error('Method not implemented.'); + public async getUserSession(userId?: string): Promise { + const sessionData: SessionData = await this.storageManager.getSessionData(userId); + + return { + scopes: sessionData?.scope?.split(' '), + sessionState: sessionData?.session_state ?? '', + }; } - getConfiguration(): T { - throw new Error('Method not implemented.'); + public async getCrypto(): Promise { + return this.cryptoHelper; } - exchangeToken(_config: TokenExchangeRequestConfig, _sessionId?: string): Promise { - throw new Error('Method not implemented.'); + public async revokeAccessToken(userId?: string): Promise { + return revokeAccessToken(this.storageManager, userId); } - signInSilently(_options?: SignInOptions): Promise { - throw new Error('Method not implemented.'); + public async refreshAccessToken(userId?: string): Promise { + return refreshAccessToken(this.storageManager, this.cryptoHelper, userId); } - getAccessToken(_sessionId?: string): Promise { - throw new Error('Method not implemented.'); + public async getAccessToken(userId?: string): Promise { + return (await this.storageManager.getSessionData(userId))?.access_token; } - clearSession(_sessionId?: string): void { - throw new Error('Method not implemented.'); + public async exchangeToken(config: TokenExchangeRequestConfig, userId?: string): Promise { + return exchangeToken(this.storageManager, this.cryptoHelper, config, userId); } - setSession(_sessionData: Record, _sessionId?: string): Promise { - throw new Error('Method not implemented.'); + public async isSignedIn(userId?: string): Promise { + const isAccessTokenAvailable: boolean = Boolean(await this.getAccessToken(userId)); + const sessionData: SessionData = await this.storageManager.getSessionData(userId); + const expiresInString: string = sessionData?.expires_in; + + if (!expiresInString) { + return false; + } + + const expiresIn: number = parseInt(expiresInString, 10) * 1000; + const isAccessTokenValid: boolean = sessionData.created_at + expiresIn > new Date().getTime(); + + return isAccessTokenAvailable && isAccessTokenValid; } - decodeJwtToken>(_token: string): Promise { - throw new Error('Method not implemented.'); + public async getPKCECode(state: string, userId?: string): Promise { + return (await this.storageManager.getTemporaryDataParameter( + extractPkceStorageKeyFromState(state), + userId, + )) as string; } - signIn(_options?: SignInOptions): Promise { - throw new Error('Method not implemented.'); + public async setPKCECode(pkce: string, state: string, userId?: string): Promise { + return this.storageManager.setTemporaryDataParameter(extractPkceStorageKeyFromState(state), pkce, userId); } - signOut( - _options?: SignOutOptions, - _sessionIdOrAfterSignOut?: string | ((afterSignOutUrl: string) => void), - _afterSignOut?: (afterSignOutUrl: string) => void, - ): Promise { - throw new Error('Method not implemented.'); + public static isSignOutSuccessful(afterSignOutUrl: string): boolean { + const url: URL = new URL(afterSignOutUrl); + const stateParam: string | null = url.searchParams.get(OIDCRequestConstants.Params.STATE); + const error: boolean = Boolean(url.searchParams.get('error')); + + return stateParam ? stateParam === OIDCRequestConstants.Params.SIGN_OUT_SUCCESS && !error : false; } - recover(_payload: EmbeddedFlowExecuteRequestPayload): Promise { - throw new Error('Method not implemented.'); + public static didSignOutFail(afterSignOutUrl: string): boolean { + const url: URL = new URL(afterSignOutUrl); + const stateParam: string | null = url.searchParams.get(OIDCRequestConstants.Params.STATE); + const error: boolean = Boolean(url.searchParams.get('error')); + + return stateParam ? stateParam === OIDCRequestConstants.Params.SIGN_OUT_SUCCESS && error : false; } - signUp(options?: SignUpOptions): Promise; + public async reInitialize(config: Partial): Promise { + const currentConfig: T = this.storageManager.getConfigData() as unknown as T; + const newConfig: T = deepMerge(currentConfig, config); - signUp(payload: EmbeddedFlowExecuteRequestPayload): Promise; + await this.storageManager.setConfigData(newConfig as unknown as AuthClientConfig); + await loadOpenIDProviderConfiguration(this.storageManager, true); - signUp( - _optionsOrPayload?: SignUpOptions | EmbeddedFlowExecuteRequestPayload, - ): Promise { - throw new Error('Method not implemented.'); + return true; + } + + public clearSession(sessionId?: string): void { + if (this.storageManager) { + clearSession(this.storageManager, sessionId); + } + } + + public static async clearSession(userId?: string): Promise { + if (AsgardeoJavaScriptClient._storageManager) { + await clearSession(AsgardeoJavaScriptClient._storageManager, userId); + } } - /* eslint-enable class-methods-use-this, @typescript-eslint/no-unused-vars */ public async getAgentToken(agentConfig: AgentConfig): Promise { const customParam: Record = { response_mode: 'direct', }; - const authorizeURL: URL = new URL(await this.auth.getSignInUrl(customParam)); + const authorizeURL: URL = new URL(await this.getSignInUrl(customParam)); const authorizeResponse: EmbeddedSignInFlowInitiateResponse = await initializeEmbeddedSignInFlow({ payload: Object.fromEntries(authorizeURL.searchParams.entries()), @@ -220,7 +494,7 @@ class AsgardeoJavaScriptClient implements AsgardeoClient { throw new Error('Agent authentication failed.'); } - return this.auth.requestAccessToken( + return this.requestAccessToken( authnResponse.authData['code'], authnResponse.authData['session_state'], authnResponse.authData['state'], @@ -232,7 +506,7 @@ class AsgardeoJavaScriptClient implements AsgardeoClient { requested_actor: agentConfig.agentID, }; - const authURL: string | undefined = await this.auth.getSignInUrl(customParam); + const authURL: string | undefined = await this.getSignInUrl(customParam); if (authURL) { return authURL.toString(); @@ -244,20 +518,82 @@ class AsgardeoJavaScriptClient implements AsgardeoClient { public async getOBOToken(agentConfig: AgentConfig, authCodeResponse: AuthCodeResponse): Promise { const agentToken: TokenResponse = await this.getAgentToken(agentConfig); - const tokenRequestConfig: {params: {actor_token: string}} = { - params: { - actor_token: agentToken.accessToken, - }, - }; - - return this.auth.requestAccessToken( + return this.requestAccessToken( authCodeResponse.code, authCodeResponse.session_state, authCodeResponse.state, undefined, - tokenRequestConfig, + {params: {actor_token: agentToken.accessToken}}, ); } + + /* eslint-disable class-methods-use-this, @typescript-eslint/no-unused-vars */ + switchOrganization(_organization: Organization, _sessionId?: string): Promise { + throw new Error('Method not implemented.'); + } + + getAllOrganizations(_options?: any, _sessionId?: string): Promise { + throw new Error('Method not implemented.'); + } + + getMyOrganizations(_options?: any, _sessionId?: string): Promise { + throw new Error('Method not implemented.'); + } + + getCurrentOrganization(_sessionId?: string): Promise { + throw new Error('Method not implemented.'); + } + + getUserProfile(_options?: any): Promise { + throw new Error('Method not implemented.'); + } + + isLoading(): boolean { + throw new Error('Method not implemented.'); + } + + updateUserProfile(_payload: any, _userId?: string): Promise { + throw new Error('Method not implemented.'); + } + + getConfiguration(): T { + throw new Error('Method not implemented.'); + } + + recover(_payload: EmbeddedFlowExecuteRequestPayload): Promise { + throw new Error('Method not implemented.'); + } + + signInSilently(_options?: SignInOptions): Promise { + throw new Error('Method not implemented.'); + } + + setSession(_sessionData: Record, _sessionId?: string): Promise { + throw new Error('Method not implemented.'); + } + + signIn(_options?: SignInOptions): Promise { + throw new Error('Method not implemented.'); + } + + signOut( + _options?: SignOutOptions, + _sessionIdOrAfterSignOut?: string | ((afterSignOutUrl: string) => void), + _afterSignOut?: (afterSignOutUrl: string) => void, + ): Promise { + throw new Error('Method not implemented.'); + } + + signUp(options?: SignUpOptions): Promise; + + signUp(payload: EmbeddedFlowExecuteRequestPayload): Promise; + + signUp( + _optionsOrPayload?: SignUpOptions | EmbeddedFlowExecuteRequestPayload, + ): Promise { + throw new Error('Method not implemented.'); + } + /* eslint-enable class-methods-use-this, @typescript-eslint/no-unused-vars */ } export default AsgardeoJavaScriptClient; diff --git a/packages/javascript/src/StorageManager.ts b/packages/javascript/src/StorageManager.ts index 1225bf917..6f8f2b95f 100644 --- a/packages/javascript/src/StorageManager.ts +++ b/packages/javascript/src/StorageManager.ts @@ -16,7 +16,7 @@ * under the License. */ -import {AuthClientConfig} from './__legacy__/models'; +import {AuthClientConfig} from './models/auth-client-config'; import {OIDCDiscoveryApiResponse} from './models/oidc-discovery'; import {SessionData} from './models/session'; import {Stores, Storage, TemporaryStore, TemporaryStoreValue} from './models/store'; diff --git a/packages/javascript/src/__legacy__/client.ts b/packages/javascript/src/__legacy__/client.ts deleted file mode 100644 index 113867f19..000000000 --- a/packages/javascript/src/__legacy__/client.ts +++ /dev/null @@ -1,1189 +0,0 @@ -/** - * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. - * - * 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 {AuthenticationHelper} from './helpers'; -import {AuthClientConfig, StrictAuthClientConfig} from './models'; -import OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; -import OIDCRequestConstants from '../constants/OIDCRequestConstants'; -import PKCEConstants from '../constants/PKCEConstants'; -import OIDCDiscoveryConstantsV2 from '../constants/v2/OIDCDiscoveryConstants'; -import {AsgardeoAuthException} from '../errors/exception'; -import {IsomorphicCrypto} from '../IsomorphicCrypto'; -import {Crypto} from '../models/crypto'; -import {ExtendedAuthorizeRequestUrlParams} from '../models/oauth-request'; -import {OIDCDiscoveryApiResponse} from '../models/oidc-discovery'; -import {OIDCEndpoints} from '../models/oidc-endpoints'; -import {Platform} from '../models/platforms'; -import {SessionData, UserSession} from '../models/session'; -import {Storage, TemporaryStore} from '../models/store'; -import {TokenResponse, IdToken, TokenExchangeRequestConfig} from '../models/token'; -import {User} from '../models/user'; -import StorageManager from '../StorageManager'; -import deepMerge from '../utils/deepMerge'; -import extractPkceStorageKeyFromState from '../utils/extractPkceStorageKeyFromState'; -import generatePkceStorageKey from '../utils/generatePkceStorageKey'; -import getAuthorizeRequestUrlParams from '../utils/getAuthorizeRequestUrlParams'; -import processOpenIDScopes from '../utils/processOpenIDScopes'; - -/** - * Default configurations. - */ -const DefaultConfig: Partial> = { - enablePKCE: true, - responseMode: 'query', - sendCookiesInRequests: true, - tokenValidation: { - idToken: { - clockTolerance: 300, - validate: true, - validateIssuer: true, - }, - }, -}; - -/** - * This class provides the necessary methods needed to implement authentication. - */ -export class AsgardeoAuthClient { - private storageManager!: StorageManager; - - private configProvider: () => Promise; - - private oidcProviderMetaDataProvider: () => Promise; - - private authHelper: AuthenticationHelper; - - private cryptoUtils: Crypto; - - private cryptoHelper: IsomorphicCrypto; - - private instanceIdValue: number; - - // FIXME: Validate this. - // Ref: https://github.com/asgardeo/asgardeo-auth-js-core/pull/205 - static authHelperInstance: any; - - /** - * This is the constructor method that returns an instance of the . - * - * @param store - The store object. - * - * @example - * ``` - * const _store: Store = new DataStore(); - * const auth = new AsgardeoAuthClient(_store); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#constructor} - * - * @preserve - */ - public constructor() { - // intentionally empty - } - - /** - * - * This method initializes the SDK with the config data. - * - * @param config - The config object to initialize with. - * - * @example - * const config = \{ - * afterSignInUrl: "http://localhost:3000/sign-in", - * clientId: "client ID", - * baseUrl: "https://localhost:9443" - * \} - * - * await auth.initialize(config); - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#initialize} - * - * @preserve - */ - public async initialize( - config: AuthClientConfig, - store: Storage, - inputCryptoUtils: Crypto, - instanceID?: number, - ): Promise { - const {clientId} = config; - - if (!this.instanceIdValue) { - this.instanceIdValue = 0; - } else { - this.instanceIdValue += 1; - } - - if (instanceID !== undefined) { - this.instanceIdValue = instanceID; - } - - if (!clientId) { - this.storageManager = new StorageManager(`instance_${this.instanceIdValue}`, store); - } else { - this.storageManager = new StorageManager(`instance_${this.instanceIdValue}-${clientId}`, store); - } - - this.cryptoUtils = inputCryptoUtils; - this.cryptoHelper = new IsomorphicCrypto(inputCryptoUtils); - this.authHelper = new AuthenticationHelper(this.storageManager, this.cryptoHelper); - this.configProvider = async (): Promise => this.storageManager.getConfigData(); - this.oidcProviderMetaDataProvider = async (): Promise => - this.storageManager.loadOpenIDProviderConfiguration(); - - // FIXME: Validate this. - // Ref: https://github.com/asgardeo/asgardeo-auth-js-core/pull/205 - AsgardeoAuthClient.authHelperInstance = this.authHelper; - - const {applicationId, platform, endpoints} = config; - let resolvedApplicationId: string | undefined = applicationId; - - if (applicationId) { - await this.storageManager.setPersistedData({ - applicationId, - }); - } else { - const persistedData: TemporaryStore = await this.storageManager.getPersistedData(); - - if (persistedData['applicationId']) { - resolvedApplicationId = persistedData['applicationId'] as string; - } - } - - const resolvedEndpoints: Partial = endpoints || {}; - - if (platform === Platform.AsgardeoV2) { - if (!resolvedEndpoints['wellKnown']) { - resolvedEndpoints['wellKnown'] = OIDCDiscoveryConstantsV2.Endpoints.WELL_KNOWN; - } - } - - await this.storageManager.setConfigData({ - ...DefaultConfig, - ...config, - applicationId: resolvedApplicationId, - endpoints: resolvedEndpoints, - scope: processOpenIDScopes(config.scopes), - }); - } - - /** - * This method returns the `StorageManager` object that allows you to access authentication data. - * - * @returns - The `StorageManager` object. - * - * @example - * ``` - * const data = auth.getStorageManager(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getStorageManager} - * - * @preserve - */ - public getStorageManager(): StorageManager { - return this.storageManager; - } - - /** - * This method returns the `instanceID` variable of the given instance. - * - * @returns - The `instanceID` number. - * - * @example - * ``` - * const instanceId = auth.getInstanceId(); - * ``` - * - * @preserve - */ - // eslint-disable-next-line class-methods-use-this - public getInstanceId(): number { - return this.instanceIdValue; - } - - /** - * This is an async method that returns a Promise that resolves with the authorization URL. - * - * @param config - (Optional) A config object to force initialization and pass - * custom path parameters such as the fidp parameter. - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A promise that resolves with the authorization URL. - * - * @example - * ``` - * auth.getSignInUrl().then((url)=>{ - * // console.log(url); - * }).catch((error)=>{ - * // console.error(error); - * }); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getSignInUrl} - * - * @preserve - */ - public async getSignInUrl(requestConfig?: ExtendedAuthorizeRequestUrlParams, userId?: string): Promise { - const authRequestConfig: ExtendedAuthorizeRequestUrlParams = {...requestConfig}; - - delete authRequestConfig?.forceInit; - - const buildSignInUrl = async (): Promise => { - const authorizeEndpoint: string = (await this.storageManager.getOIDCProviderMetaDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.AUTHORIZATION as keyof OIDCDiscoveryApiResponse, - )) as string; - - if (!authorizeEndpoint || authorizeEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GAU-NF01', - 'No authorization endpoint found.', - 'No authorization endpoint was found in the OIDC provider meta data from the well-known endpoint ' + - 'or the authorization endpoint passed to the SDK is empty.', - ); - } - - const authorizeRequest: URL = new URL(authorizeEndpoint); - const configData: StrictAuthClientConfig = await this.configProvider(); - const tempStore: TemporaryStore = await this.storageManager.getTemporaryData(userId); - const pkceKey: string = await generatePkceStorageKey(tempStore); - - let codeVerifier: string | undefined; - let codeChallenge: string | undefined; - - if (configData.enablePKCE) { - codeVerifier = this.cryptoHelper?.getCodeVerifier(); - codeChallenge = await this.cryptoHelper?.getCodeChallenge(codeVerifier); - await this.storageManager.setTemporaryDataParameter(pkceKey, codeVerifier, userId); - } - - if (authRequestConfig['client_secret']) { - authRequestConfig['client_secret'] = configData.clientSecret; - } - - const authorizeRequestParams: Map = getAuthorizeRequestUrlParams( - { - clientId: configData.clientId, - codeChallenge, - codeChallengeMethod: PKCEConstants.DEFAULT_CODE_CHALLENGE_METHOD, - instanceId: this.getInstanceId().toString(), - prompt: configData.prompt, - redirectUri: configData.afterSignInUrl, - responseMode: configData.responseMode, - scopes: processOpenIDScopes(configData.scopes), - }, - {key: pkceKey}, - authRequestConfig, - ); - - Array.from(authorizeRequestParams.entries()).forEach(([paramKey, paramValue]: [string, string]) => { - authorizeRequest.searchParams.append(paramKey, paramValue); - }); - - return authorizeRequest.toString(); - }; - - if ( - await this.storageManager.getTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - ) - ) { - return buildSignInUrl(); - } - - return this.loadOpenIDProviderConfiguration(requestConfig?.forceInit as boolean).then(() => buildSignInUrl()); - } - - /** - * This is an async method that sends a request to obtain the access token and returns a Promise - * that resolves with the token and other relevant data. - * - * @param authorizationCode - The authorization code. - * @param sessionState - The session state. - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the token response. - * - * @example - * ``` - * auth.requestAccessToken(authCode, sessionState).then((token)=>{ - * // console.log(token); - * }).catch((error)=>{ - * // console.error(error); - * }); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#requestAccessToken} - * - * - * @preserve - */ - public async requestAccessToken( - authorizationCode: string, - sessionState: string, - state: string, - userId?: string, - tokenRequestConfig?: { - params: Record; - }, - ): Promise { - if ( - !(await this.storageManager.getTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - )) - ) { - await this.loadOpenIDProviderConfiguration(false); - } - - const tokenEndpoint: string | undefined = (await this.oidcProviderMetaDataProvider()).token_endpoint; - const configData: StrictAuthClientConfig = await this.configProvider(); - - if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT1-NF01', - 'Token endpoint not found.', - 'No token endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + - 'or the token endpoint passed to the SDK is empty.', - ); - } - - if (sessionState) { - await this.storageManager.setSessionDataParameter( - OIDCRequestConstants.Params.SESSION_STATE as keyof SessionData, - sessionState, - userId, - ); - } - - const body: URLSearchParams = new URLSearchParams(); - - body.set('client_id', configData.clientId); - - if (configData.clientSecret && configData.clientSecret.trim().length > 0) { - body.set('client_secret', configData.clientSecret); - } - - const code: string = authorizationCode; - - body.set('code', code); - - body.set('grant_type', 'authorization_code'); - body.set('redirect_uri', configData.afterSignInUrl); - - if (tokenRequestConfig?.params) { - Object.entries(tokenRequestConfig.params).forEach(([key, value]: [key: string, value: unknown]) => { - body.append(key, value as string); - }); - } - - if (configData.enablePKCE) { - body.set( - 'code_verifier', - `${await this.storageManager.getTemporaryDataParameter(extractPkceStorageKeyFromState(state), userId)}`, - ); - - await this.storageManager.removeTemporaryDataParameter(extractPkceStorageKeyFromState(state), userId); - } - - let tokenResponse: Response; - - try { - tokenResponse = await fetch(tokenEndpoint, { - body, - credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - }, - method: 'POST', - }); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT1-NE02', - 'Requesting access token failed', - error ?? 'The request to get the access token from the server failed.', - ); - } - - if (!tokenResponse.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT1-HE03', - `Requesting access token failed with ${tokenResponse.statusText}`, - (await tokenResponse.json()) as string, - ); - } - - return this.authHelper.handleTokenResponse(tokenResponse, userId); - } - - public async loadOpenIDProviderConfiguration(forceInit: boolean): Promise { - const configData: StrictAuthClientConfig = await this.configProvider(); - - if ( - !forceInit && - (await this.storageManager.getTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - )) - ) { - return Promise.resolve(); - } - - const {wellKnownEndpoint, platform, discovery, baseUrl, endpoints} = configData as any; - - const resolvedWellKnownEndpoint: string | undefined = - wellKnownEndpoint || - (platform === Platform.AsgardeoV2 && discovery?.wellKnown?.enabled - ? `${baseUrl}${endpoints?.wellKnown ?? '/.well-known/openid-configuration'}` - : undefined); - - if (resolvedWellKnownEndpoint) { - let response: Response; - - try { - response = await fetch(resolvedWellKnownEndpoint); - if (response.status !== 200 || !response.ok) { - throw new Error(); - } - } catch { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GOPMD-HE01', - 'Invalid well-known response', - 'The well known endpoint response has been failed with an error.', - ); - } - - await this.storageManager.setOIDCProviderMetaData(await this.authHelper.resolveEndpoints(await response.json())); - await this.storageManager.setTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - true, - ); - - return Promise.resolve(); - } - if ((configData as any).baseUrl) { - try { - await this.storageManager.setOIDCProviderMetaData(await this.authHelper.resolveEndpointsByBaseURL()); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GOPMD-IV02', - 'Resolving endpoints failed.', - error ?? 'Resolving endpoints by base url failed.', - ); - } - await this.storageManager.setTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - true, - ); - - return Promise.resolve(); - } - await this.storageManager.setOIDCProviderMetaData(await this.authHelper.resolveEndpointsExplicitly()); - - await this.storageManager.setTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - true, - ); - - return Promise.resolve(); - } - - /** - * This method returns the sign-out URL. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * **This doesn't clear the authentication data.** - * - * @returns - A Promise that resolves with the sign-out URL. - * - * @example - * ``` - * const signOutUrl = await auth.getSignOutUrl(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getSignOutUrl} - * - * @preserve - */ - public async getSignOutUrl(userId?: string): Promise { - const logoutEndpoint: string | undefined = (await this.oidcProviderMetaDataProvider())?.end_session_endpoint; - const configData: StrictAuthClientConfig = await this.configProvider(); - - if (!logoutEndpoint || logoutEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GSOU-NF01', - 'Sign-out endpoint not found.', - 'No sign-out endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + - 'or the sign-out endpoint passed to the SDK is empty.', - ); - } - - const callbackURL: string = configData?.afterSignOutUrl ?? configData?.afterSignInUrl; - - if (!callbackURL || callbackURL.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GSOU-NF03', - 'No sign-out redirect URL found.', - 'The sign-out redirect URL cannot be found or the URL passed to the SDK is empty. ' + - 'No sign-in redirect URL has been found either. ', - ); - } - const queryParams: URLSearchParams = new URLSearchParams(); - - queryParams.set('post_logout_redirect_uri', callbackURL); - - if (configData.sendIdTokenInLogoutRequest) { - const idToken: string = (await this.storageManager.getSessionData(userId))?.id_token; - - if (!idToken || idToken.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GSOU-NF02', - 'ID token not found.', - 'No ID token could be found. Either the session information is lost or you have not signed in.', - ); - } - queryParams.set('id_token_hint', idToken); - } else { - queryParams.set('client_id', configData.clientId); - } - - queryParams.set('state', OIDCRequestConstants.Params.SIGN_OUT_SUCCESS); - - return `${logoutEndpoint}?${queryParams.toString()}`; - } - - /** - * This method returns OIDC service endpoints that are fetched from the `.well-known` endpoint. - * - * @returns - A Promise that resolves with an object containing the OIDC service endpoints. - * - * @example - * ``` - * const endpoints = await auth.getOpenIDProviderEndpoints(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getOpenIDProviderEndpoints} - * - * @preserve - */ - public async getOpenIDProviderEndpoints(): Promise> { - const oidcProviderMetaData: OIDCDiscoveryApiResponse = await this.oidcProviderMetaDataProvider(); - - return { - authorizationEndpoint: oidcProviderMetaData.authorization_endpoint ?? '', - checkSessionIframe: oidcProviderMetaData.check_session_iframe ?? '', - endSessionEndpoint: oidcProviderMetaData.end_session_endpoint ?? '', - introspectionEndpoint: oidcProviderMetaData.introspection_endpoint ?? '', - issuer: oidcProviderMetaData.issuer ?? '', - jwksUri: oidcProviderMetaData.jwks_uri ?? '', - registrationEndpoint: oidcProviderMetaData.registration_endpoint ?? '', - revocationEndpoint: oidcProviderMetaData.revocation_endpoint ?? '', - tokenEndpoint: oidcProviderMetaData.token_endpoint ?? '', - userinfoEndpoint: oidcProviderMetaData.userinfo_endpoint ?? '', - }; - } - - /** - * This method decodes a given JWT token and returns the payload. - * - * @param token - The token to be decoded. - * @returns - A Promise that resolves with the decoded token payload. - * - * @example - * ``` - * const decodedToken = await auth.decodeJwtToken(token); - * ``` - */ - public async decodeJwtToken>(token: string): Promise { - return this.cryptoHelper.decodeJwtToken(token); - } - - /** - * This method decodes the payload of the ID token and returns it. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the decoded ID token payload. - * - * @example - * ``` - * const decodedIdToken = await auth.getDecodedIdToken(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getDecodedIdToken} - * - * @preserve - */ - public async getDecodedIdToken(userId?: string, idToken?: string): Promise { - const storedIdToken: string = (await this.storageManager.getSessionData(userId)).id_token; - const payload: IdToken = this.cryptoHelper.decodeJwtToken(storedIdToken ?? idToken); - - return payload; - } - - /** - * This method returns the ID token. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the ID token. - * - * @example - * ``` - * const idToken = await auth.getIdToken(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getIdToken} - * - * @preserve - */ - public async getIdToken(userId?: string): Promise { - return (await this.storageManager.getSessionData(userId)).id_token; - } - - /** - * This method returns the basic user information obtained from the ID token. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with an object containing the basic user information. - * - * @example - * ``` - * const userInfo = await auth.getUser(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getUser} - * - * @preserve - */ - public async getUser(userId?: string): Promise { - const sessionData: SessionData = await this.storageManager.getSessionData(userId); - const authenticatedUser: User = this.authHelper.getAuthenticatedUserInfo(sessionData?.id_token); - - Object.keys(authenticatedUser).forEach((key: string) => { - if (authenticatedUser[key] === undefined || authenticatedUser[key] === '' || authenticatedUser[key] === null) { - delete authenticatedUser[key]; - } - }); - - return authenticatedUser; - } - - public async getUserSession(userId?: string): Promise { - const sessionData: SessionData = await this.storageManager.getSessionData(userId); - - return { - scopes: sessionData?.scope?.split(' '), - sessionState: sessionData?.session_state ?? '', - }; - } - - /** - * This method returns the crypto helper object. - * - * @returns - A Promise that resolves with a IsomorphicCrypto object. - * - * @example - * ``` - * const cryptoHelper = await auth.IsomorphicCrypto(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getCrypto} - * - * @preserve - */ - public async getCrypto(): Promise { - return this.cryptoHelper; - } - - /** - * This method revokes the access token. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * **This method also clears the authentication data.** - * - * @returns - A Promise that returns the response of the revoke-access-token request. - * - * @example - * ``` - * auth.revokeAccessToken().then((response)=>{ - * // console.log(response); - * }).catch((error)=>{ - * // console.error(error); - * }); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#revokeAccessToken} - * - * @preserve - */ - public async revokeAccessToken(userId?: string): Promise { - const revokeTokenEndpoint: string | undefined = (await this.oidcProviderMetaDataProvider()).revocation_endpoint; - const configData: StrictAuthClientConfig = await this.configProvider(); - - if (!revokeTokenEndpoint || revokeTokenEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT3-NF01', - 'No revoke access token endpoint found.', - 'No revoke access token endpoint was found in the OIDC provider meta data returned by ' + - 'the well-known endpoint or the revoke access token endpoint passed to the SDK is empty.', - ); - } - - const body: string[] = []; - - body.push(`client_id=${configData.clientId}`); - body.push(`token=${(await this.storageManager.getSessionData(userId)).access_token}`); - body.push('token_type_hint=access_token'); - - if (configData.clientSecret && configData.clientSecret.trim().length > 0) { - body.push(`client_secret=${configData.clientSecret}`); - } - - let response: Response; - - try { - response = await fetch(revokeTokenEndpoint, { - body: body.join('&'), - credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - }, - method: 'POST', - }); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT3-NE02', - 'The request to revoke access token failed.', - error ?? 'The request sent to revoke the access token failed.', - ); - } - - if (response.status !== 200 || !response.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT3-HE03', - `Invalid response status received for revoke access token request (${response.statusText}).`, - (await response.json()) as string, - ); - } - - this.authHelper.clearSession(userId); - - return Promise.resolve(response); - } - - /** - * This method refreshes the access token and returns a Promise that resolves with the new access - * token and other relevant data. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the token response. - * - * @example - * ``` - * auth.refreshAccessToken().then((response)=>{ - * // console.log(response); - * }).catch((error)=>{ - * // console.error(error); - * }); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#refreshAccessToken} - * - * @preserve - */ - public async refreshAccessToken(userId?: string): Promise { - const tokenEndpoint: string | undefined = (await this.oidcProviderMetaDataProvider()).token_endpoint; - const configData: StrictAuthClientConfig = await this.configProvider(); - const sessionData: SessionData = await this.storageManager.getSessionData(userId); - - if (!sessionData.refresh_token) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT2-NF01', - 'No refresh token found.', - "There was no refresh token found. Asgardeo doesn't return a " + - 'refresh token if the refresh token grant is not enabled.', - ); - } - - if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT2-NF02', - 'No refresh token endpoint found.', - 'No refresh token endpoint was in the OIDC provider meta data returned by the well-known ' + - 'endpoint or the refresh token endpoint passed to the SDK is empty.', - ); - } - - const body: string[] = []; - - body.push(`client_id=${configData.clientId}`); - body.push(`refresh_token=${sessionData.refresh_token}`); - body.push('grant_type=refresh_token'); - - if (configData.clientSecret && configData.clientSecret.trim().length > 0) { - body.push(`client_secret=${configData.clientSecret}`); - } - - let tokenResponse: Response; - - try { - tokenResponse = await fetch(tokenEndpoint, { - body: body.join('&'), - credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - }, - method: 'POST', - }); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT2-NR03', - 'Refresh access token request failed.', - error ?? 'The request to refresh the access token failed.', - ); - } - - if (!tokenResponse.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT2-HE04', - `Refreshing access token failed with ${tokenResponse.statusText}`, - (await tokenResponse.json()) as string, - ); - } - - return this.authHelper.handleTokenResponse(tokenResponse, userId); - } - - /** - * This method returns the access token. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the access token. - * - * @example - * ``` - * const accessToken = await auth.getAccessToken(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getAccessToken} - * - * @preserve - */ - public async getAccessToken(userId?: string): Promise { - return (await this.storageManager.getSessionData(userId))?.access_token; - } - - /** - * This method sends a custom-grant request and returns a Promise that resolves with the response - * depending on the config passed. - * - * @param config - A config object containing the custom grant configurations. - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the response depending - * on your configurations. - * - * @example - * ``` - * const config = { - * attachToken: false, - * data: { - * client_id: "{{clientId}}", - * grant_type: "account_switch", - * scope: "{{scope}}", - * token: "{{token}}", - * }, - * id: "account-switch", - * returnResponse: true, - * returnsSession: true, - * signInRequired: true - * } - * - * auth.exchangeToken(config).then((response)=>{ - * // console.log(response); - * }).catch((error)=>{ - * // console.error(error); - * }); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#exchangeToken} - * - * @preserve - */ - public async exchangeToken(config: TokenExchangeRequestConfig, userId?: string): Promise { - if ( - !(await this.storageManager.getTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - )) - ) { - await this.loadOpenIDProviderConfiguration(false); - } - - const oidcProviderMetadata: OIDCDiscoveryApiResponse = await this.oidcProviderMetaDataProvider(); - const configData: StrictAuthClientConfig = await this.configProvider(); - - let tokenEndpoint: string | undefined; - - if (config.tokenEndpoint && config.tokenEndpoint.trim().length !== 0) { - tokenEndpoint = config.tokenEndpoint; - } else { - tokenEndpoint = oidcProviderMetadata.token_endpoint; - } - - if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RCG-NF01', - 'Token endpoint not found.', - 'No token endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + - 'or the token endpoint passed to the SDK is empty.', - ); - } - - const data: string[] = await Promise.all( - Object.entries(config.data).map(async ([key, value]: [key: string, value: any]) => { - const newValue: string = await this.authHelper.replaceCustomGrantTemplateTags(value as string, userId); - - return `${key}=${newValue}`; - }), - ); - - let requestHeaders: Record = { - Accept: 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - }; - - if (config.attachToken) { - requestHeaders = { - ...requestHeaders, - Authorization: `Bearer ${(await this.storageManager.getSessionData(userId)).access_token}`, - }; - } - - const requestConfig: RequestInit = { - body: data.join('&'), - credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', - headers: new Headers(requestHeaders), - method: 'POST', - }; - - let response: Response; - - try { - response = await fetch(tokenEndpoint, requestConfig); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RCG-NE02', - 'The custom grant request failed.', - error ?? 'The request sent to get the custom grant failed.', - ); - } - - if (response.status !== 200 || !response.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RCG-HE03', - `Invalid response status received for the custom grant request. (${response.statusText})`, - (await response.json()) as string, - ); - } - - if (config.returnsSession) { - return this.authHelper.handleTokenResponse(response, userId); - } - return Promise.resolve((await response.json()) as TokenResponse | Response); - } - - /** - * This method returns if the user is authenticated or not. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with `true` if the user is authenticated, `false` otherwise. - * - * @example - * ``` - * await auth.isSignedIn(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#isSignedIn} - * - * @preserve - */ - public async isSignedIn(userId?: string): Promise { - const isAccessTokenAvailable: boolean = Boolean(await this.getAccessToken(userId)); - - // Check if the access token is expired. - const createdAt: number = (await this.storageManager.getSessionData(userId))?.created_at; - - // Get the expires in value. - const expiresInString: string = (await this.storageManager.getSessionData(userId))?.expires_in; - - // If the expires in value is not available, the token is invalid and the user is not authenticated. - if (!expiresInString) { - return false; - } - - // Convert to milliseconds. - const expiresIn: number = parseInt(expiresInString, 10) * 1000; - const currentTime: number = new Date().getTime(); - const isAccessTokenValid: boolean = createdAt + expiresIn > currentTime; - - const isSignedIn: boolean = isAccessTokenAvailable && isAccessTokenValid; - - return isSignedIn; - } - - /** - * This method returns the PKCE code generated during the generation of the authentication URL. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * @param state - The state parameter that was passed in the authentication URL. - * - * @returns - A Promise that resolves with the PKCE code. - * - * @example - * ``` - * const pkce = await getPKCECode(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getPKCECode} - * - * @preserve - */ - public async getPKCECode(state: string, userId?: string): Promise { - return (await this.storageManager.getTemporaryDataParameter( - extractPkceStorageKeyFromState(state), - userId, - )) as string; - } - - /** - * This method sets the PKCE code to the data store. - * - * @param pkce - The PKCE code. - * @param state - The state parameter that was passed in the authentication URL. - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @example - * ``` - * await auth.setPKCECode("pkce_code") - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#setPKCECode} - * - * @preserve - */ - public async setPKCECode(pkce: string, state: string, userId?: string): Promise { - return this.storageManager.setTemporaryDataParameter(extractPkceStorageKeyFromState(state), pkce, userId); - } - - /** - * This method returns if the sign-out is successful or not. - * - * @param signOutRedirectUrl - The URL to which the user has been redirected to after signing-out. - * - * **The server appends path parameters to the `afterSignOutUrl` and these path parameters - * are required for this method to function.** - * - * @returns - `true` if successful, `false` otherwise. - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#isSignOutSuccessful} - * - * @preserve - */ - public static isSignOutSuccessful(afterSignOutUrl: string): boolean { - const url: URL = new URL(afterSignOutUrl); - const stateParam: string | null = url.searchParams.get(OIDCRequestConstants.Params.STATE); - const error: boolean = Boolean(url.searchParams.get('error')); - - return stateParam ? stateParam === OIDCRequestConstants.Params.SIGN_OUT_SUCCESS && !error : false; - } - - /** - * This method returns if the sign-out has failed or not. - * - * @param signOutRedirectUrl - The URL to which the user has been redirected to after signing-out. - * - * **The server appends path parameters to the `afterSignOutUrl` and these path parameters - * are required for this method to function.** - * - * @returns - `true` if successful, `false` otherwise. - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#didSignOutFail} - * - * @preserve - */ - public static didSignOutFail(afterSignOutUrl: string): boolean { - const url: URL = new URL(afterSignOutUrl); - const stateParam: string | null = url.searchParams.get(OIDCRequestConstants.Params.STATE); - const error: boolean = Boolean(url.searchParams.get('error')); - - return stateParam ? stateParam === OIDCRequestConstants.Params.SIGN_OUT_SUCCESS && error : false; - } - - /** - * This method updates the configuration that was passed into the constructor when instantiating this class. - * - * @param config - A config object to update the SDK configurations with. - * - * @example - * ``` - * const config = { - * afterSignInUrl: "http://localhost:3000/sign-in", - * clientId: "client ID", - * baseUrl: "https://localhost:9443" - * } - * - * await auth.reInitialize(config); - * ``` - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#reInitialize} - * - * @preserve - */ - public async reInitialize(config: Partial>): Promise { - const currentConfig: AuthClientConfig = this.storageManager.getConfigData() as unknown as AuthClientConfig; - const newConfig: AuthClientConfig = deepMerge(currentConfig, config); - - await this.storageManager.setConfigData(newConfig); - await this.loadOpenIDProviderConfiguration(true); - } - - public static async clearSession(userId?: string): Promise { - await this.authHelperInstance.clearSession(userId); - } -} diff --git a/packages/javascript/src/__legacy__/helpers/authentication-helper.ts b/packages/javascript/src/__legacy__/helpers/authentication-helper.ts deleted file mode 100644 index 63267eb5c..000000000 --- a/packages/javascript/src/__legacy__/helpers/authentication-helper.ts +++ /dev/null @@ -1,336 +0,0 @@ -/** - * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. - * - * 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 OIDCDiscoveryConstants from '../../constants/OIDCDiscoveryConstants'; -import TokenExchangeConstants from '../../constants/TokenExchangeConstants'; -import {AsgardeoAuthException} from '../../errors/exception'; -import {IsomorphicCrypto} from '../../IsomorphicCrypto'; -import {Config} from '../../models/config'; -import {JWKInterface} from '../../models/crypto'; -import {OIDCDiscoveryEndpointsApiResponse, OIDCDiscoveryApiResponse} from '../../models/oidc-discovery'; -import {Platform} from '../../models/platforms'; -import {SessionData} from '../../models/session'; -import {IdToken, TokenResponse, AccessTokenApiResponse} from '../../models/token'; -import {User} from '../../models/user'; -import StorageManager from '../../StorageManager'; -import extractUserClaimsFromIdToken from '../../utils/extractUserClaimsFromIdToken'; -import processOpenIDScopes from '../../utils/processOpenIDScopes'; -import {AuthClientConfig, StrictAuthClientConfig} from '../models'; - -export class AuthenticationHelper { - private storageManager: StorageManager; - - private config: () => Promise; - - private oidcProviderMetaData: () => Promise; - - private cryptoHelper: IsomorphicCrypto; - - public constructor(storageManagerInstance: StorageManager, cryptoHelperInstance: IsomorphicCrypto) { - this.storageManager = storageManagerInstance; - this.config = async (): Promise => this.storageManager.getConfigData(); - this.oidcProviderMetaData = async (): Promise => - this.storageManager.loadOpenIDProviderConfiguration(); - this.cryptoHelper = cryptoHelperInstance; - } - - public async resolveEndpoints(response: OIDCDiscoveryApiResponse): Promise { - const oidcProviderMetaData: OIDCDiscoveryApiResponse = {}; - const configData: StrictAuthClientConfig = await this.config(); - - if (configData.endpoints) { - Object.keys(configData.endpoints).forEach((endpointName: string) => { - const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); - - oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; - }); - } - - return {...response, ...oidcProviderMetaData}; - } - - public async resolveEndpointsExplicitly(): Promise { - const oidcProviderMetaData: OIDCDiscoveryApiResponse = {}; - const configData: StrictAuthClientConfig = await this.config(); - - const requiredEndpoints: string[] = [ - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.AUTHORIZATION, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.END_SESSION, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.JWKS, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.SESSION_IFRAME, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.REVOCATION, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.TOKEN, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.ISSUER, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.USERINFO, - ]; - - const isRequiredEndpointsContains: boolean = configData.endpoints - ? requiredEndpoints.every((reqEndpointName: string) => - configData.endpoints - ? Object.keys(configData.endpoints).some((endpointName: string) => { - const snakeCasedName: string = endpointName.replace( - /[A-Z]/g, - (letter: string) => `_${letter.toLowerCase()}`, - ); - - return snakeCasedName === reqEndpointName; - }) - : false, - ) - : false; - - if (!isRequiredEndpointsContains) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER-REE-NF01', - 'Required endpoints missing', - 'Some or all of the required endpoints are missing in the object passed to the `endpoints` ' + - 'attribute of the`AuthConfig` object.', - ); - } - - if (configData.endpoints) { - Object.keys(configData.endpoints).forEach((endpointName: string) => { - const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); - - oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; - }); - } - - return {...oidcProviderMetaData}; - } - - public async resolveEndpointsByBaseURL(): Promise { - const oidcProviderMetaData: OIDCDiscoveryEndpointsApiResponse = {}; - const configData: StrictAuthClientConfig = await this.config(); - - const {baseUrl} = configData as any; - - if (!baseUrl) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER_REBO-NF01', - 'Base URL not defined.', - 'Base URL is not defined in AuthClient config.', - ); - } - - if (configData.endpoints) { - Object.keys(configData.endpoints).forEach((endpointName: string) => { - const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); - - oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; - }); - } - - const endpointKeys: typeof OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints = - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints; - const endpointPaths: typeof OIDCDiscoveryConstants.Endpoints = OIDCDiscoveryConstants.Endpoints; - - const defaultEndpoints: OIDCDiscoveryApiResponse = { - [endpointKeys.AUTHORIZATION]: `${baseUrl}${endpointPaths.AUTHORIZATION}`, - [endpointKeys.END_SESSION]: `${baseUrl}${endpointPaths.END_SESSION}`, - [endpointKeys.ISSUER]: `${baseUrl}${endpointPaths.ISSUER}`, - [endpointKeys.JWKS]: `${baseUrl}${endpointPaths.JWKS}`, - [endpointKeys.SESSION_IFRAME]: `${baseUrl}${endpointPaths.SESSION_IFRAME}`, - [endpointKeys.REVOCATION]: `${baseUrl}${endpointPaths.REVOCATION}`, - [endpointKeys.TOKEN]: `${baseUrl}${endpointPaths.TOKEN}`, - [endpointKeys.USERINFO]: `${baseUrl}${endpointPaths.USERINFO}`, - }; - - // For AsgardeoV2 (Thunder), the issuer must be the base URL (e.g., https://localhost:8090) - // to comply with RFC 8414 (Section 2 & 3) and OpenID Connect Discovery specs. - // The issuer should be a URL using "https" scheme with no query or fragment components. - // The well-known metadata endpoint is derived by inserting "/.well-known/oauth-authorization-server" - // between the host and path components of the issuer identifier. - // Reference: https://datatracker.ietf.org/doc/html/rfc8414#section-2 - // Trackers: - // - https://github.com/asgardeo/thunder/issues/815 - // - https://github.com/asgardeo/javascript/issues/322 - if ((configData as Config).platform === Platform.AsgardeoV2) { - defaultEndpoints[OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.ISSUER] = `${baseUrl}`; - } - - return {...defaultEndpoints, ...oidcProviderMetaData}; - } - - public async validateIdToken(idToken: string): Promise { - const jwksEndpoint: string | undefined = (await this.storageManager.loadOpenIDProviderConfiguration()).jwks_uri; - const configData: StrictAuthClientConfig = await this.config(); - - if (!jwksEndpoint || jwksEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS_AUTH_HELPER-VIT-NF01', - 'JWKS endpoint not found.', - 'No JWKS endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + - 'or the JWKS endpoint passed to the SDK is empty.', - ); - } - - let response: Response; - - try { - response = await fetch(jwksEndpoint, { - credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', - }); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER-VIT-NE02', - 'Request to jwks endpoint failed.', - error ?? 'The request sent to get the jwks from the server failed.', - ); - } - - if (response.status !== 200 || !response.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER-VIT-HE03', - `Invalid response status received for jwks request (${response.statusText}).`, - (await response.json()) as string, - ); - } - - const {issuer} = await this.oidcProviderMetaData(); - - const {keys}: {keys: JWKInterface[]} = (await response.json()) as { - keys: JWKInterface[]; - }; - - const jwk: any = await this.cryptoHelper.getJWKForTheIdToken(idToken.split('.')[0], keys); - - return this.cryptoHelper.isValidIdToken( - idToken, - jwk, - (await this.config()).clientId, - issuer ?? '', - this.cryptoHelper.decodeJwtToken(idToken).sub, - (await this.config()).tokenValidation?.idToken?.clockTolerance, - (await this.config()).tokenValidation?.idToken?.validateIssuer ?? true, - ); - } - - public getAuthenticatedUserInfo(idToken: string): User { - const payload: IdToken = this.cryptoHelper.decodeJwtToken(idToken); - const username: string = payload?.['username'] ?? ''; - const givenName: string = payload?.['given_name'] ?? ''; - const familyName: string = payload?.['family_name'] ?? ''; - const fullName: string = givenName && familyName ? `${givenName} ${familyName}` : givenName || familyName || ''; - const displayName: string = payload.preferred_username ?? fullName; - - return { - displayName, - username, - ...extractUserClaimsFromIdToken(payload), - }; - } - - public async replaceCustomGrantTemplateTags(text: string, userId?: string): Promise { - const configData: StrictAuthClientConfig = await this.config(); - - const sourceInstanceId: number | null = configData.organizationChain?.sourceInstanceId ?? null; - - let sessionData: SessionData; - - if (sourceInstanceId) { - const {clientId} = configData; - let instanceKey: string; - if (clientId) { - instanceKey = `instance_${sourceInstanceId}-${clientId}`; - } else { - instanceKey = `instance_${sourceInstanceId}`; - } - sessionData = await this.storageManager.getSessionData(userId, instanceKey); - - if (!sessionData || !sessionData.access_token) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER-RCGTT-NE01', - 'No session data found for source instance.', - 'Failed to retrieve session data from the source organization context.', - ); - } - } else { - sessionData = await this.storageManager.getSessionData(userId); - } - - const scope: string = processOpenIDScopes(configData.scopes); - - if (typeof text !== 'string') { - return text; - } - - return text - .replace(TokenExchangeConstants.Placeholders.ACCESS_TOKEN, sessionData.access_token) - .replace( - TokenExchangeConstants.Placeholders.USERNAME, - this.getAuthenticatedUserInfo(sessionData.id_token).username, - ) - .replace(TokenExchangeConstants.Placeholders.SCOPES, scope) - .replace(TokenExchangeConstants.Placeholders.CLIENT_ID, configData.clientId) - .replace(TokenExchangeConstants.Placeholders.CLIENT_SECRET, configData.clientSecret ?? ''); - } - - public async clearSession(userId?: string): Promise { - await this.storageManager.removeTemporaryData(userId); - await this.storageManager.removeSessionData(userId); - } - - public async handleTokenResponse(response: Response, userId?: string): Promise { - if (response.status !== 200 || !response.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER-HTR-NE01', - `Invalid response status received for token request (${response.statusText}).`, - (await response.json()) as string, - ); - } - - // Get the response in JSON - const parsedResponse: AccessTokenApiResponse = (await response.json()) as AccessTokenApiResponse; - - parsedResponse.created_at = new Date().getTime(); - - const shouldValidateIdToken: boolean | undefined = (await this.config()).tokenValidation?.idToken?.validate; - - if (shouldValidateIdToken) { - return this.validateIdToken(parsedResponse.id_token).then(async () => { - await this.storageManager.setSessionData(parsedResponse, userId); - - const tokenResponse: TokenResponse = { - accessToken: parsedResponse.access_token, - createdAt: parsedResponse.created_at, - expiresIn: parsedResponse.expires_in, - idToken: parsedResponse.id_token, - refreshToken: parsedResponse.refresh_token, - scope: parsedResponse.scope, - tokenType: parsedResponse.token_type, - }; - - return Promise.resolve(tokenResponse); - }); - } - const tokenResponse: TokenResponse = { - accessToken: parsedResponse.access_token, - createdAt: parsedResponse.created_at, - expiresIn: parsedResponse.expires_in, - idToken: parsedResponse.id_token, - refreshToken: parsedResponse.refresh_token, - scope: parsedResponse.scope, - tokenType: parsedResponse.token_type, - }; - - await this.storageManager.setSessionData(parsedResponse, userId); - - return Promise.resolve(tokenResponse); - } -} diff --git a/packages/javascript/src/__legacy__/models/index.ts b/packages/javascript/src/__legacy__/models/index.ts deleted file mode 100644 index 2d461ba29..000000000 --- a/packages/javascript/src/__legacy__/models/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. - * - * 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. - */ - -export * from './client-config'; diff --git a/packages/javascript/src/api/exchangeToken.ts b/packages/javascript/src/api/exchangeToken.ts new file mode 100644 index 000000000..fdc94adb7 --- /dev/null +++ b/packages/javascript/src/api/exchangeToken.ts @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; +import {AsgardeoAuthException} from '../errors/exception'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {TokenExchangeRequestConfig, TokenResponse} from '../models/token'; +import StorageManager from '../StorageManager'; +import replaceCustomGrantTemplateTags from '../utils/replaceCustomGrantTemplateTags'; +import handleTokenResponse from './handleTokenResponse'; +import loadOpenIDProviderConfiguration from './loadOpenIDProviderConfiguration'; + +export default async function exchangeToken( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + config: TokenExchangeRequestConfig, + userId?: string, +): Promise { + if ( + !(await storageManager.getTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + )) + ) { + await loadOpenIDProviderConfiguration(storageManager, false); + } + + const oidcProviderMetadata = await storageManager.loadOpenIDProviderConfiguration(); + const configData: StrictAuthClientConfig = await storageManager.getConfigData(); + + let tokenEndpoint: string | undefined; + + if (config.tokenEndpoint && config.tokenEndpoint.trim().length !== 0) { + tokenEndpoint = config.tokenEndpoint; + } else { + tokenEndpoint = oidcProviderMetadata.token_endpoint; + } + + if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RCG-NF01', + 'Token endpoint not found.', + 'No token endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + + 'or the token endpoint passed to the SDK is empty.', + ); + } + + const data: string[] = await Promise.all( + Object.entries(config.data).map(async ([key, value]: [key: string, value: any]) => { + const newValue: string = await replaceCustomGrantTemplateTags(storageManager, cryptoHelper, value as string, userId); + + return `${key}=${newValue}`; + }), + ); + + let requestHeaders: Record = { + Accept: 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + }; + + if (config.attachToken) { + requestHeaders = { + ...requestHeaders, + Authorization: `Bearer ${(await storageManager.getSessionData(userId)).access_token}`, + }; + } + + const requestConfig: RequestInit = { + body: data.join('&'), + credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', + headers: new Headers(requestHeaders), + method: 'POST', + }; + + let response: Response; + + try { + response = await fetch(tokenEndpoint, requestConfig); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RCG-NE02', + 'The custom grant request failed.', + error ?? 'The request sent to get the custom grant failed.', + ); + } + + if (response.status !== 200 || !response.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RCG-HE03', + `Invalid response status received for the custom grant request. (${response.statusText})`, + (await response.json()) as string, + ); + } + + if (config.returnsSession) { + return handleTokenResponse(storageManager, cryptoHelper, response, userId); + } + + return (await response.json()) as TokenResponse | Response; +} diff --git a/packages/javascript/src/api/handleTokenResponse.ts b/packages/javascript/src/api/handleTokenResponse.ts new file mode 100644 index 000000000..29fc005ec --- /dev/null +++ b/packages/javascript/src/api/handleTokenResponse.ts @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 {AsgardeoAuthException} from '../errors/exception'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import {AccessTokenApiResponse, TokenResponse} from '../models/token'; +import StorageManager from '../StorageManager'; +import validateIdToken from './validateIdToken'; + +export default async function handleTokenResponse( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + response: Response, + userId?: string, +): Promise { + if (response.status !== 200 || !response.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER-HTR-NE01', + `Invalid response status received for token request (${response.statusText}).`, + (await response.json()) as string, + ); + } + + const parsedResponse: AccessTokenApiResponse = (await response.json()) as AccessTokenApiResponse; + + parsedResponse.created_at = new Date().getTime(); + + const shouldValidateIdToken: boolean | undefined = (await storageManager.getConfigData()).tokenValidation?.idToken + ?.validate; + + const tokenResponse: TokenResponse = { + accessToken: parsedResponse.access_token, + createdAt: parsedResponse.created_at, + expiresIn: parsedResponse.expires_in, + idToken: parsedResponse.id_token, + refreshToken: parsedResponse.refresh_token, + scope: parsedResponse.scope, + tokenType: parsedResponse.token_type, + }; + + if (shouldValidateIdToken) { + await validateIdToken(storageManager, cryptoHelper, parsedResponse.id_token); + } + + await storageManager.setSessionData(parsedResponse, userId); + + return tokenResponse; +} diff --git a/packages/javascript/src/api/loadOpenIDProviderConfiguration.ts b/packages/javascript/src/api/loadOpenIDProviderConfiguration.ts new file mode 100644 index 000000000..2323e6528 --- /dev/null +++ b/packages/javascript/src/api/loadOpenIDProviderConfiguration.ts @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; +import OIDCDiscoveryConstantsV2 from '../constants/v2/OIDCDiscoveryConstants'; +import {AsgardeoAuthException} from '../errors/exception'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {Platform} from '../models/platforms'; +import StorageManager from '../StorageManager'; +import resolveEndpoints from '../utils/resolveEndpoints'; +import resolveEndpointsByBaseURL from '../utils/resolveEndpointsByBaseURL'; +import resolveEndpointsExplicitly from '../utils/resolveEndpointsExplicitly'; + +export default async function loadOpenIDProviderConfiguration( + storageManager: StorageManager, + forceInit: boolean, +): Promise { + const configData: StrictAuthClientConfig = await storageManager.getConfigData(); + + if ( + !forceInit && + (await storageManager.getTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + )) + ) { + return; + } + + const {wellKnownEndpoint, platform, discovery, baseUrl, endpoints} = configData as any; + + const resolvedWellKnownEndpoint: string | undefined = + wellKnownEndpoint || + (platform === Platform.AsgardeoV2 && discovery?.wellKnown?.enabled + ? `${baseUrl}${endpoints?.wellKnown ?? OIDCDiscoveryConstantsV2.Endpoints.WELL_KNOWN}` + : undefined); + + if (resolvedWellKnownEndpoint) { + let response: Response; + + try { + response = await fetch(resolvedWellKnownEndpoint); + if (response.status !== 200 || !response.ok) { + throw new Error(); + } + } catch { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GOPMD-HE01', + 'Invalid well-known response', + 'The well known endpoint response has been failed with an error.', + ); + } + + await storageManager.setOIDCProviderMetaData(await resolveEndpoints(storageManager, await response.json())); + await storageManager.setTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + true, + ); + + return; + } + + if ((configData as any).baseUrl) { + try { + await storageManager.setOIDCProviderMetaData(await resolveEndpointsByBaseURL(storageManager)); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GOPMD-IV02', + 'Resolving endpoints failed.', + error ?? 'Resolving endpoints by base url failed.', + ); + } + await storageManager.setTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + true, + ); + + return; + } + + await storageManager.setOIDCProviderMetaData(await resolveEndpointsExplicitly(storageManager)); + await storageManager.setTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + true, + ); +} diff --git a/packages/javascript/src/api/refreshAccessToken.ts b/packages/javascript/src/api/refreshAccessToken.ts new file mode 100644 index 000000000..6f433c230 --- /dev/null +++ b/packages/javascript/src/api/refreshAccessToken.ts @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 {AsgardeoAuthException} from '../errors/exception'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {SessionData} from '../models/session'; +import {TokenResponse} from '../models/token'; +import StorageManager from '../StorageManager'; +import handleTokenResponse from './handleTokenResponse'; + +export default async function refreshAccessToken( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + userId?: string, +): Promise { + const tokenEndpoint: string | undefined = (await storageManager.loadOpenIDProviderConfiguration()).token_endpoint; + const configData: StrictAuthClientConfig = await storageManager.getConfigData(); + const sessionData: SessionData = await storageManager.getSessionData(userId); + + if (!sessionData.refresh_token) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT2-NF01', + 'No refresh token found.', + "There was no refresh token found. Asgardeo doesn't return a " + + 'refresh token if the refresh token grant is not enabled.', + ); + } + + if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT2-NF02', + 'No refresh token endpoint found.', + 'No refresh token endpoint was in the OIDC provider meta data returned by the well-known ' + + 'endpoint or the refresh token endpoint passed to the SDK is empty.', + ); + } + + const body: string[] = []; + + body.push(`client_id=${configData.clientId}`); + body.push(`refresh_token=${sessionData.refresh_token}`); + body.push('grant_type=refresh_token'); + + if (configData.clientSecret && configData.clientSecret.trim().length > 0) { + body.push(`client_secret=${configData.clientSecret}`); + } + + let tokenResponse: Response; + + try { + tokenResponse = await fetch(tokenEndpoint, { + body: body.join('&'), + credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + }); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT2-NR03', + 'Refresh access token request failed.', + error ?? 'The request to refresh the access token failed.', + ); + } + + if (!tokenResponse.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT2-HE04', + `Refreshing access token failed with ${tokenResponse.statusText}`, + (await tokenResponse.json()) as string, + ); + } + + return handleTokenResponse(storageManager, cryptoHelper, tokenResponse, userId); +} diff --git a/packages/javascript/src/api/requestAccessToken.ts b/packages/javascript/src/api/requestAccessToken.ts new file mode 100644 index 000000000..8d19cc806 --- /dev/null +++ b/packages/javascript/src/api/requestAccessToken.ts @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; +import OIDCRequestConstants from '../constants/OIDCRequestConstants'; +import {AsgardeoAuthException} from '../errors/exception'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {SessionData} from '../models/session'; +import {TokenResponse} from '../models/token'; +import StorageManager from '../StorageManager'; +import extractPkceStorageKeyFromState from '../utils/extractPkceStorageKeyFromState'; +import handleTokenResponse from './handleTokenResponse'; +import loadOpenIDProviderConfiguration from './loadOpenIDProviderConfiguration'; + +export default async function requestAccessToken( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + authorizationCode: string, + sessionState: string, + state: string, + userId?: string, + tokenRequestConfig?: {params: Record}, +): Promise { + if ( + !(await storageManager.getTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + )) + ) { + await loadOpenIDProviderConfiguration(storageManager, false); + } + + const tokenEndpoint: string | undefined = (await storageManager.loadOpenIDProviderConfiguration()).token_endpoint; + const configData: StrictAuthClientConfig = await storageManager.getConfigData(); + + if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT1-NF01', + 'Token endpoint not found.', + 'No token endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + + 'or the token endpoint passed to the SDK is empty.', + ); + } + + if (sessionState) { + await storageManager.setSessionDataParameter( + OIDCRequestConstants.Params.SESSION_STATE as keyof SessionData, + sessionState, + userId, + ); + } + + const body: URLSearchParams = new URLSearchParams(); + + body.set('client_id', configData.clientId); + + if (configData.clientSecret && configData.clientSecret.trim().length > 0) { + body.set('client_secret', configData.clientSecret); + } + + body.set('code', authorizationCode); + body.set('grant_type', 'authorization_code'); + body.set('redirect_uri', configData.afterSignInUrl); + + if (tokenRequestConfig?.params) { + Object.entries(tokenRequestConfig.params).forEach(([key, value]: [key: string, value: unknown]) => { + body.append(key, value as string); + }); + } + + if (configData.enablePKCE) { + body.set( + 'code_verifier', + `${await storageManager.getTemporaryDataParameter(extractPkceStorageKeyFromState(state), userId)}`, + ); + + await storageManager.removeTemporaryDataParameter(extractPkceStorageKeyFromState(state), userId); + } + + let tokenResponse: Response; + + try { + tokenResponse = await fetch(tokenEndpoint, { + body, + credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + }); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT1-NE02', + 'Requesting access token failed', + error ?? 'The request to get the access token from the server failed.', + ); + } + + if (!tokenResponse.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT1-HE03', + `Requesting access token failed with ${tokenResponse.statusText}`, + (await tokenResponse.json()) as string, + ); + } + + return handleTokenResponse(storageManager, cryptoHelper, tokenResponse, userId); +} diff --git a/packages/javascript/src/api/revokeAccessToken.ts b/packages/javascript/src/api/revokeAccessToken.ts new file mode 100644 index 000000000..eb669cc3b --- /dev/null +++ b/packages/javascript/src/api/revokeAccessToken.ts @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 {AsgardeoAuthException} from '../errors/exception'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import StorageManager from '../StorageManager'; +import clearSession from '../utils/clearSession'; + +export default async function revokeAccessToken( + storageManager: StorageManager, + userId?: string, +): Promise { + const revokeTokenEndpoint: string | undefined = ( + await storageManager.loadOpenIDProviderConfiguration() + ).revocation_endpoint; + const configData: StrictAuthClientConfig = await storageManager.getConfigData(); + + if (!revokeTokenEndpoint || revokeTokenEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT3-NF01', + 'No revoke access token endpoint found.', + 'No revoke access token endpoint was found in the OIDC provider meta data returned by ' + + 'the well-known endpoint or the revoke access token endpoint passed to the SDK is empty.', + ); + } + + const body: string[] = []; + + body.push(`client_id=${configData.clientId}`); + body.push(`token=${(await storageManager.getSessionData(userId)).access_token}`); + body.push('token_type_hint=access_token'); + + if (configData.clientSecret && configData.clientSecret.trim().length > 0) { + body.push(`client_secret=${configData.clientSecret}`); + } + + let response: Response; + + try { + response = await fetch(revokeTokenEndpoint, { + body: body.join('&'), + credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + }); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT3-NE02', + 'The request to revoke access token failed.', + error ?? 'The request sent to revoke the access token failed.', + ); + } + + if (response.status !== 200 || !response.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT3-HE03', + `Invalid response status received for revoke access token request (${response.statusText}).`, + (await response.json()) as string, + ); + } + + await clearSession(storageManager, userId); + + return response; +} diff --git a/packages/javascript/src/api/validateIdToken.ts b/packages/javascript/src/api/validateIdToken.ts new file mode 100644 index 000000000..36d77daf4 --- /dev/null +++ b/packages/javascript/src/api/validateIdToken.ts @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 {AsgardeoAuthException} from '../errors/exception'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {JWKInterface} from '../models/crypto'; +import {IdToken} from '../models/token'; +import StorageManager from '../StorageManager'; + +export default async function validateIdToken( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + idToken: string, +): Promise { + const jwksEndpoint: string | undefined = (await storageManager.loadOpenIDProviderConfiguration()).jwks_uri; + const configData: StrictAuthClientConfig = await storageManager.getConfigData(); + + if (!jwksEndpoint || jwksEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS_AUTH_HELPER-VIT-NF01', + 'JWKS endpoint not found.', + 'No JWKS endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + + 'or the JWKS endpoint passed to the SDK is empty.', + ); + } + + let response: Response; + + try { + response = await fetch(jwksEndpoint, { + credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', + }); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER-VIT-NE02', + 'Request to jwks endpoint failed.', + error ?? 'The request sent to get the jwks from the server failed.', + ); + } + + if (response.status !== 200 || !response.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER-VIT-HE03', + `Invalid response status received for jwks request (${response.statusText}).`, + (await response.json()) as string, + ); + } + + const {issuer} = await storageManager.loadOpenIDProviderConfiguration(); + + const {keys}: {keys: JWKInterface[]} = (await response.json()) as { + keys: JWKInterface[]; + }; + + const jwk: any = await cryptoHelper.getJWKForTheIdToken(idToken.split('.')[0], keys); + + return cryptoHelper.isValidIdToken( + idToken, + jwk, + configData.clientId, + issuer ?? '', + cryptoHelper.decodeJwtToken(idToken).sub, + configData.tokenValidation?.idToken?.clockTolerance, + configData.tokenValidation?.idToken?.validateIssuer ?? true, + ); +} diff --git a/packages/javascript/src/index.ts b/packages/javascript/src/index.ts index edc15b289..597efe331 100644 --- a/packages/javascript/src/index.ts +++ b/packages/javascript/src/index.ts @@ -16,7 +16,6 @@ * under the License. */ -export {AsgardeoAuthClient} from './__legacy__/client'; export { DefaultAuthClientConfig, WellKnownAuthClientConfig, @@ -24,7 +23,7 @@ export { ExplicitAuthClientConfig, StrictAuthClientConfig, AuthClientConfig, -} from './__legacy__/models'; +} from './models/auth-client-config'; export {IsomorphicCrypto} from './IsomorphicCrypto'; diff --git a/packages/javascript/src/__legacy__/models/client-config.ts b/packages/javascript/src/models/auth-client-config.ts similarity index 62% rename from packages/javascript/src/__legacy__/models/client-config.ts rename to packages/javascript/src/models/auth-client-config.ts index ea6ff7bb0..09cb1de3e 100644 --- a/packages/javascript/src/__legacy__/models/client-config.ts +++ b/packages/javascript/src/models/auth-client-config.ts @@ -16,65 +16,32 @@ * under the License. */ -import {OAuthResponseMode} from '../../models/oauth-response'; -import {OIDCEndpoints} from '../../models/oidc-endpoints'; -import {Platform} from '../../models/platforms'; +import {OAuthResponseMode} from './oauth-response'; +import {OIDCEndpoints} from './oidc-endpoints'; +import {Platform} from './platforms'; export interface DefaultAuthClientConfig { afterSignInUrl: string; afterSignOutUrl?: string; - /** - * Application UUID for the client. - */ applicationId?: string; clientHost?: string; clientId?: string; clientSecret?: string; enablePKCE?: boolean; organizationChain?: { - /** - * Instance ID of the source organization context to retrieve access token from for organization token exchange. - * Used in linked organization scenarios to automatically fetch the source organization's access token. - */ sourceInstanceId?: number; - /** - * Organization ID for the target organization. - * When provided with sourceInstanceId, triggers automatic organization token exchange. - */ targetOrganizationId?: string; }; - /** - * Optional platform where the application is running. - * This helps the SDK to optimize its behavior based on the platform. - * If not provided, the SDK will attempt to auto-detect the platform. - */ platform?: keyof typeof Platform; prompt?: string; responseMode?: OAuthResponseMode; scopes?: string | string[] | undefined; - /** - * Specifies if cookies should be sent with access-token requests, refresh-token requests, - * custom-grant requests, etc. - * - */ sendCookiesInRequests?: boolean; sendIdTokenInLogoutRequest?: boolean; tokenValidation?: { - /** - * ID token validation config. - */ idToken?: { - /** - * Allowed leeway for ID tokens (in seconds). - */ clockTolerance?: number; - /** - * Whether to validate ID tokens. - */ validate?: boolean; - /** - * Whether to validate the issuer of ID tokens. - */ validateIssuer?: boolean; }; }; diff --git a/packages/javascript/src/__legacy__/helpers/index.ts b/packages/javascript/src/utils/clearSession.ts similarity index 71% rename from packages/javascript/src/__legacy__/helpers/index.ts rename to packages/javascript/src/utils/clearSession.ts index cc9eb3414..9046af076 100644 --- a/packages/javascript/src/__legacy__/helpers/index.ts +++ b/packages/javascript/src/utils/clearSession.ts @@ -16,4 +16,9 @@ * under the License. */ -export * from './authentication-helper'; +import StorageManager from '../StorageManager'; + +export default async function clearSession(storageManager: StorageManager, userId?: string): Promise { + await storageManager.removeTemporaryData(userId); + await storageManager.removeSessionData(userId); +} diff --git a/packages/javascript/src/utils/getAuthenticatedUserInfo.ts b/packages/javascript/src/utils/getAuthenticatedUserInfo.ts new file mode 100644 index 000000000..bdc391880 --- /dev/null +++ b/packages/javascript/src/utils/getAuthenticatedUserInfo.ts @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 {IsomorphicCrypto} from '../IsomorphicCrypto'; +import {IdToken} from '../models/token'; +import {User} from '../models/user'; +import extractUserClaimsFromIdToken from './extractUserClaimsFromIdToken'; + +export default function getAuthenticatedUserInfo(cryptoHelper: IsomorphicCrypto, idToken: string): User { + const payload: IdToken = cryptoHelper.decodeJwtToken(idToken); + const username: string = payload?.['username'] ?? ''; + const givenName: string = payload?.['given_name'] ?? ''; + const familyName: string = payload?.['family_name'] ?? ''; + const fullName: string = givenName && familyName ? `${givenName} ${familyName}` : givenName || familyName || ''; + const displayName: string = payload.preferred_username ?? fullName; + + return { + displayName, + username, + ...extractUserClaimsFromIdToken(payload), + }; +} diff --git a/packages/javascript/src/utils/replaceCustomGrantTemplateTags.ts b/packages/javascript/src/utils/replaceCustomGrantTemplateTags.ts new file mode 100644 index 000000000..c13da935c --- /dev/null +++ b/packages/javascript/src/utils/replaceCustomGrantTemplateTags.ts @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 TokenExchangeConstants from '../constants/TokenExchangeConstants'; +import {AsgardeoAuthException} from '../errors/exception'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {SessionData} from '../models/session'; +import StorageManager from '../StorageManager'; +import getAuthenticatedUserInfo from './getAuthenticatedUserInfo'; +import processOpenIDScopes from './processOpenIDScopes'; + +export default async function replaceCustomGrantTemplateTags( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + text: string, + userId?: string, +): Promise { + const configData: StrictAuthClientConfig = await storageManager.getConfigData(); + + const sourceInstanceId: number | null = configData.organizationChain?.sourceInstanceId ?? null; + + let sessionData: SessionData; + + if (sourceInstanceId) { + const {clientId} = configData; + const instanceKey: string = clientId ? `instance_${sourceInstanceId}-${clientId}` : `instance_${sourceInstanceId}`; + + sessionData = await storageManager.getSessionData(userId, instanceKey); + + if (!sessionData || !sessionData.access_token) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER-RCGTT-NE01', + 'No session data found for source instance.', + 'Failed to retrieve session data from the source organization context.', + ); + } + } else { + sessionData = await storageManager.getSessionData(userId); + } + + const scope: string = processOpenIDScopes(configData.scopes); + + if (typeof text !== 'string') { + return text; + } + + return text + .replace(TokenExchangeConstants.Placeholders.ACCESS_TOKEN, sessionData.access_token) + .replace( + TokenExchangeConstants.Placeholders.USERNAME, + getAuthenticatedUserInfo(cryptoHelper, sessionData.id_token).username, + ) + .replace(TokenExchangeConstants.Placeholders.SCOPES, scope) + .replace(TokenExchangeConstants.Placeholders.CLIENT_ID, configData.clientId) + .replace(TokenExchangeConstants.Placeholders.CLIENT_SECRET, configData.clientSecret ?? ''); +} diff --git a/packages/javascript/src/utils/resolveEndpoints.ts b/packages/javascript/src/utils/resolveEndpoints.ts new file mode 100644 index 000000000..96c18f6e5 --- /dev/null +++ b/packages/javascript/src/utils/resolveEndpoints.ts @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 {StrictAuthClientConfig} from '../models/auth-client-config'; +import {OIDCDiscoveryApiResponse} from '../models/oidc-discovery'; +import StorageManager from '../StorageManager'; + +export default async function resolveEndpoints( + storageManager: StorageManager, + response: OIDCDiscoveryApiResponse, +): Promise { + const oidcProviderMetaData: OIDCDiscoveryApiResponse = {}; + const configData: StrictAuthClientConfig = await storageManager.getConfigData(); + + if (configData.endpoints) { + Object.keys(configData.endpoints).forEach((endpointName: string) => { + const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); + + oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; + }); + } + + return {...response, ...oidcProviderMetaData}; +} diff --git a/packages/javascript/src/utils/resolveEndpointsByBaseURL.ts b/packages/javascript/src/utils/resolveEndpointsByBaseURL.ts new file mode 100644 index 000000000..690971c44 --- /dev/null +++ b/packages/javascript/src/utils/resolveEndpointsByBaseURL.ts @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; +import {AsgardeoAuthException} from '../errors/exception'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {Config} from '../models/config'; +import {OIDCDiscoveryApiResponse, OIDCDiscoveryEndpointsApiResponse} from '../models/oidc-discovery'; +import {Platform} from '../models/platforms'; +import StorageManager from '../StorageManager'; + +export default async function resolveEndpointsByBaseURL( + storageManager: StorageManager, +): Promise { + const oidcProviderMetaData: OIDCDiscoveryEndpointsApiResponse = {}; + const configData: StrictAuthClientConfig = await storageManager.getConfigData(); + + const {baseUrl} = configData as any; + + if (!baseUrl) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER_REBO-NF01', + 'Base URL not defined.', + 'Base URL is not defined in AuthClient config.', + ); + } + + if (configData.endpoints) { + Object.keys(configData.endpoints).forEach((endpointName: string) => { + const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); + + oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; + }); + } + + const endpointKeys: typeof OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints = + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints; + const endpointPaths: typeof OIDCDiscoveryConstants.Endpoints = OIDCDiscoveryConstants.Endpoints; + + const defaultEndpoints: OIDCDiscoveryApiResponse = { + [endpointKeys.AUTHORIZATION]: `${baseUrl}${endpointPaths.AUTHORIZATION}`, + [endpointKeys.END_SESSION]: `${baseUrl}${endpointPaths.END_SESSION}`, + [endpointKeys.ISSUER]: `${baseUrl}${endpointPaths.ISSUER}`, + [endpointKeys.JWKS]: `${baseUrl}${endpointPaths.JWKS}`, + [endpointKeys.SESSION_IFRAME]: `${baseUrl}${endpointPaths.SESSION_IFRAME}`, + [endpointKeys.REVOCATION]: `${baseUrl}${endpointPaths.REVOCATION}`, + [endpointKeys.TOKEN]: `${baseUrl}${endpointPaths.TOKEN}`, + [endpointKeys.USERINFO]: `${baseUrl}${endpointPaths.USERINFO}`, + }; + + // For AsgardeoV2 (Thunder), the issuer must be the base URL to comply with RFC 8414. + // Reference: https://datatracker.ietf.org/doc/html/rfc8414#section-2 + if ((configData as Config).platform === Platform.AsgardeoV2) { + defaultEndpoints[OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.ISSUER] = `${baseUrl}`; + } + + return {...defaultEndpoints, ...oidcProviderMetaData}; +} diff --git a/packages/javascript/src/utils/resolveEndpointsExplicitly.ts b/packages/javascript/src/utils/resolveEndpointsExplicitly.ts new file mode 100644 index 000000000..2145d7f0a --- /dev/null +++ b/packages/javascript/src/utils/resolveEndpointsExplicitly.ts @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * 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 OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; +import {AsgardeoAuthException} from '../errors/exception'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {OIDCDiscoveryApiResponse, OIDCDiscoveryEndpointsApiResponse} from '../models/oidc-discovery'; +import StorageManager from '../StorageManager'; + +export default async function resolveEndpointsExplicitly( + storageManager: StorageManager, +): Promise { + const oidcProviderMetaData: OIDCDiscoveryApiResponse = {}; + const configData: StrictAuthClientConfig = await storageManager.getConfigData(); + + const requiredEndpoints: string[] = [ + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.AUTHORIZATION, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.END_SESSION, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.JWKS, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.SESSION_IFRAME, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.REVOCATION, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.TOKEN, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.ISSUER, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.USERINFO, + ]; + + const isRequiredEndpointsContains: boolean = configData.endpoints + ? requiredEndpoints.every((reqEndpointName: string) => + configData.endpoints + ? Object.keys(configData.endpoints).some((endpointName: string) => { + const snakeCasedName: string = endpointName.replace( + /[A-Z]/g, + (letter: string) => `_${letter.toLowerCase()}`, + ); + + return snakeCasedName === reqEndpointName; + }) + : false, + ) + : false; + + if (!isRequiredEndpointsContains) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER-REE-NF01', + 'Required endpoints missing', + 'Some or all of the required endpoints are missing in the object passed to the `endpoints` ' + + 'attribute of the`AuthConfig` object.', + ); + } + + if (configData.endpoints) { + Object.keys(configData.endpoints).forEach((endpointName: string) => { + const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); + + oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; + }); + } + + return {...oidcProviderMetaData}; +} diff --git a/packages/node/src/__legacy__/core/authentication.ts b/packages/node/src/AsgardeoNodeCore.ts similarity index 94% rename from packages/node/src/__legacy__/core/authentication.ts rename to packages/node/src/AsgardeoNodeCore.ts index f5edfebab..932c68501 100644 --- a/packages/node/src/__legacy__/core/authentication.ts +++ b/packages/node/src/AsgardeoNodeCore.ts @@ -17,7 +17,7 @@ */ import { - AsgardeoAuthClient, + AsgardeoJavaScriptClient, AsgardeoAuthException, AuthClientConfig, Crypto, @@ -30,13 +30,13 @@ import { TokenResponse, User, } from '@asgardeo/javascript'; -import {AuthURLCallback} from '../models'; -import {MemoryCacheStore} from '../stores'; -import {Logger, SessionUtils} from '../utils'; -import {NodeCryptoUtils} from '../utils/crypto-utils'; +import {AuthURLCallback} from './models'; +import {MemoryCacheStore} from './stores'; +import {Logger, SessionUtils} from './utils'; +import {NodeCryptoUtils} from './DefaultCrypto'; export class AsgardeoNodeCore { - private auth: AsgardeoAuthClient; + private auth: AsgardeoJavaScriptClient; private cryptoUtils: Crypto; @@ -52,10 +52,9 @@ export class AsgardeoNodeCore { this.store = store; } this.cryptoUtils = new NodeCryptoUtils(); - this.auth = new AsgardeoAuthClient(); - this.auth.initialize(config, this.store, this.cryptoUtils); + this.auth = new AsgardeoJavaScriptClient(config, this.store, this.cryptoUtils); this.storageManager = this.auth.getStorageManager(); - Logger.debug('Initialized AsgardeoAuthClient successfully'); + Logger.debug('Initialized AsgardeoJavaScriptClient successfully'); } public async signIn( @@ -236,7 +235,7 @@ export class AsgardeoNodeCore { return this.auth.exchangeToken(config, userId); } - public async reInitialize(config: Partial>): Promise { + public async reInitialize(config: Partial>): Promise { return this.auth.reInitialize(config); } diff --git a/packages/node/src/__legacy__/utils/crypto-utils.ts b/packages/node/src/DefaultCrypto.ts similarity index 100% rename from packages/node/src/__legacy__/utils/crypto-utils.ts rename to packages/node/src/DefaultCrypto.ts diff --git a/packages/node/src/__legacy__/client.ts b/packages/node/src/LegacyAsgardeoNodeClient.ts similarity index 99% rename from packages/node/src/__legacy__/client.ts rename to packages/node/src/LegacyAsgardeoNodeClient.ts index 2fdfe7ad9..77c5bfa1e 100644 --- a/packages/node/src/__legacy__/client.ts +++ b/packages/node/src/LegacyAsgardeoNodeClient.ts @@ -27,7 +27,7 @@ import { User, ExtendedAuthorizeRequestUrlParams, } from '@asgardeo/javascript'; -import {AsgardeoNodeCore} from './core'; +import {AsgardeoNodeCore} from './AsgardeoNodeCore'; import {AuthURLCallback} from './models'; /** @@ -314,7 +314,7 @@ export class AsgardeoNodeClient { } /** - * This method can be used to update the configurations passed into the constructor of the AsgardeoAuthClient. + * This method can be used to update the configurations passed into the constructor of the AsgardeoJavaScriptClient. * @param {AuthClientConfig} config - The config object containing the attributes * that can be used to configure the SDK * @@ -332,7 +332,7 @@ export class AsgardeoNodeClient { * @memberof AsgardeoNodeClient * */ - public async reInitialize(config: Partial>): Promise { + public async reInitialize(config: Partial>): Promise { return this.authCore.reInitialize(config); } diff --git a/packages/node/src/__legacy__/constants/index.ts b/packages/node/src/constants/index.ts similarity index 100% rename from packages/node/src/__legacy__/constants/index.ts rename to packages/node/src/constants/index.ts diff --git a/packages/node/src/__legacy__/constants/logger-config.ts b/packages/node/src/constants/logger-config.ts similarity index 100% rename from packages/node/src/__legacy__/constants/logger-config.ts rename to packages/node/src/constants/logger-config.ts diff --git a/packages/node/src/__legacy__/constants/uuid-config.ts b/packages/node/src/constants/uuid-config.ts similarity index 100% rename from packages/node/src/__legacy__/constants/uuid-config.ts rename to packages/node/src/constants/uuid-config.ts diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index f4ced8e8b..37dcc0f09 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -26,9 +26,9 @@ if (!globalThis.fetch) { globalThis.Response = Response; } -export {AsgardeoNodeClient as LegacyAsgardeoNodeClient} from './__legacy__/client'; -export * from './__legacy__/models'; -export * from './__legacy__/utils/logger-utils'; +export {AsgardeoNodeClient as LegacyAsgardeoNodeClient} from './LegacyAsgardeoNodeClient'; +export * from './models'; +export * from './utils/NodeLogger'; export {default as CookieConfig} from './constants/CookieConfig'; diff --git a/packages/node/src/__legacy__/models/index.ts b/packages/node/src/models/index.ts similarity index 100% rename from packages/node/src/__legacy__/models/index.ts rename to packages/node/src/models/index.ts diff --git a/packages/node/src/__legacy__/models/session-data.ts b/packages/node/src/models/session-data.ts similarity index 100% rename from packages/node/src/__legacy__/models/session-data.ts rename to packages/node/src/models/session-data.ts diff --git a/packages/node/src/__legacy__/models/url-callback.ts b/packages/node/src/models/url-callback.ts similarity index 100% rename from packages/node/src/__legacy__/models/url-callback.ts rename to packages/node/src/models/url-callback.ts diff --git a/packages/node/src/__legacy__/stores/memory-cache-store.ts b/packages/node/src/stores/MemoryCacheStore.ts similarity index 100% rename from packages/node/src/__legacy__/stores/memory-cache-store.ts rename to packages/node/src/stores/MemoryCacheStore.ts diff --git a/packages/node/src/stores/index.ts b/packages/node/src/stores/index.ts new file mode 100644 index 000000000..f2bb0e4eb --- /dev/null +++ b/packages/node/src/stores/index.ts @@ -0,0 +1 @@ +export * from './MemoryCacheStore'; diff --git a/packages/node/src/__legacy__/utils/logger-utils.ts b/packages/node/src/utils/NodeLogger.ts similarity index 100% rename from packages/node/src/__legacy__/utils/logger-utils.ts rename to packages/node/src/utils/NodeLogger.ts diff --git a/packages/node/src/__legacy__/utils/session-utils.ts b/packages/node/src/utils/SessionUtils.ts similarity index 100% rename from packages/node/src/__legacy__/utils/session-utils.ts rename to packages/node/src/utils/SessionUtils.ts diff --git a/packages/node/src/utils/index.ts b/packages/node/src/utils/index.ts new file mode 100644 index 000000000..436ae3a71 --- /dev/null +++ b/packages/node/src/utils/index.ts @@ -0,0 +1,2 @@ +export * from './SessionUtils'; +export * from './NodeLogger'; From edd99f0b7d5eeb153df0f4b347e2de2eeee5f8f3 Mon Sep 17 00:00:00 2001 From: Brion Date: Tue, 12 May 2026 14:54:56 +0530 Subject: [PATCH 2/2] Fix build issues --- packages/express/src/AsgardeoExpressClient.ts | 203 +- .../src/LegacyAsgardeoExpressClient.ts | 228 -- packages/express/src/index.ts | 4 +- .../express/src/middleware/authentication.ts | 11 +- .../express/src/middleware/protect-route.ts | 2 +- packages/nextjs/src/AsgardeoNextClient.ts | 111 +- packages/nextjs/src/server/index.ts | 4 + packages/node/src/AsgardeoNodeClient.ts | 242 +- packages/node/src/AsgardeoNodeCore.ts | 261 -- packages/node/src/LegacyAsgardeoNodeClient.ts | 435 --- packages/node/src/index.ts | 1 - .../src/runtime/server/AsgardeoNuxtClient.ts | 208 +- packages/react/src/AsgardeoReactClient.ts | 8 +- packages/react/src/__temp__/api.ts | 2 +- packages/vue/src/AsgardeoVueClient.ts | 6 +- pnpm-lock.yaml | 2504 ++++++++++++++++- 16 files changed, 2879 insertions(+), 1351 deletions(-) delete mode 100644 packages/express/src/LegacyAsgardeoExpressClient.ts delete mode 100644 packages/node/src/AsgardeoNodeCore.ts delete mode 100644 packages/node/src/LegacyAsgardeoNodeClient.ts diff --git a/packages/express/src/AsgardeoExpressClient.ts b/packages/express/src/AsgardeoExpressClient.ts index 577065a83..8d02db1fc 100644 --- a/packages/express/src/AsgardeoExpressClient.ts +++ b/packages/express/src/AsgardeoExpressClient.ts @@ -16,15 +16,202 @@ * under the License. */ -import {LegacyAsgardeoNodeClient} from '@asgardeo/node'; +import { + AsgardeoNodeClient, + AsgardeoRuntimeError, + AuthClientConfig, + AuthURLCallback, + Logger, + SignInOptions, + Storage, + TokenResponse, + User, +} from '@asgardeo/node'; +import express from 'express'; +import {v4 as generateUUID} from 'uuid'; +import {CookieConfig, DEFAULT_LOGIN_PATH, DEFAULT_LOGOUT_PATH} from './constants'; import {AsgardeoExpressConfig} from './models/config'; +import {UnauthenticatedCallback} from './models'; +import {asgardeoExpressAuth, protectRoute} from './middleware'; +import {ExpressClientConfig} from './models/express-client-config'; +import {ExpressUtils} from './utils/ExpressUtils'; -/** - * Base class for implementing Asgardeo in Express.js based applications. - * This class provides the core functionality for managing user authentication and sessions. - * - * @typeParam T - Configuration type that extends AsgardeoExpressConfig. - */ -abstract class AsgardeoExpressClient extends LegacyAsgardeoNodeClient {} +class AsgardeoExpressClient extends AsgardeoNodeClient { + private static _clientConfig: ExpressClientConfig; + private static _instance: AsgardeoExpressClient; + + constructor(config: ExpressClientConfig, storage?: Storage) { + const nodeClientConfig = { + ...config, + afterSignInUrl: config.appURL + (config.loginPath ?? DEFAULT_LOGIN_PATH), + afterSignOutUrl: config.appURL + (config.logoutPath ?? DEFAULT_LOGOUT_PATH), + } as unknown as AuthClientConfig; + + super(nodeClientConfig, storage); + AsgardeoExpressClient._clientConfig = {...config}; + } + + public static getInstance(config: ExpressClientConfig, storage?: Storage): AsgardeoExpressClient; + public static getInstance(): AsgardeoExpressClient; + public static getInstance(config?: ExpressClientConfig, storage?: Storage): AsgardeoExpressClient { + if (!AsgardeoExpressClient._instance && config) { + AsgardeoExpressClient._instance = new AsgardeoExpressClient(config, storage); + Logger.debug('Initialized AsgardeoExpressClient successfully'); + } + + if (!AsgardeoExpressClient._instance && !config) { + throw new AsgardeoRuntimeError( + 'User configuration is not found', + 'EXPRESS-CLIENT-GI1-NF01', + '@asgardeo/express', + 'User config has not been passed to initialize AsgardeoExpressClient', + ); + } + + return AsgardeoExpressClient._instance; + } + + public override signIn( + req: express.Request, + res: express.Response, + next: express.NextFunction, + signInConfig?: Record, + ): Promise; + public override signIn( + authURLCallback: AuthURLCallback, + userId: string, + authorizationCode?: string, + sessionState?: string, + state?: string, + signInConfig?: Record, + ): Promise; + public override signIn(options?: SignInOptions): Promise; + public override async signIn( + reqOrCallbackOrOptions?: express.Request | AuthURLCallback | SignInOptions, + resOrUserId?: express.Response | string, + nextOrCode?: express.NextFunction | string, + signInConfigOrSessionState?: Record | string, + state?: string, + signInConfig?: Record, + ): Promise { + if (resOrUserId !== undefined && typeof resOrUserId !== 'string') { + return this._expressSignIn( + reqOrCallbackOrOptions as express.Request, + resOrUserId, + nextOrCode as express.NextFunction, + signInConfigOrSessionState as Record | undefined, + ); + } + + if (typeof reqOrCallbackOrOptions === 'function') { + return super.signIn( + reqOrCallbackOrOptions, + resOrUserId as string, + nextOrCode as string, + signInConfigOrSessionState as string, + state, + signInConfig, + ); + } + + return super.signIn(reqOrCallbackOrOptions as SignInOptions); + } + + private async _expressSignIn( + req: express.Request, + res: express.Response, + next: express.NextFunction, + signInConfig?: Record, + ): Promise { + if (ExpressUtils.hasErrorInURL(req.originalUrl)) { + return Promise.reject( + new AsgardeoRuntimeError( + 'Invalid login request URL', + 'EXPRESS-CLIENT-SI-IV01', + '@asgardeo/express', + 'Login request contains an error query parameter in the URL', + ), + ); + } + + let userId: string = req.cookies.ASGARDEO_SESSION_ID; + if (!userId) { + userId = generateUUID(); + } + + const authRedirectCallback: AuthURLCallback = (url: string) => { + if (url) { + Logger.debug('Redirecting to: ' + url); + res.cookie('ASGARDEO_SESSION_ID', userId, { + maxAge: AsgardeoExpressClient._clientConfig.cookieConfig?.maxAge ?? CookieConfig.defaultMaxAge, + httpOnly: AsgardeoExpressClient._clientConfig.cookieConfig?.httpOnly ?? CookieConfig.defaultHttpOnly, + sameSite: AsgardeoExpressClient._clientConfig.cookieConfig?.sameSite ?? CookieConfig.defaultSameSite, + secure: AsgardeoExpressClient._clientConfig.cookieConfig?.secure ?? CookieConfig.defaultSecure, + }); + res.redirect(url); + + if (typeof next === 'function') { + next(); + } + } + }; + + const authResponse: TokenResponse = await super.signIn( + authRedirectCallback, + userId, + req.query.code as string, + req.query.session_state as string, + req.query.state as string, + signInConfig, + ); + + if (authResponse.accessToken || authResponse.idToken) { + return authResponse; + } + + return { + accessToken: '', + createdAt: 0, + expiresIn: '', + idToken: '', + refreshToken: '', + scope: '', + tokenType: '', + }; + } + + public static protectRoute( + callback: UnauthenticatedCallback, + ): (req: express.Request, res: express.Response, next: express.NextFunction) => Promise { + if (!this._instance) { + throw new AsgardeoRuntimeError( + 'AsgardeoExpressClient is not instantiated', + 'EXPRESS-CLIENT-PR-NF01', + '@asgardeo/express', + 'Create an instance of AsgardeoExpressClient before calling this method.', + ); + } + + return protectRoute(this._instance, callback); + } + + public static asgardeoExpressAuth( + onSignIn: (res: express.Response, response: TokenResponse) => void, + onSignOut: (res: express.Response) => void, + onError: (res: express.Response, exception: AsgardeoRuntimeError) => void, + ): any { + if (!this._instance) { + throw new AsgardeoRuntimeError( + 'AsgardeoExpressClient is not instantiated', + 'EXPRESS-CLIENT-AEA-NF01', + '@asgardeo/express', + 'Create an instance of AsgardeoExpressClient before calling this method.', + ); + } + + return asgardeoExpressAuth(this._instance, AsgardeoExpressClient._clientConfig, onSignIn, onSignOut, onError); + } +} +export {AsgardeoExpressClient}; export default AsgardeoExpressClient; diff --git a/packages/express/src/LegacyAsgardeoExpressClient.ts b/packages/express/src/LegacyAsgardeoExpressClient.ts deleted file mode 100644 index 044c8da8d..000000000 --- a/packages/express/src/LegacyAsgardeoExpressClient.ts +++ /dev/null @@ -1,228 +0,0 @@ -/** - * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.com) All Rights Reserved. - * - * WSO2 Inc. 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 { - LegacyAsgardeoNodeClient, - AuthClientConfig, - AuthURLCallback, - TokenResponse, - Storage, - User, - OIDCEndpoints, - IdToken, - TokenExchangeRequestConfig, - AsgardeoAuthException, - Logger, -} from '@asgardeo/node'; -import {CookieConfig, DEFAULT_LOGIN_PATH, DEFAULT_LOGOUT_PATH} from './constants'; -import {ExpressClientConfig, UnauthenticatedCallback} from './models'; -import express from 'express'; -import {v4 as uuidv4} from 'uuid'; -import {asgardeoExpressAuth, protectRoute} from './middleware'; -import {ExpressUtils} from './utils/ExpressUtils'; - -export class AsgardeoExpressClient { - private _authClient: LegacyAsgardeoNodeClient; - private _storage?: Storage; - private static _clientConfig: ExpressClientConfig; - - private static _instance: AsgardeoExpressClient; - - private constructor(config: ExpressClientConfig, storage?: Storage) { - AsgardeoExpressClient._clientConfig = {...config}; - - const nodeClientConfig: AuthClientConfig = { - ...config, - afterSignInUrl: config.appURL + (config.loginPath || DEFAULT_LOGIN_PATH), - afterSignOutUrl: config.appURL + (config.logoutPath || DEFAULT_LOGOUT_PATH), - }; - - if (storage) { - Logger.debug('Initializing user provided storage'); - this._storage = storage; - } - - this._authClient = new LegacyAsgardeoNodeClient(); - this._authClient.initialize(nodeClientConfig, this._storage); - } - - public static getInstance(config: ExpressClientConfig, storage?: Storage): AsgardeoExpressClient; - public static getInstance(): AsgardeoExpressClient; - public static getInstance(config?: ExpressClientConfig, storage?: Storage): AsgardeoExpressClient { - if (!AsgardeoExpressClient._instance && config) { - AsgardeoExpressClient._instance = new AsgardeoExpressClient(config, storage); - Logger.debug('Initialized AsgardeoExpressClient successfully'); - } - - if (!AsgardeoExpressClient._instance && !config) { - throw Error( - new AsgardeoAuthException( - 'EXPRESS-CLIENT-GI1-NF01', - 'User configuration is not found', - 'User config has not been passed to initialize AsgardeoExpressClient', - ).toString(), - ); - } - - return AsgardeoExpressClient._instance; - } - - public async signIn( - req: express.Request, - res: express.Response, - next: express.nextFunction, - signInConfig?: Record, - ): Promise { - if (ExpressUtils.hasErrorInURL(req.originalUrl)) { - return Promise.reject( - new AsgardeoAuthException( - 'EXPRESS-CLIENT-SI-IV01', - 'Invalid login request URL', - 'Login request contains an error query parameter in the URL', - ), - ); - } - - let userId = req.cookies.ASGARDEO_SESSION_ID; - if (!userId) { - userId = uuidv4(); - } - - const authRedirectCallback = (url: string) => { - if (url) { - Logger.debug('Redirecting to: ' + url); - res.cookie('ASGARDEO_SESSION_ID', userId, { - maxAge: AsgardeoExpressClient._clientConfig.cookieConfig?.maxAge - ? AsgardeoExpressClient._clientConfig.cookieConfig.maxAge - : CookieConfig.defaultMaxAge, - httpOnly: AsgardeoExpressClient._clientConfig.cookieConfig?.httpOnly ?? CookieConfig.defaultHttpOnly, - sameSite: AsgardeoExpressClient._clientConfig.cookieConfig?.sameSite ?? CookieConfig.defaultSameSite, - secure: AsgardeoExpressClient._clientConfig.cookieConfig?.secure ?? CookieConfig.defaultSecure, - }); - res.redirect(url); - - next && typeof next === 'function' && next(); - } - }; - - const authResponse: TokenResponse = await this._authClient.signIn( - authRedirectCallback, - userId, - req.query.code, - req.query.session_state, - req.query.state, - signInConfig, - ); - - if (authResponse.accessToken || authResponse.idToken) { - return authResponse; - } else { - return { - accessToken: '', - createdAt: 0, - expiresIn: '', - idToken: '', - refreshToken: '', - scope: '', - tokenType: '', - }; - } - } - - public async signOut(userId: string): Promise { - return this._authClient.signOut(userId); - } - - public async isSignedIn(userId: string): Promise { - return this._authClient.isSignedIn(userId); - } - - public async getIdToken(userId: string): Promise { - return this._authClient.getIdToken(userId); - } - - public async getUser(userId: string): Promise { - return this._authClient.getUser(userId); - } - - public async getOpenIDProviderEndpoints(): Promise { - return this._authClient.getOpenIDProviderEndpoints(); - } - - public async getDecodedIdToken(userId?: string): Promise { - return this._authClient.getDecodedIdToken(userId); - } - - public async getAccessToken(userId?: string): Promise { - return this._authClient.getAccessToken(userId); - } - - public async exchangeToken(config: TokenExchangeRequestConfig, userId?: string): Promise { - return this._authClient.exchangeToken(config, userId); - } - - public async reInitialize(config: Partial): Promise { - return this._authClient.reInitialize(config); - } - - public async revokeAccessToken(userId?: string): Promise { - return this._authClient.revokeAccessToken(userId); - } - - public static didSignOutFail(afterSignOutUrl: string): boolean { - return LegacyAsgardeoNodeClient.didSignOutFail(afterSignOutUrl); - } - - public static isSignOutSuccessful(afterSignOutUrl: string): boolean { - return LegacyAsgardeoNodeClient.isSignOutSuccessful(afterSignOutUrl); - } - - public static protectRoute( - callback: UnauthenticatedCallback, - ): (req: express.Request, res: express.Response, next: express.nextFunction) => Promise { - if (!this._instance) { - throw new AsgardeoAuthException( - 'EXPRESS-CLIENT-PR-NF01', - 'AsgardeoExpressClient is not instantiated', - 'Create an instance of AsgardeoExpressClient before using calling this method.', - ); - } - - return protectRoute(this._instance, callback); - } - - public static asgardeoExpressAuth( - onSignIn: (response: TokenResponse) => void, - onSignOut: () => void, - onError: (exception: AsgardeoAuthException) => void, - ): any { - if (!this._instance) { - throw new AsgardeoAuthException( - 'EXPRESS-CLIENT-AEA-NF01', - 'AsgardeoExpressClient is not instantiated', - 'Create an instance of AsgardeoExpressClient before using calling this method.', - ); - } - - return asgardeoExpressAuth(this._instance, AsgardeoExpressClient._clientConfig, onSignIn, onSignOut, onError); - } - - public async getStorageManager() { - return this._authClient.getStorageManager(); - } -} diff --git a/packages/express/src/index.ts b/packages/express/src/index.ts index 8f7becdac..bcee0906b 100644 --- a/packages/express/src/index.ts +++ b/packages/express/src/index.ts @@ -18,8 +18,6 @@ export * from './models'; -export {AsgardeoExpressClient as LegacyAsgardeoExpressClient} from './LegacyAsgardeoExpressClient'; - -export {default as AsgardeoExpressClient} from './AsgardeoExpressClient'; +export {AsgardeoExpressClient} from './AsgardeoExpressClient'; export * from '@asgardeo/node'; diff --git a/packages/express/src/middleware/authentication.ts b/packages/express/src/middleware/authentication.ts index 4ef3ae1f6..df10296fb 100644 --- a/packages/express/src/middleware/authentication.ts +++ b/packages/express/src/middleware/authentication.ts @@ -16,9 +16,9 @@ * under the License. */ -import {AsgardeoAuthException, Logger, TokenResponse} from '@asgardeo/node'; +import {AsgardeoRuntimeError, Logger, TokenResponse} from '@asgardeo/node'; import express from 'express'; -import {AsgardeoExpressClient} from '../LegacyAsgardeoExpressClient'; +import {AsgardeoExpressClient} from '../AsgardeoExpressClient'; import {DEFAULT_LOGIN_PATH, DEFAULT_LOGOUT_PATH} from '../constants'; import {ExpressClientConfig} from '../models'; @@ -27,7 +27,7 @@ export const asgardeoExpressAuth = ( config: ExpressClientConfig, onSignIn: (res: express.Response, tokenResponse: TokenResponse) => void, onSignOut: (res: express.Response) => void, - onError: (res: express.Response, exception: AsgardeoAuthException) => void, + onError: (res: express.Response, exception: AsgardeoRuntimeError) => void, ): any => { const router = new express.Router(); @@ -64,9 +64,10 @@ export const asgardeoExpressAuth = ( if (req.cookies.ASGARDEO_SESSION_ID === undefined) { onError( res, - new AsgardeoAuthException( - 'EXPRESS-AUTH_MW-LOGOUT-NF01', + new AsgardeoRuntimeError( 'No cookie found in the request', + 'EXPRESS-AUTH_MW-LOGOUT-NF01', + '@asgardeo/express', 'No cookie was sent with the request. The user may not have signed in yet.', ), ); diff --git a/packages/express/src/middleware/protect-route.ts b/packages/express/src/middleware/protect-route.ts index fe738339a..9e36f9ad1 100644 --- a/packages/express/src/middleware/protect-route.ts +++ b/packages/express/src/middleware/protect-route.ts @@ -18,7 +18,7 @@ import {Logger} from '@asgardeo/node'; import express from 'express'; -import {AsgardeoExpressClient} from '../LegacyAsgardeoExpressClient'; +import {AsgardeoExpressClient} from '../AsgardeoExpressClient'; import {UnauthenticatedCallback} from '../models'; export const protectRoute = ( diff --git a/packages/nextjs/src/AsgardeoNextClient.ts b/packages/nextjs/src/AsgardeoNextClient.ts index 3662d6c50..862daca73 100644 --- a/packages/nextjs/src/AsgardeoNextClient.ts +++ b/packages/nextjs/src/AsgardeoNextClient.ts @@ -22,19 +22,15 @@ import { AsgardeoRuntimeError, AuthClientConfig, CreateOrganizationPayload, - EmbeddedFlowExecuteRequestConfig, EmbeddedFlowExecuteRequestPayload, EmbeddedFlowExecuteResponse, - EmbeddedSignInFlowHandleRequestPayload, ExtendedAuthorizeRequestUrlParams, FlattenedSchema, IdToken, - LegacyAsgardeoNodeClient, Organization, OrganizationDetails, Schema, SignInOptions, - SignOutOptions, SignUpOptions, Storage, TokenExchangeRequestConfig, @@ -63,7 +59,7 @@ import getSessionId from './server/actions/getSessionId'; import decorateConfigWithNextEnv from './utils/decorateConfigWithNextEnv'; /** - * Client for mplementing Asgardeo in Next.js applications. + * Client for implementing Asgardeo in Next.js applications. * This class provides the core functionality for managing user authentication and sessions. * * This class is implemented as a singleton to ensure a single instance across the application. @@ -73,14 +69,10 @@ import decorateConfigWithNextEnv from './utils/decorateConfigWithNextEnv'; class AsgardeoNextClient extends AsgardeoNodeClient { private static instance: AsgardeoNextClient; - private asgardeo: LegacyAsgardeoNodeClient; - public isInitialized: boolean = false; private constructor() { super(); - - this.asgardeo = new LegacyAsgardeoNodeClient(); } /** @@ -132,7 +124,7 @@ class AsgardeoNextClient exte const origin: string = await getClientOrigin(); - return this.asgardeo.initialize( + return super.initialize( { afterSignInUrl: afterSignInUrl ?? origin, afterSignOutUrl: afterSignOutUrl ?? origin, @@ -144,7 +136,7 @@ class AsgardeoNextClient exte signInUrl, signUpUrl, ...rest, - } as any, + } as unknown as T, storage, ); } @@ -153,7 +145,7 @@ class AsgardeoNextClient exte let isInitialized: boolean = false; try { - await this.asgardeo.reInitialize(config as any); + await super.reInitialize(config); isInitialized = true; } catch (error) { @@ -173,7 +165,7 @@ class AsgardeoNextClient exte const resolvedSessionId: string = userId || ((await getSessionId()) as string); try { - const configData: AuthClientConfig = await this.asgardeo.getConfigData(); + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string | undefined = configData?.baseUrl; const profile: User = await getScim2Me({ @@ -192,7 +184,7 @@ class AsgardeoNextClient exte return generateUserProfile(profile, flattenUserSchema(schemas)); } catch (error) { - return this.asgardeo.getUser(resolvedSessionId); + return super.getUser(resolvedSessionId); } } @@ -200,7 +192,7 @@ class AsgardeoNextClient exte await this.ensureInitialized(); try { - const configData: AuthClientConfig = await this.asgardeo.getConfigData(); + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string | undefined = configData?.baseUrl; const profile: User = await getScim2Me({ @@ -228,8 +220,8 @@ class AsgardeoNextClient exte return output; } catch (error) { return { - flattenedProfile: extractUserClaimsFromIdToken(await this.asgardeo.getDecodedIdToken(userId)), - profile: extractUserClaimsFromIdToken(await this.asgardeo.getDecodedIdToken(userId)), + flattenedProfile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)), + profile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)), schemas: [], }; } @@ -239,7 +231,7 @@ class AsgardeoNextClient exte await this.ensureInitialized(); try { - const configData: AuthClientConfig = await this.asgardeo.getConfigData(); + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string | undefined = configData?.baseUrl; const userProfile: User = await updateMeProfile({ @@ -255,7 +247,7 @@ class AsgardeoNextClient exte throw new AsgardeoRuntimeError( `Failed to update user profile: ${error instanceof Error ? error.message : String(error)}`, 'AsgardeoNextClient-UpdateProfileError-001', - 'react', + 'nextjs', 'An error occurred while updating the user profile. Please check your configuration and network connection.', ); } @@ -263,7 +255,7 @@ class AsgardeoNextClient exte async createOrganization(payload: CreateOrganizationPayload, userId?: string): Promise { try { - const configData: AuthClientConfig = await this.asgardeo.getConfigData(); + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string = configData?.baseUrl as string; const createdOrg: Organization = await createOrganization({ @@ -287,7 +279,7 @@ class AsgardeoNextClient exte async getOrganization(organizationId: string, userId?: string): Promise { try { - const configData: AuthClientConfig = await this.asgardeo.getConfigData(); + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string = configData?.baseUrl as string; const organization: OrganizationDetails = await getOrganization({ @@ -311,7 +303,7 @@ class AsgardeoNextClient exte override async getMyOrganizations(options?: any, userId?: string): Promise { try { - const configData: AuthClientConfig = await this.asgardeo.getConfigData(); + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string = configData?.baseUrl as string; const myOrganizations: Organization[] = await getMeOrganizations({ @@ -336,7 +328,7 @@ class AsgardeoNextClient exte override async getAllOrganizations(options?: any, userId?: string): Promise { try { - const configData: AuthClientConfig = await this.asgardeo.getConfigData(); + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string = configData?.baseUrl as string; const allOrganizations: AllOrganizationsApiResponse = await getAllOrganizations({ @@ -358,7 +350,7 @@ class AsgardeoNextClient exte } override async getCurrentOrganization(userId?: string): Promise { - const idToken: IdToken = await this.asgardeo.getDecodedIdToken(userId); + const idToken: IdToken = await super.getDecodedIdToken(userId); return { id: idToken?.org_id as string, @@ -393,9 +385,7 @@ class AsgardeoNextClient exte signInRequired: true, }; - const tokenResponse: TokenResponse | Response = await this.asgardeo.exchangeToken(exchangeConfig, userId); - - return tokenResponse; + return super.exchangeToken(exchangeConfig, userId); } catch (error) { throw new AsgardeoRuntimeError( `Failed to switch organization: ${error instanceof Error ? error.message : String(JSON.stringify(error))}`, @@ -412,17 +402,13 @@ class AsgardeoNextClient exte } override isSignedIn(sessionId?: string): Promise { - return this.asgardeo.isSignedIn(sessionId as string); + return super.isSignedIn(sessionId); } override exchangeToken(config: TokenExchangeRequestConfig, sessionId?: string): Promise { - return this.asgardeo.exchangeToken(config, sessionId); + return super.exchangeToken(config, sessionId); } - /** - * Gets the access token from the session cookie if no sessionId is provided, - * otherwise falls back to legacy client method. - */ // eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars override async getAccessToken(_sessionId?: string): Promise { const {default: getAccessToken} = await import('./server/actions/getAccessToken'); @@ -440,30 +426,16 @@ class AsgardeoNextClient exte return token; } - /** - * Get the decoded ID token for a session - */ - async getDecodedIdToken(sessionId?: string, idToken?: string): Promise { + override async getDecodedIdToken(sessionId?: string, idToken?: string): Promise { await this.ensureInitialized(); - return this.asgardeo.getDecodedIdToken(sessionId as string, idToken); + return super.getDecodedIdToken(sessionId, idToken); } override getConfiguration(): T { - return this.asgardeo.getConfigData() as unknown as T; + return this.getConfigData() as unknown as T; } - override signIn( - options?: SignInOptions, - sessionId?: string, - onSignInSuccess?: (afterSignInUrl: string) => void, - ): Promise; - override signIn( - payload: EmbeddedSignInFlowHandleRequestPayload, - request: EmbeddedFlowExecuteRequestConfig, - sessionId?: string, - onSignInSuccess?: (afterSignInUrl: string) => void, - ): Promise; - override async signIn(...args: any[]): Promise { + override async signIn(...args: any[]): Promise { const arg1: any = args[0]; const arg2: any = args[1]; const arg3: any = args[2]; @@ -490,7 +462,7 @@ class AsgardeoNextClient exte }); } - return this.asgardeo.signIn( + return super.signIn( arg4, arg3, arg1?.code, @@ -500,12 +472,6 @@ class AsgardeoNextClient exte ) as unknown as Promise; } - override signOut(options?: SignOutOptions, afterSignOut?: (afterSignOutUrl: string) => void): Promise; - override signOut( - options?: SignOutOptions, - sessionId?: string, - afterSignOut?: (afterSignOutUrl: string) => void, - ): Promise; override async signOut(...args: any[]): Promise { if (args[1] && typeof args[1] !== 'string') { throw new Error('The second argument must be a string.'); @@ -513,7 +479,7 @@ class AsgardeoNextClient exte const resolvedSessionId: string = args[1] || ((await getSessionId()) as string); - return Promise.resolve(await this.asgardeo.signOut(resolvedSessionId)); + return super.signOut(resolvedSessionId); } override async signUp(options?: SignUpOptions): Promise; @@ -531,7 +497,7 @@ class AsgardeoNextClient exte const firstArg: any = args[0]; if (typeof firstArg === 'object' && 'flowType' in firstArg) { - const configData: AuthClientConfig = await this.asgardeo.getConfigData(); + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string | undefined = configData?.baseUrl; return executeEmbeddedSignUpFlow({ @@ -557,31 +523,16 @@ class AsgardeoNextClient exte ); } - /** - * Gets the sign-in URL for authentication. - * Ensures the client is initialized before making the call. - * - * @param customParams - Custom parameters to include in the sign-in URL. - * @param userId - The user ID - * @returns Promise that resolves to the sign-in URL - */ public async getAuthorizeRequestUrl( customParams: ExtendedAuthorizeRequestUrlParams, userId?: string, ): Promise { await this.ensureInitialized(); - return this.asgardeo.getSignInUrl(customParams, userId); + return super.getSignInUrl(customParams, userId); } - /** - * Gets the storage manager from the underlying Asgardeo client. - * Ensures the client is initialized before making the call. - * - * @returns Promise that resolves to the storage manager - */ - public async getStorageManager(): Promise { - await this.ensureInitialized(); - return this.asgardeo.getStorageManager(); + public override getStorageManager(): any { + return super.getStorageManager(); } // eslint-disable-next-line class-methods-use-this @@ -595,11 +546,11 @@ class AsgardeoNextClient exte } override async setSession(sessionData: Record, sessionId?: string): Promise { - return (await this.asgardeo.getStorageManager()).setSessionData(sessionData, sessionId); + return super.getStorageManager().setSessionData(sessionData, sessionId); } override decodeJwtToken>(token: string): Promise { - return this.asgardeo.decodeJwtToken(token); + return super.decodeJwtToken(token); } } diff --git a/packages/nextjs/src/server/index.ts b/packages/nextjs/src/server/index.ts index 49f3ec784..ef8c4cd2f 100644 --- a/packages/nextjs/src/server/index.ts +++ b/packages/nextjs/src/server/index.ts @@ -22,3 +22,7 @@ export {default as asgardeo} from './asgardeo'; export {default as AsgardeoProvider} from './AsgardeoProvider.js'; export * from './AsgardeoProvider.js'; + +export {default as asgardeoMiddleware} from './middleware/asgardeoMiddleware'; +export type {AsgardeoMiddlewareContext, AsgardeoMiddlewareOptions} from './middleware/asgardeoMiddleware'; +export {default as createRouteMatcher} from './middleware/createRouteMatcher'; diff --git a/packages/node/src/AsgardeoNodeClient.ts b/packages/node/src/AsgardeoNodeClient.ts index e65df081d..9944c6d32 100644 --- a/packages/node/src/AsgardeoNodeClient.ts +++ b/packages/node/src/AsgardeoNodeClient.ts @@ -16,15 +16,241 @@ * under the License. */ -import {AsgardeoJavaScriptClient} from '@asgardeo/javascript'; +import { + AsgardeoJavaScriptClient, + AsgardeoRuntimeError, + AuthClientConfig, + Crypto, + ExtendedAuthorizeRequestUrlParams, + IdToken, + OIDCEndpoints, + SessionData, + SignInOptions, + SignOutOptions, + Storage, + StorageManager, + TokenExchangeRequestConfig, + TokenResponse, + User, +} from '@asgardeo/javascript'; +import {AuthURLCallback} from './models'; import {AsgardeoNodeConfig} from './models/config'; +import {MemoryCacheStore} from './stores'; +import {Logger, SessionUtils} from './utils'; +import {NodeCryptoUtils} from './DefaultCrypto'; -/** - * Base class for implementing Asgardeo in Node.js based applications. - * This class provides the core functionality for managing user authentication and sessions. - *getConfigData - * @typeParam T - Configuration type that extends AsgardeoNodeConfig. - */ -abstract class AsgardeoNodeClient extends AsgardeoJavaScriptClient {} +class AsgardeoNodeClient extends AsgardeoJavaScriptClient { + constructor(config?: AuthClientConfig, store?: Storage) { + const cacheStore: Storage = store ?? new MemoryCacheStore(); + const cryptoUtils: Crypto = new NodeCryptoUtils(); + super(config, cacheStore, cryptoUtils); + if (config) { + Logger.debug('Initialized AsgardeoNodeClient successfully'); + } + } + + public override async initialize(config: T, storage?: Storage): Promise { + const store: Storage = storage ?? new MemoryCacheStore(); + const result = await super.initialize(config, store); + Logger.debug('Initialized AsgardeoNodeClient successfully'); + return result; + } + + public override signIn( + authURLCallback: AuthURLCallback, + userId: string, + authorizationCode?: string, + sessionState?: string, + state?: string, + signInConfig?: Record, + ): Promise; + public override signIn(options?: SignInOptions): Promise; + public override async signIn( + authURLCallbackOrOptions?: AuthURLCallback | SignInOptions, + userId?: string, + authorizationCode?: string, + sessionState?: string, + state?: string, + signInConfig?: Record, + ): Promise { + if (typeof authURLCallbackOrOptions !== 'function') { + return super.signIn(authURLCallbackOrOptions); + } + + const authURLCallback = authURLCallbackOrOptions as AuthURLCallback; + + if (!userId) { + return Promise.reject( + new AsgardeoRuntimeError( + 'No user ID was provided.', + 'NODE-AUTH_CORE-SI-NF01', + '@asgardeo/node', + 'Unable to sign in the user as no user ID was provided.', + ), + ); + } + + if (await this.isSignedIn(userId)) { + const sessionData: SessionData = await this.getStorageManager().getSessionData(userId); + + return { + accessToken: sessionData.access_token, + createdAt: sessionData.created_at, + expiresIn: sessionData.expires_in, + idToken: sessionData.id_token, + refreshToken: sessionData.refresh_token ?? '', + scope: sessionData.scope, + tokenType: sessionData.token_type, + }; + } + + if (!authorizationCode || !state) { + const authURL: string = await this.getAuthURL(userId, signInConfig); + authURLCallback(authURL); + + return { + accessToken: '', + createdAt: 0, + expiresIn: '', + idToken: '', + refreshToken: '', + scope: '', + session: '', + tokenType: '', + }; + } + + return super.requestAccessToken(authorizationCode, sessionState ?? '', state, userId); + } + + public override signOut(userId: string): Promise; + public override signOut( + options?: SignOutOptions, + sessionIdOrAfterSignOut?: string | ((afterSignOutUrl: string) => void), + afterSignOut?: (afterSignOutUrl: string) => void, + ): Promise; + public override async signOut( + userIdOrOptions?: string | SignOutOptions, + sessionIdOrAfterSignOut?: string | ((afterSignOutUrl: string) => void), + afterSignOut?: (afterSignOutUrl: string) => void, + ): Promise { + if (typeof userIdOrOptions === 'string') { + const signOutURL: string = await this.getSignOutUrl(userIdOrOptions); + + if (!signOutURL) { + return Promise.reject( + new AsgardeoRuntimeError( + 'Signing out the user failed.', + 'NODE-AUTH_CORE-SO-NF01', + '@asgardeo/node', + 'Could not obtain the sign-out URL from the server.', + ), + ); + } + + return signOutURL; + } + + return super.signOut(userIdOrOptions, sessionIdOrAfterSignOut, afterSignOut); + } + + public async getAuthURL(userId: string, signInConfig?: Record): Promise { + const authURL: string | undefined = await super.getSignInUrl(signInConfig, userId); + + if (authURL) { + return authURL.toString(); + } + + return Promise.reject( + new AsgardeoRuntimeError( + 'Getting Authorization URL failed.', + 'NODE-AUTH_CORE-GAU-NF01', + '@asgardeo/node', + 'No authorization URL was returned by the Asgardeo Auth JS SDK.', + ), + ); + } + + public override async isSignedIn(userId?: string): Promise { + try { + if (!(await super.isSignedIn(userId))) { + return false; + } + + const storageManager: StorageManager = this.getStorageManager(); + + if (await SessionUtils.validateSession(await storageManager.getSessionData(userId))) { + return true; + } + + const refreshedToken: TokenResponse = await this.refreshAccessToken(userId); + + if (refreshedToken) { + return true; + } + + storageManager.removeSessionData(userId); + await storageManager.getTemporaryData(userId); + + return false; + } catch (error) { + return Promise.reject(error); + } + } + + public async getConfigData(): Promise> { + return this.getStorageManager().getConfigData(); + } + + public override async getSignInUrl( + requestConfig?: ExtendedAuthorizeRequestUrlParams, + userId?: string, + ): Promise { + return super.getSignInUrl(requestConfig, userId); + } + + public override async getUser(userId?: string): Promise { + return super.getUser(userId); + } + + public override async getOpenIDProviderEndpoints(): Promise> { + return super.getOpenIDProviderEndpoints(); + } + + public override async getDecodedIdToken(userId?: string, idToken?: string): Promise { + return super.getDecodedIdToken(userId, idToken); + } + + public override async getAccessToken(userId?: string): Promise { + return super.getAccessToken(userId); + } + + public override async exchangeToken( + config: TokenExchangeRequestConfig, + userId?: string, + ): Promise { + return super.exchangeToken(config, userId); + } + + public override async reInitialize(config: Partial): Promise { + return super.reInitialize(config); + } + + public override async revokeAccessToken(userId?: string): Promise { + return super.revokeAccessToken(userId); + } + + public override async refreshAccessToken(userId?: string): Promise { + return super.refreshAccessToken(userId); + } + + public override async decodeJwtToken>(token: string): Promise { + return super.decodeJwtToken(token); + } + + public override getStorageManager(): StorageManager { + return super.getStorageManager(); + } +} export default AsgardeoNodeClient; diff --git a/packages/node/src/AsgardeoNodeCore.ts b/packages/node/src/AsgardeoNodeCore.ts deleted file mode 100644 index 932c68501..000000000 --- a/packages/node/src/AsgardeoNodeCore.ts +++ /dev/null @@ -1,261 +0,0 @@ -/** - * Copyright (c) 2025, 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 { - AsgardeoJavaScriptClient, - AsgardeoAuthException, - AuthClientConfig, - Crypto, - TokenExchangeRequestConfig, - StorageManager, - IdToken, - OIDCEndpoints, - SessionData, - Storage, - TokenResponse, - User, -} from '@asgardeo/javascript'; -import {AuthURLCallback} from './models'; -import {MemoryCacheStore} from './stores'; -import {Logger, SessionUtils} from './utils'; -import {NodeCryptoUtils} from './DefaultCrypto'; - -export class AsgardeoNodeCore { - private auth: AsgardeoJavaScriptClient; - - private cryptoUtils: Crypto; - - private store: Storage; - - private storageManager: StorageManager; - - constructor(config: AuthClientConfig, store?: Storage) { - // Initialize the default memory cache store if an external store is not passed. - if (!store) { - this.store = new MemoryCacheStore(); - } else { - this.store = store; - } - this.cryptoUtils = new NodeCryptoUtils(); - this.auth = new AsgardeoJavaScriptClient(config, this.store, this.cryptoUtils); - this.storageManager = this.auth.getStorageManager(); - Logger.debug('Initialized AsgardeoJavaScriptClient successfully'); - } - - public async signIn( - authURLCallback: AuthURLCallback, - userId: string, - authorizationCode?: string, - sessionState?: string, - state?: string, - signInConfig?: Record, - ): Promise { - if (!userId) { - return Promise.reject( - new AsgardeoAuthException( - 'NODE-AUTH_CORE-SI-NF01', - 'No user ID was provided.', - 'Unable to sign in the user as no user ID was provided.', - ), - ); - } - - if (await this.isSignedIn(userId)) { - const sessionData: SessionData = await this.storageManager.getSessionData(userId); - - return Promise.resolve({ - accessToken: sessionData.access_token, - createdAt: sessionData.created_at, - expiresIn: sessionData.expires_in, - idToken: sessionData.id_token, - refreshToken: sessionData.refresh_token ?? '', - scope: sessionData.scope, - tokenType: sessionData.token_type, - }); - } - - // Check if the authorization code or session state is there. - // If so, generate the access token, otherwise generate the auth URL and return with callback function. - if (!authorizationCode || !state) { - if (!authURLCallback || typeof authURLCallback !== 'function') { - return Promise.reject( - new AsgardeoAuthException( - 'NODE-AUTH_CORE-SI-NF02', - 'Invalid AuthURLCallback function.', - 'The AuthURLCallback is not defined or is not a function.', - ), - ); - } - const authURL: string = await this.getAuthURL(userId, signInConfig); - authURLCallback(authURL); - - return Promise.resolve({ - accessToken: '', - createdAt: 0, - expiresIn: '', - idToken: '', - refreshToken: '', - scope: '', - session: '', - tokenType: '', - }); - } - - return this.requestAccessToken(authorizationCode, sessionState ?? '', userId, state); - } - - public async getAuthURL(userId: string, signInConfig?: Record): Promise { - const authURL: string | undefined = await this.auth.getSignInUrl(signInConfig, userId); - - if (authURL) { - return Promise.resolve(authURL.toString()); - } - return Promise.reject( - new AsgardeoAuthException( - 'NODE-AUTH_CORE-GAU-NF01', - 'Getting Authorization URL failed.', - 'No authorization URL was returned by the Asgardeo Auth JS SDK.', - ), - ); - } - - public async requestAccessToken( - authorizationCode: string, - sessionState: string, - userId: string, - state: string, - ): Promise { - return this.auth.requestAccessToken(authorizationCode, sessionState, state, userId); - } - - public async getIdToken(userId: string): Promise { - const isLoggedIn: boolean = await this.isSignedIn(userId); - if (!isLoggedIn) { - return Promise.reject( - new AsgardeoAuthException( - 'NODE-AUTH_CORE-GIT-NF01', - 'The user is not logged in.', - 'No session ID was found for the requested user. User is not logged in.', - ), - ); - } - const idToken: string = await this.auth.getIdToken(userId); - if (idToken) { - return Promise.resolve(idToken); - } - return Promise.reject( - new AsgardeoAuthException( - 'NODE-AUTH_CORE-GIT-NF02', - 'Requesting ID Token Failed', - 'No ID Token was returned by the Asgardeo Auth JS SDK.', - ), - ); - } - - public async refreshAccessToken(userId?: string): Promise { - return this.auth.refreshAccessToken(userId); - } - - public async isSignedIn(userId: string): Promise { - try { - if (!(await this.auth.isSignedIn(userId))) { - return await Promise.resolve(false); - } - - if (await SessionUtils.validateSession(await this.storageManager.getSessionData(userId))) { - return await Promise.resolve(true); - } - - const refreshedToken: TokenResponse = await this.refreshAccessToken(userId); - - if (refreshedToken) { - return await Promise.resolve(true); - } - - this.storageManager.removeSessionData(userId); - this.storageManager.getTemporaryData(userId); - return await Promise.resolve(false); - } catch (error) { - return Promise.reject(error); - } - } - - public async signOut(userId: string): Promise { - const signOutURL: string = await this.auth.getSignOutUrl(userId); - - if (!signOutURL) { - return Promise.reject( - new AsgardeoAuthException( - 'NODE-AUTH_CORE-SO-NF01', - 'Signing out the user failed.', - 'Could not obtain the sign-out URL from the server.', - ), - ); - } - - return Promise.resolve(signOutURL); - } - - public async getUser(userId: string): Promise { - return this.auth.getUser(userId); - } - - public async getConfigData(): Promise> { - return this.storageManager.getConfigData(); - } - - public async getOpenIDProviderEndpoints(): Promise { - return this.auth.getOpenIDProviderEndpoints() as Promise; - } - - public async getDecodedIdToken(userId?: string, idToken?: string): Promise { - return this.auth.getDecodedIdToken(userId, idToken); - } - - public async getAccessToken(userId?: string): Promise { - return this.auth.getAccessToken(userId); - } - - public async exchangeToken(config: TokenExchangeRequestConfig, userId?: string): Promise { - return this.auth.exchangeToken(config, userId); - } - - public async reInitialize(config: Partial>): Promise { - return this.auth.reInitialize(config); - } - - public async revokeAccessToken(userId?: string): Promise { - return this.auth.revokeAccessToken(userId); - } - - public static didSignOutFail(afterSignOutUrl: string): boolean { - return AsgardeoNodeCore.didSignOutFail(afterSignOutUrl); - } - - public static isSignOutSuccessful(afterSignOutUrl: string): boolean { - return AsgardeoNodeCore.isSignOutSuccessful(afterSignOutUrl); - } - - public getStorageManager(): StorageManager { - return this.storageManager; - } - - public async decodeJwtToken>(token: string): Promise { - return this.auth.decodeJwtToken(token); - } -} diff --git a/packages/node/src/LegacyAsgardeoNodeClient.ts b/packages/node/src/LegacyAsgardeoNodeClient.ts deleted file mode 100644 index 77c5bfa1e..000000000 --- a/packages/node/src/LegacyAsgardeoNodeClient.ts +++ /dev/null @@ -1,435 +0,0 @@ -/** - * Copyright (c) 2025, 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 { - AuthClientConfig, - TokenExchangeRequestConfig, - StorageManager, - IdToken, - OIDCEndpoints, - Storage, - TokenResponse, - User, - ExtendedAuthorizeRequestUrlParams, -} from '@asgardeo/javascript'; -import {AsgardeoNodeCore} from './AsgardeoNodeCore'; -import {AuthURLCallback} from './models'; - -/** - * This class provides the necessary methods needed to implement authentication. - * - * @export - * @class AsgardeoNodeClient - */ -export class AsgardeoNodeClient { - private authCore: AsgardeoNodeCore; - - /** - * This is the constructor method that returns an instance of the `AsgardeoNodeClient` class. - * - * @param {AuthClientConfig} config - The configuration object. - * @param {Storage} store - The store object. - * - * @example - * ``` - * const _store: Storage = new DataStore(); - * const _config = { - afterSignInUrl: "http://localhost:3000/sign-in", - afterSignOutUrl: "http://localhost:3000/dashboard", - clientId: "client ID", - serverOrigin: "https://api.asgardeo.io/t/" - }; - * const auth = new AsgardeoNodeClient(_config,_store); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#constructor - * @preserve - */ - // eslint-disable-next-line @typescript-eslint/no-empty-function - constructor() {} - - public async initialize(config: AuthClientConfig, store?: Storage): Promise { - this.authCore = new AsgardeoNodeCore(config, store); - - return Promise.resolve(true); - } - - /** - * This method logs in a user. If the authorization code is not available it will resolve with the - * authorization URL to authorize the user. - * @param {string} authorizationCode - The authorization code obtained from Asgardeo after a user signs in. - * @param {String} sessionState - The session state obtained from Asgardeo after a user signs in. - * @param {string} userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * @param {string} state - The state parameter in the redirect URL. - * - * @return {Promise} - A Promise that resolves with the - * [`URLResponse`](#URLResponse) object or a Promise that resolves with - * the [`NodeTokenResponse`](#NodeTokenResponse) object. - * - * @example - * ``` - * authClient.signIn(req.query.code, req.query.session_state).then(response => { - * //URL property will available if the user has not been authenticated already - * if (response.hasOwnProperty('url')) { - * res.redirect(response.url) - * } else { - * //Set the cookie - * res.cookie('ASGARDEO_SESSION_ID', response.session, { maxAge: 900000, httpOnly: true, SameSite: true }); - * res.status(200).send(response) - * } - *}); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#signIn - * - * @memberof AsgardeoNodeClient - * - */ - public async signIn( - authURLCallback: AuthURLCallback, - userId: string, - authorizationCode?: string, - sessionState?: string, - state?: string, - signInConfig?: Record, - ): Promise { - return this.authCore.signIn(authURLCallback, userId, authorizationCode, sessionState, state, signInConfig); - } - - /** - * Method to get the configuration data. - * - * @returns {Promise>} - A promise that resolves with the configuration data. - */ - public async getConfigData(): Promise> { - return this.authCore.getConfigData(); - } - - /** - * This method clears all session data and returns the sign-out URL. - * @param {string} userId - The userId of the user. (If you are using ExpressJS, - * you may get this from the request cookies) - * - * @return {Promise} - A Promise that resolves with the sign-out URL. - * - * @example - * ``` - * const signOutUrl = await auth.signOut(userId); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#signOut - * - * @memberof AsgardeoNodeClient - * - */ - public async signOut(userId: string): Promise { - return this.authCore.signOut(userId); - } - - /** - * This method returns a boolean value indicating if the user is authenticated or not. - * @param {string} userId - The userId of the user. - * (If you are using ExpressJS, you may get this from the request cookies) - * - * @return { Promise} -A boolean value that indicates of the user is authenticated or not. - * - * @example - * ``` - * const isAuth = await authClient.isSignedIn("a2a2972c-51cd-5e9d-a9ae-058fae9f7927"); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#isSignedIn - * - * @memberof AsgardeoNodeClient - * - */ - public async isSignedIn(userId: string): Promise { - return this.authCore.isSignedIn(userId); - } - - /** - * This method returns the id token. - * @param {string} userId - The userId of the user. - * (If you are using ExpressJS, you may get this from the request cookies) - * - * @return {Promise} -A Promise that resolves with the ID Token. - * - * @example - * ``` - * const isAuth = await authClient.getIdToken("a2a2972c-51cd-5e9d-a9ae-058fae9f7927"); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getIdToken - * - * @memberof AsgardeoNodeClient - * - */ - public async getIdToken(userId: string): Promise { - return this.authCore.getIdToken(userId); - } - - /** - * This method returns an object containing basic user information obtained from the id token. - * @param {string} userId - The userId of the user. - * (If you are using ExpressJS, you may get this from the request cookies) - * - * @return {Promise} -A Promise that resolves with the - * An object containing basic user information obtained from the id token. - * - * @example - * ``` - * const basicInfo = await authClient.getUser("a2a2972c-51cd-5e9d-a9ae-058fae9f7927"); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getUser - * - * @memberof AsgardeoNodeClient - * - */ - public async getUser(userId: string): Promise { - return this.authCore.getUser(userId); - } - - /** - * This method returns an object containing the OIDC service endpoints returned by the `.well-known` endpoint. - * @return {Promise} -A Promise that resolves with - * an object containing the OIDC service endpoints returned by the `.well-known` endpoint. - * - * @example - * ``` - * const oidcEndpoints = await auth.getOpenIDProviderEndpoints(); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getOpenIDProviderEndpoints - * - * @memberof AsgardeoNodeClient - * - */ - public async getOpenIDProviderEndpoints(): Promise { - return this.authCore.getOpenIDProviderEndpoints(); - } - - /** - * This method returns the decoded ID token payload. - * @param {string} userId - The userId of the user. - * (If you are using ExpressJS, you may get this from the request cookies) - * - * @return {Promise} -A Promise that resolves with - * an object containing the decoded ID token payload. - * - * @example - * ``` - * const decodedIDTokenPayload = await auth.getDecodedIdToken("a2a2972c-51cd-5e9d-a9ae-058fae9f7927"); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getDecodedIdToken - * - * @memberof AsgardeoNodeClient - * - */ - public async getDecodedIdToken(userId?: string, idToken?: string): Promise { - return this.authCore.getDecodedIdToken(userId, idToken); - } - - /** - * This method returns the access token. - * @param {string} userId - The userId of the user. - * (If you are using ExpressJS, you may get this from the request cookies) - * - * @return {Promise} -A Promise that resolves with - * the access token stored in the store - * - * @example - * ``` - *const accessToken = await auth.getAccessToken("a2a2972c-51cd-5e9d-a9ae-058fae9f7927"); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getAccessToken - * - * @memberof AsgardeoNodeClient - * - */ - public async getAccessToken(userId?: string): Promise { - return this.authCore.getAccessToken(userId); - } - - /** - * This method returns Promise that resolves with the token information - * or the response returned by the server depending on the configuration passed. - * @param {TokenExchangeRequestConfig} config - The config object contains attributes that would be used - * to configure the custom grant request. - * - * @param {string} userId - The userId of the user. - * (If you are using ExpressJS, you may get this from the request cookies) - * - * @return {Promise} -A Promise that resolves with the token information - * or the response returned by the server depending on the configuration passed. - * - * @example - * ``` - * const config = { - * attachToken: false, - * data: { - * client_id: "{{clientId}}", - * grant_type: "account_switch", - * scope: "{{scope}}", - * token: "{{token}}", - * }, - * id: "account-switch", - * returnResponse: true, - * returnsSession: true, - * signInRequired: true - * } - - * auth.exchangeToken(config).then((response)=>{ - * console.log(response); - * }).catch((error)=>{ - * console.error(error); - * }); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#exchangeToken - * - * @memberof AsgardeoNodeClient - * - */ - public async exchangeToken(config: TokenExchangeRequestConfig, userId?: string): Promise { - return this.authCore.exchangeToken(config, userId); - } - - /** - * This method can be used to update the configurations passed into the constructor of the AsgardeoJavaScriptClient. - * @param {AuthClientConfig} config - The config object containing the attributes - * that can be used to configure the SDK - * - * @return {Promise} -A Promise that resolves with a void. - * - * @example - * ``` - * const reInitialize = await auth.reInitialize({ - * afterSignOutUrl: "http://localhost:3000/sign-out" - * }); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#reInitialize - * - * @memberof AsgardeoNodeClient - * - */ - public async reInitialize(config: Partial>): Promise { - return this.authCore.reInitialize(config); - } - - public async getSignInUrl(requestConfig?: ExtendedAuthorizeRequestUrlParams, userId?: string): Promise { - return this.authCore.getAuthURL(userId, requestConfig); - } - - /** - * This method returns a Promise that resolves with the response returned by the server. - * @param {string} userId - The userId of the user. - * (If you are using ExpressJS, you may get this from the request cookies) - * - * @return {Promise} -A Promise that resolves with the response returned by the server. - * - * @example - * ``` - * const revokeToken = await auth.revokeAccessToken("a2a2972c-51cd-5e9d-a9ae-058fae9f7927"); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#revokeAccessToken - * - * @memberof AsgardeoNodeClient - * - */ - public async revokeAccessToken(userId?: string): Promise { - return this.authCore.revokeAccessToken(userId); - } - - /** - * This method refreshes the access token and returns a Promise that resolves with the new access - * token and other relevant data. - * - * @param {string} userId - A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns {Promise} - A Promise that resolves with the token response. - * - * @example - * ``` - * const tokenResponse = await auth.refreshAccessToken("a2a2972c-51cd-5e9d-a9ae-058fae9f7927") - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#refreshAccessToken - * - * @memberof AsgardeoNodeClient - */ - public refreshAccessToken(userId?: string): Promise { - return this.authCore.refreshAccessToken(userId); - } - - /** - * This method returns if the user has been successfully signed out or not. - * @param {string} afterSignOutUrl - The URL to which the user is redirected to - * after signing out from the server. - * - * @return {boolean} - A boolean value indicating if the user has been signed out or not. - * - * @example - * ``` - * const isSignedOut = auth.isSignOutSuccessful();; - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#isSignOutSuccessful - * - * @memberof AsgardeoNodeClient - * - */ - public static isSignOutSuccessful(afterSignOutUrl: string): boolean { - return AsgardeoNodeClient.isSignOutSuccessful(afterSignOutUrl); - } - - /** - * This method returns if sign-out failed or not - * @param {string} afterSignOutUrl - The URL to which the user is redirected to - * after signing out from the server. - * - * @return {boolean} - A boolean value indicating if sign-out failed or not. - * - * @example - * ``` - * const isSignedOut = auth.isSignOutSuccessful(); - * ``` - * - * @link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#didSignOutFail - * - * @memberof AsgardeoNodeClient - * - */ - public static didSignOutFail(afterSignOutUrl: string): boolean { - return AsgardeoNodeClient.didSignOutFail(afterSignOutUrl); - } - - public async getStorageManager(): Promise> { - return this.authCore.getStorageManager(); - } - - public async decodeJwtToken>(token: string): Promise { - return this.authCore.decodeJwtToken(token); - } -} diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 37dcc0f09..b3903f6df 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -26,7 +26,6 @@ if (!globalThis.fetch) { globalThis.Response = Response; } -export {AsgardeoNodeClient as LegacyAsgardeoNodeClient} from './LegacyAsgardeoNodeClient'; export * from './models'; export * from './utils/NodeLogger'; diff --git a/packages/nuxt/src/runtime/server/AsgardeoNuxtClient.ts b/packages/nuxt/src/runtime/server/AsgardeoNuxtClient.ts index bfc030a14..608f14d37 100644 --- a/packages/nuxt/src/runtime/server/AsgardeoNuxtClient.ts +++ b/packages/nuxt/src/runtime/server/AsgardeoNuxtClient.ts @@ -18,13 +18,13 @@ import { AsgardeoNodeClient, - LegacyAsgardeoNodeClient, type AuthClientConfig, type IdToken, type Organization, type OrganizationDetails, type CreateOrganizationPayload, type Storage, + type StorageManager, type TokenExchangeRequestConfig, type TokenResponse, type User, @@ -46,7 +46,6 @@ import { initializeEmbeddedSignInFlow, executeEmbeddedSignInFlow, executeEmbeddedSignUpFlow, - type EmbeddedSignInFlowHandleRequestPayload, type EmbeddedFlowExecuteRequestConfig, type EmbeddedFlowExecuteRequestPayload, type EmbeddedFlowExecuteResponse, @@ -58,14 +57,7 @@ import type {AsgardeoNuxtConfig, AsgardeoSessionPayload} from '../types'; /** * Singleton Asgardeo client for Nuxt applications. * - * Mirrors the {@link AsgardeoNextClient} pattern: a single shared instance per - * server process that delegates OAuth/OIDC operations to an internal - * {@link LegacyAsgardeoNodeClient}. The legacy client provisions its own default - * in-memory store (`MemoryCacheStore`) for PKCE state and tokens so that state - * persists across the sign-in → callback boundary. - * - * Consumers call {@link getInstance} directly from server routes and plugins — - * there is no per-request wrapper factory. Initialization happens once per + * Extends {@link AsgardeoNodeClient} directly — initialization happens once per * process (guarded by {@link isInitialized}) from the `asgardeo-init` Nitro * plugin on the first request. * @@ -81,13 +73,10 @@ import type {AsgardeoNuxtConfig, AsgardeoSessionPayload} from '../types'; class AsgardeoNuxtClient extends AsgardeoNodeClient { private static instance: AsgardeoNuxtClient; - private legacy: LegacyAsgardeoNodeClient; - public isInitialized: boolean = false; private constructor() { super(); - this.legacy = new LegacyAsgardeoNodeClient(); } /** @@ -101,9 +90,9 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { } /** - * Initializes the underlying legacy client with OAuth/OIDC settings derived - * from the Nuxt module config. Idempotent — repeated calls are no-ops after - * the first successful initialization. + * Initializes the client with OAuth/OIDC settings derived from the Nuxt + * module config. Idempotent — repeated calls are no-ops after the first + * successful initialization. */ override async initialize(config: AsgardeoNuxtConfig, storage?: Storage): Promise { if (this.isInitialized) { @@ -120,40 +109,30 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { scopes: config.scopes || ['openid', 'profile'], } as AuthClientConfig; - const result: boolean = await this.legacy.initialize(authConfig, storage); + const result: boolean = await super.initialize(authConfig as unknown as AsgardeoNuxtConfig, storage); this.isInitialized = true; return result; } override async reInitialize(config: Partial): Promise { - await this.legacy.reInitialize(config as any); + await super.reInitialize(config); return true; } /** - * Seeds the legacy in-memory token store from a verified session JWT payload. - * - * The signed session cookie is the source of truth for tokens in this SDK — it - * survives server restarts and new worker processes. The underlying - * {@link LegacyAsgardeoNodeClient}, however, keeps tokens in a - * {@link MemoryCacheStore} keyed by `sessionId`, and its - * `getAccessToken` / `getUser` / `getDecodedIdToken` / `signOut` paths all - * read from that store. Without rehydration, those calls fail whenever the - * in-memory store and the cookie diverge (the classic case: `nuxi dev` - * restart while the browser still holds a valid session cookie). + * Seeds the in-memory token store from a verified session JWT payload. * - * Writes the snake_case token shape the legacy helper expects - * (see `AuthenticationHelper.processTokenResponse`). Safe to call on every - * request — it's an in-memory write and the cookie always reflects the - * freshest tokens (the refresh path re-issues the cookie too). + * The signed session cookie is the source of truth for tokens — it survives + * server restarts and new worker processes. Without rehydration, token + * lookups fail whenever the in-memory store and the cookie diverge (e.g. + * after a `nuxi dev` restart while the browser still holds a valid cookie). */ async rehydrateSessionFromPayload(session: AsgardeoSessionPayload): Promise { if (!this.isInitialized || !session?.sessionId || !session?.accessToken) { return; } - type StorageManager = Awaited['getStorageManager']>>; - const storageManager: StorageManager = await this.legacy.getStorageManager(); + const storageManager: StorageManager = this.getStorageManager(); const iatSeconds: number = typeof session.iat === 'number' ? session.iat : Math.floor(Date.now() / 1000); const expiresInSeconds: number = typeof session.accessTokenExpiresAt === 'number' ? Math.max(0, session.accessTokenExpiresAt - iatSeconds) : 3600; @@ -176,38 +155,14 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { /** * Initiates the authorization code flow, handles an embedded sign-in step, * or exchanges a code for tokens. - * - * Overload 1 — **redirect-flow** (existing callers like `signin.get.ts`): - * ``` - * signIn(authURLCallback, sessionId, code?, sessionState?, state?, config?) - * ``` - * Overload 2 — **embedded flow initiate** (flowId === ''): - * ``` - * signIn({flowId: ''}, request, sessionId) - * ``` - * Dispatches to `initializeEmbeddedSignInFlow`. - * - * Overload 3 — **embedded flow execute** (flowId set): - * ``` - * signIn(payload, request, sessionId) - * ``` - * Dispatches to `executeEmbeddedSignInFlow`. - * - * Overload 4 — **code exchange** (completion after embedded flow): - * ``` - * signIn({code, state, session_state}, {}, sessionId) - * ``` - * Falls through to the legacy redirect-flow code-exchange path. */ - override signIn(...args: any[]): Promise { + override async signIn(...args: any[]): Promise { const arg0: unknown = args[0]; - // Embedded flow: first argument is a non-null object with a `flowId` property. if (typeof arg0 === 'object' && arg0 !== null && 'flowId' in arg0) { const sessionId: string | undefined = args[2] as string | undefined; if (arg0.flowId === '') { - // Initialize embedded sign-in flow. return this.getAuthorizeRequestUrl( {client_secret: '{{clientSecret}}', response_mode: 'direct'}, sessionId, @@ -220,49 +175,33 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { }); } - // Execute embedded sign-in step. const request: EmbeddedFlowExecuteRequestConfig = args[1] ?? {}; return executeEmbeddedSignInFlow({ - payload: arg0 as EmbeddedSignInFlowHandleRequestPayload, + payload: arg0 as any, url: request.url, }); } - // Code exchange path: {code, state, session_state} as arg0, {} as arg1, sessionId as arg2. - // Falls through to the legacy client mirroring AsgardeoNextClient. if (typeof arg0 === 'object' && arg0 !== null && ('code' in arg0 || 'state' in arg0)) { - const payload: {code?: unknown; session_state?: unknown; state?: unknown} = arg0 as { - code?: unknown; - session_state?: unknown; - state?: unknown; - }; + const payload: {code?: unknown; session_state?: unknown; state?: unknown} = arg0 as any; const code: string | undefined = typeof payload.code === 'string' ? payload.code : undefined; const sessionState: string | undefined = typeof payload.session_state === 'string' ? payload.session_state : undefined; const state: string | undefined = typeof payload.state === 'string' ? payload.state : undefined; const extraParams: Record = {}; - if (code) { - extraParams.code = code; - } - if (sessionState) { - extraParams.session_state = sessionState; - } - if (state) { - extraParams.state = state; - } + if (code) extraParams.code = code; + if (sessionState) extraParams.session_state = sessionState; + if (state) extraParams.state = state; - // args[3] would be onSignInSuccess (undefined), args[2] is sessionId - return this.legacy.signIn(args[3], args[2], code, sessionState, state, extraParams); + return super.signIn(args[3], args[2], code, sessionState, state, extraParams); } - // Redirect-flow: first argument is a callback function. - return this.legacy.signIn(args[0], args[1], args[2], args[3], args[4], args[5]); + return super.signIn(args[0], args[1], args[2], args[3], args[4], args[5]); } /** * Executes the embedded sign-up flow step. - * Mirrors `AsgardeoNextClient.signUp` with an `EmbeddedFlowExecuteRequestPayload`. */ override signUp(options?: SignUpOptions): Promise; override signUp(payload: EmbeddedFlowExecuteRequestPayload): Promise; @@ -270,78 +209,54 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { payloadOrOptions?: EmbeddedFlowExecuteRequestPayload | SignUpOptions, ): Promise { if (!payloadOrOptions || !('flowType' in payloadOrOptions)) { - // Redirect-flow sign-up: not meaningful server-side, but satisfies the interface. return undefined; } - const configData: AuthClientConfig | undefined = (await this.legacy.getConfigData?.()) as - | AuthClientConfig - | undefined; + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string | undefined = configData?.baseUrl as string | undefined; - const response: EmbeddedFlowExecuteResponse = await executeEmbeddedSignUpFlow({ + return executeEmbeddedSignUpFlow({ baseUrl, payload: payloadOrOptions as EmbeddedFlowExecuteRequestPayload, }); - return response; } /** * Returns the OAuth2 authorization URL. - * Used by the redirect-flow GET handler and the embedded-flow initiation path. - * - * Mirrors `AsgardeoNextClient.getAuthorizeRequestUrl`. */ public async getAuthorizeRequestUrl( customParams: ExtendedAuthorizeRequestUrlParams, userId?: string, ): Promise { - return this.legacy.getSignInUrl(customParams, userId); + return super.getSignInUrl(customParams, userId); } - /** - * Clears the session and returns the RP-Initiated Logout URL. - * Accepts either `(sessionId: string)` or `(options?, sessionId?, callback?)`. - */ override async signOut(...args: any[]): Promise { const sessionId: string = typeof args[0] === 'string' ? args[0] : (args[1] as string); - return this.legacy.signOut(sessionId); + return super.signOut(sessionId); } override getUser(sessionId?: string): Promise { - return this.legacy.getUser(sessionId as string); + return super.getUser(sessionId); } override getAccessToken(sessionId?: string): Promise { - return this.legacy.getAccessToken(sessionId as string); + return super.getAccessToken(sessionId); } - /** - * Decodes and returns the ID token claims for the given session. - * Exposed here (as on {@link AsgardeoNextClient}) so route handlers can - * access ID token claims without falling back to the legacy client. - */ - getDecodedIdToken(sessionId?: string, idToken?: string): Promise { - return this.legacy.getDecodedIdToken(sessionId as string, idToken); + override getDecodedIdToken(sessionId?: string, idToken?: string): Promise { + return super.getDecodedIdToken(sessionId, idToken); } override isSignedIn(sessionId?: string): Promise { - return this.legacy.isSignedIn(sessionId as string); + return super.isSignedIn(sessionId); } override exchangeToken(config: TokenExchangeRequestConfig, sessionId?: string): Promise { - return this.legacy.exchangeToken(config, sessionId); + return super.exchangeToken(config, sessionId); } - /** - * Fetches the flattened SCIM2 user profile for the given session. - * Mirrors `AsgardeoNextClient.getUserProfile` — calls `getScim2Me` + - * `getSchemas` + `generateFlattenedUserProfile` and falls back to - * `getUser` claims if SCIM2 is unavailable. - */ override async getUserProfile(sessionId: string): Promise { const accessToken: string = await this.getAccessToken(sessionId); - const configData: AuthClientConfig | undefined = (await this.legacy.getConfigData?.()) as - | AuthClientConfig - | undefined; + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string = (configData?.baseUrl ?? '') as string; try { @@ -360,16 +275,11 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { schemas: processedSchemas, }; } catch { - // Fall back to user claims from the ID token const user: User = await this.getUser(sessionId); return {flattenedProfile: user, profile: user, schemas: []}; } } - /** - * Extracts the current organisation from the decoded ID token. - * Returns null when the user is not acting within an organisation. - */ override async getCurrentOrganization(sessionId: string): Promise { try { const idToken: IdToken = await this.getDecodedIdToken(sessionId); @@ -386,14 +296,9 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { } } - /** - * Returns the list of organisations the authenticated user is a member of. - */ override async getMyOrganizations(sessionId: string): Promise { const accessToken: string = await this.getAccessToken(sessionId); - const configData: AuthClientConfig | undefined = (await this.legacy.getConfigData?.()) as - | AuthClientConfig - | undefined; + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string = (configData?.baseUrl ?? '') as string; return getMeOrganizations({ @@ -402,44 +307,27 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { }); } - /** - * Fetches the branding preference for the tenant / application. - * Delegates to the standalone `getBrandingPreference` API helper from - * `@asgardeo/node`, which does not require an authenticated session. - */ // eslint-disable-next-line class-methods-use-this async getBrandingPreference(config: GetBrandingPreferenceConfig): Promise { return getBrandingPreference(config); } - /** - * Updates the SCIM2 /Me profile for the authenticated user. - * Mirrors `AsgardeoNextClient.updateUserProfile`. - */ override async updateUserProfile(config: UpdateMeProfileConfig, sessionId: string): Promise { const accessToken: string = await this.getAccessToken(sessionId); - const configData: AuthClientConfig | undefined = (await this.legacy.getConfigData?.()) as - | AuthClientConfig - | undefined; + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string = (configData?.baseUrl ?? '') as string; return updateMeProfile({ - ...config, // pass-through, includes payload + ...config, baseUrl, headers: {...config.headers, Authorization: `Bearer ${accessToken}`}, }); } - /** - * Retrieves all organisations accessible to the authenticated user - * (paginated). Mirrors `AsgardeoNextClient.getAllOrganizations`. - */ override async getAllOrganizations(options?: any, sessionId?: string): Promise { const resolvedSessionId: string = sessionId ?? ''; const accessToken: string = await this.getAccessToken(resolvedSessionId); - const configData: AuthClientConfig | undefined = (await this.legacy.getConfigData?.()) as - | AuthClientConfig - | undefined; + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string = (configData?.baseUrl ?? '') as string; return getAllOrganizations({ @@ -448,14 +336,9 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { }); } - /** - * Creates a new sub-organisation. Mirrors `AsgardeoNextClient.createOrganization`. - */ async createOrganization(payload: CreateOrganizationPayload, sessionId: string): Promise { const accessToken: string = await this.getAccessToken(sessionId); - const configData: AuthClientConfig | undefined = (await this.legacy.getConfigData?.()) as - | AuthClientConfig - | undefined; + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string = (configData?.baseUrl ?? '') as string; return createOrganization({ @@ -465,15 +348,9 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { }); } - /** - * Fetches the details of a single organisation by ID. - * Mirrors `AsgardeoNextClient.getOrganization`. - */ async getOrganization(organizationId: string, sessionId: string): Promise { const accessToken: string = await this.getAccessToken(sessionId); - const configData: AuthClientConfig | undefined = (await this.legacy.getConfigData?.()) as - | AuthClientConfig - | undefined; + const configData: AuthClientConfig = await this.getConfigData(); const baseUrl: string = (configData?.baseUrl ?? '') as string; return getOrganization({ @@ -483,13 +360,6 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { }); } - /** - * Performs an organisation-switch token exchange and returns the new - * `TokenResponse`. The caller (the Nitro route) is responsible for - * persisting the new session cookie. - * - * Mirrors `AsgardeoNextClient.switchOrganization`. - */ override async switchOrganization(organization: Organization, sessionId: string): Promise { if (!organization.id) { throw new Error('Organization ID is required for switching organizations.'); @@ -510,7 +380,7 @@ class AsgardeoNuxtClient extends AsgardeoNodeClient { signInRequired: true, }; - return this.legacy.exchangeToken(exchangeConfig, sessionId); + return super.exchangeToken(exchangeConfig, sessionId); } } diff --git a/packages/react/src/AsgardeoReactClient.ts b/packages/react/src/AsgardeoReactClient.ts index 9873cb6c3..4317dcac8 100644 --- a/packages/react/src/AsgardeoReactClient.ts +++ b/packages/react/src/AsgardeoReactClient.ts @@ -92,7 +92,7 @@ class AsgardeoReactClient e * Get the instance ID for this client. * @returns The instance ID used for multi-auth context support. */ - public getInstanceId(): number { + public override getInstanceId(): number { return this.clientInstanceId; } @@ -182,11 +182,11 @@ class AsgardeoReactClient e } } - async getDecodedIdToken(sessionId?: string): Promise { + override async getDecodedIdToken(sessionId?: string): Promise { return this.asgardeo.getDecodedIdToken(sessionId); } - async getIdToken(): Promise { + override async getIdToken(): Promise { return this.withLoading(async () => this.asgardeo.getIdToken()); } @@ -576,7 +576,7 @@ class AsgardeoReactClient e return (await this.asgardeo.getStorageManager()).setSessionData(sessionData, sessionId); } - async getStorageManager(): Promise { + override getStorageManager(): any { return this.asgardeo.getStorageManager(); } diff --git a/packages/react/src/__temp__/api.ts b/packages/react/src/__temp__/api.ts index 88a44762d..c2ab9bf80 100644 --- a/packages/react/src/__temp__/api.ts +++ b/packages/react/src/__temp__/api.ts @@ -101,7 +101,7 @@ class AuthAPI { return this.client.getConfigData(); } - public async getStorageManager(): Promise { + public getStorageManager(): any { return this.client.getStorageManager(); } diff --git a/packages/vue/src/AsgardeoVueClient.ts b/packages/vue/src/AsgardeoVueClient.ts index 82af859d2..21de9304e 100644 --- a/packages/vue/src/AsgardeoVueClient.ts +++ b/packages/vue/src/AsgardeoVueClient.ts @@ -80,7 +80,7 @@ class AsgardeoVueClient extends this.asgardeo = new AuthAPI(undefined, instanceId); } - public getInstanceId(): number { + public override getInstanceId(): number { return this.clientInstanceId; } @@ -153,11 +153,11 @@ class AsgardeoVueClient extends } } - async getDecodedIdToken(sessionId?: string): Promise { + override async getDecodedIdToken(sessionId?: string): Promise { return this.asgardeo.getDecodedIdToken(sessionId); } - async getIdToken(): Promise { + override async getIdToken(): Promise { return this.withLoading(async () => this.asgardeo.getIdToken()); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3779917cc..8d0d6a37e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -688,6 +688,157 @@ importers: specifier: 3.5.30 version: 3.5.30(typescript@5.7.2) + samples/asgardeo-react: + dependencies: + '@asgardeo/react': + specifier: workspace:* + version: link:../../packages/react + react: + specifier: ^19.2.4 + version: 19.2.4 + react-dom: + specifier: ^19.2.4 + version: 19.2.4(react@19.2.4) + devDependencies: + '@eslint/js': + specifier: ^9.39.4 + version: 9.39.4 + '@types/react': + specifier: 19.1.5 + version: 19.1.5 + '@types/react-dom': + specifier: 19.1.5 + version: 19.1.5(@types/react@19.1.5) + '@vitejs/plugin-react': + specifier: ^6.0.1 + version: 6.0.1(vite@8.0.11(@types/node@22.15.30)(esbuild@0.28.0)(jiti@2.6.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3)) + eslint: + specifier: ^9.39.4 + version: 9.39.4(jiti@2.6.1) + eslint-plugin-react-hooks: + specifier: ^7.0.1 + version: 7.1.1(eslint@9.39.4(jiti@2.6.1)) + eslint-plugin-react-refresh: + specifier: ^0.5.2 + version: 0.5.2(eslint@9.39.4(jiti@2.6.1)) + globals: + specifier: ^17.4.0 + version: 17.6.0 + vite: + specifier: ^8.0.1 + version: 8.0.11(@types/node@22.15.30)(esbuild@0.28.0)(jiti@2.6.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) + + samples/esignet-portal: + dependencies: + '@asgardeo/react': + specifier: workspace:* + version: link:../../packages/react + '@asgardeo/react-router': + specifier: workspace:* + version: link:../../packages/react-router + '@radix-ui/react-dropdown-menu': + specifier: ^2.1.16 + version: 2.1.16(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tailwindcss/vite': + specifier: 4.1.8 + version: 4.1.8(vite@5.4.21(@types/node@22.15.30)(lightningcss@1.32.0)(terser@5.39.2)) + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + tailwindcss: + specifier: 4.1.8 + version: 4.1.8 + devDependencies: + '@types/react': + specifier: 19.1.5 + version: 19.1.5 + '@types/react-dom': + specifier: 19.1.5 + version: 19.1.5(@types/react@19.1.5) + '@vitejs/plugin-react': + specifier: ^4.2.0 + version: 4.4.1(vite@5.4.21(@types/node@22.15.30)(lightningcss@1.32.0)(terser@5.39.2)) + vite: + specifier: ^5.0.0 + version: 5.4.21(@types/node@22.15.30)(lightningcss@1.32.0)(terser@5.39.2) + + samples/esignet-portal-next: + dependencies: + '@asgardeo/nextjs': + specifier: workspace:* + version: link:../../packages/nextjs + next: + specifier: 16.1.6 + version: 16.1.6(@babel/core@7.27.1)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: + specifier: 19.2.3 + version: 19.2.3 + react-dom: + specifier: 19.2.3 + version: 19.2.3(react@19.2.3) + devDependencies: + '@tailwindcss/postcss': + specifier: ^4 + version: 4.3.0 + '@types/node': + specifier: ^20 + version: 20.19.41 + '@types/react': + specifier: 19.1.5 + version: 19.1.5 + '@types/react-dom': + specifier: 19.1.5 + version: 19.1.5(@types/react@19.1.5) + eslint: + specifier: ^9 + version: 9.39.4(jiti@2.6.1) + eslint-config-next: + specifier: 16.1.6 + version: 16.1.6(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) + tailwindcss: + specifier: ^4 + version: 4.1.8 + typescript: + specifier: ^5 + version: 5.8.3 + + samples/health-portal: + dependencies: + '@asgardeo/react': + specifier: workspace:* + version: link:../../packages/react + '@asgardeo/react-router': + specifier: workspace:* + version: link:../../packages/react-router + '@tailwindcss/vite': + specifier: 4.1.8 + version: 4.1.8(vite@5.4.21(@types/node@22.15.30)(lightningcss@1.32.0)(terser@5.39.2)) + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + tailwindcss: + specifier: 4.1.8 + version: 4.1.8 + devDependencies: + '@types/react': + specifier: 19.1.5 + version: 19.1.5 + '@types/react-dom': + specifier: 19.1.5 + version: 19.1.5(@types/react@19.1.5) + '@vitejs/plugin-react': + specifier: ^4.2.0 + version: 4.4.1(vite@5.4.21(@types/node@22.15.30)(lightningcss@1.32.0)(terser@5.39.2)) + vite: + specifier: ^5.0.0 + version: 5.4.21(@types/node@22.15.30)(lightningcss@1.32.0)(terser@5.39.2) + samples/nuxt: dependencies: '@asgardeo/nuxt': @@ -1244,6 +1395,12 @@ packages: '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + '@esbuild/aix-ppc64@0.25.9': resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==} engines: {node: '>=18'} @@ -1268,6 +1425,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm64@0.25.9': resolution: {integrity: sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==} engines: {node: '>=18'} @@ -1292,6 +1455,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.25.9': resolution: {integrity: sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==} engines: {node: '>=18'} @@ -1316,6 +1485,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + '@esbuild/android-x64@0.25.9': resolution: {integrity: sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==} engines: {node: '>=18'} @@ -1340,6 +1515,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-arm64@0.25.9': resolution: {integrity: sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==} engines: {node: '>=18'} @@ -1364,6 +1545,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.25.9': resolution: {integrity: sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==} engines: {node: '>=18'} @@ -1388,6 +1575,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-arm64@0.25.9': resolution: {integrity: sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==} engines: {node: '>=18'} @@ -1412,6 +1605,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.9': resolution: {integrity: sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==} engines: {node: '>=18'} @@ -1436,6 +1635,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.25.9': resolution: {integrity: sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==} engines: {node: '>=18'} @@ -1460,6 +1665,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + '@esbuild/linux-arm@0.25.9': resolution: {integrity: sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==} engines: {node: '>=18'} @@ -1484,6 +1695,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-ia32@0.25.9': resolution: {integrity: sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==} engines: {node: '>=18'} @@ -1508,6 +1725,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.25.9': resolution: {integrity: sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==} engines: {node: '>=18'} @@ -1532,6 +1755,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-mips64el@0.25.9': resolution: {integrity: sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==} engines: {node: '>=18'} @@ -1556,6 +1785,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-ppc64@0.25.9': resolution: {integrity: sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==} engines: {node: '>=18'} @@ -1580,6 +1815,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-riscv64@0.25.9': resolution: {integrity: sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==} engines: {node: '>=18'} @@ -1604,6 +1845,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-s390x@0.25.9': resolution: {integrity: sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==} engines: {node: '>=18'} @@ -1628,6 +1875,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.25.9': resolution: {integrity: sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==} engines: {node: '>=18'} @@ -1676,6 +1929,12 @@ packages: cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.9': resolution: {integrity: sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==} engines: {node: '>=18'} @@ -1724,6 +1983,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.9': resolution: {integrity: sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==} engines: {node: '>=18'} @@ -1772,6 +2037,12 @@ packages: cpu: [arm64] os: [openharmony] + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.25.9': resolution: {integrity: sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==} engines: {node: '>=18'} @@ -1796,6 +2067,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-arm64@0.25.9': resolution: {integrity: sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==} engines: {node: '>=18'} @@ -1820,6 +2097,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.25.9': resolution: {integrity: sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==} engines: {node: '>=18'} @@ -1844,6 +2127,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.25.9': resolution: {integrity: sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==} engines: {node: '>=18'} @@ -1874,18 +2163,36 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/regexpp@4.12.1': resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint/config-array@0.20.0': resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-array@0.21.2': + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.2.2': resolution: {integrity: sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.13.0': resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1894,6 +2201,10 @@ packages: resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@2.1.4': resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1902,6 +2213,10 @@ packages: resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@3.3.5': + resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@8.57.0': resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1910,10 +2225,18 @@ packages: resolution: {integrity: sha512-iWhsUS8Wgxz9AXNfvfOPFSW4VfMXdVhp1hjkZVhXCrpgh/aLcc45rX6MPu+tIVUWDw0HfNwth7O28M1xDxNf9w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@9.39.4': + resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/object-schema@2.1.6': resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/plugin-kit@0.3.4': resolution: {integrity: sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2238,21 +2561,39 @@ packages: '@next/env@15.5.12': resolution: {integrity: sha512-pUvdJN1on574wQHjaBfNGDt9Mz5utDSZFsIIQkMzPgNS8ZvT4H2mwOrOIClwsQOb6EGx5M76/CZr6G8i6pSpLg==} + '@next/env@16.1.6': + resolution: {integrity: sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==} + '@next/eslint-plugin-next@13.5.11': resolution: {integrity: sha512-0qjDhes9UTSxirt/dYzrv20hs8SUhcIOvlEioj5+XucVrBHihnAk6Om7Vzk+VZ2nRE7tcShm/6lH1xSkJ3XMpg==} + '@next/eslint-plugin-next@16.1.6': + resolution: {integrity: sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ==} + '@next/swc-darwin-arm64@15.5.12': resolution: {integrity: sha512-RnRjBtH8S8eXCpUNkQ+543DUc7ys8y15VxmFU9HRqlo9BG3CcBUiwNtF8SNoi2xvGCVJq1vl2yYq+3oISBS0Zg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] + '@next/swc-darwin-arm64@16.1.6': + resolution: {integrity: sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + '@next/swc-darwin-x64@15.5.12': resolution: {integrity: sha512-nqa9/7iQlboF1EFtNhWxQA0rQstmYRSBGxSM6g3GxvxHxcoeqVXfGNr9stJOme674m2V7r4E3+jEhhGvSQhJRA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] + '@next/swc-darwin-x64@16.1.6': + resolution: {integrity: sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + '@next/swc-linux-arm64-gnu@15.5.12': resolution: {integrity: sha512-dCzAjqhDHwmoB2M4eYfVKqXs99QdQxNQVpftvP1eGVppamXh/OkDAwV737Zr0KPXEqRUMN4uCjh6mjO+XtF3Mw==} engines: {node: '>= 10'} @@ -2260,6 +2601,13 @@ packages: os: [linux] libc: [glibc] + '@next/swc-linux-arm64-gnu@16.1.6': + resolution: {integrity: sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@next/swc-linux-arm64-musl@15.5.12': resolution: {integrity: sha512-+fpGWvQiITgf7PUtbWY1H7qUSnBZsPPLyyq03QuAKpVoTy/QUx1JptEDTQMVvQhvizCEuNLEeghrQUyXQOekuw==} engines: {node: '>= 10'} @@ -2267,6 +2615,13 @@ packages: os: [linux] libc: [musl] + '@next/swc-linux-arm64-musl@16.1.6': + resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + '@next/swc-linux-x64-gnu@15.5.12': resolution: {integrity: sha512-jSLvgdRRL/hrFAPqEjJf1fFguC719kmcptjNVDJl26BnJIpjL3KH5h6mzR4mAweociLQaqvt4UyzfbFjgAdDcw==} engines: {node: '>= 10'} @@ -2274,6 +2629,13 @@ packages: os: [linux] libc: [glibc] + '@next/swc-linux-x64-gnu@16.1.6': + resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + '@next/swc-linux-x64-musl@15.5.12': resolution: {integrity: sha512-/uaF0WfmYqQgLfPmN6BvULwxY0dufI2mlN2JbOKqqceZh1G4hjREyi7pg03zjfyS6eqNemHAZPSoP84x17vo6w==} engines: {node: '>= 10'} @@ -2281,18 +2643,37 @@ packages: os: [linux] libc: [musl] + '@next/swc-linux-x64-musl@16.1.6': + resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + '@next/swc-win32-arm64-msvc@15.5.12': resolution: {integrity: sha512-xhsL1OvQSfGmlL5RbOmU+FV120urrgFpYLq+6U8C6KIym32gZT6XF/SDE92jKzzlPWskkbjOKCpqk5m4i8PEfg==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] + '@next/swc-win32-arm64-msvc@16.1.6': + resolution: {integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + '@next/swc-win32-x64-msvc@15.5.12': resolution: {integrity: sha512-Z1Dh6lhFkxvBDH1FoW6OU/L6prYwPSlwjLiZkExIAh8fbP6iI/M7iGTQAJPYJ9YFlWobCZ1PHbchFhFYb2ADkw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] + '@next/swc-win32-x64-msvc@16.1.6': + resolution: {integrity: sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} @@ -2308,6 +2689,10 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@nolyfill/is-core-module@1.0.39': + resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} + engines: {node: '>=12.4.0'} + '@nuxt/cli@3.34.0': resolution: {integrity: sha512-KVI4xSo96UtUUbmxr9ouWTytbj1LzTw5alsM4vC/gSY/l8kPMRAlq0XpNSAVTDJyALzLY70WhaIMX24LJLpdFw==} engines: {node: ^16.14.0 || >=18.0.0} @@ -2662,6 +3047,35 @@ packages: '@poppinss/exception@1.2.3': resolution: {integrity: sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==} + '@radix-ui/primitive@1.1.3': + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} + + '@radix-ui/react-arrow@1.1.7': + resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} + peerDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-collection@1.1.7': + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} + peerDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-compose-refs@1.1.2': resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} peerDependencies: @@ -2671,6 +3085,81 @@ packages: '@types/react': optional: true + '@radix-ui/react-context@1.1.2': + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-direction@1.1.1': + resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dismissable-layer@1.1.11': + resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} + peerDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-dropdown-menu@2.1.16': + resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} + peerDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-focus-guards@1.1.3': + resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-focus-scope@1.1.7': + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} + peerDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-id@1.1.1': + resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-label@2.1.7': resolution: {integrity: sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==} peerDependencies: @@ -2684,6 +3173,58 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-menu@2.1.16': + resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} + peerDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-popper@1.2.8': + resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} + peerDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-portal@1.1.9': + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} + peerDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-presence@1.1.5': + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} + peerDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-primitive@2.1.3': resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} peerDependencies: @@ -2697,6 +3238,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-roving-focus@1.1.11': + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} + peerDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-slot@1.2.3': resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} peerDependencies: @@ -2706,6 +3260,72 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-callback-ref@1.1.1': + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-escape-keydown@1.1.1': + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.1': + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-rect@1.1.1': + resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-size@1.1.1': + resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/rect@1.1.1': + resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@rolldown/binding-android-arm64@1.0.0-rc.18': resolution: {integrity: sha512-lIDyUAfD7U3+BWKzdxMbJcsYHuqXqmGz40aeRqvuAm3y5TkJSYTBW2RDrn65DJFPQqVjUAUqq5uz8urzQ8aBdQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2804,8 +3424,8 @@ packages: '@rolldown/pluginutils@1.0.0-rc.18': resolution: {integrity: sha512-CUY5Mnhe64xQBGZEEXQ5WyZwsc1JU3vAZLIxtrsBt3LO6UOb+C8GunVKqe9sT8NeWb4lqSaoJtp2xo6GxT1MNw==} - '@rolldown/pluginutils@1.0.0-rc.2': - resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} + '@rolldown/pluginutils@1.0.0-rc.7': + resolution: {integrity: sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==} '@rollup/plugin-alias@5.1.1': resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} @@ -3184,39 +3804,79 @@ packages: '@tailwindcss/node@4.1.8': resolution: {integrity: sha512-OWwBsbC9BFAJelmnNcrKuf+bka2ZxCE2A4Ft53Tkg4uoiE67r/PMEYwCsourC26E+kmxfwE0hVzMdxqeW+xu7Q==} + '@tailwindcss/node@4.3.0': + resolution: {integrity: sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==} + '@tailwindcss/oxide-android-arm64@4.1.8': resolution: {integrity: sha512-Fbz7qni62uKYceWYvUjRqhGfZKwhZDQhlrJKGtnZfuNtHFqa8wmr+Wn74CTWERiW2hn3mN5gTpOoxWKk0jRxjg==} engines: {node: '>= 10'} cpu: [arm64] os: [android] + '@tailwindcss/oxide-android-arm64@4.3.0': + resolution: {integrity: sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + '@tailwindcss/oxide-darwin-arm64@4.1.8': resolution: {integrity: sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] + '@tailwindcss/oxide-darwin-arm64@4.3.0': + resolution: {integrity: sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + '@tailwindcss/oxide-darwin-x64@4.1.8': resolution: {integrity: sha512-t6PgxjEMLp5Ovf7uMb2OFmb3kqzVTPPakWpBIFzppk4JE4ix0yEtbtSjPbU8+PZETpaYMtXvss2Sdkx8Vs4XRw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] + '@tailwindcss/oxide-darwin-x64@4.3.0': + resolution: {integrity: sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + '@tailwindcss/oxide-freebsd-x64@4.1.8': resolution: {integrity: sha512-g8C8eGEyhHTqwPStSwZNSrOlyx0bhK/V/+zX0Y+n7DoRUzyS8eMbVshVOLJTDDC+Qn9IJnilYbIKzpB9n4aBsg==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] + '@tailwindcss/oxide-freebsd-x64@4.3.0': + resolution: {integrity: sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.8': resolution: {integrity: sha512-Jmzr3FA4S2tHhaC6yCjac3rGf7hG9R6Gf2z9i9JFcuyy0u79HfQsh/thifbYTF2ic82KJovKKkIB6Z9TdNhCXQ==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.1.8': - resolution: {integrity: sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q==} - engines: {node: '>= 10'} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': + resolution: {integrity: sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.8': + resolution: {integrity: sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': + resolution: {integrity: sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==} + engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [glibc] @@ -3228,6 +3888,13 @@ packages: os: [linux] libc: [musl] + '@tailwindcss/oxide-linux-arm64-musl@4.3.0': + resolution: {integrity: sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [musl] + '@tailwindcss/oxide-linux-x64-gnu@4.1.8': resolution: {integrity: sha512-32iEXX/pXwikshNOGnERAFwFSfiltmijMIAbUhnNyjFr3tmWmMJWQKU2vNcFX0DACSXJ3ZWcSkzNbaKTdngH6g==} engines: {node: '>= 10'} @@ -3235,6 +3902,13 @@ packages: os: [linux] libc: [glibc] + '@tailwindcss/oxide-linux-x64-gnu@4.3.0': + resolution: {integrity: sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [glibc] + '@tailwindcss/oxide-linux-x64-musl@4.1.8': resolution: {integrity: sha512-s+VSSD+TfZeMEsCaFaHTaY5YNj3Dri8rST09gMvYQKwPphacRG7wbuQ5ZJMIJXN/puxPcg/nU+ucvWguPpvBDg==} engines: {node: '>= 10'} @@ -3242,6 +3916,13 @@ packages: os: [linux] libc: [musl] + '@tailwindcss/oxide-linux-x64-musl@4.3.0': + resolution: {integrity: sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [musl] + '@tailwindcss/oxide-wasm32-wasi@4.1.8': resolution: {integrity: sha512-CXBPVFkpDjM67sS1psWohZ6g/2/cd+cq56vPxK4JeawelxwK4YECgl9Y9TjkE2qfF+9/s1tHHJqrC4SS6cVvSg==} engines: {node: '>=14.0.0'} @@ -3254,22 +3935,53 @@ packages: - '@emnapi/wasi-threads' - tslib + '@tailwindcss/oxide-wasm32-wasi@4.3.0': + resolution: {integrity: sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + '@tailwindcss/oxide-win32-arm64-msvc@4.1.8': resolution: {integrity: sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] + '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': + resolution: {integrity: sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + '@tailwindcss/oxide-win32-x64-msvc@4.1.8': resolution: {integrity: sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] + '@tailwindcss/oxide-win32-x64-msvc@4.3.0': + resolution: {integrity: sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + '@tailwindcss/oxide@4.1.8': resolution: {integrity: sha512-d7qvv9PsM5N3VNKhwVUhpK6r4h9wtLkJ6lz9ZY9aeZgrUWk1Z8VPyqyDT9MZlem7GTGseRQHkeB1j3tC7W1P+A==} engines: {node: '>= 10'} + '@tailwindcss/oxide@4.3.0': + resolution: {integrity: sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==} + engines: {node: '>= 20'} + + '@tailwindcss/postcss@4.3.0': + resolution: {integrity: sha512-Jm05Tjx+9yCLGv5qw1c+84Psds8MnyrEQYCB+FFk2lgGiUjlRqdxke4mVTuYrj2xnVZqKim2Apr5ySuQRYAw/w==} + '@tailwindcss/vite@4.1.8': resolution: {integrity: sha512-CQ+I8yxNV5/6uGaJjiuymgw0kEQiNKRinYbZXPdx1fk5WgiyReG0VaUx/Xq6aVNSUNJFzxm6o8FNKS5aMaim5A==} peerDependencies: @@ -3372,6 +4084,9 @@ packages: '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + '@types/node@20.19.41': + resolution: {integrity: sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ==} + '@types/node@22.13.4': resolution: {integrity: sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==} @@ -3420,6 +4135,14 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/eslint-plugin@8.59.3': + resolution: {integrity: sha512-PwFvSKsXGShKGW6n5bZOhGHEcCZXM8HofLK9fNsEwZXzFRjoY+XT1Vsf1zgyXdwTr0ZYz1/2tkZ0DBTT9jZjhw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.59.3 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/experimental-utils@5.62.0': resolution: {integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3443,6 +4166,19 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/parser@8.59.3': + resolution: {integrity: sha512-HPwA+hVkfcriajbNvTmZv4VRauibay+cWArYUYq7u7W7PmGShMxbPxLvrwDme55a6d5alG3nrYfhyJ/G28XlLg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/project-service@8.59.3': + resolution: {integrity: sha512-ECiUWa/KYRGDFUqTNehaRgzDshnJfkTABJxVemHk4ko22gcr0ukloKjWvyQ64g8YCV/UI47kN1dbmjf/GaQYng==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/scope-manager@5.62.0': resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3455,6 +4191,16 @@ packages: resolution: {integrity: sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.59.3': + resolution: {integrity: sha512-t2LvZnoEfzKtnPjgeEu41xw5gxq9mQVfYy4OoZ4Vlt0sk3JwxmhCca/AR7DwOiHrjWgjAj6as4AhRLKSDfvZIA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.59.3': + resolution: {integrity: sha512-PcIJHjmaREXLgIAIzLnSY9VucEzz8FKXsRgFa1DmdGCK/5tJpW03TKJF01Q6VZd1lLdz2sIKPWaDUZN9dp//dw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/type-utils@6.21.0': resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} engines: {node: ^16.0.0 || >=18.0.0} @@ -3472,6 +4218,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/type-utils@8.59.3': + resolution: {integrity: sha512-g71d8QD8UaiHGvrJwyIS1hCX5r63w6Jll+4VEYhEAHXTDIqX1JgxhTAbEHtKntL9kuc4jRo7/GWw5xfCepSccQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/types@5.62.0': resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3484,6 +4237,10 @@ packages: resolution: {integrity: sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.59.3': + resolution: {integrity: sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@5.62.0': resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3508,6 +4265,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/typescript-estree@8.59.3': + resolution: {integrity: sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@5.62.0': resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3527,6 +4290,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/utils@8.59.3': + resolution: {integrity: sha512-JAvT14goBzRzzzZyqq3P9BLArIxTtQURUtFgQ/V7FO+eU+Gg6ES+5ymOPP1wRxXcxAYeivCk4uS3jCKWI1K8Zg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/visitor-keys@5.62.0': resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3539,6 +4309,10 @@ packages: resolution: {integrity: sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.59.3': + resolution: {integrity: sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} @@ -3547,6 +4321,109 @@ packages: peerDependencies: vue: '>=3.5.18' + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + cpu: [x64] + os: [win32] + '@vercel/nft@1.5.0': resolution: {integrity: sha512-IWTDeIoWhQ7ZtRO/JRKH+jhmeQvZYhtGPmzw/QGDY+wDCQqfm25P9yIdoAFagu4fWsK4IwZXDFIjrmp5rRm/sA==} engines: {node: '>=20'} @@ -3564,6 +4441,19 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + '@vitejs/plugin-react@6.0.1': + resolution: {integrity: sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + '@vitejs/plugin-vue-jsx@4.2.0': resolution: {integrity: sha512-DSTrmrdLp+0LDNF77fqrKfx7X0ErRbOcUAgJL/HbSesqQwoUvUQ4uYQqaex+rovqgGcoPqVk+AwUh3v9CuiYIw==} engines: {node: ^18.0.0 || >=20.0.0} @@ -3835,6 +4725,9 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + alien-signals@1.0.13: resolution: {integrity: sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==} @@ -3887,6 +4780,10 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} @@ -4707,6 +5604,9 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + devalue@5.7.1: resolution: {integrity: sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA==} @@ -4832,6 +5732,10 @@ packages: resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} engines: {node: '>=10.13.0'} + enhanced-resolve@5.21.3: + resolution: {integrity: sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==} + engines: {node: '>=10.13.0'} + enquirer@2.3.6: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} engines: {node: '>=8.6'} @@ -4905,6 +5809,11 @@ packages: peerDependencies: esbuild: ^0.21.0 + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + esbuild@0.25.9: resolution: {integrity: sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==} engines: {node: '>=18'} @@ -4969,6 +5878,15 @@ packages: eslint-plugin-react: ^7.28.0 eslint-plugin-react-hooks: ^4.3.0 + eslint-config-next@16.1.6: + resolution: {integrity: sha512-vKq40io2B0XtkkNDYyleATwblNt8xuh3FWp8SpSz3pt7P01OkBFlKsJZ2mWt5WsCySlDQLckb1zMY9yE9Qy0LA==} + peerDependencies: + eslint: '>=9.0.0' + typescript: '>=3.3.1' + peerDependenciesMeta: + typescript: + optional: true + eslint-config-prettier@8.10.0: resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==} hasBin: true @@ -4978,6 +5896,19 @@ packages: eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + eslint-import-resolver-typescript@3.10.1: + resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + eslint-plugin-import-x: '*' + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + eslint-module-utils@2.12.1: resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} engines: {node: '>=4'} @@ -5074,11 +6005,22 @@ packages: peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + eslint-plugin-react-hooks@7.1.1: + resolution: {integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0 + eslint-plugin-react-refresh@0.4.19: resolution: {integrity: sha512-eyy8pcr/YxSYjBoqIFSrlbn9i/xvxUFa8CjzAYo9cFjgGXqq1hyjihcpZvxRLalpaWmueWR81xn7vuKmAFijDQ==} peerDependencies: eslint: '>=8.40' + eslint-plugin-react-refresh@0.5.2: + resolution: {integrity: sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==} + peerDependencies: + eslint: ^9 || ^10 + eslint-plugin-react@7.37.5: resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} engines: {node: '>=4'} @@ -5140,6 +6082,10 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + eslint@8.57.0: resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5156,6 +6102,16 @@ packages: jiti: optional: true + eslint@9.39.4: + resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + espree@10.4.0: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5242,6 +6198,10 @@ packages: fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} @@ -5442,6 +6402,10 @@ packages: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} + get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + get-port-please@3.2.0: resolution: {integrity: sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==} @@ -5522,6 +6486,14 @@ packages: resolution: {integrity: sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==} engines: {node: '>=18'} + globals@16.4.0: + resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} + engines: {node: '>=18'} + + globals@17.6.0: + resolution: {integrity: sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==} + engines: {node: '>=18'} + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -5600,6 +6572,12 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + hmac-drbg@1.0.1: resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} @@ -5748,6 +6726,9 @@ packages: resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} + is-bun-module@2.0.0: + resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} + is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -6453,6 +7434,9 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + minimatch@5.1.9: resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} engines: {node: '>=10'} @@ -6544,6 +7528,11 @@ packages: nanotar@0.2.1: resolution: {integrity: sha512-MUrzzDUcIOPbv7ubhDV/L4CIfVTATd9XhDE2ixFeCrM5yp9AlzUpn91JrnN0HD6hksdxvz9IW9aKANz0Bta0GA==} + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} @@ -6579,6 +7568,27 @@ packages: sass: optional: true + next@16.1.6: + resolution: {integrity: sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==} + engines: {node: '>=20.9.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.51.1 + babel-plugin-react-compiler: '*' + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + nitropack@2.13.3: resolution: {integrity: sha512-C8vO7RxkU0AQ3HbYUumuG6MVM5JjRaBchke/rYFOp3EvrLtTBHZYhDVGECdpa27vNuOYRzm3GtQMn2YDOjDJLA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7308,6 +8318,16 @@ packages: rc9@3.0.1: resolution: {integrity: sha512-gMDyleLWVE+i6Sgtc0QbbY6pEKqYs97NGi6isHQPqYlLemPoO8dxQ3uGi0f4NiP98c+jMW6cG1Kx9dDwfvqARQ==} + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + peerDependencies: + react: ^18.3.1 + + react-dom@19.2.3: + resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} + peerDependencies: + react: ^19.2.3 + react-dom@19.2.4: resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} peerDependencies: @@ -7326,6 +8346,26 @@ packages: resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-remove-scroll@2.7.2: + resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + react-router@7.12.0: resolution: {integrity: sha512-kTPDYPFzDVGIIGNLS5VJykK0HfHLY5MF3b+xj0/tTyNYL1gF1qs7u67Z9jEhQk2sQ98SUaHxlG31g1JtF7IfVw==} engines: {node: '>=20.0.0'} @@ -7336,6 +8376,24 @@ packages: react-dom: optional: true + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + + react@19.2.3: + resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} + engines: {node: '>=0.10.0'} + react@19.2.4: resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} engines: {node: '>=0.10.0'} @@ -7564,6 +8622,9 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -7751,6 +8812,9 @@ packages: engines: {node: '>=20.16.0'} hasBin: true + stable-hash@0.0.5: + resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -7935,10 +8999,17 @@ packages: tailwindcss@4.1.8: resolution: {integrity: sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==} + tailwindcss@4.3.0: + resolution: {integrity: sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==} + tapable@2.2.2: resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==} engines: {node: '>=6'} + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} @@ -8088,6 +9159,12 @@ packages: peerDependencies: typescript: '>=4.8.4' + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} @@ -8178,6 +9255,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + typescript-eslint@8.59.3: + resolution: {integrity: sha512-KgusgyDgG4LI8Ih/sWaCtZ06tckLAS5CvT5A4D1Q7bYVoAAyzwiZvE4BmwDHkhRVkvhRBepKeASoFzQetha7Fg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + typescript@5.7.2: resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} engines: {node: '>=14.17'} @@ -8291,6 +9375,9 @@ packages: resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==} engines: {node: ^20.19.0 || >=22.12.0} + unrs-resolver@1.11.1: + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + unstorage@1.17.5: resolution: {integrity: sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==} peerDependencies: @@ -8382,6 +9469,26 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': 19.1.5 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + use-sync-external-store@1.6.0: resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} peerDependencies: @@ -8468,6 +9575,37 @@ packages: vite: ^6.0.0 || ^7.0.0 vue: ^3.5.0 + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + vite@6.4.1: resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -8857,6 +9995,15 @@ packages: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} + zod-validation-error@4.0.2: + resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + snapshots: '@acemir/cssom@0.9.31': {} @@ -9424,6 +10571,9 @@ snapshots: '@emotion/weak-memoize@0.4.0': {} + '@esbuild/aix-ppc64@0.21.5': + optional: true + '@esbuild/aix-ppc64@0.25.9': optional: true @@ -9436,6 +10586,9 @@ snapshots: '@esbuild/aix-ppc64@0.28.0': optional: true + '@esbuild/android-arm64@0.21.5': + optional: true + '@esbuild/android-arm64@0.25.9': optional: true @@ -9448,6 +10601,9 @@ snapshots: '@esbuild/android-arm64@0.28.0': optional: true + '@esbuild/android-arm@0.21.5': + optional: true + '@esbuild/android-arm@0.25.9': optional: true @@ -9460,6 +10616,9 @@ snapshots: '@esbuild/android-arm@0.28.0': optional: true + '@esbuild/android-x64@0.21.5': + optional: true + '@esbuild/android-x64@0.25.9': optional: true @@ -9472,6 +10631,9 @@ snapshots: '@esbuild/android-x64@0.28.0': optional: true + '@esbuild/darwin-arm64@0.21.5': + optional: true + '@esbuild/darwin-arm64@0.25.9': optional: true @@ -9484,6 +10646,9 @@ snapshots: '@esbuild/darwin-arm64@0.28.0': optional: true + '@esbuild/darwin-x64@0.21.5': + optional: true + '@esbuild/darwin-x64@0.25.9': optional: true @@ -9496,6 +10661,9 @@ snapshots: '@esbuild/darwin-x64@0.28.0': optional: true + '@esbuild/freebsd-arm64@0.21.5': + optional: true + '@esbuild/freebsd-arm64@0.25.9': optional: true @@ -9508,6 +10676,9 @@ snapshots: '@esbuild/freebsd-arm64@0.28.0': optional: true + '@esbuild/freebsd-x64@0.21.5': + optional: true + '@esbuild/freebsd-x64@0.25.9': optional: true @@ -9520,6 +10691,9 @@ snapshots: '@esbuild/freebsd-x64@0.28.0': optional: true + '@esbuild/linux-arm64@0.21.5': + optional: true + '@esbuild/linux-arm64@0.25.9': optional: true @@ -9532,6 +10706,9 @@ snapshots: '@esbuild/linux-arm64@0.28.0': optional: true + '@esbuild/linux-arm@0.21.5': + optional: true + '@esbuild/linux-arm@0.25.9': optional: true @@ -9544,6 +10721,9 @@ snapshots: '@esbuild/linux-arm@0.28.0': optional: true + '@esbuild/linux-ia32@0.21.5': + optional: true + '@esbuild/linux-ia32@0.25.9': optional: true @@ -9556,6 +10736,9 @@ snapshots: '@esbuild/linux-ia32@0.28.0': optional: true + '@esbuild/linux-loong64@0.21.5': + optional: true + '@esbuild/linux-loong64@0.25.9': optional: true @@ -9568,6 +10751,9 @@ snapshots: '@esbuild/linux-loong64@0.28.0': optional: true + '@esbuild/linux-mips64el@0.21.5': + optional: true + '@esbuild/linux-mips64el@0.25.9': optional: true @@ -9580,6 +10766,9 @@ snapshots: '@esbuild/linux-mips64el@0.28.0': optional: true + '@esbuild/linux-ppc64@0.21.5': + optional: true + '@esbuild/linux-ppc64@0.25.9': optional: true @@ -9592,6 +10781,9 @@ snapshots: '@esbuild/linux-ppc64@0.28.0': optional: true + '@esbuild/linux-riscv64@0.21.5': + optional: true + '@esbuild/linux-riscv64@0.25.9': optional: true @@ -9604,6 +10796,9 @@ snapshots: '@esbuild/linux-riscv64@0.28.0': optional: true + '@esbuild/linux-s390x@0.21.5': + optional: true + '@esbuild/linux-s390x@0.25.9': optional: true @@ -9616,6 +10811,9 @@ snapshots: '@esbuild/linux-s390x@0.28.0': optional: true + '@esbuild/linux-x64@0.21.5': + optional: true + '@esbuild/linux-x64@0.25.9': optional: true @@ -9640,6 +10838,9 @@ snapshots: '@esbuild/netbsd-arm64@0.28.0': optional: true + '@esbuild/netbsd-x64@0.21.5': + optional: true + '@esbuild/netbsd-x64@0.25.9': optional: true @@ -9664,6 +10865,9 @@ snapshots: '@esbuild/openbsd-arm64@0.28.0': optional: true + '@esbuild/openbsd-x64@0.21.5': + optional: true + '@esbuild/openbsd-x64@0.25.9': optional: true @@ -9688,6 +10892,9 @@ snapshots: '@esbuild/openharmony-arm64@0.28.0': optional: true + '@esbuild/sunos-x64@0.21.5': + optional: true + '@esbuild/sunos-x64@0.25.9': optional: true @@ -9700,6 +10907,9 @@ snapshots: '@esbuild/sunos-x64@0.28.0': optional: true + '@esbuild/win32-arm64@0.21.5': + optional: true + '@esbuild/win32-arm64@0.25.9': optional: true @@ -9712,6 +10922,9 @@ snapshots: '@esbuild/win32-arm64@0.28.0': optional: true + '@esbuild/win32-ia32@0.21.5': + optional: true + '@esbuild/win32-ia32@0.25.9': optional: true @@ -9724,6 +10937,9 @@ snapshots: '@esbuild/win32-ia32@0.28.0': optional: true + '@esbuild/win32-x64@0.21.5': + optional: true + '@esbuild/win32-x64@0.25.9': optional: true @@ -9746,8 +10962,20 @@ snapshots: eslint: 9.25.0(jiti@2.6.1) eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.8.0(eslint@9.39.4(jiti@2.6.1))': + dependencies: + eslint: 9.39.4(jiti@2.6.1) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.6.1))': + dependencies: + eslint: 9.39.4(jiti@2.6.1) + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.12.1': {} + '@eslint-community/regexpp@4.12.2': {} + '@eslint/config-array@0.20.0': dependencies: '@eslint/object-schema': 2.1.6 @@ -9756,8 +10984,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/config-array@0.21.2': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + '@eslint/config-helpers@0.2.2': {} + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + '@eslint/core@0.13.0': dependencies: '@types/json-schema': 7.0.15 @@ -9766,6 +11006,10 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 @@ -9794,12 +11038,30 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/eslintrc@3.3.5': + dependencies: + ajv: 6.15.0 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + '@eslint/js@8.57.0': {} '@eslint/js@9.25.0': {} + '@eslint/js@9.39.4': {} + '@eslint/object-schema@2.1.6': {} + '@eslint/object-schema@2.1.7': {} + '@eslint/plugin-kit@0.3.4': dependencies: '@eslint/core': 0.15.2 @@ -9816,6 +11078,12 @@ snapshots: '@floating-ui/core': 1.7.1 '@floating-ui/utils': 0.2.9 + '@floating-ui/react-dom@2.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/dom': 1.7.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + '@floating-ui/react-dom@2.1.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@floating-ui/dom': 1.7.1 @@ -10101,34 +11369,64 @@ snapshots: '@next/env@15.5.12': {} + '@next/env@16.1.6': {} + '@next/eslint-plugin-next@13.5.11': dependencies: glob: 7.1.7 + '@next/eslint-plugin-next@16.1.6': + dependencies: + fast-glob: 3.3.1 + '@next/swc-darwin-arm64@15.5.12': optional: true + '@next/swc-darwin-arm64@16.1.6': + optional: true + '@next/swc-darwin-x64@15.5.12': optional: true + '@next/swc-darwin-x64@16.1.6': + optional: true + '@next/swc-linux-arm64-gnu@15.5.12': optional: true + '@next/swc-linux-arm64-gnu@16.1.6': + optional: true + '@next/swc-linux-arm64-musl@15.5.12': optional: true + '@next/swc-linux-arm64-musl@16.1.6': + optional: true + '@next/swc-linux-x64-gnu@15.5.12': optional: true + '@next/swc-linux-x64-gnu@16.1.6': + optional: true + '@next/swc-linux-x64-musl@15.5.12': optional: true + '@next/swc-linux-x64-musl@16.1.6': + optional: true + '@next/swc-win32-arm64-msvc@15.5.12': optional: true + '@next/swc-win32-arm64-msvc@16.1.6': + optional: true + '@next/swc-win32-x64-msvc@15.5.12': optional: true + '@next/swc-win32-x64-msvc@16.1.6': + optional: true + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': dependencies: eslint-scope: 5.1.1 @@ -10145,6 +11443,8 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 + '@nolyfill/is-core-module@1.0.39': {} + '@nuxt/cli@3.34.0(@nuxt/schema@3.16.2)(cac@6.7.14)(magicast@0.5.2)': dependencies: '@bomb.sh/tab': 0.0.14(cac@6.7.14)(citty@0.2.2) @@ -10444,9 +11744,9 @@ snapshots: '@rollup/plugin-replace': 6.0.3(rollup@4.50.0) '@vitejs/plugin-vue': 5.2.4(vite@6.4.1(@types/node@22.13.4)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.30(typescript@5.8.3)) '@vitejs/plugin-vue-jsx': 4.2.0(vite@6.4.1(@types/node@22.13.4)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.30(typescript@5.8.3)) - autoprefixer: 10.5.0(postcss@8.5.8) + autoprefixer: 10.5.0(postcss@8.5.14) consola: 3.4.2 - cssnano: 7.1.5(postcss@8.5.8) + cssnano: 7.1.5(postcss@8.5.14) defu: 6.1.4 esbuild: 0.25.9 escape-string-regexp: 5.0.0 @@ -10463,7 +11763,7 @@ snapshots: pathe: 2.0.3 perfect-debounce: 1.0.0 pkg-types: 2.3.0 - postcss: 8.5.8 + postcss: 8.5.14 rollup-plugin-visualizer: 5.14.0(rollup@4.50.0) std-env: 3.10.0 ufo: 1.6.3 @@ -10505,9 +11805,9 @@ snapshots: '@rollup/plugin-replace': 6.0.3(rollup@4.60.2) '@vitejs/plugin-vue': 5.2.4(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.30(typescript@5.9.3)) '@vitejs/plugin-vue-jsx': 4.2.0(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.30(typescript@5.9.3)) - autoprefixer: 10.5.0(postcss@8.5.8) + autoprefixer: 10.5.0(postcss@8.5.14) consola: 3.4.2 - cssnano: 7.1.5(postcss@8.5.8) + cssnano: 7.1.5(postcss@8.5.14) defu: 6.1.4 esbuild: 0.25.9 escape-string-regexp: 5.0.0 @@ -10524,7 +11824,7 @@ snapshots: pathe: 2.0.3 perfect-debounce: 1.0.0 pkg-types: 2.3.0 - postcss: 8.5.8 + postcss: 8.5.14 rollup-plugin-visualizer: 5.14.0(rollup@4.60.2) std-env: 3.10.0 ufo: 1.6.3 @@ -10732,49 +12032,289 @@ snapshots: '@polka/url@1.0.0-next.29': {} - '@poppinss/colors@4.1.6': + '@poppinss/colors@4.1.6': + dependencies: + kleur: 4.1.5 + + '@poppinss/dumper@0.7.0': + dependencies: + '@poppinss/colors': 4.1.6 + '@sindresorhus/is': 7.2.0 + supports-color: 10.2.2 + + '@poppinss/exception@1.2.3': {} + + '@radix-ui/primitive@1.1.3': {} + + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.5)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.5 + + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.5)(react@19.2.4)': + dependencies: + react: 19.2.4 + optionalDependencies: + '@types/react': 19.1.5 + + '@radix-ui/react-context@1.1.2(@types/react@19.1.5)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.5 + + '@radix-ui/react-direction@1.1.1(@types/react@19.1.5)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.5 + + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-focus-guards@1.1.3(@types/react@19.1.5)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.5 + + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-id@1.1.1(@types/react@19.1.5)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.5 + + '@radix-ui/react-label@2.1.7(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-menu@2.1.16(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.5)(react@18.3.1) + aria-hidden: 1.2.6 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.7.2(@types/react@19.1.5)(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/react-dom': 2.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-use-rect': 1.1.1(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/rect': 1.1.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.5)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + '@types/react-dom': 19.1.5(@types/react@19.1.5) + + '@radix-ui/react-slot@1.2.3(@types/react@19.1.5)(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.5 + + '@radix-ui/react-slot@1.2.3(@types/react@19.1.5)(react@19.2.4)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.5)(react@19.2.4) + react: 19.2.4 + optionalDependencies: + '@types/react': 19.1.5 + + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.1.5)(react@18.3.1)': dependencies: - kleur: 4.1.5 + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.5 - '@poppinss/dumper@0.7.0': + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.1.5)(react@18.3.1)': dependencies: - '@poppinss/colors': 4.1.6 - '@sindresorhus/is': 7.2.0 - supports-color: 10.2.2 + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.1.5)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.5 - '@poppinss/exception@1.2.3': {} + '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.1.5)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 19.1.5 - '@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.5)(react@19.2.4)': + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.1.5)(react@18.3.1)': dependencies: - react: 19.2.4 + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 optionalDependencies: '@types/react': 19.1.5 - '@radix-ui/react-label@2.1.7(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.1.5)(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) + react: 18.3.1 optionalDependencies: '@types/react': 19.1.5 - '@types/react-dom': 19.1.5(@types/react@19.1.5) - '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.5(@types/react@19.1.5))(@types/react@19.1.5)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@radix-ui/react-use-rect@1.1.1(@types/react@19.1.5)(react@18.3.1)': dependencies: - '@radix-ui/react-slot': 1.2.3(@types/react@19.1.5)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) + '@radix-ui/rect': 1.1.1 + react: 18.3.1 optionalDependencies: '@types/react': 19.1.5 - '@types/react-dom': 19.1.5(@types/react@19.1.5) - '@radix-ui/react-slot@1.2.3(@types/react@19.1.5)(react@19.2.4)': + '@radix-ui/react-use-size@1.1.1(@types/react@19.1.5)(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.5)(react@19.2.4) - react: 19.2.4 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.5)(react@18.3.1) + react: 18.3.1 optionalDependencies: '@types/react': 19.1.5 + '@radix-ui/rect@1.1.1': {} + '@rolldown/binding-android-arm64@1.0.0-rc.18': optional: true @@ -10826,7 +12366,7 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.18': {} - '@rolldown/pluginutils@1.0.0-rc.2': {} + '@rolldown/pluginutils@1.0.0-rc.7': {} '@rollup/plugin-alias@5.1.1(rollup@4.50.0)': optionalDependencies: @@ -11108,42 +12648,88 @@ snapshots: source-map-js: 1.2.1 tailwindcss: 4.1.8 + '@tailwindcss/node@4.3.0': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.21.3 + jiti: 2.6.1 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.3.0 + '@tailwindcss/oxide-android-arm64@4.1.8': optional: true + '@tailwindcss/oxide-android-arm64@4.3.0': + optional: true + '@tailwindcss/oxide-darwin-arm64@4.1.8': optional: true + '@tailwindcss/oxide-darwin-arm64@4.3.0': + optional: true + '@tailwindcss/oxide-darwin-x64@4.1.8': optional: true + '@tailwindcss/oxide-darwin-x64@4.3.0': + optional: true + '@tailwindcss/oxide-freebsd-x64@4.1.8': optional: true + '@tailwindcss/oxide-freebsd-x64@4.3.0': + optional: true + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.8': optional: true + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': + optional: true + '@tailwindcss/oxide-linux-arm64-gnu@4.1.8': optional: true + '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': + optional: true + '@tailwindcss/oxide-linux-arm64-musl@4.1.8': optional: true + '@tailwindcss/oxide-linux-arm64-musl@4.3.0': + optional: true + '@tailwindcss/oxide-linux-x64-gnu@4.1.8': optional: true + '@tailwindcss/oxide-linux-x64-gnu@4.3.0': + optional: true + '@tailwindcss/oxide-linux-x64-musl@4.1.8': optional: true + '@tailwindcss/oxide-linux-x64-musl@4.3.0': + optional: true + '@tailwindcss/oxide-wasm32-wasi@4.1.8': optional: true + '@tailwindcss/oxide-wasm32-wasi@4.3.0': + optional: true + '@tailwindcss/oxide-win32-arm64-msvc@4.1.8': optional: true + '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': + optional: true + '@tailwindcss/oxide-win32-x64-msvc@4.1.8': optional: true + '@tailwindcss/oxide-win32-x64-msvc@4.3.0': + optional: true + '@tailwindcss/oxide@4.1.8': dependencies: detect-libc: 2.1.2 @@ -11162,6 +12748,36 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.8 '@tailwindcss/oxide-win32-x64-msvc': 4.1.8 + '@tailwindcss/oxide@4.3.0': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.0 + '@tailwindcss/oxide-darwin-arm64': 4.3.0 + '@tailwindcss/oxide-darwin-x64': 4.3.0 + '@tailwindcss/oxide-freebsd-x64': 4.3.0 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.0 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.0 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.0 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.0 + '@tailwindcss/oxide-linux-x64-musl': 4.3.0 + '@tailwindcss/oxide-wasm32-wasi': 4.3.0 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.0 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.0 + + '@tailwindcss/postcss@4.3.0': + dependencies: + '@alloc/quick-lru': 5.2.0 + '@tailwindcss/node': 4.3.0 + '@tailwindcss/oxide': 4.3.0 + postcss: 8.5.14 + tailwindcss: 4.3.0 + + '@tailwindcss/vite@4.1.8(vite@5.4.21(@types/node@22.15.30)(lightningcss@1.32.0)(terser@5.39.2))': + dependencies: + '@tailwindcss/node': 4.1.8 + '@tailwindcss/oxide': 4.1.8 + tailwindcss: 4.1.8 + vite: 5.4.21(@types/node@22.15.30)(lightningcss@1.32.0)(terser@5.39.2) + '@tailwindcss/vite@4.1.8(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@tailwindcss/node': 4.1.8 @@ -11276,6 +12892,10 @@ snapshots: '@types/node@12.20.55': {} + '@types/node@20.19.41': + dependencies: + undici-types: 6.21.0 + '@types/node@22.13.4': dependencies: undici-types: 6.20.0 @@ -11342,6 +12962,22 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/eslint-plugin@8.59.3(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.59.3 + '@typescript-eslint/type-utils': 8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/utils': 8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.59.3 + eslint: 9.39.4(jiti@2.6.1) + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/experimental-utils@5.62.0(eslint@8.57.0)(typescript@5.7.2)': dependencies: '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.7.2) @@ -11375,6 +13011,27 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.59.3 + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/typescript-estree': 8.59.3(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.59.3 + debug: 4.4.3 + eslint: 9.39.4(jiti@2.6.1) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.59.3(typescript@5.8.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.59.3(typescript@5.8.3) + '@typescript-eslint/types': 8.59.3 + debug: 4.4.3 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -11390,6 +13047,15 @@ snapshots: '@typescript-eslint/types': 8.30.1 '@typescript-eslint/visitor-keys': 8.30.1 + '@typescript-eslint/scope-manager@8.59.3': + dependencies: + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/visitor-keys': 8.59.3 + + '@typescript-eslint/tsconfig-utils@8.59.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@typescript-eslint/type-utils@6.21.0(eslint@8.57.0)(typescript@5.7.2)': dependencies: '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.7.2) @@ -11413,12 +13079,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/typescript-estree': 8.59.3(typescript@5.8.3) + '@typescript-eslint/utils': 8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) + debug: 4.4.3 + eslint: 9.39.4(jiti@2.6.1) + ts-api-utils: 2.5.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/types@5.62.0': {} '@typescript-eslint/types@6.21.0': {} '@typescript-eslint/types@8.30.1': {} + '@typescript-eslint/types@8.59.3': {} + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.7.2)': dependencies: '@typescript-eslint/types': 5.62.0 @@ -11462,6 +13142,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.59.3(typescript@5.8.3)': + dependencies: + '@typescript-eslint/project-service': 8.59.3(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.59.3(typescript@5.8.3) + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/visitor-keys': 8.59.3 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.7.4 + tinyglobby: 0.2.16 + ts-api-utils: 2.5.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.7.2)': dependencies: '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0) @@ -11502,6 +13197,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.59.3 + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/typescript-estree': 8.59.3(typescript@5.8.3) + eslint: 9.39.4(jiti@2.6.1) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -11517,6 +13223,11 @@ snapshots: '@typescript-eslint/types': 8.30.1 eslint-visitor-keys: 4.2.1 + '@typescript-eslint/visitor-keys@8.59.3': + dependencies: + '@typescript-eslint/types': 8.59.3 + eslint-visitor-keys: 5.0.1 + '@ungap/structured-clone@1.3.0': {} '@unhead/vue@2.1.13(vue@3.5.30(typescript@5.8.3))': @@ -11531,6 +13242,65 @@ snapshots: unhead: 2.1.13 vue: 3.5.30(typescript@5.9.3) + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + optional: true + + '@unrs/resolver-binding-android-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + optional: true + '@vercel/nft@1.5.0(rollup@4.60.2)': dependencies: '@mapbox/node-pre-gyp': 2.0.3 @@ -11554,6 +13324,17 @@ snapshots: dependencies: vite: 6.4.1(@types/node@22.15.30)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) + '@vitejs/plugin-react@4.4.1(vite@5.4.21(@types/node@22.15.30)(lightningcss@1.32.0)(terser@5.39.2))': + 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: 5.4.21(@types/node@22.15.30)(lightningcss@1.32.0)(terser@5.39.2) + transitivePeerDependencies: + - supports-color + '@vitejs/plugin-react@4.4.1(vite@6.4.1(@types/node@22.15.30)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@babel/core': 7.27.1 @@ -11565,11 +13346,16 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitejs/plugin-react@6.0.1(vite@8.0.11(@types/node@22.15.30)(esbuild@0.28.0)(jiti@2.6.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@rolldown/pluginutils': 1.0.0-rc.7 + vite: 8.0.11(@types/node@22.15.30)(esbuild@0.28.0)(jiti@2.6.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) + '@vitejs/plugin-vue-jsx@4.2.0(vite@6.4.1(@types/node@22.13.4)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.30(typescript@5.8.3))': dependencies: '@babel/core': 7.27.1 '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.27.1) - '@rolldown/pluginutils': 1.0.0-rc.2 + '@rolldown/pluginutils': 1.0.0-rc.18 '@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.27.1) vite: 6.4.1(@types/node@22.13.4)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) vue: 3.5.30(typescript@5.8.3) @@ -11580,7 +13366,7 @@ snapshots: dependencies: '@babel/core': 7.27.1 '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.27.1) - '@rolldown/pluginutils': 1.0.0-rc.2 + '@rolldown/pluginutils': 1.0.0-rc.18 '@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.27.1) vite: 6.4.1(@types/node@22.15.30)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) vue: 3.5.30(typescript@5.9.3) @@ -11839,7 +13625,7 @@ snapshots: '@vue/shared': 3.5.30 estree-walker: 2.0.2 magic-string: 0.30.21 - postcss: 8.5.8 + postcss: 8.5.14 source-map-js: 1.2.1 '@vue/compiler-ssr@3.5.30': @@ -12060,6 +13846,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + alien-signals@1.0.13: {} ansi-colors@4.1.3: {} @@ -12113,6 +13906,10 @@ snapshots: argparse@2.0.1: {} + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + aria-query@5.3.0: dependencies: dequal: 2.0.3 @@ -12238,6 +14035,15 @@ snapshots: postcss: 8.4.31 postcss-value-parser: 4.2.0 + autoprefixer@10.5.0(postcss@8.5.14): + dependencies: + browserslist: 4.28.2 + caniuse-lite: 1.0.30001788 + fraction.js: 5.3.4 + picocolors: 1.1.1 + postcss: 8.5.14 + postcss-value-parser: 4.2.0 + autoprefixer@10.5.0(postcss@8.5.8): dependencies: browserslist: 4.28.2 @@ -12800,9 +14606,9 @@ snapshots: randombytes: 2.1.0 randomfill: 1.0.4 - css-declaration-sorter@7.4.0(postcss@8.5.8): + css-declaration-sorter@7.4.0(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 css-select@5.2.2: dependencies: @@ -12826,49 +14632,49 @@ snapshots: cssesc@3.0.0: {} - cssnano-preset-default@7.0.13(postcss@8.5.8): + cssnano-preset-default@7.0.13(postcss@8.5.14): dependencies: browserslist: 4.28.2 - css-declaration-sorter: 7.4.0(postcss@8.5.8) - cssnano-utils: 5.0.1(postcss@8.5.8) - postcss: 8.5.8 - postcss-calc: 10.1.1(postcss@8.5.8) - postcss-colormin: 7.0.8(postcss@8.5.8) - postcss-convert-values: 7.0.10(postcss@8.5.8) - postcss-discard-comments: 7.0.6(postcss@8.5.8) - postcss-discard-duplicates: 7.0.2(postcss@8.5.8) - postcss-discard-empty: 7.0.1(postcss@8.5.8) - postcss-discard-overridden: 7.0.1(postcss@8.5.8) - postcss-merge-longhand: 7.0.5(postcss@8.5.8) - postcss-merge-rules: 7.0.9(postcss@8.5.8) - postcss-minify-font-values: 7.0.1(postcss@8.5.8) - postcss-minify-gradients: 7.0.3(postcss@8.5.8) - postcss-minify-params: 7.0.7(postcss@8.5.8) - postcss-minify-selectors: 7.0.6(postcss@8.5.8) - postcss-normalize-charset: 7.0.1(postcss@8.5.8) - postcss-normalize-display-values: 7.0.1(postcss@8.5.8) - postcss-normalize-positions: 7.0.1(postcss@8.5.8) - postcss-normalize-repeat-style: 7.0.1(postcss@8.5.8) - postcss-normalize-string: 7.0.1(postcss@8.5.8) - postcss-normalize-timing-functions: 7.0.1(postcss@8.5.8) - postcss-normalize-unicode: 7.0.7(postcss@8.5.8) - postcss-normalize-url: 7.0.1(postcss@8.5.8) - postcss-normalize-whitespace: 7.0.1(postcss@8.5.8) - postcss-ordered-values: 7.0.2(postcss@8.5.8) - postcss-reduce-initial: 7.0.7(postcss@8.5.8) - postcss-reduce-transforms: 7.0.1(postcss@8.5.8) - postcss-svgo: 7.1.1(postcss@8.5.8) - postcss-unique-selectors: 7.0.5(postcss@8.5.8) - - cssnano-utils@5.0.1(postcss@8.5.8): + css-declaration-sorter: 7.4.0(postcss@8.5.14) + cssnano-utils: 5.0.1(postcss@8.5.14) + postcss: 8.5.14 + postcss-calc: 10.1.1(postcss@8.5.14) + postcss-colormin: 7.0.8(postcss@8.5.14) + postcss-convert-values: 7.0.10(postcss@8.5.14) + postcss-discard-comments: 7.0.6(postcss@8.5.14) + postcss-discard-duplicates: 7.0.2(postcss@8.5.14) + postcss-discard-empty: 7.0.1(postcss@8.5.14) + postcss-discard-overridden: 7.0.1(postcss@8.5.14) + postcss-merge-longhand: 7.0.5(postcss@8.5.14) + postcss-merge-rules: 7.0.9(postcss@8.5.14) + postcss-minify-font-values: 7.0.1(postcss@8.5.14) + postcss-minify-gradients: 7.0.3(postcss@8.5.14) + postcss-minify-params: 7.0.7(postcss@8.5.14) + postcss-minify-selectors: 7.0.6(postcss@8.5.14) + postcss-normalize-charset: 7.0.1(postcss@8.5.14) + postcss-normalize-display-values: 7.0.1(postcss@8.5.14) + postcss-normalize-positions: 7.0.1(postcss@8.5.14) + postcss-normalize-repeat-style: 7.0.1(postcss@8.5.14) + postcss-normalize-string: 7.0.1(postcss@8.5.14) + postcss-normalize-timing-functions: 7.0.1(postcss@8.5.14) + postcss-normalize-unicode: 7.0.7(postcss@8.5.14) + postcss-normalize-url: 7.0.1(postcss@8.5.14) + postcss-normalize-whitespace: 7.0.1(postcss@8.5.14) + postcss-ordered-values: 7.0.2(postcss@8.5.14) + postcss-reduce-initial: 7.0.7(postcss@8.5.14) + postcss-reduce-transforms: 7.0.1(postcss@8.5.14) + postcss-svgo: 7.1.1(postcss@8.5.14) + postcss-unique-selectors: 7.0.5(postcss@8.5.14) + + cssnano-utils@5.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 - cssnano@7.1.5(postcss@8.5.8): + cssnano@7.1.5(postcss@8.5.14): dependencies: - cssnano-preset-default: 7.0.13(postcss@8.5.8) + cssnano-preset-default: 7.0.13(postcss@8.5.14) lilconfig: 3.1.3 - postcss: 8.5.8 + postcss: 8.5.14 csso@5.0.5: dependencies: @@ -13002,6 +14808,8 @@ snapshots: detect-libc@2.1.2: {} + detect-node-es@1.1.0: {} + devalue@5.7.1: {} didyoumean@1.2.2: {} @@ -13122,6 +14930,11 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.2.2 + enhanced-resolve@5.21.3: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + enquirer@2.3.6: dependencies: ansi-colors: 4.1.3 @@ -13257,6 +15070,32 @@ snapshots: dependencies: esbuild: 0.25.9 + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + esbuild@0.25.9: optionalDependencies: '@esbuild/aix-ppc64': 0.25.9 @@ -13411,6 +15250,26 @@ snapshots: object.assign: 4.1.7 object.entries: 1.1.9 + eslint-config-next@16.1.6(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3): + dependencies: + '@next/eslint-plugin-next': 16.1.6 + eslint: 9.39.4(jiti@2.6.1) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.4(jiti@2.6.1)) + eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@2.6.1)) + eslint-plugin-react-hooks: 7.1.1(eslint@9.39.4(jiti@2.6.1)) + globals: 16.4.0 + typescript-eslint: 8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-webpack + - eslint-plugin-import-x + - supports-color + eslint-config-prettier@8.10.0(eslint@8.57.0): dependencies: eslint: 8.57.0 @@ -13423,6 +15282,21 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.4.3 + eslint: 9.39.4(jiti@2.6.1) + get-tsconfig: 4.13.6 + is-bun-module: 2.0.0 + stable-hash: 0.0.5 + tinyglobby: 0.2.16 + unrs-resolver: 1.11.1 + optionalDependencies: + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)) + transitivePeerDependencies: + - supports-color + eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): dependencies: debug: 3.2.7 @@ -13433,6 +15307,17 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) + eslint: 9.39.4(jiti@2.6.1) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)) + transitivePeerDependencies: + - supports-color + eslint-plugin-es@3.0.1(eslint@8.57.0): dependencies: eslint: 8.57.0 @@ -13472,7 +15357,36 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.7.2) + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.7.2) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)): + 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: 9.39.4(jiti@2.6.1) + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)) + 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': 8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -13507,6 +15421,25 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 + eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@2.6.1)): + dependencies: + aria-query: 5.3.2 + array-includes: 3.1.9 + array.prototype.flatmap: 1.3.3 + ast-types-flow: 0.0.8 + axe-core: 4.11.0 + axobject-query: 4.1.0 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + eslint: 9.39.4(jiti@2.6.1) + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + safe-regex-test: 1.1.0 + string.prototype.includes: 2.0.1 + eslint-plugin-node@11.1.0(eslint@8.57.0): dependencies: eslint: 8.57.0 @@ -13533,10 +15466,25 @@ snapshots: dependencies: eslint: 9.25.0(jiti@2.6.1) + eslint-plugin-react-hooks@7.1.1(eslint@9.39.4(jiti@2.6.1)): + dependencies: + '@babel/core': 7.27.1 + '@babel/parser': 7.29.0 + eslint: 9.39.4(jiti@2.6.1) + hermes-parser: 0.25.1 + zod: 4.4.3 + zod-validation-error: 4.0.2(zod@4.4.3) + transitivePeerDependencies: + - supports-color + eslint-plugin-react-refresh@0.4.19(eslint@9.25.0(jiti@2.6.1)): dependencies: eslint: 9.25.0(jiti@2.6.1) + eslint-plugin-react-refresh@0.5.2(eslint@9.39.4(jiti@2.6.1)): + dependencies: + eslint: 9.39.4(jiti@2.6.1) + eslint-plugin-react@7.37.5(eslint@8.57.0): dependencies: array-includes: 3.1.9 @@ -13559,6 +15507,28 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.6.1)): + dependencies: + array-includes: 3.1.9 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.1 + eslint: 9.39.4(jiti@2.6.1) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + eslint-plugin-testing-library@5.11.1(eslint@8.57.0)(typescript@5.7.2): dependencies: '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.7.2) @@ -13615,6 +15585,8 @@ snapshots: eslint-visitor-keys@4.2.1: {} + eslint-visitor-keys@5.0.1: {} + eslint@8.57.0: dependencies: '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0) @@ -13700,6 +15672,47 @@ snapshots: transitivePeerDependencies: - supports-color + eslint@9.39.4(jiti@2.6.1): + dependencies: + '@eslint-community/eslint-utils': 4.8.0(eslint@9.39.4(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.2 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.5 + '@eslint/js': 9.39.4 + '@eslint/plugin-kit': 0.3.4 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + ajv: 6.15.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 + transitivePeerDependencies: + - supports-color + espree@10.4.0: dependencies: acorn: 8.16.0 @@ -13815,6 +15828,14 @@ snapshots: fast-fifo@1.3.2: {} + fast-glob@3.3.1: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -14021,6 +16042,8 @@ snapshots: hasown: 2.0.2 math-intrinsics: 1.1.0 + get-nonce@1.0.1: {} + get-port-please@3.2.0: {} get-proto@1.0.1: @@ -14115,6 +16138,10 @@ snapshots: globals@16.0.0: {} + globals@16.4.0: {} + + globals@17.6.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -14214,6 +16241,12 @@ snapshots: he@1.2.0: {} + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + hmac-drbg@1.0.1: dependencies: hash.js: 1.1.7 @@ -14401,6 +16434,10 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 + is-bun-module@2.0.0: + dependencies: + semver: 7.7.4 + is-callable@1.2.7: {} is-core-module@2.16.1: @@ -15079,6 +17116,10 @@ snapshots: dependencies: brace-expansion: 1.1.13 + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.13 + minimatch@5.1.9: dependencies: brace-expansion: 2.0.2 @@ -15109,17 +17150,17 @@ snapshots: mkdist@2.4.1(typescript@5.8.3)(vue-sfc-transformer@0.1.17(@vue/compiler-core@3.5.30)(esbuild@0.28.0)(vue@3.5.30(typescript@5.8.3)))(vue-tsc@2.2.8(typescript@5.8.3))(vue@3.5.30(typescript@5.8.3)): dependencies: - autoprefixer: 10.5.0(postcss@8.5.8) + autoprefixer: 10.5.0(postcss@8.5.14) citty: 0.1.6 - cssnano: 7.1.5(postcss@8.5.8) + cssnano: 7.1.5(postcss@8.5.14) defu: 6.1.4 esbuild: 0.25.9 jiti: 1.21.7 mlly: 1.8.2 pathe: 2.0.3 pkg-types: 2.3.0 - postcss: 8.5.8 - postcss-nested: 7.0.2(postcss@8.5.8) + postcss: 8.5.14 + postcss-nested: 7.0.2(postcss@8.5.14) semver: 7.7.3 tinyglobby: 0.2.15 optionalDependencies: @@ -15157,6 +17198,8 @@ snapshots: nanotar@0.2.1: {} + napi-postinstall@0.3.4: {} + natural-compare-lite@1.4.0: {} natural-compare@1.4.0: {} @@ -15189,6 +17232,31 @@ snapshots: - '@babel/core' - babel-plugin-macros + next@16.1.6(@babel/core@7.27.1)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + dependencies: + '@next/env': 16.1.6 + '@swc/helpers': 0.5.15 + baseline-browser-mapping: 2.10.20 + caniuse-lite: 1.0.30001788 + postcss: 8.4.31 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + styled-jsx: 5.1.6(@babel/core@7.27.1)(react@19.2.3) + optionalDependencies: + '@next/swc-darwin-arm64': 16.1.6 + '@next/swc-darwin-x64': 16.1.6 + '@next/swc-linux-arm64-gnu': 16.1.6 + '@next/swc-linux-arm64-musl': 16.1.6 + '@next/swc-linux-x64-gnu': 16.1.6 + '@next/swc-linux-x64-musl': 16.1.6 + '@next/swc-win32-arm64-msvc': 16.1.6 + '@next/swc-win32-x64-msvc': 16.1.6 + '@playwright/test': 1.58.2 + sharp: 0.34.5 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + nitropack@2.13.3(srvx@0.11.15): dependencies: '@cloudflare/kv-asset-handler': 0.4.2 @@ -15967,42 +18035,42 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-calc@10.1.1(postcss@8.5.8): + postcss-calc@10.1.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-selector-parser: 7.1.1 postcss-value-parser: 4.2.0 - postcss-colormin@7.0.8(postcss@8.5.8): + postcss-colormin@7.0.8(postcss@8.5.14): dependencies: '@colordx/core': 5.2.0 browserslist: 4.28.2 caniuse-api: 3.0.0 - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-convert-values@7.0.10(postcss@8.5.8): + postcss-convert-values@7.0.10(postcss@8.5.14): dependencies: browserslist: 4.28.2 - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-discard-comments@7.0.6(postcss@8.5.8): + postcss-discard-comments@7.0.6(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-selector-parser: 7.1.1 - postcss-discard-duplicates@7.0.2(postcss@8.5.8): + postcss-discard-duplicates@7.0.2(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 - postcss-discard-empty@7.0.1(postcss@8.5.8): + postcss-discard-empty@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 - postcss-discard-overridden@7.0.1(postcss@8.5.8): + postcss-discard-overridden@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-import@15.1.0(postcss@8.5.8): dependencies: @@ -16025,43 +18093,43 @@ snapshots: tsx: 4.21.0 yaml: 2.8.3 - postcss-merge-longhand@7.0.5(postcss@8.5.8): + postcss-merge-longhand@7.0.5(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - stylehacks: 7.0.9(postcss@8.5.8) + stylehacks: 7.0.9(postcss@8.5.14) - postcss-merge-rules@7.0.9(postcss@8.5.8): + postcss-merge-rules@7.0.9(postcss@8.5.14): dependencies: browserslist: 4.28.2 caniuse-api: 3.0.0 - cssnano-utils: 5.0.1(postcss@8.5.8) - postcss: 8.5.8 + cssnano-utils: 5.0.1(postcss@8.5.14) + postcss: 8.5.14 postcss-selector-parser: 7.1.1 - postcss-minify-font-values@7.0.1(postcss@8.5.8): + postcss-minify-font-values@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-minify-gradients@7.0.3(postcss@8.5.8): + postcss-minify-gradients@7.0.3(postcss@8.5.14): dependencies: '@colordx/core': 5.2.0 - cssnano-utils: 5.0.1(postcss@8.5.8) - postcss: 8.5.8 + cssnano-utils: 5.0.1(postcss@8.5.14) + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-minify-params@7.0.7(postcss@8.5.8): + postcss-minify-params@7.0.7(postcss@8.5.14): dependencies: browserslist: 4.28.2 - cssnano-utils: 5.0.1(postcss@8.5.8) - postcss: 8.5.8 + cssnano-utils: 5.0.1(postcss@8.5.14) + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-minify-selectors@7.0.6(postcss@8.5.8): + postcss-minify-selectors@7.0.6(postcss@8.5.14): dependencies: cssesc: 3.0.0 - postcss: 8.5.8 + postcss: 8.5.14 postcss-selector-parser: 7.1.1 postcss-nested@6.2.0(postcss@8.5.8): @@ -16069,9 +18137,9 @@ snapshots: postcss: 8.5.8 postcss-selector-parser: 6.1.2 - postcss-nested@7.0.2(postcss@8.5.8): + postcss-nested@7.0.2(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-selector-parser: 7.1.1 postcss-nesting@13.0.2(postcss@8.5.8): @@ -16081,66 +18149,66 @@ snapshots: postcss: 8.5.8 postcss-selector-parser: 7.1.1 - postcss-normalize-charset@7.0.1(postcss@8.5.8): + postcss-normalize-charset@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 - postcss-normalize-display-values@7.0.1(postcss@8.5.8): + postcss-normalize-display-values@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-normalize-positions@7.0.1(postcss@8.5.8): + postcss-normalize-positions@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-normalize-repeat-style@7.0.1(postcss@8.5.8): + postcss-normalize-repeat-style@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-normalize-string@7.0.1(postcss@8.5.8): + postcss-normalize-string@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-normalize-timing-functions@7.0.1(postcss@8.5.8): + postcss-normalize-timing-functions@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-normalize-unicode@7.0.7(postcss@8.5.8): + postcss-normalize-unicode@7.0.7(postcss@8.5.14): dependencies: browserslist: 4.28.2 - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-normalize-url@7.0.1(postcss@8.5.8): + postcss-normalize-url@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-normalize-whitespace@7.0.1(postcss@8.5.8): + postcss-normalize-whitespace@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-ordered-values@7.0.2(postcss@8.5.8): + postcss-ordered-values@7.0.2(postcss@8.5.14): dependencies: - cssnano-utils: 5.0.1(postcss@8.5.8) - postcss: 8.5.8 + cssnano-utils: 5.0.1(postcss@8.5.14) + postcss: 8.5.14 postcss-value-parser: 4.2.0 - postcss-reduce-initial@7.0.7(postcss@8.5.8): + postcss-reduce-initial@7.0.7(postcss@8.5.14): dependencies: browserslist: 4.28.2 caniuse-api: 3.0.0 - postcss: 8.5.8 + postcss: 8.5.14 - postcss-reduce-transforms@7.0.1(postcss@8.5.8): + postcss-reduce-transforms@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 postcss-selector-parser@6.1.2: @@ -16153,15 +18221,15 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-svgo@7.1.1(postcss@8.5.8): + postcss-svgo@7.1.1(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-value-parser: 4.2.0 svgo: 4.0.1 - postcss-unique-selectors@7.0.5(postcss@8.5.8): + postcss-unique-selectors@7.0.5(postcss@8.5.14): dependencies: - postcss: 8.5.8 + postcss: 8.5.14 postcss-selector-parser: 7.1.1 postcss-value-parser@4.2.0: {} @@ -16284,6 +18352,17 @@ snapshots: defu: 6.1.7 destr: 2.0.5 + react-dom@18.3.1(react@18.3.1): + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + + react-dom@19.2.3(react@19.2.3): + dependencies: + react: 19.2.3 + scheduler: 0.27.0 + react-dom@19.2.4(react@19.2.4): dependencies: react: 19.2.4 @@ -16297,6 +18376,25 @@ snapshots: react-refresh@0.17.0: {} + react-remove-scroll-bar@2.3.8(@types/react@19.1.5)(react@18.3.1): + dependencies: + react: 18.3.1 + react-style-singleton: 2.2.3(@types/react@19.1.5)(react@18.3.1) + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.5 + + react-remove-scroll@2.7.2(@types/react@19.1.5)(react@18.3.1): + dependencies: + react: 18.3.1 + react-remove-scroll-bar: 2.3.8(@types/react@19.1.5)(react@18.3.1) + react-style-singleton: 2.2.3(@types/react@19.1.5)(react@18.3.1) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@19.1.5)(react@18.3.1) + use-sidecar: 1.1.3(@types/react@19.1.5)(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.5 + react-router@7.12.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: cookie: 1.0.2 @@ -16305,6 +18403,20 @@ snapshots: optionalDependencies: react-dom: 19.2.4(react@19.2.4) + react-style-singleton@2.2.3(@types/react@19.1.5)(react@18.3.1): + dependencies: + get-nonce: 1.0.1 + react: 18.3.1 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.5 + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + + react@19.2.3: {} + react@19.2.4: {} read-cache@1.0.0: @@ -16618,6 +18730,10 @@ snapshots: dependencies: xmlchars: 2.2.0 + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + scheduler@0.27.0: {} scule@1.3.0: {} @@ -16844,6 +18960,8 @@ snapshots: srvx@0.11.15: {} + stable-hash@0.0.5: {} + stackback@0.0.2: {} standard-as-callback@2.1.0: {} @@ -16977,6 +19095,13 @@ snapshots: structured-clone-es@1.0.0: {} + styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.2.3): + dependencies: + client-only: 0.0.1 + react: 19.2.3 + optionalDependencies: + '@babel/core': 7.27.1 + styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.2.4): dependencies: client-only: 0.0.1 @@ -16984,10 +19109,10 @@ snapshots: optionalDependencies: '@babel/core': 7.27.1 - stylehacks@7.0.9(postcss@8.5.8): + stylehacks@7.0.9(postcss@8.5.14): dependencies: browserslist: 4.28.2 - postcss: 8.5.8 + postcss: 8.5.14 postcss-selector-parser: 7.1.1 stylis@4.2.0: {} @@ -17076,8 +19201,12 @@ snapshots: tailwindcss@4.1.8: {} + tailwindcss@4.3.0: {} + tapable@2.2.2: {} + tapable@2.3.3: {} + tar-stream@2.2.0: dependencies: bl: 4.1.0 @@ -17229,6 +19358,10 @@ snapshots: dependencies: typescript: 5.8.3 + ts-api-utils@2.5.0(typescript@5.8.3): + dependencies: + typescript: 5.8.3 + ts-interface-checker@0.1.13: {} tsconfck@3.1.6(typescript@5.8.3): @@ -17334,6 +19467,17 @@ snapshots: transitivePeerDependencies: - supports-color + typescript-eslint@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.59.3(@typescript-eslint/parser@8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/parser': 8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.59.3(typescript@5.8.3) + '@typescript-eslint/utils': 8.59.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) + eslint: 9.39.4(jiti@2.6.1) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + typescript@5.7.2: {} typescript@5.8.3: {} @@ -17524,6 +19668,30 @@ snapshots: picomatch: 4.0.3 webpack-virtual-modules: 0.6.2 + unrs-resolver@1.11.1: + dependencies: + napi-postinstall: 0.3.4 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + unstorage@1.17.5(db0@0.3.4)(ioredis@5.10.1): dependencies: anymatch: 3.1.3 @@ -17579,6 +19747,21 @@ snapshots: dependencies: punycode: 2.3.1 + use-callback-ref@1.3.3(@types/react@19.1.5)(react@18.3.1): + dependencies: + react: 18.3.1 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.5 + + use-sidecar@1.1.3(@types/react@19.1.5)(react@18.3.1): + dependencies: + detect-node-es: 1.1.0 + react: 18.3.1 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.5 + use-sync-external-store@1.6.0(react@19.2.4): dependencies: react: 19.2.4 @@ -17783,6 +19966,17 @@ snapshots: vite: 8.0.11(@types/node@22.15.30)(esbuild@0.28.0)(jiti@1.21.7)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) vue: 3.5.30(typescript@5.9.3) + vite@5.4.21(@types/node@22.15.30)(lightningcss@1.32.0)(terser@5.39.2): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.14 + rollup: 4.60.2 + optionalDependencies: + '@types/node': 22.15.30 + fsevents: 2.3.3 + lightningcss: 1.32.0 + terser: 5.39.2 + vite@6.4.1(@types/node@22.13.4)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3): dependencies: esbuild: 0.25.9 @@ -17866,6 +20060,22 @@ snapshots: tsx: 4.21.0 yaml: 2.8.3 + vite@8.0.11(@types/node@22.15.30)(esbuild@0.28.0)(jiti@2.6.1)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.14 + rolldown: 1.0.0-rc.18 + tinyglobby: 0.2.16 + optionalDependencies: + '@types/node': 22.15.30 + esbuild: 0.28.0 + fsevents: 2.3.3 + jiti: 2.6.1 + terser: 5.39.2 + tsx: 4.21.0 + yaml: 2.8.3 + vitest-environment-nuxt@1.0.1(@playwright/test@1.58.2)(@types/node@22.13.4)(@vue/test-utils@2.4.6)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.32.0)(magicast@0.5.2)(playwright-core@1.58.2)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(vitest@3.1.1(@types/node@22.13.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3))(yaml@2.8.3): dependencies: '@nuxt/test-utils': 3.17.2(@playwright/test@1.58.2)(@types/node@22.13.4)(@vue/test-utils@2.4.6)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.32.0)(magicast@0.5.2)(playwright-core@1.58.2)(terser@5.39.2)(tsx@4.21.0)(typescript@5.8.3)(vitest@3.1.1(@types/node@22.13.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.32.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3))(yaml@2.8.3) @@ -18337,3 +20547,9 @@ snapshots: archiver-utils: 5.0.2 compress-commons: 6.0.2 readable-stream: 4.7.0 + + zod-validation-error@4.0.2(zod@4.4.3): + dependencies: + zod: 4.4.3 + + zod@4.4.3: {}