From 93a2e26495374d7230f82e49f7d2698aed5c99c1 Mon Sep 17 00:00:00 2001 From: Gabriel Stein Date: Mon, 8 Jun 2026 15:45:35 -0700 Subject: [PATCH] feat(sample-apps): Standardize SDK Configuration SDKS-5067 feat(reactjs-todo-oidc): migrate SDK config to config.json feat(reactjs-todo-journey): migrate SDK config to config.json feat(sample-apps): inject SDK config via env var for e2e, fall back to config.json fix(reactjs-todo-davinci): migrate fido playwright block to unified config fix(reactjs-todo-journey): replace deprecated assert with import attribute fix(reactjs-todo-oidc): remove REST_OAUTH vars from env.example, add CI clarification docs: update README setup sections to reflect config.json migration feat(reactjs-todo-davinci): wire make*Config from sdk-utilities feat(reactjs-todo-oidc): wire makeOidcConfig from sdk-utilities feat(reactjs-todo-journey): wire make*Config from sdk-utilities fix(sample-apps): derive redirectUri dynamically from window.location.origin --- javascript/reactjs-todo-davinci/.env.example | 7 +- javascript/reactjs-todo-davinci/.gitignore | 1 + javascript/reactjs-todo-davinci/README.md | 28 ++++-- .../hooks/create-client.utils.js | 3 +- .../reactjs-todo-davinci/client/constants.js | 40 ++++----- .../client/context/oidc.context.js | 5 +- .../reactjs-todo-davinci/config.example.json | 7 ++ .../config.test.fido.json | 8 ++ .../reactjs-todo-davinci/config.test.json | 8 ++ javascript/reactjs-todo-davinci/package.json | 1 + .../reactjs-todo-davinci/playwright.config.ts | 12 +-- .../reactjs-todo-davinci/webpack.config.js | 14 +-- javascript/reactjs-todo-journey/.env.example | 11 +-- javascript/reactjs-todo-journey/.gitignore | 1 + javascript/reactjs-todo-journey/README.md | 29 ++++-- .../client/components/journey/journey.hook.js | 16 ++-- .../reactjs-todo-journey/client/constants.js | 35 ++++---- .../client/context/oidc.context.js | 7 +- .../reactjs-todo-journey/config.example.json | 7 ++ .../reactjs-todo-journey/config.test.json | 8 ++ .../e2e/embedded-login.spec.js | 8 ++ javascript/reactjs-todo-journey/package.json | 1 + .../reactjs-todo-journey/playwright.config.js | 9 +- .../reactjs-todo-journey/vite.config.js | 19 +++- javascript/reactjs-todo-oidc/.env.example | 16 ++-- javascript/reactjs-todo-oidc/.gitignore | 1 + javascript/reactjs-todo-oidc/README.md | 33 +++++-- javascript/reactjs-todo-oidc/client/README.md | 35 ++++++-- .../reactjs-todo-oidc/client/constants.js | 26 ++++-- .../client/context/oidc.context.js | 3 +- .../reactjs-todo-oidc/config.example.json | 7 ++ .../reactjs-todo-oidc/config.test.pingam.json | 8 ++ .../config.test.pingone.json | 8 ++ javascript/reactjs-todo-oidc/package.json | 1 + .../reactjs-todo-oidc/playwright.config.ts | 14 ++- .../reactjs-todo-oidc/webpack.config.js | 14 +-- package-lock.json | 89 +++++++++++++++---- 37 files changed, 386 insertions(+), 154 deletions(-) create mode 100644 javascript/reactjs-todo-davinci/config.example.json create mode 100644 javascript/reactjs-todo-davinci/config.test.fido.json create mode 100644 javascript/reactjs-todo-davinci/config.test.json create mode 100644 javascript/reactjs-todo-journey/config.example.json create mode 100644 javascript/reactjs-todo-journey/config.test.json create mode 100644 javascript/reactjs-todo-oidc/config.example.json create mode 100644 javascript/reactjs-todo-oidc/config.test.pingam.json create mode 100644 javascript/reactjs-todo-oidc/config.test.pingone.json diff --git a/javascript/reactjs-todo-davinci/.env.example b/javascript/reactjs-todo-davinci/.env.example index 65c7e725..8a82e09d 100644 --- a/javascript/reactjs-todo-davinci/.env.example +++ b/javascript/reactjs-todo-davinci/.env.example @@ -1,10 +1,7 @@ -WELLKNOWN_URL= -WEB_OAUTH_CLIENT= API_URL=http://localhost:9443 DEBUGGER_OFF=true DEVELOPMENT=true PORT=8443 -SCOPE="openid profile email phone name revoke" # INIT_PROTECT (optional) - bootstrap | flow # 'bootstrap' will initialize protect at app bootstrap time @@ -12,3 +9,7 @@ SCOPE="openid profile email phone name revoke" INIT_PROTECT= # PINGONE_ENV_ID - required when ProtectCollector is present PINGONE_ENV_ID= + +# SDK configuration (clientId, discoveryEndpoint, scopes, redirectUri) is no +# longer sourced from environment variables. Copy config.example.json to +# config.json and fill in your values. diff --git a/javascript/reactjs-todo-davinci/.gitignore b/javascript/reactjs-todo-davinci/.gitignore index 68c5d18f..96b12efc 100644 --- a/javascript/reactjs-todo-davinci/.gitignore +++ b/javascript/reactjs-todo-davinci/.gitignore @@ -1,4 +1,5 @@ node_modules/ +config.json /test-results/ /playwright-report/ /blob-report/ diff --git a/javascript/reactjs-todo-davinci/README.md b/javascript/reactjs-todo-davinci/README.md index 9f9d7c11..156f9d60 100644 --- a/javascript/reactjs-todo-davinci/README.md +++ b/javascript/reactjs-todo-davinci/README.md @@ -50,20 +50,36 @@ Once you have the requirements above met, we can build the project. 1. DaVinci Policies: Select your DaVinci application -### Configure Your `.env` File +### Configure SDK Credentials + +Copy `config.example.json` to `config.json` at the app root and fill in your values: + +```sh +cp config.example.json config.json +``` + +`config.json` (gitignored): + +```json +{ + "oidc": { + "clientId": "", + "discoveryEndpoint": "https:///.well-known/openid-configuration", + "scopes": ["openid", "profile", "email"], + "redirectUri": "https://localhost:8443/callback.html" + } +} +``` -Change the name of `.env.example` to `.env` and replace the dummy values (e.g. `$CLIENT_ID`) with your values. +### Configure Your `.env` File -Example with annotations: +Change the name of `.env.example` to `.env` and set the remaining runtime values: ```text -WELLKNOWN_URL=<> -WEB_OAUTH_CLIENT=<> API_URL=http://localhost:9443 DEBUGGER_OFF=true DEVELOPMENT=true PORT=8443 -SCOPE="openid profile email phone name revoke" ``` ### Installing Dependencies diff --git a/javascript/reactjs-todo-davinci/client/components/davinci-client/hooks/create-client.utils.js b/javascript/reactjs-todo-davinci/client/components/davinci-client/hooks/create-client.utils.js index a1151b5a..d39c63f7 100644 --- a/javascript/reactjs-todo-davinci/client/components/davinci-client/hooks/create-client.utils.js +++ b/javascript/reactjs-todo-davinci/client/components/davinci-client/hooks/create-client.utils.js @@ -9,6 +9,7 @@ */ import { davinci } from '@forgerock/davinci-client'; +import { makeDavinciConfig } from '@forgerock/sdk-utilities'; import { CONFIG } from '../../../constants.js'; /** @@ -17,7 +18,7 @@ import { CONFIG } from '../../../constants.js'; */ export default async function createClient() { try { - const davinciClient = await davinci({ config: CONFIG }); + const davinciClient = await davinci({ config: makeDavinciConfig(CONFIG) }); return davinciClient; } catch (error) { console.error('Error creating DaVinci client'); diff --git a/javascript/reactjs-todo-davinci/client/constants.js b/javascript/reactjs-todo-davinci/client/constants.js index 57106b46..9275c5fe 100755 --- a/javascript/reactjs-todo-davinci/client/constants.js +++ b/javascript/reactjs-todo-davinci/client/constants.js @@ -8,32 +8,30 @@ * of the MIT license. See the LICENSE file for details. */ +/** *************************************************************************** + * SDK INTEGRATION POINT + * Summary: Configure the DaVinci client + * ---------------------------------------------------------------------------- + * Details: CONFIG uses the unified SDK configuration schema. Pass it to + * `makeDavinciConfig(CONFIG)` from `@forgerock/sdk-utilities` before calling + * the factory — e.g. `davinci({ config: makeDavinciConfig(CONFIG) })`. + * + * Local dev: copy config.example.json → config.json and fill in your values. + * E2e / CI: set SDK_CONFIG to a JSON string (e.g. from config.test.json). + *************************************************************************** */ +import sdkConfigJson from '../config.json'; export const API_URL = process.env.API_URL; // Yes, the debugger boolean is intentionally reversed export const DEBUGGER = process.env.DEBUGGER_OFF === 'false'; -export const WEB_OAUTH_CLIENT = process.env.WEB_OAUTH_CLIENT; -export const SCOPE = process.env.SCOPE; -export const WELLKNOWN_URL = process.env.WELLKNOWN_URL; export const INIT_PROTECT = process.env.INIT_PROTECT; export const PINGONE_ENV_ID = process.env.PINGONE_ENV_ID; -/** *************************************************************************** - * SDK INTEGRATION POINT - * Summary: Configure the OIDC client - * ---------------------------------------------------------------------------- - * Details: The config object below is passed to the `oidc()` initializer in - * `oidc.context.js` to configure the OIDC client: - * - clientId: the OAuth 2.0 client ID registered in PingOne - * - redirectUri: the URI of this app to which the OAuth 2.0 flow redirects - * after authentication (points to callback.html for the redirect handler) - * - scope: the OAuth 2.0 scopes requested from PingOne - * - serverConfig.wellknown: the OpenID Connect discovery URL for your - * PingOne environment, used to resolve authorization/token endpoints - *************************************************************************** */ + +const rawConfig = process.env.SDK_CONFIG ? JSON.parse(process.env.SDK_CONFIG) : sdkConfigJson; + export const CONFIG = { - clientId: WEB_OAUTH_CLIENT, - redirectUri: `${window.location.origin}/callback.html`, - scope: SCOPE, - serverConfig: { - wellknown: WELLKNOWN_URL, + ...rawConfig, + oidc: { + ...rawConfig.oidc, + redirectUri: `${window.location.origin}/callback.html`, }, }; diff --git a/javascript/reactjs-todo-davinci/client/context/oidc.context.js b/javascript/reactjs-todo-davinci/client/context/oidc.context.js index 6a65b8e3..d9e1047a 100644 --- a/javascript/reactjs-todo-davinci/client/context/oidc.context.js +++ b/javascript/reactjs-todo-davinci/client/context/oidc.context.js @@ -10,6 +10,7 @@ import { useState, createContext, useEffect } from 'react'; import { oidc } from '@forgerock/oidc-client'; +import { makeOidcConfig } from '@forgerock/sdk-utilities'; import { DEBUGGER } from '../constants'; const email = window.sessionStorage.getItem('sdk_email'); @@ -19,7 +20,7 @@ const username = window.sessionStorage.getItem('sdk_username'); * @function useInitOidcState - A custom hook to get initial OIDC state for managing user authentication * @returns {Array} - OIDC client, state values and state methods */ -export function useInitOidcState(config) { +export function useInitOidcState(json) { /** * Create state properties for "global" OIDC state. * The destructing of the hook's array results in index 0 having the state values, @@ -44,7 +45,7 @@ export function useInitOidcState(config) { * but it can be done outside of the React component for better performance. ************************************************************************* */ if (DEBUGGER) debugger; - let client = await oidc({ config }); + let client = await oidc({ config: makeOidcConfig(json) }); if ('error' in client) { console.error(`Error initializing OIDC client: ${client.error}`); client = null; diff --git a/javascript/reactjs-todo-davinci/config.example.json b/javascript/reactjs-todo-davinci/config.example.json new file mode 100644 index 00000000..dae21d05 --- /dev/null +++ b/javascript/reactjs-todo-davinci/config.example.json @@ -0,0 +1,7 @@ +{ + "oidc": { + "clientId": "", + "discoveryEndpoint": "https:///.well-known/openid-configuration", + "scopes": ["openid", "profile", "email"] + } +} diff --git a/javascript/reactjs-todo-davinci/config.test.fido.json b/javascript/reactjs-todo-davinci/config.test.fido.json new file mode 100644 index 00000000..1e680846 --- /dev/null +++ b/javascript/reactjs-todo-davinci/config.test.fido.json @@ -0,0 +1,8 @@ +{ + "oidc": { + "clientId": "20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0", + "discoveryEndpoint": "https://auth.pingone.ca/02fb4743-189a-4bc7-9d6c-a919edfe6447/as/.well-known/openid-configuration", + "scopes": ["openid", "profile", "email", "phone", "name", "revoke"], + "redirectUri": "http://localhost:5829/callback.html" + } +} diff --git a/javascript/reactjs-todo-davinci/config.test.json b/javascript/reactjs-todo-davinci/config.test.json new file mode 100644 index 00000000..42612c95 --- /dev/null +++ b/javascript/reactjs-todo-davinci/config.test.json @@ -0,0 +1,8 @@ +{ + "oidc": { + "clientId": "724ec718-c41c-4d51-98b0-84a583f450f9", + "discoveryEndpoint": "https://auth.pingone.ca/02fb4743-189a-4bc7-9d6c-a919edfe6447/as/.well-known/openid-configuration", + "scopes": ["openid", "profile", "email", "phone", "name", "revoke"], + "redirectUri": "http://localhost:8443/callback.html" + } +} diff --git a/javascript/reactjs-todo-davinci/package.json b/javascript/reactjs-todo-davinci/package.json index 325d7b06..2ffdef1c 100644 --- a/javascript/reactjs-todo-davinci/package.json +++ b/javascript/reactjs-todo-davinci/package.json @@ -41,6 +41,7 @@ "dependencies": { "@forgerock/davinci-client": "latest", "@forgerock/oidc-client": "latest", + "@forgerock/sdk-utilities": "latest", "@forgerock/protect": "latest", "cookie-parser": "^1.4.5", "cors": "^2.8.5", diff --git a/javascript/reactjs-todo-davinci/playwright.config.ts b/javascript/reactjs-todo-davinci/playwright.config.ts index 7ba90994..ec5fc556 100644 --- a/javascript/reactjs-todo-davinci/playwright.config.ts +++ b/javascript/reactjs-todo-davinci/playwright.config.ts @@ -1,4 +1,6 @@ import { defineConfig, devices } from '@playwright/test'; +import testConfig from './config.test.json'; +import testFidoConfig from './config.test.fido.json'; const url = process.env.PLAYWRIGHT_TEST_BASE_URL || 'http://localhost:8443'; @@ -27,11 +29,8 @@ export default defineConfig({ DEBUGGER_OFF: 'true', DEVELOPMENT: 'false', PORT: '8443', - WEB_OAUTH_CLIENT: '724ec718-c41c-4d51-98b0-84a583f450f9', - SCOPE: 'openid profile email phone name revoke', - WELLKNOWN_URL: - 'https://auth.pingone.ca/02fb4743-189a-4bc7-9d6c-a919edfe6447/as/.well-known/openid-configuration', PINGONE_ENV_ID: '02fb4743-189a-4bc7-9d6c-a919edfe6447', + SDK_CONFIG: JSON.stringify(testConfig), }, ignoreHTTPSErrors: true, }, @@ -61,10 +60,7 @@ export default defineConfig({ // DEBUGGER_OFF: 'true', // DEVELOPMENT: 'false', // PORT: '5829', - // WEB_OAUTH_CLIENT: '20dd0ed0-bb9b-4c8f-9a60-9ebeb4b348e0', - // SCOPE: 'openid profile email phone name revoke', - // WELLKNOWN_URL: - // 'https://auth.pingone.ca/02fb4743-189a-4bc7-9d6c-a919edfe6447/as/.well-known/openid-configuration', + // SDK_CONFIG: JSON.stringify(testFidoConfig), // }, // ignoreHTTPSErrors: true, // }, diff --git a/javascript/reactjs-todo-davinci/webpack.config.js b/javascript/reactjs-todo-davinci/webpack.config.js index 2c47ea44..503505ff 100644 --- a/javascript/reactjs-todo-davinci/webpack.config.js +++ b/javascript/reactjs-todo-davinci/webpack.config.js @@ -1,4 +1,5 @@ const dotenv = require('dotenv'); +const fs = require('fs'); const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const webpack = require('webpack'); @@ -12,10 +13,8 @@ module.exports = () => { const API_URL = process.env.API_URL || localEnv.API_URL; const DEBUGGER_OFF = process.env.DEBUGGER_OFF || localEnv.DEBUGGER_OFF; const DEVELOPMENT = process.env.DEVELOPMENT || localEnv.DEVELOPMENT; - const WEB_OAUTH_CLIENT = process.env.WEB_OAUTH_CLIENT || localEnv.WEB_OAUTH_CLIENT; - const SCOPE = process.env.SCOPE || localEnv.SCOPE; - const WELLKNOWN_URL = process.env.WELLKNOWN_URL || localEnv.WELLKNOWN_URL; const INIT_PROTECT = process.env.INIT_PROTECT || localEnv.INIT_PROTECT; + const SDK_CONFIG = process.env.SDK_CONFIG || null; const PINGONE_ENV_ID = process.env.PINGONE_ENV_ID || localEnv.PINGONE_ENV_ID; return { @@ -101,15 +100,18 @@ module.exports = () => { }, plugins: [ new MiniCssExtractPlugin(), + new webpack.NormalModuleReplacementPlugin(/config\.json$/, (resource) => { + if (!fs.existsSync(path.resolve(__dirname, 'config.json'))) { + resource.request = resource.request.replace('config.json', 'config.example.json'); + } + }), new webpack.DefinePlugin({ // Inject all the environment variable into the Webpack build 'process.env.API_URL': JSON.stringify(API_URL), 'process.env.DEBUGGER_OFF': JSON.stringify(DEBUGGER_OFF), - 'process.env.WEB_OAUTH_CLIENT': JSON.stringify(WEB_OAUTH_CLIENT), - 'process.env.SCOPE': JSON.stringify(SCOPE), - 'process.env.WELLKNOWN_URL': JSON.stringify(WELLKNOWN_URL), 'process.env.INIT_PROTECT': JSON.stringify(INIT_PROTECT), 'process.env.PINGONE_ENV_ID': JSON.stringify(PINGONE_ENV_ID), + 'process.env.SDK_CONFIG': JSON.stringify(SDK_CONFIG), }), ], }; diff --git a/javascript/reactjs-todo-journey/.env.example b/javascript/reactjs-todo-journey/.env.example index b1200b86..694d15d0 100644 --- a/javascript/reactjs-todo-journey/.env.example +++ b/javascript/reactjs-todo-journey/.env.example @@ -1,17 +1,18 @@ -VITE_WELLKNOWN_URL= -VITE_WEB_OAUTH_CLIENT= VITE_API_URL=http://localhost:9443 VITE_PORT=8443 VITE_DEBUGGER_OFF=true VITE_DEVELOPMENT=true -VITE_SCOPE='openid profile email' VITE_JOURNEY_LOGIN=Login VITE_JOURNEY_REGISTER=Registration # VITE_INIT_PROTECT (optional) - bootstrap | journey # 'bootstrap' will initialize protect at app bootstrap time # 'journey' relies on the PingOneProtectEvaluationCallback for initialization -VITE_INIT_PROTECT= +VITE_INIT_PROTECT= # VITE_PINGONE_ENV_ID - required if VITE_INIT_PROTECT is set -VITE_PINGONE_ENV_ID= +VITE_PINGONE_ENV_ID= + +# SDK configuration (clientId, discoveryEndpoint, scopes, redirectUri) is no +# longer sourced from environment variables. Copy config.example.json to +# config.json and fill in your values. diff --git a/javascript/reactjs-todo-journey/.gitignore b/javascript/reactjs-todo-journey/.gitignore index 1e272645..eb14be30 100644 --- a/javascript/reactjs-todo-journey/.gitignore +++ b/javascript/reactjs-todo-journey/.gitignore @@ -1,4 +1,5 @@ node_modules/ +config.json build/ /test-results/ /playwright-report/ diff --git a/javascript/reactjs-todo-journey/README.md b/javascript/reactjs-todo-journey/README.md index cca04ea0..66958cb4 100644 --- a/javascript/reactjs-todo-journey/README.md +++ b/javascript/reactjs-todo-journey/README.md @@ -56,23 +56,38 @@ Once you have the 5 requirements above met, we can build the project. WebAuthn type steps for registration and authentication are also supported -### Configure Your `.env` File +### Configure SDK Credentials + +Copy `config.example.json` to `config.json` at the app root and fill in your values: + +```sh +cp config.example.json config.json +``` + +`config.json` (gitignored): + +```json +{ + "oidc": { + "clientId": "", + "discoveryEndpoint": "https:///.well-known/openid-configuration", + "scopes": ["openid", "profile", "email"], + "redirectUri": "https://localhost:8443/callback.html" + } +} +``` -Change the name of `.env.example` to `.env` and fill the environment variables with your values. +### Configure Your `.env` File -Example with annotations: +Change the name of `.env.example` to `.env` and set the remaining runtime values: ```text -VITE_WELLKNOWN_URL=<<>> -VITE_WEB_OAUTH_CLIENT=<<>> VITE_API_URL=http://localhost:9443 VITE_PORT=8443 VITE_DEBUGGER_OFF=true VITE_DEVELOPMENT=true -VITE_SCOPE='openid profile email' VITE_JOURNEY_LOGIN=Login VITE_JOURNEY_REGISTER=Registration -VITE_REALM_PATH=<<>> ``` ### Installing Dependencies and Run Build diff --git a/javascript/reactjs-todo-journey/client/components/journey/journey.hook.js b/javascript/reactjs-todo-journey/client/components/journey/journey.hook.js index 8ef9829e..6ef94813 100644 --- a/javascript/reactjs-todo-journey/client/components/journey/journey.hook.js +++ b/javascript/reactjs-todo-journey/client/components/journey/journey.hook.js @@ -13,6 +13,7 @@ import { CONFIG, DEBUGGER } from '../../constants.js'; import { htmlDecode } from '../../utilities/decode.js'; import { OidcContext } from '../../context/oidc.context.js'; import { callbackType, journey } from '@forgerock/journey-client'; +import { makeJourneyConfig } from '@forgerock/sdk-utilities'; /** * @function isGenericError - Helper function to determine if a step is a GenericError @@ -69,7 +70,7 @@ export default function useJourney({ formMetadata, resumeUrl }) { ********************************************************************* */ if (DEBUGGER) debugger; try { - const client = await journey({ config: CONFIG }); + const client = await journey({ config: makeJourneyConfig(CONFIG) }); setJourneyClient(client); if (resumeUrl) { @@ -253,7 +254,11 @@ export default function useJourney({ formMetadata, resumeUrl }) { const previousCallbacks = prev?.callbacks; const previousPayload = prev?.payload; - if (stepCount.current === 1 && newStep.type === 'Step' && newStep.getStage() === previousStage) { + if ( + stepCount.current === 1 && + newStep.type === 'Step' && + newStep.getStage() === previousStage + ) { newStep.callbacks = previousCallbacks; newStep.payload = { ...previousPayload, @@ -286,12 +291,7 @@ export default function useJourney({ formMetadata, resumeUrl }) { if (submissionStep && journeyClient) { setStep(submissionStep); } - }, [ - formMetadata.tree, - submissionStep, - journeyClient, - authorize, - ]); + }, [formMetadata.tree, submissionStep, journeyClient, authorize]); /** * @function redirect - Redirects the user to the specified URL in the step diff --git a/javascript/reactjs-todo-journey/client/constants.js b/javascript/reactjs-todo-journey/client/constants.js index ffefd66f..c977b22b 100755 --- a/javascript/reactjs-todo-journey/client/constants.js +++ b/javascript/reactjs-todo-journey/client/constants.js @@ -13,32 +13,29 @@ export const API_URL = import.meta.env.VITE_API_URL; export const DEBUGGER = import.meta.env.VITE_DEBUGGER_OFF === 'false'; export const JOURNEY_LOGIN = import.meta.env.VITE_JOURNEY_LOGIN; export const JOURNEY_REGISTER = import.meta.env.VITE_JOURNEY_REGISTER; -export const WEB_OAUTH_CLIENT = import.meta.env.VITE_WEB_OAUTH_CLIENT; -export const SCOPE = import.meta.env.VITE_SCOPE; -export const WELLKNOWN_URL = import.meta.env.VITE_WELLKNOWN_URL; export const INIT_PROTECT = import.meta.env.VITE_INIT_PROTECT; export const PINGONE_ENV_ID = import.meta.env.VITE_PINGONE_ENV_ID; - /** *************************************************************************** * SDK INTEGRATION POINT * Summary: Configure the SDK * ---------------------------------------------------------------------------- - * Details: Below, you will see the following settings which can be used to - * configure both the OIDC and Journey clients: - * - clientId: (OAuth 2.0 only) this is the OAuth 2.0 client you created in Ping, - * such as `PingSDKClient` - * - redirectUri: (OAuth 2.0 only) this is the URI/URL of this app to which the - * OAuth 2.0 flow redirects - * - scope: (OAuth 2.0 only) these are the OAuth scopes that you will request from - * Ping - * - serverConfig: this includes the wellknown URL of your Ping client - * - realmPath: this is the realm to use within Ping, such as `alpha` or `root` + * Details: CONFIG uses the unified SDK configuration schema. Pass it to + * `makeOidcConfig(CONFIG)` or `makeJourneyConfig(CONFIG)` from + * `@forgerock/sdk-utilities` before calling the respective factory. + * + * Local dev: copy config.example.json → config.json and fill in your values. + * E2e / CI: set VITE_SDK_CONFIG to a JSON string (e.g. from config.test.json). *************************************************************************** */ +import sdkConfigJson from '../config.json'; + +const rawConfig = import.meta.env.VITE_SDK_CONFIG + ? JSON.parse(import.meta.env.VITE_SDK_CONFIG) + : sdkConfigJson; + export const CONFIG = { - clientId: WEB_OAUTH_CLIENT, - redirectUri: `${window.location.origin}/callback.html`, - scope: SCOPE, - serverConfig: { - wellknown: WELLKNOWN_URL, + ...rawConfig, + oidc: { + ...rawConfig.oidc, + redirectUri: `${window.location.origin}/callback.html`, }, }; diff --git a/javascript/reactjs-todo-journey/client/context/oidc.context.js b/javascript/reactjs-todo-journey/client/context/oidc.context.js index 25839338..ede9b76a 100644 --- a/javascript/reactjs-todo-journey/client/context/oidc.context.js +++ b/javascript/reactjs-todo-journey/client/context/oidc.context.js @@ -10,6 +10,7 @@ import { useState, createContext, useEffect } from 'react'; import { oidc } from '@forgerock/oidc-client'; +import { makeOidcConfig } from '@forgerock/sdk-utilities'; import { DEBUGGER } from '../constants'; const email = window.sessionStorage.getItem('sdk_email'); @@ -19,7 +20,7 @@ const username = window.sessionStorage.getItem('sdk_username'); * @function useInitOidcState - A custom hook to get initial OIDC state for managing user authentication * @returns {Array} - OIDC client, state values and state methods */ -export function useInitOidcState(config) { +export function useInitOidcState(json) { /** * Create state properties for "global" OIDC state. * The destructing of the hook's array results in index 0 having the state values, @@ -44,7 +45,7 @@ export function useInitOidcState(config) { * but it can be done outside of the React component for better performance. ************************************************************************* */ if (DEBUGGER) debugger; - let client = await oidc({ config }); + let client = await oidc({ config: makeOidcConfig(json) }); if ('error' in client) { console.error(`Error initializing OIDC client: ${client.error}`); client = null; @@ -59,7 +60,7 @@ export function useInitOidcState(config) { if (!oidcClient) { initOidcClient(); } - }, [config, oidcClient]); + }, [json, oidcClient]); /** * @function setAuthenticationWrapper - A wrapper for storing authentication state diff --git a/javascript/reactjs-todo-journey/config.example.json b/javascript/reactjs-todo-journey/config.example.json new file mode 100644 index 00000000..dae21d05 --- /dev/null +++ b/javascript/reactjs-todo-journey/config.example.json @@ -0,0 +1,7 @@ +{ + "oidc": { + "clientId": "", + "discoveryEndpoint": "https:///.well-known/openid-configuration", + "scopes": ["openid", "profile", "email"] + } +} diff --git a/javascript/reactjs-todo-journey/config.test.json b/javascript/reactjs-todo-journey/config.test.json new file mode 100644 index 00000000..a3eb4dba --- /dev/null +++ b/javascript/reactjs-todo-journey/config.test.json @@ -0,0 +1,8 @@ +{ + "oidc": { + "clientId": "WebOAuthClient", + "discoveryEndpoint": "https://openam-sdks.forgeblocks.com/am/oauth2/alpha/.well-known/openid-configuration", + "scopes": ["openid", "profile", "email"], + "redirectUri": "http://localhost:8443/callback.html" + } +} diff --git a/javascript/reactjs-todo-journey/e2e/embedded-login.spec.js b/javascript/reactjs-todo-journey/e2e/embedded-login.spec.js index 2397969a..9f17e97f 100644 --- a/javascript/reactjs-todo-journey/e2e/embedded-login.spec.js +++ b/javascript/reactjs-todo-journey/e2e/embedded-login.spec.js @@ -11,6 +11,14 @@ import { test, expect } from '@playwright/test'; import { password, username, displayName } from './utils/demo-user'; +test.afterEach(async ({ page, context }) => { + await page.evaluate(() => { + localStorage.clear(); + sessionStorage.clear(); + }); + await context.clearCookies(); +}); + test('React Journey - Login with embedded login', async ({ page }) => { await page.goto('http://localhost:8443/'); await page.getByRole('link', { name: 'Sign In', exact: true }).click(); diff --git a/javascript/reactjs-todo-journey/package.json b/javascript/reactjs-todo-journey/package.json index 644cdf67..c0e4094b 100644 --- a/javascript/reactjs-todo-journey/package.json +++ b/javascript/reactjs-todo-journey/package.json @@ -23,6 +23,7 @@ "@forgerock/journey-client": "latest", "@forgerock/oidc-client": "latest", "@forgerock/protect": "latest", + "@forgerock/sdk-utilities": "latest", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.19.0" diff --git a/javascript/reactjs-todo-journey/playwright.config.js b/javascript/reactjs-todo-journey/playwright.config.js index 42875447..b6229e44 100644 --- a/javascript/reactjs-todo-journey/playwright.config.js +++ b/javascript/reactjs-todo-journey/playwright.config.js @@ -10,6 +10,10 @@ import { defineConfig, devices } from '@playwright/test'; import * as dotenv from 'dotenv'; +import { createRequire } from 'module'; + +const require = createRequire(import.meta.url); +const testConfig = require('./config.test.json'); // Load environment variables from .env file dotenv.config({ path: '.env' }); @@ -42,11 +46,8 @@ export default defineConfig({ VITE_JOURNEY_LOGIN: 'Login', VITE_JOURNEY_REGISTER: 'Registration', VITE_PORT: '8443', - VITE_WELLKNOWN_URL: - 'https://openam-sdks.forgeblocks.com/am/oauth2/alpha/.well-known/openid-configuration', - VITE_SCOPE: 'profile openid email', - VITE_WEB_OAUTH_CLIENT: 'WebOAuthClient', VITE_PINGONE_ENV_ID: '02fb4743-189a-4bc7-9d6c-a919edfe6447', + VITE_SDK_CONFIG: JSON.stringify(testConfig), }, ignoreHTTPSErrors: true, }, diff --git a/javascript/reactjs-todo-journey/vite.config.js b/javascript/reactjs-todo-journey/vite.config.js index dc6e2562..959b2729 100644 --- a/javascript/reactjs-todo-journey/vite.config.js +++ b/javascript/reactjs-todo-journey/vite.config.js @@ -1,5 +1,22 @@ import { defineConfig, loadEnv } from 'vite'; import react from '@vitejs/plugin-react'; +import { existsSync } from 'fs'; + +function optionalConfigJson(configPath) { + return { + name: 'optional-config-json', + resolveId(id) { + if (id.endsWith('config.json') && !existsSync(configPath)) { + return '\0virtual:empty-config'; + } + }, + load(id) { + if (id === '\0virtual:empty-config') { + return 'export default {}'; + } + }, + }; +} export default defineConfig(({ mode }) => { const env = loadEnv(mode, process.cwd(), ''); @@ -24,7 +41,7 @@ export default defineConfig(({ mode }) => { open: true, strictPort: true, }, - plugins: [react()], + plugins: [react(), optionalConfigJson(new URL('./config.json', import.meta.url).pathname)], css: { preprocessorOptions: { scss: { diff --git a/javascript/reactjs-todo-oidc/.env.example b/javascript/reactjs-todo-oidc/.env.example index 3aaf07cc..c3961e42 100644 --- a/javascript/reactjs-todo-oidc/.env.example +++ b/javascript/reactjs-todo-oidc/.env.example @@ -1,9 +1,13 @@ -WEB_OAUTH_CLIENT= -WELLKNOWN_URL= -SCOPE= -#SERVER - 'PINGAM' or 'PINGONE' -SERVER= API_URL=http://localhost:9443 -PORT=8443 DEBUGGER_OFF=true DEVELOPMENT=true +PORT=8443 +#SERVER - 'PINGAM' or 'PINGONE' +SERVER= + +# SDK configuration (clientId, discoveryEndpoint, scopes, redirectUri) is no +# longer sourced from environment variables. Copy config.example.json to +# config.json and fill in your values. + +# REST_OAUTH_CLIENT and REST_OAUTH_SECRET are used by the todo-api test server +# during e2e runs — inject them via CI secrets, not this file. diff --git a/javascript/reactjs-todo-oidc/.gitignore b/javascript/reactjs-todo-oidc/.gitignore index f8048ca1..1c6f218a 100644 --- a/javascript/reactjs-todo-oidc/.gitignore +++ b/javascript/reactjs-todo-oidc/.gitignore @@ -1,4 +1,5 @@ node_modules/ +config.json /test-results/ /playwright-report/ /blob-report/ diff --git a/javascript/reactjs-todo-oidc/README.md b/javascript/reactjs-todo-oidc/README.md index bda023ce..91bcc9bf 100644 --- a/javascript/reactjs-todo-oidc/README.md +++ b/javascript/reactjs-todo-oidc/README.md @@ -51,21 +51,38 @@ Choose to set up either a PingOne or PingAM/PingAIC instance 1. openid profile email phone name revoke -### Configure Your `.env` File +### Configure SDK Credentials + +Copy `config.example.json` to `config.json` at the app root and fill in your values: + +```sh +cp config.example.json config.json +``` + +`config.json` (gitignored): + +```json +{ + "oidc": { + "clientId": "", + "discoveryEndpoint": "https:///.well-known/openid-configuration", + "scopes": ["openid", "profile", "email"], + "redirectUri": "https://localhost:8443/callback.html" + } +} +``` -Change the name of `.env.example` to `.env` and replace the bracketed values (e.g. `<<>>`) with your values. +### Configure Your `.env` File -Example with annotations: +Change the name of `.env.example` to `.env` and set the remaining runtime values: ```text -WEB_OAUTH_CLIENT=<<>> -SCOPE="openid profile email" -WELLKNOWN_URL=<<>> -SERVER=PINGAM API_URL=http://localhost:9443 -PORT=8443 DEBUGGER_OFF=true DEVELOPMENT=true +PORT=8443 +#SERVER - 'PINGAM' or 'PINGONE' +SERVER=PINGAM ``` ### Installing Dependencies and Run Build diff --git a/javascript/reactjs-todo-oidc/client/README.md b/javascript/reactjs-todo-oidc/client/README.md index dcae25d6..3c6999de 100644 --- a/javascript/reactjs-todo-oidc/client/README.md +++ b/javascript/reactjs-todo-oidc/client/README.md @@ -12,22 +12,43 @@ This folder contains the React client for `reactjs-todo-oidc`, which demonstrate ## Runtime configuration -Copy `.env.example` to `.env` at `javascript/reactjs-todo-oidc/.env`, then set values for your environment: +### SDK credentials + +Copy `config.example.json` to `config.json` at `javascript/reactjs-todo-oidc/config.json` and fill in your values: + +```sh +cp config.example.json config.json +``` + +```json +{ + "oidc": { + "clientId": "", + "discoveryEndpoint": "https:///.well-known/openid-configuration", + "scopes": ["openid", "profile", "email"], + "redirectUri": "https://localhost:8443/callback.html" + } +} +``` + +`config.json` is gitignored. + +### Runtime env vars + +Copy `.env.example` to `.env` at `javascript/reactjs-todo-oidc/.env`: ```text -WELLKNOWN_URL=<<>> -WEB_OAUTH_CLIENT=<<>> -SCOPE="openid profile email" API_URL=http://localhost:9443 DEBUGGER_OFF=true +DEVELOPMENT=true +PORT=8443 +#SERVER - 'PINGAM' or 'PINGONE' SERVER=PINGAM ``` Notes: -- `WELLKNOWN_URL` is the source of truth for OIDC discovery in this sample. -- `SCOPE` should include `openid` so logout and userinfo flows have the expected token set. -- `SERVER` is used to derive the user name from either PingAM or PingOne +- `SERVER` is used to derive the display name from either PingAM or PingOne token claims. ## Running locally diff --git a/javascript/reactjs-todo-oidc/client/constants.js b/javascript/reactjs-todo-oidc/client/constants.js index 82920861..c8378d1f 100755 --- a/javascript/reactjs-todo-oidc/client/constants.js +++ b/javascript/reactjs-todo-oidc/client/constants.js @@ -8,19 +8,29 @@ * of the MIT license. See the LICENSE file for details. */ +/** *************************************************************************** + * SDK INTEGRATION POINT + * Summary: Configure the OIDC client + * ---------------------------------------------------------------------------- + * Details: CONFIG uses the unified SDK configuration schema. Pass it to + * `makeOidcConfig(CONFIG)` from `@forgerock/sdk-utilities` before calling + * the factory — e.g. `oidc({ config: makeOidcConfig(CONFIG) })`. + * + * Local dev: copy config.example.json → config.json and fill in your values. + * E2e / CI: set SDK_CONFIG to a JSON string (e.g. from config.test.*.json). + *************************************************************************** */ +import sdkConfigJson from '../config.json'; export const API_URL = process.env.API_URL; // Yes, the debugger boolean is intentionally reversed export const DEBUGGER = process.env.DEBUGGER_OFF === 'false'; -export const WEB_OAUTH_CLIENT = process.env.WEB_OAUTH_CLIENT; -export const SCOPE = process.env.SCOPE; -export const WELLKNOWN_URL = process.env.WELLKNOWN_URL; export const SERVER = process.env.SERVER; +const rawConfig = process.env.SDK_CONFIG ? JSON.parse(process.env.SDK_CONFIG) : sdkConfigJson; + export const CONFIG = { - clientId: WEB_OAUTH_CLIENT, - redirectUri: `${window.location.origin}/callback.html`, - scope: SCOPE, - serverConfig: { - wellknown: WELLKNOWN_URL, + ...rawConfig, + oidc: { + ...rawConfig.oidc, + redirectUri: `${window.location.origin}/callback.html`, }, }; diff --git a/javascript/reactjs-todo-oidc/client/context/oidc.context.js b/javascript/reactjs-todo-oidc/client/context/oidc.context.js index 47be4afe..b33c2705 100644 --- a/javascript/reactjs-todo-oidc/client/context/oidc.context.js +++ b/javascript/reactjs-todo-oidc/client/context/oidc.context.js @@ -9,6 +9,7 @@ */ import { useEffect, useState, createContext } from 'react'; import { oidc } from '@forgerock/oidc-client'; +import { makeOidcConfig } from '@forgerock/sdk-utilities'; import { CONFIG, DEBUGGER } from '../constants'; const email = window.sessionStorage.getItem('sdk_email'); @@ -38,7 +39,7 @@ export function useInitOidcState() { * but it can be done outside of the React component for better performance. ************************************************************************* */ if (DEBUGGER) debugger; - let client = await oidc({ config: CONFIG }); + let client = await oidc({ config: makeOidcConfig(CONFIG) }); if ('error' in client) { console.error(`Error initializing OIDC client: ${client.error}`); client = null; diff --git a/javascript/reactjs-todo-oidc/config.example.json b/javascript/reactjs-todo-oidc/config.example.json new file mode 100644 index 00000000..dae21d05 --- /dev/null +++ b/javascript/reactjs-todo-oidc/config.example.json @@ -0,0 +1,7 @@ +{ + "oidc": { + "clientId": "", + "discoveryEndpoint": "https:///.well-known/openid-configuration", + "scopes": ["openid", "profile", "email"] + } +} diff --git a/javascript/reactjs-todo-oidc/config.test.pingam.json b/javascript/reactjs-todo-oidc/config.test.pingam.json new file mode 100644 index 00000000..bb203cb6 --- /dev/null +++ b/javascript/reactjs-todo-oidc/config.test.pingam.json @@ -0,0 +1,8 @@ +{ + "oidc": { + "clientId": "CentralLoginOAuthClient-", + "discoveryEndpoint": "https://openam-sdks.forgeblocks.com/am/oauth2/alpha/.well-known/openid-configuration", + "scopes": ["openid", "profile", "me.read", "email"], + "redirectUri": "https://localhost:8443/callback.html" + } +} diff --git a/javascript/reactjs-todo-oidc/config.test.pingone.json b/javascript/reactjs-todo-oidc/config.test.pingone.json new file mode 100644 index 00000000..971ae3f2 --- /dev/null +++ b/javascript/reactjs-todo-oidc/config.test.pingone.json @@ -0,0 +1,8 @@ +{ + "oidc": { + "clientId": "724ec718-c41c-4d51-98b0-84a583f450f9", + "discoveryEndpoint": "https://auth.pingone.ca/02fb4743-189a-4bc7-9d6c-a919edfe6447/as/.well-known/openid-configuration", + "scopes": ["openid", "profile", "email", "revoke"], + "redirectUri": "https://localhost:8444/callback.html" + } +} diff --git a/javascript/reactjs-todo-oidc/package.json b/javascript/reactjs-todo-oidc/package.json index b4cd2957..51753bc3 100644 --- a/javascript/reactjs-todo-oidc/package.json +++ b/javascript/reactjs-todo-oidc/package.json @@ -40,6 +40,7 @@ }, "dependencies": { "@forgerock/oidc-client": "latest", + "@forgerock/sdk-utilities": "latest", "cookie-parser": "^1.4.5", "cors": "^2.8.5", "dotenv": "^10.0.0", diff --git a/javascript/reactjs-todo-oidc/playwright.config.ts b/javascript/reactjs-todo-oidc/playwright.config.ts index e7186e8b..80b66353 100644 --- a/javascript/reactjs-todo-oidc/playwright.config.ts +++ b/javascript/reactjs-todo-oidc/playwright.config.ts @@ -1,7 +1,9 @@ import { defineConfig, devices } from '@playwright/test'; +import * as dotenv from 'dotenv'; +import testConfigPingam from './config.test.pingam.json'; +import testConfigPingone from './config.test.pingone.json'; const url = process.env.PLAYWRIGHT_TEST_BASE_URL || 'https://localhost:8443'; -import * as dotenv from 'dotenv'; // Load environment variables from .env file dotenv.config({ path: '.env' }); @@ -32,12 +34,9 @@ export default defineConfig({ DEVELOPMENT: 'false', PORT: '8443', SERVER: 'PINGAM', - WELLKNOWN_URL: - 'https://openam-sdks.forgeblocks.com/am/oauth2/alpha/.well-known/openid-configuration', - SCOPE: 'openid profile me.read email', - WEB_OAUTH_CLIENT: 'CentralLoginOAuthClient-', REST_OAUTH_CLIENT: 'RestOAuthClient', REST_OAUTH_SECRET: process.env.REST_OAUTH_SECRET || '', + SDK_CONFIG: JSON.stringify(testConfigPingam), }, ignoreHTTPSErrors: true, }, @@ -53,11 +52,8 @@ export default defineConfig({ DEVELOPMENT: 'false', PORT: '8444', SERVER: 'PINGONE', - WELLKNOWN_URL: - 'https://auth.pingone.ca/02fb4743-189a-4bc7-9d6c-a919edfe6447/as/.well-known/openid-configuration', - SCOPE: 'openid profile email revoke', - WEB_OAUTH_CLIENT: '724ec718-c41c-4d51-98b0-84a583f450f9', REST_OAUTH_CLIENT: '724ec718-c41c-4d51-98b0-84a583f450f9', + SDK_CONFIG: JSON.stringify(testConfigPingone), }, ignoreHTTPSErrors: true, }, diff --git a/javascript/reactjs-todo-oidc/webpack.config.js b/javascript/reactjs-todo-oidc/webpack.config.js index 50ed7fda..69e0b5ad 100644 --- a/javascript/reactjs-todo-oidc/webpack.config.js +++ b/javascript/reactjs-todo-oidc/webpack.config.js @@ -9,6 +9,7 @@ */ const dotenv = require('dotenv'); +const fs = require('fs'); const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const webpack = require('webpack'); @@ -22,10 +23,8 @@ module.exports = () => { const API_URL = process.env.API_URL || localEnv.API_URL; const DEBUGGER_OFF = process.env.DEBUGGER_OFF || localEnv.DEBUGGER_OFF; const DEVELOPMENT = process.env.DEVELOPMENT || localEnv.DEVELOPMENT; - const WEB_OAUTH_CLIENT = process.env.WEB_OAUTH_CLIENT || localEnv.WEB_OAUTH_CLIENT; - const SCOPE = process.env.SCOPE || localEnv.SCOPE; - const WELLKNOWN_URL = process.env.WELLKNOWN_URL || localEnv.WELLKNOWN_URL; const SERVER = process.env.SERVER || localEnv.SERVER; + const SDK_CONFIG = process.env.SDK_CONFIG || null; return { // Point to the top level source file @@ -108,14 +107,17 @@ module.exports = () => { }, plugins: [ new MiniCssExtractPlugin(), + new webpack.NormalModuleReplacementPlugin(/config\.json$/, (resource) => { + if (!fs.existsSync(path.resolve(__dirname, 'config.json'))) { + resource.request = resource.request.replace('config.json', 'config.example.json'); + } + }), new webpack.DefinePlugin({ // Inject all the environment variable into the Webpack build 'process.env.API_URL': JSON.stringify(API_URL), 'process.env.DEBUGGER_OFF': JSON.stringify(DEBUGGER_OFF), - 'process.env.WEB_OAUTH_CLIENT': JSON.stringify(WEB_OAUTH_CLIENT), - 'process.env.SCOPE': JSON.stringify(SCOPE), - 'process.env.WELLKNOWN_URL': JSON.stringify(WELLKNOWN_URL), 'process.env.SERVER': JSON.stringify(SERVER), + 'process.env.SDK_CONFIG': JSON.stringify(SDK_CONFIG), }), ], }; diff --git a/package-lock.json b/package-lock.json index f536283c..81c4602a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -658,6 +658,7 @@ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.14.tgz", "integrity": "sha512-Kp/MWShoYYO+R3lrrZbZgszbbLGVXHB+39mdJZwnIuZMDkeL3JsIBlSOzyJRTnpS1vITc+9jgHvP/6uKbMrW1Q==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -866,6 +867,7 @@ "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.14.tgz", "integrity": "sha512-ZPRswzaVRiqcfZoowuAM22Hr2/z10ajWOUoFDoQ9tWqz/fH/773kJv2F9VvePIekgNPCzaizqv9gF6tGNqaAwg==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -882,6 +884,7 @@ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.14.tgz", "integrity": "sha512-Mpq3v/mztQzGAQAAFV+wAI1hlXxZ0m8eDBgaN2kD3Ue+r4S6bLm1Vlryw0iyUnt05PcFIdxPT6xkcphq5pl6lw==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -903,6 +906,7 @@ "integrity": "sha512-BmmjyrFSBSYkm0tBSqpu4cwnJX/b/XvhM36mj2k8jah3tNS5zLDDx5w6tyHmaPJa/1D95MlXx2h6u7K9D+Mhew==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "7.25.2", "@jridgewell/sourcemap-codec": "^1.4.14", @@ -995,6 +999,7 @@ "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.14.tgz", "integrity": "sha512-BIPrCs93ZZTY9ym7yfoTgAQ5rs706yoYeAdrgc8kh/bDbM9DawxKlgeKBx2FLt09Y0YQ1bFhKVp0cV4gDEaMxQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -1029,6 +1034,7 @@ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.14.tgz", "integrity": "sha512-W+JTxI25su3RiZVZT3Yrw6KNUCmOIy7OZIZ+612skPgYK2f2qil7VclnW1oCwG896h50cMJU/lnAfxZxefQgyQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -1088,6 +1094,7 @@ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -1307,6 +1314,7 @@ "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -1336,6 +1344,7 @@ "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -1350,6 +1359,7 @@ "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "7.18.0", @@ -1583,6 +1593,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.1", @@ -1719,6 +1730,7 @@ "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", @@ -1849,6 +1861,7 @@ "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2149,6 +2162,7 @@ "integrity": "sha512-1F8M7nWfChzurb7obbvuE7mJXlHtY1UG58pcwcomVtpPb+kPavgAO8OEvJHYBMV+bzSxkXt5UIwL9lt9jHUxZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "7.23.9", "@jridgewell/sourcemap-codec": "^1.4.14", @@ -2226,6 +2240,7 @@ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -2447,6 +2462,7 @@ "integrity": "sha512-fs2XOhWCzRhqMmQf0eicLa/CWSaYss2feXsy7xBD/pLyWke/jCIVc2s1ikEAtSW7ina1HNhv7kONoEfVNEcdDQ==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "6.13.1", "@typescript-eslint/types": "6.13.1", @@ -3044,6 +3060,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", @@ -3108,6 +3125,7 @@ "integrity": "sha512-wovtnV2PxzteLlfNzbgm1tFXPLoZILYAMJtvoXXkD7/+1uP41eKkIt1ypWq5/q2uT94qHjXehEYfmjKOvjL9sg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -3231,6 +3249,7 @@ "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3259,6 +3278,7 @@ "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", @@ -3335,6 +3355,7 @@ "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -3434,6 +3455,7 @@ "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -4055,6 +4077,7 @@ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -4124,6 +4147,7 @@ "@forgerock/davinci-client": "latest", "@forgerock/oidc-client": "latest", "@forgerock/protect": "latest", + "@forgerock/sdk-utilities": "latest", "cookie-parser": "^1.4.5", "cors": "^2.8.5", "dotenv": "^10.0.0", @@ -4211,6 +4235,7 @@ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -4228,6 +4253,7 @@ "@forgerock/journey-client": "latest", "@forgerock/oidc-client": "latest", "@forgerock/protect": "latest", + "@forgerock/sdk-utilities": "latest", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.19.0" @@ -4326,6 +4352,7 @@ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4657,6 +4684,7 @@ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -4672,6 +4700,7 @@ "license": "ISC", "dependencies": { "@forgerock/oidc-client": "latest", + "@forgerock/sdk-utilities": "latest", "cookie-parser": "^1.4.5", "cors": "^2.8.5", "dotenv": "^10.0.0", @@ -4759,6 +4788,7 @@ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -5860,6 +5890,7 @@ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-17.3.12.tgz", "integrity": "sha512-9hsdWF4gRRcVJtPcCcYLaX1CIyM9wUu6r+xRl6zU5hq8qhl35hig6ounz7CXFAzLf0WDBdM16bPHouVGaG76lg==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -5876,6 +5907,7 @@ "integrity": "sha512-FgOvf9q5d23Cpa7cjP1FYti/v8S1FTm8DEkW3TY8lkkoxh3isu28GFKcLD1p/XF3yqfPkPVHToOFla5QwsEgBQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@angular-devkit/architect": "0.1703.17", "@angular-devkit/core": "17.3.17", @@ -6245,6 +6277,7 @@ "resolved": "https://registry.npmjs.org/@angular/common/-/common-17.3.12.tgz", "integrity": "sha512-vabJzvrx76XXFrm1RJZ6o/CyG32piTB/1sfFfKHdlH1QrmArb8It4gyk9oEjZ1IkAD0HvBWlfWmn+T6Vx3pdUw==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -6261,6 +6294,7 @@ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-17.3.12.tgz", "integrity": "sha512-vwI8oOL/gM+wPnptOVeBbMfZYwzRxQsovojZf+Zol9szl0k3SZ3FycWlxxXZGFu3VIEfrP6pXplTmyODS/Lt1w==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -6281,6 +6315,7 @@ "resolved": "https://registry.npmjs.org/@angular/core/-/core-17.3.12.tgz", "integrity": "sha512-MuFt5yKi161JmauUta4Dh0m8ofwoq6Ino+KoOtkYMBGsSx+A7dSm+DUxxNwdj7+DNyg3LjVGCFgBFnq4g8z06A==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -6315,6 +6350,7 @@ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.12.tgz", "integrity": "sha512-DYY04ptWh/ulMHzd+y52WCE8QnEYGeIiW3hEIFjCN8z0kbIdFdUtEB0IK5vjNL3ejyhUmphcpeT5PYf3YXtqWQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -6446,6 +6482,7 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -9529,6 +9566,7 @@ "integrity": "sha512-b2BudQY/Si4Y2a0PdZZL6BeJtl8llgeZa7U2j47aaJSCeAl1e4UI7y8a9bSkO3o/ZbZrgT5muy/34JbsjfIWxA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@inquirer/checkbox": "^2.4.7", "@inquirer/confirm": "^3.1.22", @@ -11604,17 +11642,6 @@ "node": ">=18" } }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "license": "MIT", - "peer": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, "node_modules/@reduxjs/toolkit": { "version": "2.11.2", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz", @@ -12200,6 +12227,7 @@ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -12229,6 +12257,7 @@ "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -12637,6 +12666,7 @@ "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0", @@ -13298,6 +13328,7 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -13936,6 +13967,7 @@ "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -14375,6 +14407,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -14691,6 +14724,7 @@ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -15700,6 +15734,7 @@ "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -17265,6 +17300,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -17337,6 +17373,7 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -17455,6 +17492,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -17565,6 +17603,7 @@ "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "builtins": "^5.0.1", @@ -17688,6 +17727,7 @@ "integrity": "sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==", "dev": true, "license": "ISC", + "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -19497,6 +19537,7 @@ "integrity": "sha512-md+vXtdCAe60s1k6AU3dUyMJnDxUyQAwfwPKoLisvgUF1IXjtlLsk2se54+qfL9Mdm26bbwvjJybpNx48NKRLw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/html-minifier-terser": "^6.0.0", "html-minifier-terser": "^6.0.2", @@ -20845,7 +20886,8 @@ "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.1.2.tgz", "integrity": "sha512-2oIUMGn00FdUiqz6epiiJr7xcFyNYj3rDcfmnzfkBnHyBQ3cBQUs4mmyGsOb7TTLb9kxk7dBcmEmqhDKkBoDyA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/jest-diff": { "version": "29.7.0", @@ -21071,6 +21113,7 @@ "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@colors/colors": "1.5.0", "body-parser": "^1.19.0", @@ -21709,6 +21752,7 @@ "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "copy-anything": "^2.0.1", "parse-node-version": "^1.0.1", @@ -23385,6 +23429,7 @@ "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -24494,6 +24539,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "@nrwl/tao": "17.1.3", "@yarnpkg/lockfile": "^1.1.0", @@ -25602,6 +25648,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -25820,6 +25867,7 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -26151,6 +26199,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -26163,6 +26212,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -26447,7 +26497,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -27059,6 +27110,7 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", + "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -28563,6 +28615,7 @@ "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -29149,7 +29202,8 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "license": "0BSD", + "peer": true }, "node_modules/tsscmp": { "version": "1.0.6", @@ -29326,6 +29380,7 @@ "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -29647,6 +29702,7 @@ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -30210,6 +30266,7 @@ "integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -30423,6 +30480,7 @@ "integrity": "sha512-9Gyu2F7+bg4Vv+pjbovuYDhHX+mqdqITykfzdM9UyKqKHlsE5aAjRhR+oOEfXW5vBeu8tarzlJFIZva4ZjAdrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", @@ -30948,7 +31006,8 @@ "version": "0.14.10", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.10.tgz", "integrity": "sha512-YGAhaO7J5ywOXW6InXNlLmfU194F8lVgu7bRntUF3TiG8Y3nBK0x1UJJuHUP/e8IyihkjCYqhCScpSwnlaSRkQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "reactjs-todo-davinci": { "version": "1.0.0",