From 8dae377726dcb4d0ad2b29d2fb80452ab8040f48 Mon Sep 17 00:00:00 2001 From: Ryan Bas Date: Wed, 5 Aug 2026 15:36:38 -0600 Subject: [PATCH 01/11] =?UTF-8?q?build:=20migrate=20effect=20v3=20?= =?UTF-8?q?=E2=86=92=20v4=20(beta.103)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate all packages from effect@^3.20 to effect@4.0.0-beta.103. Key changes: - Replace Micro with Effect throughout oidc-client and davinci-client - Migrate Either to Result in sdk-utilities and journey-client - Migrate MicroExit/exitIsFail/exitIsSuccess to Exit/Cause API - Update e2e/mock-api-v2 from @effect/platform to effect/unstable/httpapi - Bump vitest catalog to ^4.1.0 to match @effect/vitest peer requirement - Remove consolidated packages: @effect/platform, @effect/cli - Fix handleMicroExit → handleExit (renamed) - Add vi.clearAllMocks() to oidc-client afterEach (accumulated mock counts) --- e2e/mock-api-v2/package.json | 3 +- .../src/handlers/authorize.handler.ts | 5 +- .../src/handlers/capabilities.handler.ts | 15 +- .../src/handlers/end-session.handler.ts | 3 +- .../src/handlers/healthcheck.handler.ts | 2 +- .../handlers/open-id-configuration.handler.ts | 6 +- .../src/handlers/revoke.handler.ts | 2 +- e2e/mock-api-v2/src/handlers/token.handler.ts | 2 +- .../src/handlers/userinfo.handler.ts | 2 +- e2e/mock-api-v2/src/helpers/match.ts | 12 +- e2e/mock-api-v2/src/main.ts | 82 +- .../src/middleware/Authorization.ts | 33 +- .../src/middleware/CookieMiddleware.ts | 95 +- e2e/mock-api-v2/src/middleware/Session.ts | 58 +- .../src/schemas/authorize.schema.ts | 3 +- .../capabilities.request.schema.ts | 2 +- .../capabilities.response.schema.ts | 2 +- .../open-id-configuration-response.schema.ts | 6 +- ...return-success-response-redirect.schema.ts | 3 +- .../src/schemas/revoke/revoke.schema.ts | 2 +- .../src/schemas/token/token.schema.ts | 6 +- .../src/services/mock-env-helpers/index.ts | 37 +- .../src/services/session.service.ts | 176 +-- .../src/services/tokens.service.ts | 49 +- .../src/services/userinfo.service.ts | 29 +- e2e/mock-api-v2/src/spec.ts | 132 +- package.json | 3 +- .../src/lib/client.store.effects.test.ts | 20 +- .../src/lib/client.store.effects.ts | 104 +- .../davinci-client/src/lib/client.store.ts | 22 +- packages/davinci-client/src/lib/fido/fido.ts | 67 +- .../src/lib/password-policy.rules.ts | 6 +- .../journey-client/src/lib/client.store.ts | 14 +- .../src/lib/journey.utils.test.ts | 40 +- .../journey-client/src/lib/journey.utils.ts | 14 +- .../src/lib/authorize.request.micros.test.ts | 184 +-- .../src/lib/authorize.request.micros.ts | 70 +- .../oidc-client/src/lib/authorize.request.ts | 48 +- .../src/lib/authorize.request.utils.test.ts | 84 +- packages/oidc-client/src/lib/client.store.ts | 192 +-- .../oidc-client/src/lib/exchange.request.ts | 26 +- .../src/lib/exchange.utils.test.ts | 73 +- .../oidc-client/src/lib/exchange.utils.ts | 16 +- .../src/lib/logout.request.test.ts | 158 +-- .../oidc-client/src/lib/logout.request.ts | 22 +- .../src/lib/session.micros.test.ts | 336 +++-- .../oidc-client/src/lib/session.micros.ts | 66 +- .../src/lib/config/config.effects.ts | 16 +- .../src/lib/config/config.test.ts | 140 +- .../src/lib/config/config.types.ts | 8 +- .../src/lib/config/config.utils.ts | 119 +- packages/sdk-utilities/src/lib/micro.utils.ts | 26 +- pnpm-lock.yaml | 1173 ++++++----------- pnpm-workspace.yaml | 19 +- tools/release/package.json | 1 - tools/user-scripts/package.json | 1 - 56 files changed, 1799 insertions(+), 2036 deletions(-) diff --git a/e2e/mock-api-v2/package.json b/e2e/mock-api-v2/package.json index 452ad8836e..5ef1d06efa 100644 --- a/e2e/mock-api-v2/package.json +++ b/e2e/mock-api-v2/package.json @@ -6,7 +6,7 @@ "type": "module", "main": "./src/main.js", "scripts": { - "build": "pnpm nx nxBuild", + "build": "pnpm nx build", "dev": "node dist/src/main.js --watch-path=./", "lint": "pnpm nx nxLint", "serve": "node dist/src/main.js", @@ -15,7 +15,6 @@ "dependencies": { "@effect/language-service": "catalog:effect", "@effect/opentelemetry": "catalog:effect", - "@effect/platform": "catalog:effect", "@effect/platform-node": "catalog:effect", "@opentelemetry/sdk-logs": "0.207.0", "@opentelemetry/sdk-metrics": "2.2.0", diff --git a/e2e/mock-api-v2/src/handlers/authorize.handler.ts b/e2e/mock-api-v2/src/handlers/authorize.handler.ts index c636c9e762..10572db05e 100644 --- a/e2e/mock-api-v2/src/handlers/authorize.handler.ts +++ b/e2e/mock-api-v2/src/handlers/authorize.handler.ts @@ -6,11 +6,12 @@ */ import { Effect, pipe } from 'effect'; import { MockApi } from '../spec.js'; -import { HttpApiBuilder, HttpApiError, HttpServerResponse } from '@effect/platform'; +import { HttpApiBuilder, HttpApiError } from 'effect/unstable/httpapi'; +import * as HttpServerResponse from 'effect/unstable/http/HttpServerResponse'; import { getFirstElementAndRespond } from '../services/mock-env-helpers/index.js'; const AuthorizeHandlerMock = HttpApiBuilder.group(MockApi, 'Authorization', (handlers) => - handlers.handle('authorize', ({ urlParams }) => + handlers.handle('authorize', ({ query: urlParams }) => Effect.gen(function* () { const acr_value = urlParams?.acr_values ?? ''; diff --git a/e2e/mock-api-v2/src/handlers/capabilities.handler.ts b/e2e/mock-api-v2/src/handlers/capabilities.handler.ts index d82c62f3a5..2e99bd6009 100644 --- a/e2e/mock-api-v2/src/handlers/capabilities.handler.ts +++ b/e2e/mock-api-v2/src/handlers/capabilities.handler.ts @@ -6,12 +6,9 @@ */ import { Effect, pipe } from 'effect'; import { MockApi } from '../spec.js'; -import { - HttpApiBuilder, - HttpApiError, - HttpServerRequest, - HttpServerResponse, -} from '@effect/platform'; +import { HttpApiBuilder, HttpApiError } from 'effect/unstable/httpapi'; +import * as HttpServerRequest from 'effect/unstable/http/HttpServerRequest'; +import * as HttpServerResponse from 'effect/unstable/http/HttpServerResponse'; import { responseMap } from '../responses/index.js'; import { validator } from '../helpers/match.js'; import { returnSuccessResponseRedirect } from '../responses/return-success-redirect.js'; @@ -105,9 +102,9 @@ const CapabilitiesHandlerMock = HttpApiBuilder.group(MockApi, 'Capabilities', (h }, ), ), - Effect.flatMap((res) => HttpServerResponse.removeCookie(res, 'stepIndex')), - Effect.flatMap((res) => HttpServerResponse.setStatus(res, 200)), - Effect.flatMap((res) => + Effect.map((res) => HttpServerResponse.removeCookie(res, 'stepIndex')), + Effect.map((res) => HttpServerResponse.setStatus(res, 200)), + Effect.map((res) => HttpServerResponse.setHeader(res, 'Content-Type', 'application/json'), ), Effect.catchTag('CookieError', () => Effect.fail(new HttpApiError.InternalServerError())), diff --git a/e2e/mock-api-v2/src/handlers/end-session.handler.ts b/e2e/mock-api-v2/src/handlers/end-session.handler.ts index c25219e38b..1ca95a8139 100644 --- a/e2e/mock-api-v2/src/handlers/end-session.handler.ts +++ b/e2e/mock-api-v2/src/handlers/end-session.handler.ts @@ -5,7 +5,8 @@ * of the MIT license. See the LICENSE file for details. */ import { Effect, Console } from 'effect'; -import { HttpApiBuilder, HttpServerRequest } from '@effect/platform'; +import { HttpApiBuilder } from 'effect/unstable/httpapi'; +import * as HttpServerRequest from 'effect/unstable/http/HttpServerRequest'; import { MockApi } from '../spec.js'; import { SessionStorage } from '../services/session.service.js'; diff --git a/e2e/mock-api-v2/src/handlers/healthcheck.handler.ts b/e2e/mock-api-v2/src/handlers/healthcheck.handler.ts index fd9a27ce26..e40d5df7fb 100644 --- a/e2e/mock-api-v2/src/handlers/healthcheck.handler.ts +++ b/e2e/mock-api-v2/src/handlers/healthcheck.handler.ts @@ -1,4 +1,4 @@ -import { HttpApiBuilder } from '@effect/platform'; +import { HttpApiBuilder } from 'effect/unstable/httpapi'; import { MockApi } from '../spec.js'; import { Effect } from 'effect'; diff --git a/e2e/mock-api-v2/src/handlers/open-id-configuration.handler.ts b/e2e/mock-api-v2/src/handlers/open-id-configuration.handler.ts index f6b4d2a76e..3b5076e43d 100644 --- a/e2e/mock-api-v2/src/handlers/open-id-configuration.handler.ts +++ b/e2e/mock-api-v2/src/handlers/open-id-configuration.handler.ts @@ -6,11 +6,11 @@ */ import { Effect } from 'effect'; import { MockApi } from '../spec.js'; -import { HttpApiBuilder } from '@effect/platform'; -import { HttpServerRequest } from '@effect/platform/HttpServerRequest'; +import { HttpApiBuilder } from 'effect/unstable/httpapi'; +import { HttpServerRequest } from 'effect/unstable/http/HttpServerRequest'; const OpenidConfigMock = HttpApiBuilder.group(MockApi, 'OpenIDConfig', (handlers) => - handlers.handle('openid', ({ path: { envid } }) => + handlers.handle('openid', ({ params: { envid } }) => Effect.gen(function* () { const request = yield* HttpServerRequest; const url = new URL(request.url); diff --git a/e2e/mock-api-v2/src/handlers/revoke.handler.ts b/e2e/mock-api-v2/src/handlers/revoke.handler.ts index b25c8da876..05b0eb43d4 100644 --- a/e2e/mock-api-v2/src/handlers/revoke.handler.ts +++ b/e2e/mock-api-v2/src/handlers/revoke.handler.ts @@ -6,7 +6,7 @@ */ import { MockApi } from '../spec.js'; import { Tokens } from '../services/tokens.service.js'; -import { HttpApiBuilder } from '@effect/platform'; +import { HttpApiBuilder } from 'effect/unstable/httpapi'; import { Effect } from 'effect'; const RevokeTokenHandler = HttpApiBuilder.group(MockApi, 'Revoke', (handlers) => diff --git a/e2e/mock-api-v2/src/handlers/token.handler.ts b/e2e/mock-api-v2/src/handlers/token.handler.ts index 5eefdd073d..a0a1007f70 100644 --- a/e2e/mock-api-v2/src/handlers/token.handler.ts +++ b/e2e/mock-api-v2/src/handlers/token.handler.ts @@ -6,7 +6,7 @@ */ import { MockApi } from '../spec.js'; import { Tokens } from '../services/tokens.service.js'; -import { HttpApiBuilder } from '@effect/platform'; +import { HttpApiBuilder } from 'effect/unstable/httpapi'; import { Effect } from 'effect'; const TokensHandler = HttpApiBuilder.group(MockApi, 'Tokens', (handlers) => diff --git a/e2e/mock-api-v2/src/handlers/userinfo.handler.ts b/e2e/mock-api-v2/src/handlers/userinfo.handler.ts index bea15715eb..b1862f7028 100644 --- a/e2e/mock-api-v2/src/handlers/userinfo.handler.ts +++ b/e2e/mock-api-v2/src/handlers/userinfo.handler.ts @@ -7,7 +7,7 @@ import { Effect } from 'effect'; import { MockApi } from '../spec.js'; import { UserInfo } from '../services/userinfo.service.js'; -import { HttpApiBuilder, HttpApiError } from '@effect/platform'; +import { HttpApiBuilder, HttpApiError } from 'effect/unstable/httpapi'; import { BearerToken } from '../middleware/Authorization.js'; const UserInfoMockHandler = HttpApiBuilder.group(MockApi, 'ProtectedRequests', (handlers) => diff --git a/e2e/mock-api-v2/src/helpers/match.ts b/e2e/mock-api-v2/src/helpers/match.ts index 511f2ffda2..e9ca41cac1 100644 --- a/e2e/mock-api-v2/src/helpers/match.ts +++ b/e2e/mock-api-v2/src/helpers/match.ts @@ -6,7 +6,7 @@ */ import { Effect, Match, Schema } from 'effect'; -import { HttpApiError } from '@effect/platform'; +import { HttpApiError } from 'effect/unstable/httpapi'; import { CapabilitiesRequestBody } from '../schemas/capabilities/capabilities.request.schema.js'; type PingRequestData = Schema.Schema.Type; @@ -21,13 +21,11 @@ const validator = Match.type().pipe( Match.when( { parameters: { data: { formData: { username: Match.string, password: Match.string } } } }, ({ parameters }) => - Effect.if( + Effect.suspend(() => parameters.data.formData.username == 'testuser' && - parameters.data.formData.password === 'Password', - { - onFalse: () => Effect.fail(new HttpApiError.Unauthorized()), - onTrue: () => Effect.succeed(true), - }, + parameters.data.formData.password === 'Password' + ? Effect.succeed(true) + : Effect.fail(new HttpApiError.Unauthorized()), ), ), Match.orElse(() => Effect.succeed(true)), diff --git a/e2e/mock-api-v2/src/main.ts b/e2e/mock-api-v2/src/main.ts index 92e2acf3ee..259e0c7b7d 100644 --- a/e2e/mock-api-v2/src/main.ts +++ b/e2e/mock-api-v2/src/main.ts @@ -4,10 +4,14 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { Layer } from 'effect'; +import { Effect, Layer } from 'effect'; import { NodeHttpServer, NodeRuntime } from '@effect/platform-node'; import { MockApi } from './spec.js'; -import { HttpApiBuilder, HttpApiSwagger, HttpMiddleware, HttpServer } from '@effect/platform'; +import { HttpApiBuilder, HttpApiSwagger } from 'effect/unstable/httpapi'; +import * as HttpMiddleware from 'effect/unstable/http/HttpMiddleware'; +import * as HttpRouter from 'effect/unstable/http/HttpRouter'; +import * as HttpServer from 'effect/unstable/http/HttpServer'; +import type { ServeError } from 'effect/unstable/http/HttpServerError'; import { createServer } from 'node:http'; import { HealthCheckLive } from './handlers/healthcheck.handler.js'; import { OpenidConfigMock } from './handlers/open-id-configuration.handler.js'; @@ -26,47 +30,63 @@ import { BatchSpanProcessor, ConsoleSpanExporter } from '@opentelemetry/sdk-trac import { EndSessionHandlerMock } from './handlers/end-session.handler.js'; import { RevokeTokenHandler } from './handlers/revoke.handler.js'; -const Services = [ - Layer.provide(TokensMock), - Layer.provide(IncrementStepIndexMock), - Layer.provide(AuthorizationMock), - Layer.provide(UserInfoMockService), - Layer.provide(SessionMiddlewareMock), - Layer.provide(SessionStorage.Default), -] as const; - const NodeSdkLive = NodeSdk.layer(() => ({ resource: { serviceName: 'Mock-Api' }, spanProcessor: new BatchSpanProcessor(new ConsoleSpanExporter()), })); -const APIMock = HttpApiBuilder.api(MockApi).pipe( - Layer.provide(HealthCheckLive), - Layer.provide(OpenidConfigMock), - Layer.provide(AuthorizeHandlerMock), - Layer.provide(TokensHandler), - Layer.provide(CapabilitiesHandlerMock), - Layer.provide(UserInfoMockHandler), - Layer.provide(EndSessionHandlerMock), - Layer.provide(RevokeTokenHandler), - ...Services, +// Wire SessionStorage into SessionMiddlewareMock +const SessionLayer = Layer.provide( + SessionMiddlewareMock, + Layer.effect(SessionStorage, SessionStorage.make), +); + +// Merge all group handlers +const HandlersLayer = Layer.mergeAll( + HealthCheckLive, + OpenidConfigMock, + AuthorizeHandlerMock, + TokensHandler, + CapabilitiesHandlerMock, + UserInfoMockHandler, + EndSessionHandlerMock, + RevokeTokenHandler, +); + +// Merge all services +const ServicesLayer = Layer.mergeAll( + TokensMock, + IncrementStepIndexMock, + AuthorizationMock, + UserInfoMockService, + SessionLayer, +); + +// Build application routes layer with all handlers and services provided in one step each +const AppLayer = HttpApiBuilder.layer(MockApi).pipe( + Layer.provide(HandlersLayer), + Layer.provide(ServicesLayer), +); + +// Compose app + swagger, then provide the router service +const AppWithSwagger = Layer.merge(AppLayer, HttpApiSwagger.layer(MockApi)).pipe( + Layer.provide(HttpRouter.layer), ); -const ServerMock = HttpApiBuilder.serve(HttpMiddleware.logger).pipe( - Layer.provide(HttpApiSwagger.layer()), - Layer.provide( - HttpApiBuilder.middlewareCors({ +const ServerMock = HttpRouter.serve(AppWithSwagger, { + middleware: (app) => + HttpMiddleware.cors({ allowedMethods: ['GET', 'PUT', 'POST', 'OPTIONS'], allowedOrigins: ['*'], credentials: true, maxAge: 3600, - }), - ), - Layer.provide(APIMock), - - Layer.provide(NodeSdkLive), + })(HttpMiddleware.logger(app)), +}).pipe( HttpServer.withLogAddress, + Layer.provide(NodeSdkLive), Layer.provide(NodeHttpServer.layer(createServer, { port: 9443, host: 'localhost' })), ); -Layer.launch(ServerMock).pipe(NodeRuntime.runMain); +// TypeScript cannot fully resolve complex Effect layer generic compositions; +// all requirements ARE satisfied at runtime — NodeHttpServer provides FileSystem, Path, HttpPlatform, Etag. +NodeRuntime.runMain(Layer.launch(ServerMock) as Effect.Effect); diff --git a/e2e/mock-api-v2/src/middleware/Authorization.ts b/e2e/mock-api-v2/src/middleware/Authorization.ts index 1cfe3d8bee..d1873e8cb1 100644 --- a/e2e/mock-api-v2/src/middleware/Authorization.ts +++ b/e2e/mock-api-v2/src/middleware/Authorization.ts @@ -1,16 +1,18 @@ -import { Unauthorized } from '@effect/platform/HttpApiError'; -import { HttpApiMiddleware, HttpApiSecurity, OpenApi } from '@effect/platform'; -import { Brand, Context, Effect, Layer, Redacted } from 'effect'; +import { HttpApiError, HttpApiMiddleware, HttpApiSecurity, OpenApi } from 'effect/unstable/httpapi'; +import type { HttpServerResponse } from 'effect/unstable/http/HttpServerResponse'; +import { Brand, Context, Effect, Layer, Redacted, Types } from 'effect'; type BearerTokenValue = string & Brand.Brand<'BearerToken'>; const BearerTokenValue = Brand.nominal(); // Define a service that holds the bearer token -class BearerToken extends Context.Tag('BearerToken')() {} +class BearerToken extends Context.Service()('BearerToken') {} -class Authorization extends HttpApiMiddleware.Tag()('Authorization', { - failure: Unauthorized, - provides: BearerToken, +class Authorization extends HttpApiMiddleware.Service< + Authorization, + { provides: typeof BearerToken } +>()('Authorization', { + error: HttpApiError.Unauthorized, security: { myBearer: HttpApiSecurity.bearer.pipe( HttpApiSecurity.annotate(OpenApi.Description, 'Bearer token for API authentication'), @@ -24,20 +26,27 @@ const AuthorizationMock = Layer.effect( yield* Effect.log('creating Authorization middleware'); return { - myBearer: (bearerToken) => + myBearer: ( + httpEffect: Effect.Effect, + { + credential, + }: { credential: Redacted.Redacted; endpoint: unknown; group: unknown }, + ) => Effect.gen(function* () { - const tokenValue = Redacted.value(bearerToken); + const tokenValue = Redacted.value(credential); yield* Effect.log('checking bearer token', tokenValue); // Validation logic // 1. Check if token is empty // 2. Check if token has been revoked (has REVOKED_ prefix) if (!tokenValue || tokenValue.trim() === '' || tokenValue.startsWith('REVOKED_')) { - return yield* Effect.fail(new Unauthorized()); + return yield* Effect.fail(new HttpApiError.Unauthorized()); } - // Return the token value so routes can access it - return BearerTokenValue(tokenValue); + // Provide BearerToken and run the original effect + return yield* httpEffect.pipe( + Effect.provideService(BearerToken, BearerTokenValue(tokenValue)), + ); }), }; }), diff --git a/e2e/mock-api-v2/src/middleware/CookieMiddleware.ts b/e2e/mock-api-v2/src/middleware/CookieMiddleware.ts index 221709d57e..579762a5c2 100644 --- a/e2e/mock-api-v2/src/middleware/CookieMiddleware.ts +++ b/e2e/mock-api-v2/src/middleware/CookieMiddleware.ts @@ -2,17 +2,14 @@ * Copyright (c) 2025 Ping Identity Corporation. * MIT License */ -import { - HttpApiMiddleware, - HttpApp, - HttpServerRequest, - HttpServerResponse, -} from '@effect/platform'; -import { ResponseError } from '@effect/platform/HttpServerError'; +import { HttpApiMiddleware } from 'effect/unstable/httpapi'; +import * as HttpServerRequest from 'effect/unstable/http/HttpServerRequest'; +import * as HttpServerResponse from 'effect/unstable/http/HttpServerResponse'; import { Console, Effect, Layer } from 'effect'; +import type { HttpServerResponse as HttpServerResponseType } from 'effect/unstable/http/HttpServerResponse'; // Export the tag so you can .middleware(IncrementStepIndex) in your spec if desired -export class IncrementStepIndex extends HttpApiMiddleware.Tag()( +export class IncrementStepIndex extends HttpApiMiddleware.Service()( 'IncrementStepIndex', ) {} @@ -21,60 +18,48 @@ export const IncrementStepIndexMock = Layer.effect( Effect.gen(function* () { yield* Console.log('IncrementStepIndex: init'); - return Effect.gen(function* () { - // Read cookies from the current request - const request = yield* HttpServerRequest.HttpServerRequest; + return (httpEffect: Effect.Effect) => + Effect.gen(function* () { + // Read cookies from the current request + const request = yield* HttpServerRequest.HttpServerRequest; - // Parse existing stepIndex cookie or default to 0 - const cookies = request.cookies; - const currentStepIndex = cookies.stepIndex ? parseInt(cookies.stepIndex, 10) : 0; + // Parse existing stepIndex cookie or default to 0 + const cookies = request.cookies; + const currentStepIndex = cookies.stepIndex ? parseInt(cookies.stepIndex, 10) : 0; - // Normalize URL (strip query) and detect special flows - const urlPath = request.url.split('?')[0] ?? ''; - const isEndSessionRequest = - urlPath.includes('/endSession') || urlPath.includes('/end_session'); - const isAuthFlowRequest = urlPath.includes('/authorize') || urlPath.includes('/authenticate'); + // Normalize URL (strip query) and detect special flows + const urlPath = request.url.split('?')[0] ?? ''; + const isEndSessionRequest = + urlPath.includes('/endSession') || urlPath.includes('/end_session'); + const isAuthFlowRequest = + urlPath.includes('/authorize') || urlPath.includes('/authenticate'); - // Decide next value - let newStepIndex = currentStepIndex; - if (isEndSessionRequest) { - newStepIndex = 0; - yield* Console.log( - `IncrementStepIndex: end-session detected → resetting stepIndex to ${newStepIndex}`, - ); - } else if (isAuthFlowRequest) { - newStepIndex = currentStepIndex + 1; - yield* Console.log( - `IncrementStepIndex: auth flow → ${currentStepIndex} -> ${newStepIndex}`, - ); - } else { - yield* Console.log( - `IncrementStepIndex: other route ${urlPath} → keeping stepIndex ${currentStepIndex}`, - ); - } + // Decide next value + let newStepIndex = currentStepIndex; + if (isEndSessionRequest) { + newStepIndex = 0; + yield* Console.log( + `IncrementStepIndex: end-session detected → resetting stepIndex to ${newStepIndex}`, + ); + } else if (isAuthFlowRequest) { + newStepIndex = currentStepIndex + 1; + yield* Console.log( + `IncrementStepIndex: auth flow → ${currentStepIndex} -> ${newStepIndex}`, + ); + } else { + yield* Console.log( + `IncrementStepIndex: other route ${urlPath} → keeping stepIndex ${currentStepIndex}`, + ); + } - // Write cookie just before the response is sent - yield* HttpApp.appendPreResponseHandler((req, res) => - HttpServerResponse.setCookie(res, 'stepIndex', String(newStepIndex), { - // NOTE: mock defaults; tighten in prod (httpOnly: true, secure: true, sameSite: 'lax') + // Run the original handler then set the step index cookie on the response + const response = yield* httpEffect; + return yield* HttpServerResponse.setCookie(response, 'stepIndex', String(newStepIndex), { httpOnly: false, secure: false, sameSite: 'strict', path: '/', - }).pipe( - // If cookie setting fails, convert to a typed ResponseError for consistent diagnostics - Effect.catchTag( - 'CookieError', - () => - new ResponseError({ - request: req, - response: res, - reason: 'Decode', - cause: 'error updating the stepIndex cookie', - }), - ), - ), - ); - }); + }).pipe(Effect.orDie); + }); }), ); diff --git a/e2e/mock-api-v2/src/middleware/Session.ts b/e2e/mock-api-v2/src/middleware/Session.ts index c04cbec6ee..5cb670608a 100644 --- a/e2e/mock-api-v2/src/middleware/Session.ts +++ b/e2e/mock-api-v2/src/middleware/Session.ts @@ -1,12 +1,16 @@ -import { HttpApiError, HttpApiMiddleware, HttpServerRequest } from '@effect/platform'; +import { HttpApiError, HttpApiMiddleware } from 'effect/unstable/httpapi'; +import * as HttpServerRequest from 'effect/unstable/http/HttpServerRequest'; import { SessionData, SessionStorage } from '../services/session.service.js'; import { Context, Effect, Layer } from 'effect'; +import type { HttpServerResponse } from 'effect/unstable/http/HttpServerResponse'; -class Session extends Context.Tag('Session')() {} +class Session extends Context.Service()('Session') {} -export class SessionMiddleware extends HttpApiMiddleware.Tag()('Session', { - failure: HttpApiError.Unauthorized, - provides: Session, +export class SessionMiddleware extends HttpApiMiddleware.Service< + SessionMiddleware, + { provides: typeof Session } +>()('Session', { + error: HttpApiError.Unauthorized, }) {} export const SessionMiddlewareMock = Layer.effect( @@ -14,27 +18,31 @@ export const SessionMiddlewareMock = Layer.effect( Effect.gen(function* () { const sessionStorage = yield* SessionStorage; - return Effect.gen(function* () { - const request = yield* HttpServerRequest.HttpServerRequest; - const sessionData = yield* sessionStorage - .getSession(request.cookies.sessionId) - .pipe(Effect.orDie); - if (!sessionData) { - const session = yield* sessionStorage.createSession({ - userId: request.cookies.userId, - createdAt: new Date(), - expiresAt: new Date(Date.now() + 60 * 60 * 1000), // 1 hour - data: {}, - }); - - return session; - } + return (httpEffect: Effect.Effect) => + Effect.gen(function* () { + const request = yield* HttpServerRequest.HttpServerRequest; + const sessionData = yield* sessionStorage + .getSession(request.cookies.sessionId) + .pipe(Effect.orDie); - yield* sessionStorage - .refreshSession(request.cookies.sessionId, sessionData.expiresAt) - .pipe(Effect.orDie); + let session: SessionData; + if (!sessionData) { + session = yield* sessionStorage + .createSession({ + userId: request.cookies.userId, + createdAt: new Date(), + expiresAt: new Date(Date.now() + 60 * 60 * 1000), // 1 hour + data: {}, + }) + .pipe(Effect.orDie); + } else { + yield* sessionStorage + .refreshSession(request.cookies.sessionId, sessionData.expiresAt) + .pipe(Effect.orDie); + session = sessionData; + } - return sessionData; - }); + return yield* httpEffect.pipe(Effect.provideService(Session, session)); + }); }), ); diff --git a/e2e/mock-api-v2/src/schemas/authorize.schema.ts b/e2e/mock-api-v2/src/schemas/authorize.schema.ts index 470217a5ff..5dddacd0d2 100644 --- a/e2e/mock-api-v2/src/schemas/authorize.schema.ts +++ b/e2e/mock-api-v2/src/schemas/authorize.schema.ts @@ -30,8 +30,7 @@ const _DavinciAuthorizeQuery = Schema.Struct({ }); interface DavinciAuthorizeQuery extends Schema.Schema.Type {} -const DavinciAuthorizeQuery: Schema.Schema = - _DavinciAuthorizeQuery; +const DavinciAuthorizeQuery: Schema.Schema = _DavinciAuthorizeQuery; const DavinciAuthorizeFailure = Schema.Struct({ error: Schema.String, diff --git a/e2e/mock-api-v2/src/schemas/capabilities/capabilities.request.schema.ts b/e2e/mock-api-v2/src/schemas/capabilities/capabilities.request.schema.ts index 83f4c0a0f6..dcb1638258 100644 --- a/e2e/mock-api-v2/src/schemas/capabilities/capabilities.request.schema.ts +++ b/e2e/mock-api-v2/src/schemas/capabilities/capabilities.request.schema.ts @@ -21,7 +21,7 @@ const CapabilitiesRequestBody = Schema.Struct({ interactionId: Schema.String, parameters: Schema.Struct({ eventType: Schema.String, - data: Schema.Union(UsernamePassword), + data: UsernamePassword, }), }); diff --git a/e2e/mock-api-v2/src/schemas/capabilities/capabilities.response.schema.ts b/e2e/mock-api-v2/src/schemas/capabilities/capabilities.response.schema.ts index 8630ef4a85..1f318fcc6c 100644 --- a/e2e/mock-api-v2/src/schemas/capabilities/capabilities.response.schema.ts +++ b/e2e/mock-api-v2/src/schemas/capabilities/capabilities.response.schema.ts @@ -19,7 +19,7 @@ const UsernamePasswordFormData = Schema.Struct({ }), }); -const FormData = Schema.Union(UsernamePasswordFormData, ProtectSDKRequestFormData); +const FormData = Schema.Union([UsernamePasswordFormData, ProtectSDKRequestFormData]); const CapabilitiesResponse = Schema.Struct({ interactionId: Schema.String, diff --git a/e2e/mock-api-v2/src/schemas/open-id-configuration/open-id-configuration-response.schema.ts b/e2e/mock-api-v2/src/schemas/open-id-configuration/open-id-configuration-response.schema.ts index 0768594b09..22899db4f5 100644 --- a/e2e/mock-api-v2/src/schemas/open-id-configuration/open-id-configuration-response.schema.ts +++ b/e2e/mock-api-v2/src/schemas/open-id-configuration/open-id-configuration-response.schema.ts @@ -41,9 +41,7 @@ interface openIdConfigurationResponseSchema extends Schema.Schema.Type< typeof _openIdConfigurationResponseSchema > {} -const openIdConfigurationResponseSchema: Schema.Schema< - openIdConfigurationResponseSchema, - openIdConfigurationResponseSchema -> = _openIdConfigurationResponseSchema; +const openIdConfigurationResponseSchema: Schema.Schema = + _openIdConfigurationResponseSchema; export { _openIdConfigurationResponseSchema, openIdConfigurationResponseSchema }; diff --git a/e2e/mock-api-v2/src/schemas/return-success-response-redirect.schema.ts b/e2e/mock-api-v2/src/schemas/return-success-response-redirect.schema.ts index 9b9294c8dc..fe97f9c899 100644 --- a/e2e/mock-api-v2/src/schemas/return-success-response-redirect.schema.ts +++ b/e2e/mock-api-v2/src/schemas/return-success-response-redirect.schema.ts @@ -43,6 +43,5 @@ const _SuccessResponseRedirect = Schema.Struct({ }); interface SuccessResponseRedirect extends Schema.Schema.Type {} -const SuccessResponseRedirect: Schema.Schema = - _SuccessResponseRedirect; +const SuccessResponseRedirect: Schema.Schema = _SuccessResponseRedirect; export { SuccessResponseRedirect }; diff --git a/e2e/mock-api-v2/src/schemas/revoke/revoke.schema.ts b/e2e/mock-api-v2/src/schemas/revoke/revoke.schema.ts index 7e072bbebf..b363c0bbd1 100644 --- a/e2e/mock-api-v2/src/schemas/revoke/revoke.schema.ts +++ b/e2e/mock-api-v2/src/schemas/revoke/revoke.schema.ts @@ -15,7 +15,7 @@ const RevokePath = Schema.Struct({ const RevokeRequestBody = Schema.Struct({ token: Schema.String, // The token to be revoked token_type_hint: Schema.optional( - Schema.Union(Schema.Literal('access_token'), Schema.Literal('refresh_token')), + Schema.Union([Schema.Literal('access_token'), Schema.Literal('refresh_token')]), ), // Hint about token type (access_token or refresh_token) client_id: Schema.optional(Schema.String), // OAuth 2.0 client identifier client_secret: Schema.optional(Schema.String), // OAuth 2.0 client secret diff --git a/e2e/mock-api-v2/src/schemas/token/token.schema.ts b/e2e/mock-api-v2/src/schemas/token/token.schema.ts index d5701e86f1..c39f8f9c9b 100644 --- a/e2e/mock-api-v2/src/schemas/token/token.schema.ts +++ b/e2e/mock-api-v2/src/schemas/token/token.schema.ts @@ -9,13 +9,13 @@ import { Schema } from 'effect'; const _TokenRequestBody = Schema.Struct({ client_id: Schema.String, code: Schema.String, - grant_type: Schema.Union(Schema.Literal('authorization_code')), + grant_type: Schema.Union([Schema.Literal('authorization_code')]), redirect_uri: Schema.String, code_verifier: Schema.String, }); interface TokenRequestBody extends Schema.Schema.Type {} -const TokenRequestBody: Schema.Schema = _TokenRequestBody; +const TokenRequestBody: Schema.Schema = _TokenRequestBody; const _TokenResponseBody = Schema.Struct({ access_token: Schema.String, @@ -27,6 +27,6 @@ const _TokenResponseBody = Schema.Struct({ }); interface TokenResponseBody extends Schema.Schema.Type {} -const TokenResponseBody: Schema.Schema = _TokenResponseBody; +const TokenResponseBody: Schema.Schema = _TokenResponseBody; export { TokenRequestBody, TokenResponseBody }; diff --git a/e2e/mock-api-v2/src/services/mock-env-helpers/index.ts b/e2e/mock-api-v2/src/services/mock-env-helpers/index.ts index cb93a0616d..d496f48d04 100644 --- a/e2e/mock-api-v2/src/services/mock-env-helpers/index.ts +++ b/e2e/mock-api-v2/src/services/mock-env-helpers/index.ts @@ -12,7 +12,7 @@ import { CapabilitiesResponse } from '../../schemas/capabilities/capabilities.re import { QueryTypes } from '../../types/index.js'; import { validator } from '../../helpers/match.js'; -import { HttpApiError } from '@effect/platform'; +import { HttpApiError } from 'effect/unstable/httpapi'; /** * Given data in the shape of Ping's Request formData.value @@ -34,10 +34,9 @@ const getArrayFromResponseMap = (query: QueryTypes) => * to grab the array from the `responseMap`. */ const getNextStep = (bool: boolean, query: QueryTypes) => - Effect.if(bool, { - onTrue: () => getArrayFromResponseMap(query), - onFalse: () => Effect.fail(new UnableToFindNextStep()), - }); + Effect.suspend(() => + bool ? getArrayFromResponseMap(query) : Effect.fail(new UnableToFindNextStep()), + ); /** * Get the first element in the responseMap @@ -52,27 +51,25 @@ const getFirstElement = (arr: (typeof responseMap)[ResponseMapKeys]) => * */ const getFirstElementAndRespond = (query: QueryTypes) => - pipe( - Option.fromNullable(query?.acr_values), - Option.map((acr) => responseMap[acr as ResponseMapKeys]), - Effect.flatMap(getFirstElement), - Effect.catchTag('NoSuchElementException', () => new HttpApiError.NotFound()), - ); + Effect.gen(function* () { + const acr = query?.acr_values; + if (acr == null) return yield* Effect.fail(new HttpApiError.NotFound()); + const arr = responseMap[acr as ResponseMapKeys]; + if (!arr) return yield* Effect.fail(new HttpApiError.NotFound()); + return yield* getFirstElement(arr); + }); /** * helper function that dives into a request body for Capabilities Response * and will apply a validator function to ensure the request passes validation */ const validateCapabilitiesResponse = (body: any) => - pipe( - body, - Option.fromNullable, - Option.map((body) => body.parameters), - Option.map((parameters) => parameters.data), - Option.map((data) => data.formData), - Option.map((formData) => formData.value), - Effect.flatMap(validator), - ); + Effect.gen(function* () { + if (body == null) return yield* Effect.fail(new HttpApiError.InternalServerError()); + const value = body?.parameters?.data?.formData?.value; + if (value == null) return yield* Effect.fail(new HttpApiError.InternalServerError()); + return yield* validator(value); + }); export { getNextStep, diff --git a/e2e/mock-api-v2/src/services/session.service.ts b/e2e/mock-api-v2/src/services/session.service.ts index 26a3399cef..e4ae3ce317 100644 --- a/e2e/mock-api-v2/src/services/session.service.ts +++ b/e2e/mock-api-v2/src/services/session.service.ts @@ -1,4 +1,4 @@ -import { Effect } from 'effect'; +import { Context, Effect } from 'effect'; import { nanoid } from 'nanoid'; export type SessionData = { @@ -9,98 +9,104 @@ export type SessionData = { }; export interface SessionStorageApi { - createSession: (data: SessionData) => Effect.Effect; - getSession: (sessionId: string) => Effect.Effect; - deleteSession: (sessionId: string) => Effect.Effect; - updateSession: (sessionId: string, data: SessionData) => Effect.Effect; - refreshSession: (sessionId: string, expiryDate?: Date) => Effect.Effect; + createSession: (data: SessionData) => Effect.Effect; + getSession: (sessionId: string) => Effect.Effect; + deleteSession: (sessionId: string) => Effect.Effect; + updateSession: ( + sessionId: string, + data: SessionData, + ) => Effect.Effect; + refreshSession: (sessionId: string, expiryDate?: Date) => Effect.Effect; isSessionExpired: (sessionData: SessionData) => boolean; - cleanupExpiredSessions: () => Effect.Effect; + cleanupExpiredSessions: () => Effect.Effect; } -export class SessionStorage extends Effect.Service()('SessionStorage', { - sync: () => { - // In-memory session store - const _store = new Map(); - - // Check if a session is expired - const isSessionExpired = (sessionData: SessionData): boolean => { - const now = new Date(); - return sessionData.expiresAt < now; - }; - - return { - createSession: Effect.fn('CreateSessionMiddleware')(function* (data: SessionData) { - const sessionId = nanoid(); - _store.set(sessionId, data); - return data; - }), - - getSession: Effect.fn('GetSessionMiddleware')(function* (sessionId: string) { - const session = _store.get(sessionId); - - if (!session) { - return null; - } - - // Check if session is expired - if (isSessionExpired(session)) { - _store.delete(sessionId); - return null; - } - - return session; - }), - - deleteSession: Effect.fn('DeleteSessionMiddleware')(function* (sessionId: string) { - _store.delete(sessionId); - return undefined; - }), - - updateSession: Effect.fn('UpdateSessionMiddleware')(function* ( - sessionId: string, - data: SessionData, - ) { - if (!_store.has(sessionId)) { - return new Error('Session not found'); - } - _store.set(sessionId, data); - return data; - }), - - refreshSession: Effect.fn('RefreshSessionMiddleware')(function* ( - sessionId: string, - expiryDate?: Date, - ) { - const session = _store.get(sessionId); - - if (!session) { - return Effect.fail(new Error('Session not found')); - } - - if (isSessionExpired(session)) { - _store.delete(sessionId); - return new Error('Session has expired'); - } +export class SessionStorage extends Context.Service()( + 'SessionStorage', + { + make: Effect.sync(() => { + // In-memory session store + const _store = new Map(); + + // Check if a session is expired + const isSessionExpired = (sessionData: SessionData): boolean => { + const now = new Date(); + return sessionData.expiresAt < now; + }; + + return { + createSession: Effect.fn('CreateSessionMiddleware')(function* (data: SessionData) { + const sessionId = nanoid(); + _store.set(sessionId, data); + return data; + }), + + getSession: Effect.fn('GetSessionMiddleware')(function* (sessionId: string) { + const session = _store.get(sessionId); + + if (!session) { + return null; + } - // Update expiry date - const newExpiryDate = expiryDate || new Date(Date.now() + 24 * 60 * 60 * 1000); // Default: 24 hours from now - session.expiresAt = newExpiryDate; - _store.set(sessionId, session); + // Check if session is expired + if (isSessionExpired(session)) { + _store.delete(sessionId); + return null; + } - return session.data; - }), + return session; + }), - isSessionExpired, + deleteSession: Effect.fn('DeleteSessionMiddleware')(function* (sessionId: string) { + _store.delete(sessionId); + return undefined; + }), + + updateSession: Effect.fn('UpdateSessionMiddleware')(function* ( + sessionId: string, + data: SessionData, + ) { + if (!_store.has(sessionId)) { + return new Error('Session not found'); + } + _store.set(sessionId, data); + return data; + }), + + refreshSession: Effect.fn('RefreshSessionMiddleware')(function* ( + sessionId: string, + expiryDate?: Date, + ) { + const session = _store.get(sessionId); + + if (!session) { + return Effect.fail(new Error('Session not found')); + } - cleanupExpiredSessions: Effect.fn('CleanupExpiredSessionsMiddleware')(function* () { - for (const [sessionId, session] of _store.entries()) { if (isSessionExpired(session)) { _store.delete(sessionId); + return new Error('Session has expired'); + } + + // Update expiry date + const newExpiryDate = expiryDate || new Date(Date.now() + 24 * 60 * 60 * 1000); // Default: 24 hours from now + session.expiresAt = newExpiryDate; + _store.set(sessionId, session); + + return session.data; + }), + + isSessionExpired, + + cleanupExpiredSessions: Effect.fn('CleanupExpiredSessionsMiddleware')(function* () { + for (const [sessionId, session] of _store.entries()) { + if (isSessionExpired(session)) { + _store.delete(sessionId); + } } - } - return undefined; - }), - }; + return undefined; + }), + }; + }), }, -}) {} +) {} diff --git a/e2e/mock-api-v2/src/services/tokens.service.ts b/e2e/mock-api-v2/src/services/tokens.service.ts index 5c2df0c5b5..8d63924dbf 100644 --- a/e2e/mock-api-v2/src/services/tokens.service.ts +++ b/e2e/mock-api-v2/src/services/tokens.service.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ import { Context, Effect, Layer, Schema } from 'effect'; -import { HttpApiError } from '@effect/platform'; +import { HttpApiError } from 'effect/unstable/httpapi'; import { tokenResponseBody } from '../responses/token/token.js'; import { TokenResponseBody } from '../schemas/token/token.schema.js'; import { revokeResponseBody } from '../responses/revoke/revoke.js'; @@ -16,7 +16,7 @@ import { HeaderTypes } from '../types/index.js'; type TokensResponseBody = Schema.Schema.Type; type RevokeTokenResponseBody = Schema.Schema.Type; -class Tokens extends Context.Tag('@services/Tokens')< +class Tokens extends Context.Service< Tokens, { getTokens: ( @@ -27,31 +27,28 @@ class Tokens extends Context.Tag('@services/Tokens')< tokenTypeHint?: string, ) => Effect.Effect; } ->() {} +>()('@services/Tokens') {} -const TokensMock = Layer.succeed( - Tokens, - Tokens.of({ - getTokens: () => - Effect.gen(function* () { - const response = yield* Effect.tryPromise({ - try: () => Promise.resolve(tokenResponseBody), - catch: () => new HttpApiError.Unauthorized(), - }); - return response; - }), - revokeToken: (token) => - Effect.gen(function* () { - // Apply the REVOKED_ prefix to the token - // This is a simple way to mark tokens as revoked without maintaining state - // The Authorization middleware will check for this prefix - yield* Effect.log('Revoking token', { token, newToken: `REVOKED_${token}` }); +const TokensMock = Layer.succeed(Tokens, { + getTokens: () => + Effect.gen(function* () { + const response = yield* Effect.tryPromise({ + try: () => Promise.resolve(tokenResponseBody), + catch: () => new HttpApiError.Unauthorized(), + }); + return response; + }), + revokeToken: (token) => + Effect.gen(function* () { + // Apply the REVOKED_ prefix to the token + // This is a simple way to mark tokens as revoked without maintaining state + // The Authorization middleware will check for this prefix + yield* Effect.log('Revoking token', { token, newToken: `REVOKED_${token}` }); - // In a real implementation, we might store the token in a revocation list - // or update it in a database. For this mock, we'll just return success. - return revokeResponseBody; - }), - }), -); + // In a real implementation, we might store the token in a revocation list + // or update it in a database. For this mock, we'll just return success. + return revokeResponseBody; + }), +}); export { TokensMock, Tokens }; diff --git a/e2e/mock-api-v2/src/services/userinfo.service.ts b/e2e/mock-api-v2/src/services/userinfo.service.ts index b9e3dabc45..2b359d5980 100644 --- a/e2e/mock-api-v2/src/services/userinfo.service.ts +++ b/e2e/mock-api-v2/src/services/userinfo.service.ts @@ -4,12 +4,12 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { Layer, Schema } from 'effect'; -import { Effect, Context } from 'effect'; +import { Context, Layer, Schema } from 'effect'; +import { Effect } from 'effect'; import { userInfoResponse } from '../responses/userinfo/userinfo.js'; import { UserInfoSchema } from '../schemas/userinfo/userinfo.schema.js'; -import { HttpApiError } from '@effect/platform'; +import { HttpApiError } from 'effect/unstable/httpapi'; /*** * This file should be converted to a Layer that uses Request @@ -17,25 +17,22 @@ import { HttpApiError } from '@effect/platform'; type UserInfoResponse = Schema.Schema.Type; -class UserInfo extends Context.Tag('@services/userinfo')< +class UserInfo extends Context.Service< UserInfo, { getUserInfo: ( token: string, ) => Effect.Effect; } ->() {} +>()('@services/userinfo') {} -const UserInfoMockService = Layer.succeed( - UserInfo, - UserInfo.of({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - getUserInfo: (_: string) => - Effect.tryPromise({ - try: () => Promise.resolve(userInfoResponse), - catch: () => new HttpApiError.Unauthorized(), - }), - }), -); +const UserInfoMockService = Layer.succeed(UserInfo, { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + getUserInfo: (_: string) => + Effect.tryPromise({ + try: () => Promise.resolve(userInfoResponse), + catch: () => new HttpApiError.Unauthorized(), + }), +}); export { UserInfo, UserInfoMockService }; diff --git a/e2e/mock-api-v2/src/spec.ts b/e2e/mock-api-v2/src/spec.ts index 3981a26464..4ae313b64c 100644 --- a/e2e/mock-api-v2/src/spec.ts +++ b/e2e/mock-api-v2/src/spec.ts @@ -5,7 +5,13 @@ * of the MIT license. See the LICENSE file for details. */ import { Schema } from 'effect'; -import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from '@effect/platform'; +import { + HttpApi, + HttpApiEndpoint, + HttpApiError, + HttpApiGroup, + OpenApi, +} from 'effect/unstable/httpapi'; import { openIdConfigurationResponseSchema } from './schemas/open-id-configuration/open-id-configuration-response.schema.js'; import { TokenResponseBody } from './schemas/token/token.schema.js'; import { UserInfoSchema } from './schemas/userinfo/userinfo.schema.js'; @@ -45,8 +51,9 @@ const MockApi = HttpApi.make('MyApi') // Healthcheck .add( HttpApiGroup.make('Healthcheck').add( - HttpApiEndpoint.get('HealthCheck')`/healthcheck` - .addSuccess(Schema.String) + HttpApiEndpoint.get('HealthCheck', '/healthcheck', { + success: Schema.String, + }) .annotate(OpenApi.Summary, 'Server Health Check') .annotate( OpenApi.Description, @@ -57,13 +64,13 @@ const MockApi = HttpApi.make('MyApi') // Authorization .add( HttpApiGroup.make('Authorization').add( - HttpApiEndpoint.get('authorize', `/:envid/davinci/authorize`) - .setPath(Schema.Struct({ envid: Schema.String })) - .setHeaders(DavinciAuthorizeHeaders) - .setUrlParams(DavinciAuthorizeQuery) - .addSuccess(CapabilitiesResponse) - .addError(HttpApiError.NotFound) - .addError(HttpApiError.InternalServerError) + HttpApiEndpoint.get('authorize', `/:envid/davinci/authorize`, { + params: Schema.Struct({ envid: Schema.String }), + headers: DavinciAuthorizeHeaders, + query: DavinciAuthorizeQuery, + success: CapabilitiesResponse, + error: [HttpApiError.NotFound, HttpApiError.InternalServerError], + }) .annotate(OpenApi.Summary, 'Authorization Endpoint') .annotate( OpenApi.Description, @@ -78,23 +85,27 @@ const MockApi = HttpApi.make('MyApi') HttpApiEndpoint.post( 'capabilities', `/:envid/davinci/connections/:connectionID/capabilities/:capabilityName`, - ) - .setPayload(CapabilitiesRequestBody) - .setPath(CapabilitiesPathParams) - - .setHeaders(CapabilitiesHeaders) - .addSuccess(CapabilitiesResponse) - .addError(HttpApiError.NotFound) - .addError(HttpApiError.Unauthorized) - .addError(HttpApiError.InternalServerError), + { + payload: CapabilitiesRequestBody, + params: CapabilitiesPathParams, + headers: CapabilitiesHeaders, + success: CapabilitiesResponse, + error: [ + HttpApiError.NotFound, + HttpApiError.Unauthorized, + HttpApiError.InternalServerError, + ], + }, + ), ) .middleware(IncrementStepIndex), ) .add( HttpApiGroup.make('OpenIDConfig').add( - HttpApiEndpoint.get('openid', `/:envid/as/.well-known/openid-configuration`) - .setPath(Schema.Struct({ envid: Schema.String })) - .addSuccess(openIdConfigurationResponseSchema) + HttpApiEndpoint.get('openid', `/:envid/as/.well-known/openid-configuration`, { + params: Schema.Struct({ envid: Schema.String }), + success: openIdConfigurationResponseSchema, + }) .annotate(OpenApi.Summary, 'OIDC Configuration') .annotate( OpenApi.Description, @@ -106,10 +117,11 @@ const MockApi = HttpApi.make('MyApi') .add( HttpApiGroup.make('Tokens') .add( - HttpApiEndpoint.post('Tokens', `/:envid/as/token`) - .addSuccess(TokenResponseBody) - .addError(HttpApiError.Unauthorized) - .setPath(Schema.Struct({ envid: Schema.String })) + HttpApiEndpoint.post('Tokens', `/:envid/as/token`, { + params: Schema.Struct({ envid: Schema.String }), + success: TokenResponseBody, + error: HttpApiError.Unauthorized, + }) .annotate(OpenApi.Summary, 'Token Endpoint') .annotate( OpenApi.Description, @@ -123,10 +135,11 @@ const MockApi = HttpApi.make('MyApi') .add( HttpApiGroup.make('ProtectedRequests') .add( - HttpApiEndpoint.get('UserInfo', `/:envid/as/userinfo`) - .setPath(Schema.Struct({ envid: Schema.String })) - .addSuccess(UserInfoSchema) - .addError(HttpApiError.Unauthorized) + HttpApiEndpoint.get('UserInfo', `/:envid/as/userinfo`, { + params: Schema.Struct({ envid: Schema.String }), + success: UserInfoSchema, + error: HttpApiError.Unauthorized, + }) .annotate(OpenApi.Summary, 'UserInfo Endpoint') .annotate( OpenApi.Description, @@ -140,21 +153,20 @@ const MockApi = HttpApi.make('MyApi') .add( HttpApiGroup.make('SessionManagement') .add( - HttpApiEndpoint.get('EndSession', `/:envid/as/endSession`) - .setPath(EndSessionPath) - .setUrlParams(EndSessionQuery) - .setHeaders(EndSessionHeaders) - .addSuccess( - Schema.Union( - Schema.String, - Schema.Struct({ - status: Schema.Number, - headers: Schema.Record({ key: Schema.String, value: Schema.String }), - body: Schema.String, - }), - ), - ) - .addError(HttpApiError.Unauthorized) + HttpApiEndpoint.get('EndSession', `/:envid/as/endSession`, { + params: EndSessionPath, + query: EndSessionQuery, + headers: EndSessionHeaders, + success: Schema.Union([ + Schema.String, + Schema.Struct({ + status: Schema.Number, + headers: Schema.Record(Schema.String, Schema.String), + body: Schema.String, + }), + ]), + error: HttpApiError.Unauthorized, + }) .annotate(OpenApi.Summary, 'End Session Endpoint') .annotate( OpenApi.Description, @@ -164,31 +176,15 @@ const MockApi = HttpApi.make('MyApi') .middleware(Authorization) .middleware(SessionMiddleware), ) - // Protected Requests - .add( - HttpApiGroup.make('ProtectedRequests') - .add( - HttpApiEndpoint.get('UserInfo', `/:envid/as/userinfo`) - .setPath(Schema.Struct({ envid: Schema.String })) - .addSuccess(UserInfoSchema) - .addError(HttpApiError.Unauthorized) - .annotate(OpenApi.Summary, 'UserInfo Endpoint') - .annotate( - OpenApi.Description, - 'Returns claims about the authenticated end-user. Requires a valid access token.', - ), - ) - .middleware(Authorization) - .middleware(SessionMiddleware), - ) .add( HttpApiGroup.make('Revoke') .add( - HttpApiEndpoint.post('RevokeToken', `/:envid/as/revoke`) - .setPath(RevokePath) - .setPayload(RevokeRequestBody) - .addSuccess(RevokeResponseBody) - .addError(HttpApiError.Unauthorized) + HttpApiEndpoint.post('RevokeToken', `/:envid/as/revoke`, { + params: RevokePath, + payload: RevokeRequestBody, + success: RevokeResponseBody, + error: HttpApiError.Unauthorized, + }) .annotate(OpenApi.Summary, 'Token Revocation Endpoint') .annotate( OpenApi.Description, @@ -196,7 +192,7 @@ const MockApi = HttpApi.make('MyApi') ), ) .middleware(Authorization) - .middleware(SessionMiddleware), // Applies to token, end session, revoke + .middleware(SessionMiddleware), ) // Middlewares for relevant endpoints .annotate( diff --git a/package.json b/package.json index 3d5ac1e001..1b5b252a5f 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,6 @@ "@commitlint/cli": "^20.0.0", "@commitlint/config-conventional": "^20.0.0", "@commitlint/prompt": "^20.0.0", - "@effect/cli": "catalog:effect", "@eslint/eslintrc": "^3.0.0", "@eslint/js": "~9.39.0", "@evilmartians/lefthook": "^2.1.4", @@ -85,7 +84,7 @@ "@typescript-eslint/typescript-estree": "8.23.0", "@typescript-eslint/utils": "^8.13.0", "@vitest/coverage-v8": "catalog:vitest", - "@vitest/ui": "3.2.6", + "@vitest/ui": "catalog:vitest", "conventional-changelog-conventionalcommits": "^8.0.0", "cz-conventional-changelog": "^3.3.0", "cz-git": "^1.6.1", diff --git a/packages/davinci-client/src/lib/client.store.effects.test.ts b/packages/davinci-client/src/lib/client.store.effects.test.ts index 365118aac0..aaa821b399 100644 --- a/packages/davinci-client/src/lib/client.store.effects.test.ts +++ b/packages/davinci-client/src/lib/client.store.effects.test.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ -import { Micro } from 'effect'; +import { Effect, Exit } from 'effect'; import { describe, expect, vi } from 'vitest'; import { it } from '@effect/vitest'; @@ -185,7 +185,7 @@ describe('getPollingModeµ', () => { }; it.effect('succeeds with challenge mode when challenge and pollChallengeStatus are set', () => - Micro.gen(function* () { + Effect.gen(function* () { const collector: PollingCollector = { ...basePollingCollector, output: { @@ -206,7 +206,7 @@ describe('getPollingModeµ', () => { ); it.effect('succeeds with continue mode when no challenge is present', () => - Micro.gen(function* () { + Effect.gen(function* () { const result = yield* getPollingModeµ(basePollingCollector); expect(result).toStrictEqual({ @@ -218,7 +218,7 @@ describe('getPollingModeµ', () => { ); it.effect('succeeds with unknown mode for ambiguous configuration', () => - Micro.gen(function* () { + Effect.gen(function* () { const collector: PollingCollector = { ...basePollingCollector, output: { @@ -239,13 +239,13 @@ describe('getPollingModeµ', () => { ); it.effect('fails when collector type is not PollingCollector', () => - Micro.gen(function* () { + Effect.gen(function* () { const badCollector = { ...basePollingCollector, type: 'TextCollector' } as any; - const result = yield* Micro.exit(getPollingModeµ(badCollector)); + const result = yield* Effect.exit(getPollingModeµ(badCollector)); expect(result).toStrictEqual( - Micro.exitFail({ + Exit.fail({ error: { message: 'Collector provided to poll is not a PollingCollector', type: 'argument_error', @@ -257,7 +257,7 @@ describe('getPollingModeµ', () => { ); it.effect('fails when retriesRemaining is undefined in continue mode', () => - Micro.gen(function* () { + Effect.gen(function* () { const collector: PollingCollector = { ...basePollingCollector, output: { @@ -266,10 +266,10 @@ describe('getPollingModeµ', () => { }, }; - const result = yield* Micro.exit(getPollingModeµ(collector)); + const result = yield* Effect.exit(getPollingModeµ(collector)); expect(result).toStrictEqual( - Micro.exitFail({ + Exit.fail({ error: { message: 'No retries found on PollingCollector', type: 'argument_error', diff --git a/packages/davinci-client/src/lib/client.store.effects.ts b/packages/davinci-client/src/lib/client.store.effects.ts index 9923ea4b67..8546e4d089 100644 --- a/packages/davinci-client/src/lib/client.store.effects.ts +++ b/packages/davinci-client/src/lib/client.store.effects.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ -import { Micro } from 'effect'; +import { Effect } from 'effect'; import { SerializedError } from '@reduxjs/toolkit/react'; import { FetchBaseQueryError } from '@reduxjs/toolkit/query/react'; @@ -14,6 +14,7 @@ import type { logger as loggerFn } from '@forgerock/sdk-logger'; import type { ClientStore, RootState } from './client.store.utils.js'; import type { PollingStatus, InternalErrorResponse } from './client.types.js'; import type { PollingCollector } from './collector.types.js'; +import type { ContinueNode } from './node.types.js'; import { createInternalError, isInternalError } from './client.store.utils.js'; import { davinciApi } from './davinci.api.js'; @@ -55,9 +56,9 @@ const isRecord = (value: unknown): value is Record => */ export function getPollingModeµ( collector: PollingCollector, -): Micro.Micro { +): Effect.Effect { if (collector.type !== 'PollingCollector') { - return Micro.fail( + return Effect.fail( createInternalError('Collector provided to poll is not a PollingCollector', 'argument_error'), ); } @@ -66,23 +67,23 @@ export function getPollingModeµ( collector.output.config; if (challenge && pollChallengeStatus === true) { - return Micro.succeed({ _tag: 'challenge', challenge }); + return Effect.succeed({ _tag: 'challenge', challenge }); } if (!challenge && !pollChallengeStatus) { if (retriesRemaining === undefined) { - return Micro.fail( + return Effect.fail( createInternalError('No retries found on PollingCollector', 'argument_error'), ); } - return Micro.succeed({ + return Effect.succeed({ _tag: 'continue', retriesRemaining, pollInterval: pollInterval ?? 2000, }); } - return Micro.succeed({ _tag: 'unknown' }); + return Effect.succeed({ _tag: 'unknown' }); } /** @@ -114,16 +115,16 @@ export function buildChallengeEndpoint( } /** - * Lifts a selector result with { error, state } shape into a Micro. + * Lifts a selector result with { error, state } shape into an Effect. * Succeeds with state when error is null, fails with InternalErrorResponse otherwise. */ function fromSelectorµ(result: { error: { message: string } | null; state: T; -}): Micro.Micro, InternalErrorResponse> { +}): Effect.Effect, InternalErrorResponse> { return result.error - ? Micro.fail(createInternalError(result.error.message, 'state_error')) - : Micro.succeed(result.state as NonNullable); + ? Effect.fail(createInternalError(result.error.message, 'state_error')) + : Effect.succeed(result.state as NonNullable); } /** @@ -133,35 +134,35 @@ function fromSelectorµ(result: { export function validatePollingPrerequisitesµ( rootState: RootState, challenge: string, -): Micro.Micro { +): Effect.Effect { if (!challenge) { - return Micro.fail( + return Effect.fail( createInternalError('No challenge found on collector for poll operation', 'state_error'), ); } return fromSelectorµ(nodeSlice.selectors.selectContinueServer(rootState)).pipe( - Micro.filterOrFail( - (server) => !!server.interactionId, + Effect.filterOrFail( + (server: ContinueNode['server']) => !!server.interactionId, () => createInternalError( 'Missing interactionId in server info for challenge polling', 'state_error', ), ), - Micro.flatMap((server) => + Effect.flatMap((server: ContinueNode['server']) => fromSelectorµ(nodeSlice.selectors.selectSelfLink(rootState)).pipe( - Micro.map((selfLink) => ({ server, selfLink })), + Effect.map((selfLink) => ({ server, selfLink })), ), ), - Micro.flatMap(({ server, selfLink }) => { + Effect.flatMap(({ server, selfLink }: { server: ContinueNode['server']; selfLink: string }) => { const endpoint = buildChallengeEndpoint(selfLink, challenge); return typeof endpoint === 'string' - ? Micro.succeed({ + ? Effect.succeed({ interactionId: server.interactionId!, challengeEndpoint: endpoint, }) - : Micro.fail(endpoint); + : Effect.fail(endpoint); }), ); } @@ -222,14 +223,14 @@ export function interpretChallengeResponse( return pollStatus ? (pollStatus as PollingStatus) : 'error'; } - // If we reach here, Micro.repeat exhausted its schedule without the challenge completing + // If we reach here, the poll loop exhausted its retries without the challenge completing log.debug('Challenge polling timed out'); return 'timedOut'; } /** - * Builds a Micro effect for the challenge polling branch. - * validate → dispatch → repeat → interpret → lift errors + * Builds an Effect for the challenge polling branch. + * validate → dispatch initial → loop (sleep + re-dispatch) while pending → interpret */ function challengePollingµ({ collector, @@ -241,51 +242,60 @@ function challengePollingµ({ challenge: string; store: ReturnType; log: ReturnType; -}): Micro.Micro { +}): Effect.Effect { const maxRetries = collector.output.config.pollRetries ?? 60; const pollInterval = collector.output.config.pollInterval ?? 2000; - return validatePollingPrerequisitesµ(store.getState(), challenge).pipe( - Micro.flatMap(({ interactionId, challengeEndpoint }) => - Micro.promise(() => + return Effect.gen(function* () { + const { interactionId, challengeEndpoint } = yield* validatePollingPrerequisitesµ( + store.getState(), + challenge, + ); + + const doPoll = (): Effect.Effect => + Effect.promise(() => store.dispatch( davinciApi.endpoints.poll.initiate({ endpoint: challengeEndpoint, interactionId, }), ), - ), - ), - Micro.repeat({ - while: isChallengeStillPending, - // `times` tracks repetitions after the initial attempt, so decrement by one - times: maxRetries - 1, - schedule: Micro.scheduleSpaced(pollInterval), - }), - Micro.map((response) => interpretChallengeResponse(response, log)), - Micro.flatMap((result) => - isInternalError(result) ? Micro.fail(result) : Micro.succeed(result), - ), - ); + ); + + let response: PollDispatchResult = yield* doPoll(); + + for (let i = 0; i < maxRetries - 1 && isChallengeStillPending(response); i++) { + yield* Effect.sleep(pollInterval); + response = yield* doPoll(); + } + + const status = interpretChallengeResponse(response, log); + + if (isInternalError(status)) { + return yield* Effect.fail(status); + } + + return status; + }); } /** - * Builds a Micro effect for the continue polling branch. + * Builds an Effect for the continue polling branch. * If retries remain, delays by pollInterval then returns 'continue'. * If retries are exhausted, returns 'timedOut' immediately. */ function continuePollingµ( mode: Extract, -): Micro.Micro { +): Effect.Effect { if (mode.retriesRemaining <= 0) { - return Micro.succeed('timedOut' as PollingStatus); + return Effect.succeed('timedOut' as PollingStatus); } - return Micro.sleep(mode.pollInterval).pipe(Micro.map(() => 'continue')); + return Effect.sleep(mode.pollInterval).pipe(Effect.map(() => 'continue' as PollingStatus)); } /** * Routes a validated PollingMode to the appropriate polling effect. - * This is the single entry point — the caller lifts getPollingMode into Micro, pipes through this. + * This is the single entry point — the caller lifts getPollingMode into Effect, pipes through this. */ export function pollingµ({ mode, @@ -297,7 +307,7 @@ export function pollingµ({ collector: PollingCollector; store: ReturnType; log: ReturnType; -}): Micro.Micro { +}): Effect.Effect { if (mode._tag === 'challenge') { return challengePollingµ({ collector, challenge: mode.challenge, store, log }); } @@ -306,7 +316,7 @@ export function pollingµ({ return continuePollingµ(mode); } - return Micro.fail( + return Effect.fail( createInternalError('Invalid polling collector configuration', 'argument_error'), ); } diff --git a/packages/davinci-client/src/lib/client.store.ts b/packages/davinci-client/src/lib/client.store.ts index c92def90d8..e8fcdb3715 100644 --- a/packages/davinci-client/src/lib/client.store.ts +++ b/packages/davinci-client/src/lib/client.store.ts @@ -4,8 +4,7 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { Micro, Either } from 'effect'; -import { exitIsFail, exitIsSuccess } from 'effect/Micro'; +import { Effect, Exit, Cause, Option, Either } from 'effect'; import { type CustomLogger, logger as loggerFn, type LogLevel } from '@forgerock/sdk-logger'; import { createStorage } from '@forgerock/storage'; import { isGenericError, createWellknownError } from '@forgerock/sdk-utilities'; @@ -21,7 +20,7 @@ import { resolveCollectorUpdateValue, type RootState, } from './client.store.utils.js'; -import { pollingµ, getPollingModeµ } from './client.store.effects.js'; +import { pollingµ, getPollingModeµ, type PollingMode } from './client.store.effects.js'; import { nodeSlice } from './node.slice.js'; import { davinciApi } from './davinci.api.js'; import { configSlice } from './config.slice.js'; @@ -453,17 +452,22 @@ export async function davinci({ pollStatus: (collector: PollingCollector): Poller => { return async () => { const result = await getPollingModeµ(collector).pipe( - Micro.flatMap((mode) => pollingµ({ mode, collector, store, log })), - Micro.tapError((err) => Micro.sync(() => log.error(err.error.message))), - Micro.runPromiseExit, + Effect.flatMap((mode: PollingMode) => pollingµ({ mode, collector, store, log })), + Effect.tapError((err: InternalErrorResponse) => + Effect.sync(() => log.error(err.error.message)), + ), + Effect.runPromiseExit, ); - if (exitIsSuccess(result)) { + if (Exit.isSuccess(result)) { return result.value; } - if (exitIsFail(result)) { - return result.cause.error; + if (Exit.isFailure(result)) { + const maybeError = Cause.findErrorOption(result.cause); + if (Option.isSome(maybeError)) { + return maybeError.value; + } } return createInternalError( diff --git a/packages/davinci-client/src/lib/fido/fido.ts b/packages/davinci-client/src/lib/fido/fido.ts index 2434012d21..1b96ca85d8 100644 --- a/packages/davinci-client/src/lib/fido/fido.ts +++ b/packages/davinci-client/src/lib/fido/fido.ts @@ -4,8 +4,7 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { Micro } from 'effect'; -import { exitIsFail, exitIsSuccess } from 'effect/Micro'; +import { Effect, Exit, Cause, Option } from 'effect'; import { toFidoErrorCode, @@ -46,14 +45,14 @@ export function fido(): FidoClient { ); } - const createCredentialµ = Micro.sync(() => transformRegistrationOptions(options)).pipe( - Micro.flatMap((publicKeyCredentialCreationOptions) => - Micro.tryPromise({ + const createCredentialµ = Effect.sync(() => transformRegistrationOptions(options)).pipe( + Effect.flatMap((publicKeyCredentialCreationOptions: PublicKeyCredentialCreationOptions) => + Effect.tryPromise({ try: () => navigator.credentials.create({ publicKey: publicKeyCredentialCreationOptions, }), - catch: (error) => { + catch: (error: unknown) => { const code = toFidoErrorCode(error); console.error('Failed to create keypair: ', code); return createFidoError( @@ -64,9 +63,9 @@ export function fido(): FidoClient { }, }), ), - Micro.flatMap((credential) => { + Effect.flatMap((credential: Credential | null) => { if (!credential) { - return Micro.fail( + return Effect.fail( createFidoError( 'UnknownError', 'registration_error', @@ -74,19 +73,25 @@ export function fido(): FidoClient { ), ); } - return Micro.succeed(transformPublicKeyCredential(credential as PublicKeyCredential)); + return Effect.succeed(transformPublicKeyCredential(credential as PublicKeyCredential)); }), ); - const result = await Micro.runPromiseExit(createCredentialµ); + const result = await Effect.runPromiseExit(createCredentialµ); - if (exitIsSuccess(result)) { + if (Exit.isSuccess(result)) { return result.value; - } else if (exitIsFail(result)) { - return result.cause.error; - } else { - return createFidoError('UnknownError', 'registration_error', result.cause.message); } + + if (Exit.isFailure(result)) { + const maybeError = Cause.findErrorOption(result.cause); + if (Option.isSome(maybeError)) { + return maybeError.value; + } + return createFidoError('UnknownError', 'registration_error', Cause.pretty(result.cause)); + } + + return createFidoError('UnknownError', 'registration_error', 'Unexpected exit state'); }, /** @@ -103,14 +108,14 @@ export function fido(): FidoClient { ); } - const getAssertionµ = Micro.sync(() => transformAuthenticationOptions(options)).pipe( - Micro.flatMap((publicKeyCredentialRequestOptions) => - Micro.tryPromise({ + const getAssertionµ = Effect.sync(() => transformAuthenticationOptions(options)).pipe( + Effect.flatMap((publicKeyCredentialRequestOptions: PublicKeyCredentialRequestOptions) => + Effect.tryPromise({ try: () => navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions, }), - catch: (error) => { + catch: (error: unknown) => { const code = toFidoErrorCode(error); console.error('Failed to authenticate: ', code); return createFidoError( @@ -121,9 +126,9 @@ export function fido(): FidoClient { }, }), ), - Micro.flatMap((assertion) => { + Effect.flatMap((assertion: Credential | null) => { if (!assertion) { - return Micro.fail( + return Effect.fail( createFidoError( 'UnknownError', 'authentication_error', @@ -131,19 +136,25 @@ export function fido(): FidoClient { ), ); } - return Micro.succeed(transformAssertion(assertion as PublicKeyCredential)); + return Effect.succeed(transformAssertion(assertion as PublicKeyCredential)); }), ); - const result = await Micro.runPromiseExit(getAssertionµ); + const result = await Effect.runPromiseExit(getAssertionµ); - if (exitIsSuccess(result)) { + if (Exit.isSuccess(result)) { return result.value; - } else if (exitIsFail(result)) { - return result.cause.error; - } else { - return createFidoError('UnknownError', 'authentication_error', result.cause.message); } + + if (Exit.isFailure(result)) { + const maybeError = Cause.findErrorOption(result.cause); + if (Option.isSome(maybeError)) { + return maybeError.value; + } + return createFidoError('UnknownError', 'authentication_error', Cause.pretty(result.cause)); + } + + return createFidoError('UnknownError', 'authentication_error', 'Unexpected exit state'); }, }; } diff --git a/packages/davinci-client/src/lib/password-policy.rules.ts b/packages/davinci-client/src/lib/password-policy.rules.ts index 2d6f517fe5..7a74d91616 100644 --- a/packages/davinci-client/src/lib/password-policy.rules.ts +++ b/packages/davinci-client/src/lib/password-policy.rules.ts @@ -4,7 +4,7 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { Array as Arr, Option, pipe } from 'effect'; +import { Array as Arr, Result, pipe } from 'effect'; import type { ValidatedPasswordCollector } from './collector.types.js'; import type { PasswordPolicy } from './davinci.types.js'; @@ -66,8 +66,8 @@ const minCharactersRule: PasswordPolicyRule = (policy, value) => { let hits = 0; for (const ch of value) if (members.has(ch)) hits += 1; return hits < min - ? Option.some(`Password must contain at least ${min} character(s) from "${charset}"`) - : Option.none(); + ? Result.succeed(`Password must contain at least ${min} character(s) from "${charset}"`) + : Result.failVoid; }), ); }; diff --git a/packages/journey-client/src/lib/client.store.ts b/packages/journey-client/src/lib/client.store.ts index 32c2689a64..353e5ef973 100644 --- a/packages/journey-client/src/lib/client.store.ts +++ b/packages/journey-client/src/lib/client.store.ts @@ -20,7 +20,7 @@ import { createJourneyStore } from './client.store.utils.js'; import { configSlice } from './config.slice.js'; import { journeyApi } from './journey.api.js'; import { createStorage } from '@forgerock/storage'; -import * as Either from 'effect/Either'; +import * as Result from 'effect/Result'; import { createJourneyObject, parseJourneyResponse } from './journey.utils.js'; import type { JourneyResult } from './journey.utils.js'; import { wellknownApi } from './wellknown.api.js'; @@ -158,9 +158,9 @@ export async function journey({ start: async (options?: StartParam) => { const response = await store.dispatch(journeyApi.endpoints.start.initiate(options)); - return Either.match(parseJourneyResponse(response), { - onLeft: (err): JourneyResult => err, - onRight: (step): JourneyResult => createJourneyObject(step), + return Result.match(parseJourneyResponse(response), { + onFailure: (err): JourneyResult => err, + onSuccess: (step): JourneyResult => createJourneyObject(step), }); }, @@ -169,9 +169,9 @@ export async function journey({ */ next: async (step: JourneyStep, options?: NextOptions) => { const response = await store.dispatch(journeyApi.endpoints.next.initiate({ step, options })); - return Either.match(parseJourneyResponse(response), { - onLeft: (err): JourneyResult => err, - onRight: (step): JourneyResult => createJourneyObject(step), + return Result.match(parseJourneyResponse(response), { + onFailure: (err): JourneyResult => err, + onSuccess: (step): JourneyResult => createJourneyObject(step), }); }, diff --git a/packages/journey-client/src/lib/journey.utils.test.ts b/packages/journey-client/src/lib/journey.utils.test.ts index 30718d8159..a271c8bfc8 100644 --- a/packages/journey-client/src/lib/journey.utils.test.ts +++ b/packages/journey-client/src/lib/journey.utils.test.ts @@ -70,8 +70,8 @@ describe('parseJourneyResponse', () => { const result = parseJourneyResponse({ data: undefined, error }); - expect(result._tag).toBe('Right'); - expect((result as { right: unknown }).right).toBe(body); + expect(result._tag).toBe('Success'); + expect((result as { success: unknown }).success).toBe(body); }); it('returns left(GenericError) when FetchBaseQueryError has numeric status but non-object body', () => { @@ -79,8 +79,8 @@ describe('parseJourneyResponse', () => { const result = parseJourneyResponse({ data: undefined, error }); - expect(result._tag).toBe('Left'); - expect((result as { left: unknown }).left).toMatchObject({ + expect(result._tag).toBe('Failure'); + expect((result as { failure: unknown }).failure).toMatchObject({ error: 'request_failed', type: 'unknown_error', }); @@ -91,8 +91,8 @@ describe('parseJourneyResponse', () => { const result = parseJourneyResponse({ data: undefined, error }); - expect(result._tag).toBe('Left'); - expect((result as { left: { message: string } }).left.message).toContain('Network error'); + expect(result._tag).toBe('Failure'); + expect((result as { failure: { message: string } }).failure.message).toContain('Network error'); }); it('returns left(GenericError) for PARSING_ERROR', () => { @@ -105,8 +105,10 @@ describe('parseJourneyResponse', () => { const result = parseJourneyResponse({ data: undefined, error }); - expect(result._tag).toBe('Left'); - expect((result as { left: { message: string } }).left.message).toContain('JSON parse error'); + expect(result._tag).toBe('Failure'); + expect((result as { failure: { message: string } }).failure.message).toContain( + 'JSON parse error', + ); }); it('returns left(GenericError) for TIMEOUT_ERROR', () => { @@ -114,8 +116,10 @@ describe('parseJourneyResponse', () => { const result = parseJourneyResponse({ data: undefined, error }); - expect(result._tag).toBe('Left'); - expect((result as { left: { message: string } }).left.message).toContain('Request timed out'); + expect(result._tag).toBe('Failure'); + expect((result as { failure: { message: string } }).failure.message).toContain( + 'Request timed out', + ); }); it('returns left(GenericError) for CUSTOM_ERROR', () => { @@ -123,8 +127,8 @@ describe('parseJourneyResponse', () => { const result = parseJourneyResponse({ data: undefined, error }); - expect(result._tag).toBe('Left'); - expect((result as { left: { message: string } }).left.message).toContain( + expect(result._tag).toBe('Failure'); + expect((result as { failure: { message: string } }).failure.message).toContain( 'Custom error occurred', ); }); @@ -134,8 +138,8 @@ describe('parseJourneyResponse', () => { const result = parseJourneyResponse({ data: undefined, error }); - expect(result._tag).toBe('Left'); - expect((result as { left: { message: string } }).left.message).toContain( + expect(result._tag).toBe('Failure'); + expect((result as { failure: { message: string } }).failure.message).toContain( 'Something went wrong', ); }); @@ -143,8 +147,8 @@ describe('parseJourneyResponse', () => { it('returns left(GenericError) when no data and no error', () => { const result = parseJourneyResponse({ data: undefined, error: undefined }); - expect(result._tag).toBe('Left'); - expect((result as { left: unknown }).left).toMatchObject({ + expect(result._tag).toBe('Failure'); + expect((result as { failure: unknown }).failure).toMatchObject({ error: 'no_response_data', type: 'unknown_error', }); @@ -155,7 +159,7 @@ describe('parseJourneyResponse', () => { const result = parseJourneyResponse({ data, error: undefined }); - expect(result._tag).toBe('Right'); - expect((result as { right: unknown }).right).toBe(data); + expect(result._tag).toBe('Success'); + expect((result as { success: unknown }).success).toBe(data); }); }); diff --git a/packages/journey-client/src/lib/journey.utils.ts b/packages/journey-client/src/lib/journey.utils.ts index 198721e43e..3605ce05c7 100644 --- a/packages/journey-client/src/lib/journey.utils.ts +++ b/packages/journey-client/src/lib/journey.utils.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ -import * as Either from 'effect/Either'; +import * as Result from 'effect/Result'; import { StepType } from '@forgerock/sdk-types'; @@ -71,7 +71,7 @@ export function createJourneyObject( export function parseJourneyResponse(res: { data?: Step; error?: FetchBaseQueryError | SerializedError; -}): Either.Either { +}): Result.Result { // https://redux-toolkit.js.org/rtk-query/api/fetchBaseQuery#signature // AM sends LoginFailure as a structured step body over HTTP 4xx — normalise both sources so the // left guards below only see genuine transport failures, never AM application responses. @@ -88,7 +88,7 @@ export function parseJourneyResponse(res: { // https://redux-toolkit.js.org/rtk-query/usage-with-typescript#type-safe-error-handling // Non-HTTP fetch failure (network down, CORS, etc.) — definitely left, never carries an AM body if (res.error && 'error' in res.error) { - return Either.left({ + return Result.fail({ error: 'request_failed', message: `Request failed: ${res.error.error}`, type: 'unknown_error', @@ -97,7 +97,7 @@ export function parseJourneyResponse(res: { // Redux serialization error — definitely left, never carries an AM body if (res.error && 'message' in res.error) { - return Either.left({ + return Result.fail({ error: 'request_failed', message: `Request failed: ${res.error.message ?? 'Unknown error'}`, type: 'unknown_error', @@ -106,7 +106,7 @@ export function parseJourneyResponse(res: { // HTTP error whose body was not a parseable AM step — left if (res.error && !stepData) { - return Either.left({ + return Result.fail({ error: 'request_failed', message: 'Request failed: Unknown error', type: 'unknown_error', @@ -115,7 +115,7 @@ export function parseJourneyResponse(res: { // No data from either source — left if (!stepData) { - return Either.left({ + return Result.fail({ error: 'no_response_data', message: 'No data received from server', type: 'unknown_error', @@ -123,5 +123,5 @@ export function parseJourneyResponse(res: { } // Every transport failure has been ruled out — this is a valid AM step - return Either.right(stepData); + return Result.succeed(stepData); } diff --git a/packages/oidc-client/src/lib/authorize.request.micros.test.ts b/packages/oidc-client/src/lib/authorize.request.micros.test.ts index 289617eae9..6a40bbd4df 100644 --- a/packages/oidc-client/src/lib/authorize.request.micros.test.ts +++ b/packages/oidc-client/src/lib/authorize.request.micros.test.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ import { it, expect } from '@effect/vitest'; -import { Micro } from 'effect'; +import { Cause, Effect, Exit, Option } from 'effect'; import { vi, afterEach } from 'vitest'; import * as sdkOidc from '@forgerock/sdk-oidc'; import * as sdkUtilities from '@forgerock/sdk-utilities'; @@ -61,7 +61,7 @@ afterEach(() => { // ─── generateAuthValuesµ ─────────────────────────────────────────────────────── it.effect('generateAuthValuesµ returns auth URL options and store function', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.stubGlobal('sessionStorage', sessionStorageStub); const result = yield* generateAuthValuesµ(config, wellknown); const [opts, storeFn] = result; @@ -73,22 +73,24 @@ it.effect('generateAuthValuesµ returns auth URL options and store function', () ); it.effect('generateAuthValuesµ fails with auth_error when sessionStorage throws', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.spyOn(sdkOidc, 'generateAndStoreAuthUrlValues').mockImplementation(() => { throw new Error('storage unavailable'); }); - const exit = yield* Micro.exit(generateAuthValuesµ(config, wellknown)); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.type).toBe('auth_error'); - expect(exit.cause.error.error).toBe('PAR_PARAM_BUILD_ERROR'); + const exit = yield* Effect.exit(generateAuthValuesµ(config, wellknown)); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('auth_error'); + expect(errorOpt.value.error).toBe('PAR_PARAM_BUILD_ERROR'); }), ); // ─── generatePkceChallengeµ ──────────────────────────────────────────────────── it.effect('generatePkceChallengeµ returns a non-empty challenge string', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.stubGlobal('crypto', { subtle: { digest: vi.fn().mockResolvedValue(new ArrayBuffer(32)), @@ -102,20 +104,22 @@ it.effect('generatePkceChallengeµ returns a non-empty challenge string', () => ); it.effect('generatePkceChallengeµ fails with auth_error when createChallenge throws', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.spyOn(sdkUtilities, 'createChallenge').mockRejectedValue(new Error('crypto unavailable')); - const exit = yield* Micro.exit(generatePkceChallengeµ('bad-verifier')); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.type).toBe('auth_error'); - expect(exit.cause.error.error).toBe('PAR_CHALLENGE_ERROR'); + const exit = yield* Effect.exit(generatePkceChallengeµ('bad-verifier')); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('auth_error'); + expect(errorOpt.value.error).toBe('PAR_CHALLENGE_ERROR'); }), ); // ─── buildParBodyµ ───────────────────────────────────────────────────────────── it.effect('buildParBodyµ returns URLSearchParams with expected fields', () => - Micro.gen(function* () { + Effect.gen(function* () { const params = yield* buildParBodyµ(config, {}, 'challenge-abc', 'state-xyz'); expect(params.get('client_id')).toBe(clientId); expect(params.get('code_challenge')).toBe('challenge-abc'); @@ -126,29 +130,31 @@ it.effect('buildParBodyµ returns URLSearchParams with expected fields', () => ); it.effect('buildParBodyµ includes prompt when provided', () => - Micro.gen(function* () { + Effect.gen(function* () { const params = yield* buildParBodyµ(config, {}, 'challenge-abc', 'state-xyz', 'login'); expect(params.get('prompt')).toBe('login'); }), ); it.effect('buildParBodyµ fails with auth_error when buildAuthorizeParams throws', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.spyOn(sdkOidc, 'buildAuthorizeParams').mockImplementation(() => { throw new Error('build failed'); }); - const exit = yield* Micro.exit(buildParBodyµ(config, {}, 'ch', 'st')); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.type).toBe('auth_error'); - expect(exit.cause.error.error).toBe('PAR_PARAM_BUILD_ERROR'); + const exit = yield* Effect.exit(buildParBodyµ(config, {}, 'ch', 'st')); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('auth_error'); + expect(errorOpt.value.error).toBe('PAR_PARAM_BUILD_ERROR'); }), ); // ─── buildParSlimUrlµ ────────────────────────────────────────────────────────── it.effect('buildParSlimUrlµ returns URL with only client_id and request_uri', () => - Micro.gen(function* () { + Effect.gen(function* () { const url = yield* buildParSlimUrlµ( wellknown.authorization_endpoint, clientId, @@ -162,7 +168,7 @@ it.effect('buildParSlimUrlµ returns URL with only client_id and request_uri', ( ); it.effect('buildParSlimUrlµ includes prompt when provided', () => - Micro.gen(function* () { + Effect.gen(function* () { const url = yield* buildParSlimUrlµ( wellknown.authorization_endpoint, clientId, @@ -176,7 +182,7 @@ it.effect('buildParSlimUrlµ includes prompt when provided', () => // ─── storeAuthOptionsµ ───────────────────────────────────────────────────────── it.effect('storeAuthOptionsµ calls the provided store function', () => - Micro.gen(function* () { + Effect.gen(function* () { const storeFn = vi.fn(); yield* storeAuthOptionsµ(storeFn); expect(storeFn).toHaveBeenCalledOnce(); @@ -184,23 +190,25 @@ it.effect('storeAuthOptionsµ calls the provided store function', () => ); it.effect('storeAuthOptionsµ fails with unknown_error when store function throws', () => - Micro.gen(function* () { - const exit = yield* Micro.exit( + Effect.gen(function* () { + const exit = yield* Effect.exit( storeAuthOptionsµ(() => { throw new Error('storage write failed'); }), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.type).toBe('unknown_error'); - expect(exit.cause.error.error).toBe('PAR_STORAGE_ERROR'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('unknown_error'); + expect(errorOpt.value.error).toBe('PAR_STORAGE_ERROR'); }), ); // ─── validateParResponseµ ────────────────────────────────────────────────────── it.effect('validateParResponseµ succeeds when request_uri is present', () => - Micro.gen(function* () { + Effect.gen(function* () { const result = yield* validateParResponseµ({ data: { request_uri: 'urn:ietf:params:oauth:request_uri:xyz', expires_in: 60 }, }); @@ -209,8 +217,8 @@ it.effect('validateParResponseµ succeeds when request_uri is present', () => ); it.effect('validateParResponseµ fails with network_error on RTK error', () => - Micro.gen(function* () { - const exit = yield* Micro.exit( + Effect.gen(function* () { + const exit = yield* Effect.exit( validateParResponseµ({ error: { status: 400, @@ -218,26 +226,30 @@ it.effect('validateParResponseµ fails with network_error on RTK error', () => }, }), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.error).toBe('invalid_client'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('invalid_client'); }), ); it.effect('validateParResponseµ fails with network_error when request_uri is absent', () => - Micro.gen(function* () { - const exit = yield* Micro.exit(validateParResponseµ({ data: { expires_in: 60 } })); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.type).toBe('network_error'); - expect(exit.cause.error.error_description).toContain('request_uri'); + Effect.gen(function* () { + const exit = yield* Effect.exit(validateParResponseµ({ data: { expires_in: 60 } })); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('network_error'); + expect(errorOpt.value.error_description).toContain('request_uri'); }), ); // ─── createAuthorizeUrlµ ────────────────────────────────────────────────── it.effect('createAuthorizeUrlµ returns [url, options] tuple', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.stubGlobal('sessionStorage', sessionStorageStub); const opts = { clientId, @@ -257,9 +269,9 @@ it.effect('createAuthorizeUrlµ returns [url, options] tuple', () => ); it.effect('createAuthorizeUrlµ fails with auth_error when createAuthorizeUrl rejects', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.spyOn(sdkOidc, 'createAuthorizeUrl').mockRejectedValue(new Error('url build failed')); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( createAuthorizeUrlµ(wellknown.authorization_endpoint, { clientId, redirectUri, @@ -267,18 +279,20 @@ it.effect('createAuthorizeUrlµ fails with auth_error when createAuthorizeUrl re responseType, }), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.type).toBe('auth_error'); - expect(exit.cause.error.error).toBe('AuthorizationUrlError'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('auth_error'); + expect(errorOpt.value.error).toBe('AuthorizationUrlError'); }), ); // ─── handleDispatchErrorµ ────────────────────────────────────────────────────── it.effect('handleDispatchErrorµ fails immediately for CONFIGURATION_ERROR', () => - Micro.gen(function* () { - const exit = yield* Micro.exit( + Effect.gen(function* () { + const exit = yield* Effect.exit( handleDispatchErrorµ( { status: 'CUSTOM_ERROR', @@ -290,18 +304,20 @@ it.effect('handleDispatchErrorµ fails immediately for CONFIGURATION_ERROR', () { clientId, redirectUri, scope, responseType }, ), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.type).toBe('unknown_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('unknown_error'); }), ); it.effect('handleDispatchErrorµ builds redirect URL for non-config errors', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.spyOn(sdkOidc, 'createAuthorizeUrl').mockResolvedValue( 'https://example.com/authorize?error=login_required', ); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( handleDispatchErrorµ( { status: 400, @@ -315,17 +331,19 @@ it.effect('handleDispatchErrorµ builds redirect URL for non-config errors', () { clientId, redirectUri, scope, responseType }, ), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.error).toBe('login_required'); - expect(exit.cause.error).toHaveProperty('redirectUrl'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('login_required'); + expect(errorOpt.value).toHaveProperty('redirectUrl'); }), ); // ─── dispatchAuthorizeFetchµ ─────────────────────────────────────────────────── it.effect('dispatchAuthorizeFetchµ succeeds with authorizeResponse', () => - Micro.gen(function* () { + Effect.gen(function* () { const authorizeResponse = { code: 'auth-code-abc', state: 'state-xyz' }; vi.mocked(mockStore.dispatch).mockResolvedValueOnce({ data: { authorizeResponse }, @@ -344,12 +362,12 @@ it.effect('dispatchAuthorizeFetchµ succeeds with authorizeResponse', () => it.effect( 'dispatchAuthorizeFetchµ fails with unknown_error when data has no authorizeResponse', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.mocked(mockStore.dispatch).mockResolvedValueOnce({ data: {}, } as unknown as ReturnType); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( dispatchAuthorizeFetchµ(mockStore, 'https://example.com/authorize', wellknown, { clientId, redirectUri, @@ -357,16 +375,18 @@ it.effect( responseType, }), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.type).toBe('unknown_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('unknown_error'); }), ); // ─── dispatchAuthorizeIframeµ ────────────────────────────────────────────────── it.effect('dispatchAuthorizeIframeµ succeeds with iframe data', () => - Micro.gen(function* () { + Effect.gen(function* () { const iframeData = { code: 'iframe-code', state: 'state-abc' }; vi.mocked(mockStore.dispatch).mockResolvedValueOnce({ data: iframeData, @@ -383,12 +403,12 @@ it.effect('dispatchAuthorizeIframeµ succeeds with iframe data', () => ); it.effect('dispatchAuthorizeIframeµ fails with unknown_error when data is undefined', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.mocked(mockStore.dispatch).mockResolvedValueOnce({ data: undefined, } as unknown as ReturnType); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( dispatchAuthorizeIframeµ(mockStore, 'https://example.com/authorize', wellknown, { clientId, redirectUri, @@ -396,19 +416,21 @@ it.effect('dispatchAuthorizeIframeµ fails with unknown_error when data is undef responseType, }), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.type).toBe('unknown_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('unknown_error'); }), ); it.effect('dispatchAuthorizeIframeµ fails with unknown_error when data has no code or state', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.mocked(mockStore.dispatch).mockResolvedValueOnce({ data: { unexpected: 'shape' }, } as unknown as ReturnType); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( dispatchAuthorizeIframeµ( mockStore, 'https://example.com/authorize?foo=bar', @@ -416,9 +438,11 @@ it.effect('dispatchAuthorizeIframeµ fails with unknown_error when data has no c {} as import('@forgerock/sdk-types').GetAuthorizationUrlOptions, ), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; - expect(exit.cause.error.type).toBe('unknown_error'); - expect(exit.cause.error.error).toBe('Unknown_Error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('unknown_error'); + expect(errorOpt.value.error).toBe('Unknown_Error'); }), ); diff --git a/packages/oidc-client/src/lib/authorize.request.micros.ts b/packages/oidc-client/src/lib/authorize.request.micros.ts index 59fcc93caf..07f9d9428f 100644 --- a/packages/oidc-client/src/lib/authorize.request.micros.ts +++ b/packages/oidc-client/src/lib/authorize.request.micros.ts @@ -10,7 +10,7 @@ import { generateAndStoreAuthUrlValues, } from '@forgerock/sdk-oidc'; import { createChallenge } from '@forgerock/sdk-utilities'; -import { Micro } from 'effect'; +import { Effect } from 'effect'; import { buildParAuthorizeUrl, @@ -39,8 +39,8 @@ export const generateAuthValuesµ = ( config: OidcConfig, wellknown: WellknownResponse, options?: OptionalAuthorizeOptions, -): Micro.Micro, AuthorizationError, never> => { - return Micro.try({ +): Effect.Effect, AuthorizationError, never> => { + return Effect.try({ try: () => generateAndStoreAuthUrlValues({ clientId: config.clientId, @@ -60,8 +60,8 @@ export const generateAuthValuesµ = ( export const generatePkceChallengeµ = ( verifier: string, -): Micro.Micro => { - return Micro.tryPromise({ +): Effect.Effect => { + return Effect.tryPromise({ try: () => createChallenge(verifier), catch: (err): AuthorizationError => ({ error: 'PAR_CHALLENGE_ERROR', @@ -73,8 +73,8 @@ export const generatePkceChallengeµ = ( export const storeAuthOptionsµ = ( storeOptions: () => void, -): Micro.Micro => { - return Micro.try({ +): Effect.Effect => { + return Effect.try({ try: () => storeOptions(), catch: (err): AuthorizationError => ({ error: 'PAR_STORAGE_ERROR', @@ -92,8 +92,8 @@ export const buildParBodyµ = ( challenge: string, state: string, prompt?: AuthPromptValue, -): Micro.Micro => { - return Micro.try({ +): Effect.Effect => { + return Effect.try({ try: () => buildAuthorizeParams({ clientId: config.clientId, @@ -116,8 +116,8 @@ export const buildParBodyµ = ( export const createAuthorizeUrlµ = ( path: string, options: GetAuthorizationUrlOptions, -): Micro.Micro<[string, GetAuthorizationUrlOptions], AuthorizationError, never> => { - return Micro.tryPromise({ +): Effect.Effect<[string, GetAuthorizationUrlOptions], AuthorizationError, never> => { + return Effect.tryPromise({ try: async () => [await createAuthorizeUrl(path, { ...options, prompt: 'none' }), options] as [ string, @@ -136,8 +136,8 @@ export const buildAuthorizeRedirectUrlµ = ( res: { error: string; error_description: string }, wellknown: WellknownResponse, options: GetAuthorizationUrlOptions, -): Micro.Micro => { - return Micro.tryPromise({ +): Effect.Effect => { + return Effect.tryPromise({ try: () => { const { prompt: _prompt, ...interactiveOptions } = options; return createAuthorizeUrl(wellknown.authorization_endpoint, interactiveOptions); @@ -149,8 +149,8 @@ export const buildAuthorizeRedirectUrlµ = ( type: 'auth_error', }), }).pipe( - Micro.flatMap((url) => - Micro.fail({ + Effect.flatMap((url) => + Effect.fail({ error: res.error, error_description: res.error_description, type: 'auth_error', @@ -163,26 +163,26 @@ export const buildAuthorizeRedirectUrlµ = ( export const validateParResponseµ = (result: { error?: FetchBaseQueryError | SerializedError; data?: unknown; -}): Micro.Micro<{ request_uri: string; expires_in: number }, AuthorizationError, never> => { +}): Effect.Effect<{ request_uri: string; expires_in: number }, AuthorizationError, never> => { if (result.error) { - return Micro.fail(toDispatchError(result.error)); + return Effect.fail(toDispatchError(result.error)); } if (!hasPushRequestUri(result.data)) { - return Micro.fail({ + return Effect.fail({ error: 'PAR_ERROR', error_description: "PAR response missing required 'request_uri' field", type: 'network_error', } as const); } const d = result.data as { request_uri: string; expires_in?: number }; - return Micro.succeed({ request_uri: d.request_uri, expires_in: d.expires_in ?? 60 }); + return Effect.succeed({ request_uri: d.request_uri, expires_in: d.expires_in ?? 60 }); }; export const handleDispatchErrorµ = ( error: FetchBaseQueryError | SerializedError, wellknown: WellknownResponse, options: GetAuthorizationUrlOptions, -): Micro.Micro => { +): Effect.Effect => { const errorDetails = toDispatchError(error); const isConfigError = isFetchBaseQueryError(error) && @@ -190,7 +190,7 @@ export const handleDispatchErrorµ = ( error.statusText === 'CONFIGURATION_ERROR'; return isConfigError - ? Micro.fail(errorDetails) + ? Effect.fail(errorDetails) : buildAuthorizeRedirectUrlµ(errorDetails, wellknown, options); }; @@ -200,12 +200,12 @@ export const dispatchParRequestµ = ( store: ClientStore, parEndpoint: string, body: URLSearchParams, -): Micro.Micro< +): Effect.Effect< { error?: FetchBaseQueryError | SerializedError; data?: unknown }, AuthorizationError, never > => { - return Micro.tryPromise({ + return Effect.tryPromise({ try: () => store.dispatch(oidcApi.endpoints.par.initiate({ endpoint: parEndpoint, body })), catch: (error): AuthorizationError => ({ error: 'PAR_DISPATCH_ERROR', @@ -220,8 +220,8 @@ export const buildParSlimUrlµ = ( clientId: string, requestUri: string, prompt?: AuthPromptValue, -): Micro.Micro => { - return Micro.try({ +): Effect.Effect => { + return Effect.try({ try: () => buildParAuthorizeUrl({ authorizationEndpoint, clientId, requestUri, prompt }), catch: (err): AuthorizationError => ({ error: 'PAR_URL_BUILD_ERROR', @@ -238,8 +238,8 @@ export const dispatchAuthorizeFetchµ = ( url: string, wellknown: WellknownResponse, options: GetAuthorizationUrlOptions, -): Micro.Micro => { - return Micro.tryPromise({ +): Effect.Effect => { + return Effect.tryPromise({ try: () => store.dispatch(oidcApi.endpoints.authorizeFetch.initiate({ url })), catch: (error): AuthorizationError => ({ error: 'AUTHORIZE_DISPATCH_ERROR', @@ -248,14 +248,14 @@ export const dispatchAuthorizeFetchµ = ( type: 'network_error', }), }).pipe( - Micro.flatMap(({ error, data }) => { + Effect.flatMap(({ error, data }) => { if (error) { return handleDispatchErrorµ(error, wellknown, options); } if (data?.authorizeResponse) { - return Micro.succeed(data.authorizeResponse); + return Effect.succeed(data.authorizeResponse); } - return Micro.fail({ + return Effect.fail({ error: 'Unknown_Error', error_description: 'Response schema was not recognized', type: 'unknown_error', @@ -269,8 +269,8 @@ export const dispatchAuthorizeIframeµ = ( url: string, wellknown: WellknownResponse, options: GetAuthorizationUrlOptions, -): Micro.Micro => { - return Micro.tryPromise({ +): Effect.Effect => { + return Effect.tryPromise({ try: () => store.dispatch(oidcApi.endpoints.authorizeIframe.initiate({ url })), catch: (error): AuthorizationError => ({ error: 'AUTHORIZE_DISPATCH_ERROR', @@ -279,15 +279,15 @@ export const dispatchAuthorizeIframeµ = ( type: 'network_error', }), }).pipe( - Micro.flatMap(({ error, data }) => { + Effect.flatMap(({ error, data }) => { if (error) { return handleDispatchErrorµ(error, wellknown, options); } const d = data as { code?: unknown; state?: unknown } | undefined; if (d !== undefined && typeof d.code === 'string' && typeof d.state === 'string') { - return Micro.succeed(d as AuthorizationSuccess); + return Effect.succeed(d as AuthorizationSuccess); } - return Micro.fail({ + return Effect.fail({ error: 'Unknown_Error', error_description: 'Response data did not contain expected code and state fields', type: 'unknown_error', diff --git a/packages/oidc-client/src/lib/authorize.request.ts b/packages/oidc-client/src/lib/authorize.request.ts index 826ce8ec51..e458e6e0e4 100644 --- a/packages/oidc-client/src/lib/authorize.request.ts +++ b/packages/oidc-client/src/lib/authorize.request.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ import { CustomLogger } from '@forgerock/sdk-logger'; -import { Micro } from 'effect'; +import { Effect } from 'effect'; import { buildAuthorizeOptions } from './authorize.request.utils.js'; import { @@ -43,16 +43,20 @@ function dispatchAuthorizeµ( wellknown: WellknownResponse, store: ClientStore, log: CustomLogger, -): Micro.Micro { +): Effect.Effect { if (options.responseMode === 'pi.flow') { const { responseMode: _, ...redirectOptions } = options; return dispatchAuthorizeFetchµ(store, url, wellknown, redirectOptions).pipe( - Micro.tap(() => log.debug('Received success response from authorize fetch endpoint')), + Effect.tap(() => + Effect.sync(() => log.debug('Received success response from authorize fetch endpoint')), + ), ); } return dispatchAuthorizeIframeµ(store, url, wellknown, options).pipe( - Micro.tap(() => log.debug('Received success response from authorize iframe endpoint')), + Effect.tap(() => + Effect.sync(() => log.debug('Received success response from authorize iframe endpoint')), + ), ); } @@ -72,7 +76,7 @@ function dispatchAuthorizeµ( * @param options - Optional request-level overrides; `prompt` is split out * so it appears on the slim URL while the rest of the params go in the * PAR POST body. - * @returns A `Micro` that resolves to the slim authorize URL string or + * @returns An `Effect` that resolves to the slim authorize URL string or * fails with a typed `AuthorizationError`. */ export function createParAuthorizeUrlµ( @@ -81,11 +85,11 @@ export function createParAuthorizeUrlµ( log: CustomLogger, store: ClientStore, options?: OptionalAuthorizeOptions, -): Micro.Micro { +): Effect.Effect { const parEndpoint = wellknown.pushed_authorization_request_endpoint; if (!parEndpoint) { - return Micro.fail({ + return Effect.fail({ error: 'PAR_NOT_CONFIGURED', error_description: 'PAR endpoint not found in server configuration', type: 'wellknown_error', @@ -94,7 +98,7 @@ export function createParAuthorizeUrlµ( const { prompt, ...parBodyOptions } = options ?? {}; - return Micro.gen(function* () { + return Effect.gen(function* () { const [authUrlOptions, storeOptions] = yield* generateAuthValuesµ(config, wellknown, options); const challenge = yield* generatePkceChallengeµ(authUrlOptions.verifier); const body = yield* buildParBodyµ( @@ -107,7 +111,7 @@ export function createParAuthorizeUrlµ( const parResult = yield* dispatchParRequestµ(store, parEndpoint, body); const { request_uri, expires_in } = yield* validateParResponseµ(parResult); if (expires_in < 30) { - yield* Micro.sync(() => + yield* Effect.sync(() => log.warn( `PAR request_uri expires in ${expires_in}s — authorize must complete before expiry`, ), @@ -143,7 +147,7 @@ export function createParAuthorizeUrlµ( * indicating whether to use the PAR flow. The caller owns the derivation * logic (`config.par ?? require_pushed_authorization_requests === true`); * this function simply routes on the resolved value. - * @returns A `Micro` that resolves to an `AuthorizationSuccess` containing + * @returns An `Effect` that resolves to an `AuthorizationSuccess` containing * the `code` and `state`, or fails with a typed `AuthorizationError`. */ export function authorizeµ( @@ -153,7 +157,7 @@ export function authorizeµ( store: ClientStore, options: GetAuthorizationUrlOptions | undefined, useParFlow: boolean, -): Micro.Micro { +): Effect.Effect { const parDispatchOptions: GetAuthorizationUrlOptions = { clientId: config.clientId, redirectUri: config.redirectUri, @@ -163,14 +167,14 @@ export function authorizeµ( }; const parFlow = createParAuthorizeUrlµ(wellknown, config, log, store, options).pipe( - Micro.tap((url) => log.debug('PAR authorize URL created', url)), - Micro.tapError((err) => - Micro.sync(() => log.error(`PAR authorize failed [${err.type}]: ${err.error}`, err)), + Effect.tap((url) => Effect.sync(() => log.debug('PAR authorize URL created', url))), + Effect.tapError((err) => + Effect.sync(() => log.error(`PAR authorize failed [${err.type}]: ${err.error}`, err)), ), - Micro.flatMap((url) => + Effect.flatMap((url) => dispatchAuthorizeµ(url, parDispatchOptions, wellknown, store, log).pipe( - Micro.tapError((err) => - Micro.sync(() => log.error('Error dispatching PAR authorize request', err)), + Effect.tapError((err) => + Effect.sync(() => log.error('Error dispatching PAR authorize request', err)), ), ), ), @@ -178,13 +182,13 @@ export function authorizeµ( const [path, opts] = buildAuthorizeOptions(wellknown, config, options); const standardFlow = createAuthorizeUrlµ(path, opts).pipe( - Micro.tap(([url]) => log.debug('Authorize URL created', url)), - Micro.tapError((err) => Micro.sync(() => log.error('Error creating authorize URL', err))), - Micro.flatMap(([url, dispatchOpts]) => + Effect.tap(([url]) => Effect.sync(() => log.debug('Authorize URL created', url))), + Effect.tapError((err) => Effect.sync(() => log.error('Error creating authorize URL', err))), + Effect.flatMap(([url, dispatchOpts]) => dispatchAuthorizeµ(url, dispatchOpts, wellknown, store, log), ), - Micro.tapError((err) => - Micro.sync(() => log.error('Error dispatching authorize request', err)), + Effect.tapError((err) => + Effect.sync(() => log.error('Error dispatching authorize request', err)), ), ); diff --git a/packages/oidc-client/src/lib/authorize.request.utils.test.ts b/packages/oidc-client/src/lib/authorize.request.utils.test.ts index d267eb593f..8b185c10a7 100644 --- a/packages/oidc-client/src/lib/authorize.request.utils.test.ts +++ b/packages/oidc-client/src/lib/authorize.request.utils.test.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ import { it } from '@effect/vitest'; -import { Micro } from 'effect'; +import { Cause, Effect, Exit, Option } from 'effect'; import { vi, afterEach, expect } from 'vitest'; import * as sdkOidc from '@forgerock/sdk-oidc'; import { createParAuthorizeUrlµ, authorizeµ } from './authorize.request.js'; @@ -66,6 +66,7 @@ const sessionStorageStub = { getItem: vi.fn(), setItem: vi.fn(), removeItem: vi. afterEach(() => { vi.unstubAllGlobals(); + vi.clearAllMocks(); vi.restoreAllMocks(); }); @@ -131,26 +132,23 @@ it('toDispatchError delegates to toAuthorizationError for FetchBaseQueryError', // ─── createParAuthorizeUrlµ ─────────────────────────────────────────────────────────── it.effect('createParAuthorizeUrlµ fails with PAR_NOT_CONFIGURED when par endpoint is missing', () => - Micro.gen(function* () { + Effect.gen(function* () { const configWithPar: OidcConfig = { ...config, par: true }; - const result = yield* Micro.exit( + const result = yield* Effect.exit( createParAuthorizeUrlµ(wellknown, configWithPar, mockLog, mockStore), ); - expect(Micro.exitIsFailure(result)).toBe(true); - if (!Micro.exitIsFailure(result)) return; - expect(Micro.causeIsFail(result.cause)).toBe(true); - if (Micro.causeIsFail(result.cause)) { - expect(result.cause.error.error).toBe('PAR_NOT_CONFIGURED'); - expect(result.cause.error.type).toBe('wellknown_error'); - expect(result.cause.error.error_description).toBe( - 'PAR endpoint not found in server configuration', - ); - } + expect(Exit.isFailure(result)).toBe(true); + if (!Exit.isFailure(result)) return; + const errorOpt = Cause.findErrorOption(result.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('PAR_NOT_CONFIGURED'); + expect(errorOpt.value.type).toBe('wellknown_error'); + expect(errorOpt.value.error_description).toBe('PAR endpoint not found in server configuration'); }), ); it.effect('createParAuthorizeUrlµ succeeds and returns slim authorize URL', () => - Micro.gen(function* () { + Effect.gen(function* () { const configWithPar: OidcConfig = { ...config, par: true }; const requestUri = 'urn:ietf:params:oauth:request_uri:abc123'; @@ -170,7 +168,7 @@ it.effect('createParAuthorizeUrlµ succeeds and returns slim authorize URL', () ); it.effect('createParAuthorizeUrlµ fails with network_error when PAR POST returns error', () => - Micro.gen(function* () { + Effect.gen(function* () { const configWithPar: OidcConfig = { ...config, par: true }; vi.stubGlobal('sessionStorage', sessionStorageStub); @@ -182,16 +180,15 @@ it.effect('createParAuthorizeUrlµ fails with network_error when PAR POST return }, } as unknown as ReturnType); - const result = yield* Micro.exit( + const result = yield* Effect.exit( createParAuthorizeUrlµ(wellknownWithPar, configWithPar, mockLog, mockStore), ); - expect(Micro.exitIsFailure(result)).toBe(true); - if (!Micro.exitIsFailure(result)) return; - expect(Micro.causeIsFail(result.cause)).toBe(true); - if (Micro.causeIsFail(result.cause)) { - expect(result.cause.error.type).toBe('network_error'); - } + expect(Exit.isFailure(result)).toBe(true); + if (!Exit.isFailure(result)) return; + const errorOpt = Cause.findErrorOption(result.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('network_error'); expect(sessionStorageStub.setItem).not.toHaveBeenCalled(); }), ); @@ -199,7 +196,7 @@ it.effect('createParAuthorizeUrlµ fails with network_error when PAR POST return it.effect( 'createParAuthorizeUrlµ fails with network_error when PAR response is missing request_uri', () => - Micro.gen(function* () { + Effect.gen(function* () { const configWithPar: OidcConfig = { ...config, par: true }; vi.stubGlobal('sessionStorage', sessionStorageStub); @@ -207,19 +204,18 @@ it.effect( data: {}, } as unknown as ReturnType); - const result = yield* Micro.exit( + const result = yield* Effect.exit( createParAuthorizeUrlµ(wellknownWithPar, configWithPar, mockLog, mockStore), ); - expect(Micro.exitIsFailure(result)).toBe(true); - if (!Micro.exitIsFailure(result)) return; - expect(Micro.causeIsFail(result.cause)).toBe(true); - if (Micro.causeIsFail(result.cause)) { - expect(result.cause.error.type).toBe('network_error'); - expect(result.cause.error.error_description).toBe( - "PAR response missing required 'request_uri' field", - ); - } + expect(Exit.isFailure(result)).toBe(true); + if (!Exit.isFailure(result)) return; + const errorOpt = Cause.findErrorOption(result.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('network_error'); + expect(errorOpt.value.error_description).toBe( + "PAR response missing required 'request_uri' field", + ); expect(sessionStorageStub.setItem).not.toHaveBeenCalled(); }), ); @@ -227,7 +223,7 @@ it.effect( it.effect( 'createParAuthorizeUrlµ with prompt=none includes prompt on slim authorize URL and in PAR body', () => - Micro.gen(function* () { + Effect.gen(function* () { const configWithPar: OidcConfig = { ...config, par: true }; const requestUri = 'urn:ietf:params:oauth:request_uri:prompt-none-test'; @@ -288,13 +284,15 @@ it('hasPushRequestUri returns false when request_uri is missing', () => { import { validateParResponseµ } from './authorize.request.micros.js'; it.effect('validateParResponseµ with SerializedError preserves error message', () => - Micro.gen(function* () { + Effect.gen(function* () { const serializedError = { name: 'Error', message: 'network timeout', code: 'FETCH_ERROR' }; - const exit = yield* Micro.exit(validateParResponseµ({ error: serializedError })); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) return; + const exit = yield* Effect.exit(validateParResponseµ({ error: serializedError })); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; // Should surface the actual message, not generic "Unknown_Error" - expect(exit.cause.error.error_description).toContain('network timeout'); + expect(errorOpt.value.error_description).toContain('network timeout'); }), ); @@ -378,7 +376,7 @@ it('buildAuthorizeOptions falls back to "openid" scope and "code" responseType w // ─── authorizeµ flow routing ────────────────────────────────────────────────── it.effect('authorizeµ uses PAR flow when useParFlow=true', () => - Micro.gen(function* () { + Effect.gen(function* () { const requestUri = 'urn:ietf:params:oauth:request_uri:par-routing-test'; const authorizeResponse = { code: 'par-code', state: 'par-state' }; @@ -401,7 +399,7 @@ it.effect('authorizeµ uses PAR flow when useParFlow=true', () => ); it.effect('authorizeµ uses standard flow when useParFlow=false', () => - Micro.gen(function* () { + Effect.gen(function* () { const authorizeResponse = { code: 'std-code', state: 'std-state' }; vi.stubGlobal('sessionStorage', sessionStorageStub); @@ -422,7 +420,7 @@ it.effect('authorizeµ uses standard flow when useParFlow=false', () => it.effect( 'authorizeµ uses PAR flow when caller passes useParFlow=true (e.g. server requires PAR)', () => - Micro.gen(function* () { + Effect.gen(function* () { const requestUri = 'urn:ietf:params:oauth:request_uri:required-par-test'; const authorizeResponse = { code: 'req-par-code', state: 'req-par-state' }; @@ -452,7 +450,7 @@ it.effect( it.effect( 'authorizeµ routes to pi.flow fetch when options.responseMode is pi.flow (unwraps authorizeResponse)', () => - Micro.gen(function* () { + Effect.gen(function* () { // pi.flow dispatch goes through dispatchAuthorizeFetch which unwraps { authorizeResponse } const requestUri = 'urn:ietf:params:oauth:request_uri:pi-flow-test'; const authorizeResponse = { code: 'pi-code', state: 'pi-state' }; diff --git a/packages/oidc-client/src/lib/client.store.ts b/packages/oidc-client/src/lib/client.store.ts index dbd80e4221..d93fce9c1b 100644 --- a/packages/oidc-client/src/lib/client.store.ts +++ b/packages/oidc-client/src/lib/client.store.ts @@ -7,13 +7,12 @@ import { logger as loggerFn } from '@forgerock/sdk-logger'; import { createAuthorizeUrl } from '@forgerock/sdk-oidc'; import { createStorage } from '@forgerock/storage'; -import { Micro } from 'effect'; -import { causeIsDie, exitIsFail, exitIsSuccess } from 'effect/Micro'; +import { Cause, Effect, Exit, Option } from 'effect'; import { authorizeµ, createParAuthorizeUrlµ } from './authorize.request.js'; import { buildTokenExchangeµ } from './exchange.request.js'; import { createClientStore, createTokenError } from './client.store.utils.js'; -import { handleMicroExit } from '@forgerock/sdk-utilities'; +import { handleExit } from '@forgerock/sdk-utilities'; import { isExpiryWithinThreshold } from './token.utils.js'; import { logoutµ } from './logout.request.js'; import { oidcApi } from './oidc.api.js'; @@ -140,34 +139,37 @@ export async function oidc({ } if (useParFlow) { - const result = await Micro.runPromiseExit( + const result = await Effect.runPromiseExit( createParAuthorizeUrlµ(wellknown, config, log, store, options).pipe( - Micro.tapError((err) => - Micro.sync(() => + Effect.tapError((err) => + Effect.sync(() => log.error(`PAR authorize.url() failed [${err.type}]: ${err.error}`, err), ), ), ), ); - if (exitIsSuccess(result)) { + if (Exit.isSuccess(result)) { return result.value; - } else if (exitIsFail(result)) { - const authErr = result.cause.error; + } + const authUrlFailure = Cause.findErrorOption(result.cause); + if (Option.isSome(authUrlFailure)) { + const authErr = authUrlFailure.value; return { error: authErr.error, message: authErr.error_description, type: authErr.type, }; - } else { - const defect = causeIsDie(result.cause) ? result.cause.defect : undefined; - return { - error: 'PAR authorization failure', - message: - defect instanceof Error ? defect.message : String(defect ?? 'Unknown defect'), - type: 'auth_error', - }; } + const authUrlDefect = Cause.squash(result.cause); + return { + error: 'PAR authorization failure', + message: + authUrlDefect instanceof Error + ? authUrlDefect.message + : String(authUrlDefect ?? 'Unknown defect'), + type: 'auth_error', + }; } const optionsWithDefaults = { @@ -207,7 +209,7 @@ export async function oidc({ }; } - const result = await Micro.runPromiseExit( + const result = await Effect.runPromiseExit( authorizeµ( wellknown, config, @@ -218,19 +220,22 @@ export async function oidc({ ), ); - if (exitIsSuccess(result)) { + if (Exit.isSuccess(result)) { return result.value; - } else if (exitIsFail(result)) { - return result.cause.error; - } else { - const defect = causeIsDie(result.cause) ? result.cause.defect : undefined; - return { - error: 'Authorization failure', - error_description: - defect instanceof Error ? defect.message : String(defect ?? 'Unknown defect'), - type: 'auth_error', - }; } + const bgAuthFailure = Cause.findErrorOption(result.cause); + if (Option.isSome(bgAuthFailure)) { + return bgAuthFailure.value; + } + const bgAuthDefect = Cause.squash(result.cause); + return { + error: 'Authorization failure', + error_description: + bgAuthDefect instanceof Error + ? bgAuthDefect.message + : String(bgAuthDefect ?? 'Unknown defect'), + type: 'auth_error', + }; }, }, /** @@ -269,14 +274,10 @@ export async function oidc({ endpoint: wellknown.token_endpoint, store, options, - }).pipe( - Micro.tap(async (tokens) => { - await storageClient.set(tokens); - }), - ); + }).pipe(Effect.tap((tokens) => Effect.promise(() => storageClient.set(tokens)))); - const result = await Micro.runPromiseExit(getTokensµ); - return handleMicroExit(result, 'Token Exchange failure', 'exchange_error'); + const result = await Effect.runPromiseExit(getTokensµ); + return handleExit(result, 'Token Exchange failure', 'exchange_error'); }, /** @@ -338,47 +339,54 @@ export async function oidc({ { ...(authorizeOptions ?? ({} as GetAuthorizationUrlOptions)), prompt: 'none' as const }, useParFlow, ).pipe( - Micro.flatMap((response): Micro.Micro => { - return buildTokenExchangeµ({ - code: response.code, - config, - log, - state: response.state, - endpoint: wellknown.token_endpoint, - store, - options: storageOptions, - }); - }), - Micro.tap(async (newTokens) => { - if (tokens && 'accessToken' in tokens) { - await store.dispatch( - oidcApi.endpoints.revoke.initiate({ - accessToken: tokens.accessToken, - clientId: config.clientId, - endpoint: wellknown.revocation_endpoint, - }), - ); - await storageClient.remove(); - } - await storageClient.set(newTokens); - }), + Effect.flatMap( + (response): Effect.Effect => { + return buildTokenExchangeµ({ + code: response.code, + config, + log, + state: response.state, + endpoint: wellknown.token_endpoint, + store, + options: storageOptions, + }); + }, + ), + Effect.tap((newTokens) => + Effect.promise(async () => { + if (tokens && 'accessToken' in tokens) { + await store.dispatch( + oidcApi.endpoints.revoke.initiate({ + accessToken: tokens.accessToken, + clientId: config.clientId, + endpoint: wellknown.revocation_endpoint, + }), + ); + await storageClient.remove(); + } + await storageClient.set(newTokens); + }), + ), ); - const result = await Micro.runPromiseExit(attemptAuthorizeGetTokensµ); + const result = await Effect.runPromiseExit(attemptAuthorizeGetTokensµ); - if (exitIsSuccess(result)) { + if (Exit.isSuccess(result)) { return result.value; - } else if (exitIsFail(result)) { - return result.cause.error; - } else { - const defect = causeIsDie(result.cause) ? result.cause.defect : undefined; - return { - error: 'Background token renewal failed', - error_description: - defect instanceof Error ? defect.message : String(defect ?? 'Unknown defect'), - type: 'auth_error', - }; } + const tokenGetFailure = Cause.findErrorOption(result.cause); + if (Option.isSome(tokenGetFailure)) { + return tokenGetFailure.value; + } + const tokenGetDefect = Cause.squash(result.cause); + return { + error: 'Background token renewal failed', + error_description: + tokenGetDefect instanceof Error + ? tokenGetDefect.message + : String(tokenGetDefect ?? 'Unknown defect'), + type: 'auth_error', + }; }, /** * @method revoke @@ -406,7 +414,7 @@ export async function oidc({ }; } - const revokeµ = Micro.promise(() => + const revokeµ = Effect.promise(() => store.dispatch( oidcApi.endpoints.revoke.initiate({ accessToken: tokens.accessToken, @@ -415,7 +423,7 @@ export async function oidc({ }), ), ).pipe( - Micro.map(({ error }) => { + Effect.map(({ error }) => { if (error) { let message = 'An error occurred while revoking the token'; let status: number | string = 'unknown'; @@ -436,9 +444,9 @@ export async function oidc({ return null; }), // Delete local token and return combined results - Micro.flatMap((revokeResponse) => - Micro.promise(() => storageClient.remove()).pipe( - Micro.flatMap((deleteResponse) => { + Effect.flatMap((revokeResponse) => + Effect.promise(() => storageClient.remove()).pipe( + Effect.flatMap((deleteResponse) => { const isInnerRequestError = (revokeResponse && 'error' in revokeResponse) || (deleteResponse && 'error' in deleteResponse); @@ -449,21 +457,21 @@ export async function oidc({ revokeResponse, deleteResponse, }; - return Micro.fail(result); + return Effect.fail(result); } else { const result: RevokeSuccessResult = { revokeResponse: null, deleteResponse: null, }; - return Micro.succeed(result); + return Effect.succeed(result); } }), ), ), ); - const result = await Micro.runPromiseExit(revokeµ); - return handleMicroExit(result, 'Token revocation failure', 'auth_error'); + const result = await Effect.runPromiseExit(revokeµ); + return handleExit(result, 'Token revocation failure', 'auth_error'); }, }, @@ -497,7 +505,7 @@ export async function oidc({ }; } - const info = Micro.promise(() => + const info = Effect.promise(() => store.dispatch( oidcApi.endpoints.userInfo.initiate({ accessToken: tokens.accessToken, @@ -505,7 +513,7 @@ export async function oidc({ }), ), ).pipe( - Micro.flatMap(({ data, error }) => { + Effect.flatMap(({ data, error }) => { if (error) { let message = 'An error occurred while fetching user info'; let status: number | string = 'unknown'; @@ -515,19 +523,19 @@ export async function oidc({ if ('status' in error) { status = error.status; } - return Micro.fail({ + return Effect.fail({ error: 'User Info retrieval failure', message, type: 'auth_error', status, } as const); } - return Micro.succeed(data); + return Effect.succeed(data); }), ); - const result = await Micro.runPromiseExit(info); - return handleMicroExit(result, 'User Info retrieval failure', 'auth_error'); + const result = await Effect.runPromiseExit(info); + return handleExit(result, 'User Info retrieval failure', 'auth_error'); }, /** @@ -568,10 +576,10 @@ export async function oidc({ return createTokenError('no_id_token'); } - const result = await Micro.runPromiseExit( + const result = await Effect.runPromiseExit( logoutµ({ tokens, config, wellknown, store, storageClient }), ); - return handleMicroExit(result, 'Logout_Failure', 'auth_error'); + return handleExit(result, 'Logout_Failure', 'auth_error'); }, /** @@ -596,13 +604,13 @@ export async function oidc({ }; } - const micro = + const effect = options?.responseType === 'id_token' ? sessionCheckIdTokenµ(wellknown, config, store, storageClient, log, options) : sessionCheckNoneµ(wellknown, config, store, storageClient, log, options); - const result = await Micro.runPromiseExit(micro); - return handleMicroExit(result, 'Session check failure', 'unknown_error'); + const result = await Effect.runPromiseExit(effect); + return handleExit(result, 'Session check failure', 'unknown_error'); }, }, }; diff --git a/packages/oidc-client/src/lib/exchange.request.ts b/packages/oidc-client/src/lib/exchange.request.ts index 4fb4e57110..62b08a09f9 100644 --- a/packages/oidc-client/src/lib/exchange.request.ts +++ b/packages/oidc-client/src/lib/exchange.request.ts @@ -4,7 +4,7 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { Micro } from 'effect'; +import { Effect } from 'effect'; import { logger } from '@forgerock/sdk-logger'; @@ -34,22 +34,22 @@ export function buildTokenExchangeµ({ state, store, options, -}: BuildTokenExchangeµParams): Micro.Micro { +}: BuildTokenExchangeµParams): Effect.Effect { return createValuesµ(code, config, state, endpoint, options).pipe( - Micro.flatMap((options) => validateValuesµ(options)), - Micro.tap((options) => log.debug('Token exchange values created', options)), - Micro.tapError((options) => - Micro.sync(() => log.error('Error creating token exchange values', options)), + Effect.flatMap((options) => validateValuesµ(options)), + Effect.tap((options) => Effect.sync(() => log.debug('Token exchange values created', options))), + Effect.tapError((options) => + Effect.sync(() => log.error('Error creating token exchange values', options)), ), - Micro.flatMap((requestOptions) => - Micro.promise(() => store.dispatch(oidcApi.endpoints.exchange.initiate(requestOptions))), + Effect.flatMap((requestOptions) => + Effect.promise(() => store.dispatch(oidcApi.endpoints.exchange.initiate(requestOptions))), ), - Micro.flatMap(({ data, error }) => handleTokenResponseµ(data, error)), - Micro.tap((data) => log.debug('Token exchange response handled', data)), - Micro.tapError((error) => - Micro.sync(() => log.error('Error handling token exchange response', error)), + Effect.flatMap(({ data, error }) => handleTokenResponseµ(data, error)), + Effect.tap((data) => Effect.sync(() => log.debug('Token exchange response handled', data))), + Effect.tapError((error) => + Effect.sync(() => log.error('Error handling token exchange response', error)), ), - Micro.map((data) => { + Effect.map((data) => { const tokens = { accessToken: data.access_token, idToken: data.id_token, diff --git a/packages/oidc-client/src/lib/exchange.utils.test.ts b/packages/oidc-client/src/lib/exchange.utils.test.ts index d64cccabc8..454ac105ce 100644 --- a/packages/oidc-client/src/lib/exchange.utils.test.ts +++ b/packages/oidc-client/src/lib/exchange.utils.test.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ import { it, expect } from '@effect/vitest'; -import { Micro } from 'effect'; +import { Cause, Effect, Exit, Option } from 'effect'; import { handleTokenResponseµ, validateValuesµ } from './exchange.utils.js'; import type { OidcConfig } from './config.types.js'; import type { GetAuthorizationUrlOptions } from '@forgerock/sdk-types'; @@ -35,7 +35,7 @@ const storedValues: GetAuthorizationUrlOptions = { }; it.effect('validateValuesµ succeeds with TokenRequestOptions', () => - Micro.gen(function* () { + Effect.gen(function* () { const result = yield* validateValuesµ({ code, state, @@ -53,7 +53,7 @@ it.effect('validateValuesµ succeeds with TokenRequestOptions', () => ); it.effect('validateValuesµ with verifier succeeds with TokenRequestOptions', () => - Micro.gen(function* () { + Effect.gen(function* () { const verifier = 'verifier123'; const result = yield* validateValuesµ({ code, @@ -76,8 +76,8 @@ it.effect('validateValuesµ with verifier succeeds with TokenRequestOptions', () ); it.effect('validateValuesµ fails with state mismatch', () => - Micro.gen(function* () { - const result = yield* Micro.exit( + Effect.gen(function* () { + const result = yield* Effect.exit( validateValuesµ({ code, state: 'abcState', @@ -90,14 +90,17 @@ it.effect('validateValuesµ fails with state mismatch', () => }), ); - expect(result).toStrictEqual( - Micro.fail({ - error: 'State mismatch', - message: - 'The provided state does not match the stored state. This is likely due to passing in used, returned, authorize parameters.', - type: 'state_error', - }), - ); + expect(Exit.isFailure(result)).toBe(true); + if (!Exit.isFailure(result)) return; + const errorOpt = Cause.findErrorOption(result.cause); + expect(Option.isSome(errorOpt)).toBe(true); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value).toStrictEqual({ + error: 'State mismatch', + message: + 'The provided state does not match the stored state. This is likely due to passing in used, returned, authorize parameters.', + type: 'state_error', + }); }), ); @@ -107,7 +110,7 @@ it.effect('handleTokenResponseµ with data succeeds', () => { id_token: '67890', }; - return Micro.gen(function* () { + return Effect.gen(function* () { const result = yield* handleTokenResponseµ(data); expect(result).toStrictEqual(data); @@ -115,35 +118,41 @@ it.effect('handleTokenResponseµ with data succeeds', () => { }); it.effect('handleTokenResponseµ with no data fails', () => { - return Micro.gen(function* () { - const result = yield* Micro.exit(handleTokenResponseµ(undefined)); + return Effect.gen(function* () { + const result = yield* Effect.exit(handleTokenResponseµ(undefined)); - expect(result).toStrictEqual( - Micro.fail({ - error: 'Token Exchange failure', - message: 'No data returned from token exchange', - type: 'exchange_error', - }), - ); + expect(Exit.isFailure(result)).toBe(true); + if (!Exit.isFailure(result)) return; + const errorOpt = Cause.findErrorOption(result.cause); + expect(Option.isSome(errorOpt)).toBe(true); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value).toStrictEqual({ + error: 'Token Exchange failure', + message: 'No data returned from token exchange', + type: 'exchange_error', + }); }); }); it.effect('handleTokenResponseµ with error fails', () => { const errMessage = 'Fetch error message'; - return Micro.gen(function* () { - const result = yield* Micro.exit( + return Effect.gen(function* () { + const result = yield* Effect.exit( handleTokenResponseµ(undefined, { status: 'FETCH_ERROR', error: errMessage, }), ); - expect(result).toStrictEqual( - Micro.fail({ - error: 'Token Exchange failure', - message: errMessage, - type: 'exchange_error', - }), - ); + expect(Exit.isFailure(result)).toBe(true); + if (!Exit.isFailure(result)) return; + const errorOpt = Cause.findErrorOption(result.cause); + expect(Option.isSome(errorOpt)).toBe(true); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value).toStrictEqual({ + error: 'Token Exchange failure', + message: errMessage, + type: 'exchange_error', + }); }); }); diff --git a/packages/oidc-client/src/lib/exchange.utils.ts b/packages/oidc-client/src/lib/exchange.utils.ts index b3314a6ab4..30745c27a4 100644 --- a/packages/oidc-client/src/lib/exchange.utils.ts +++ b/packages/oidc-client/src/lib/exchange.utils.ts @@ -6,7 +6,7 @@ */ import type { SerializedError } from '@reduxjs/toolkit'; import type { FetchBaseQueryError } from '@reduxjs/toolkit/query'; -import { Micro } from 'effect'; +import { Effect } from 'effect'; import { getStoredAuthUrlValues } from '@forgerock/sdk-oidc'; import type { GetAuthorizationUrlOptions } from '@forgerock/sdk-types'; @@ -23,7 +23,7 @@ export function createValuesµ( endpoint: string, options?: Partial, ) { - return Micro.sync(() => { + return Effect.sync(() => { const storedValues = getStoredAuthUrlValues(config.clientId, options?.prefix); return { @@ -39,7 +39,7 @@ export function createValuesµ( export function handleTokenResponseµ( data: TokenExchangeResponse | undefined, error?: FetchBaseQueryError | SerializedError, -): Micro.Micro { +): Effect.Effect { if (error) { let message; if ('status' in error) { @@ -48,7 +48,7 @@ export function handleTokenResponseµ( message = error.message; } - return Micro.fail({ + return Effect.fail({ error: 'Token Exchange failure', message: message || 'Unknown error during token exchange', type: 'exchange_error', @@ -56,14 +56,14 @@ export function handleTokenResponseµ( } if (!data) { - return Micro.fail({ + return Effect.fail({ error: 'Token Exchange failure', message: 'No data returned from token exchange', type: 'exchange_error', } as TokenExchangeErrorResponse); } - return Micro.succeed(data); + return Effect.succeed(data); } export function validateValuesµ({ @@ -87,9 +87,9 @@ export function validateValuesµ({ type: 'state_error', } as const; - return Micro.fail(err); + return Effect.fail(err); } - return Micro.succeed({ + return Effect.succeed({ code, config, endpoint, diff --git a/packages/oidc-client/src/lib/logout.request.test.ts b/packages/oidc-client/src/lib/logout.request.test.ts index 1beaf712f4..81a662fb06 100644 --- a/packages/oidc-client/src/lib/logout.request.test.ts +++ b/packages/oidc-client/src/lib/logout.request.test.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ import { it, expect, describe } from 'vitest'; -import { Micro } from 'effect'; +import { Cause, Effect, Exit, Option } from 'effect'; import { deepStrictEqual } from 'node:assert'; import { setupServer } from 'msw/node'; import { http, HttpResponse } from 'msw'; @@ -101,8 +101,8 @@ const partialWellknown = { describe('signOutRedirectUri', () => { it('logoutµ appends post_logout_redirect_uri when signOutRedirectUri is set in config', () => - Micro.runPromise( - Micro.gen(function* () { + Effect.runPromise( + Effect.gen(function* () { const end_session_endpoint = 'https://example.com/am/oauth2/alpha/connect/endSession'; const revocation_endpoint = 'https://example.com/am/oauth2/alpha/token/revoke'; let capturedUrl = ''; @@ -132,8 +132,8 @@ describe('signOutRedirectUri', () => { )); it('logoutµ omits post_logout_redirect_uri when signOutRedirectUri is absent', () => - Micro.runPromise( - Micro.gen(function* () { + Effect.runPromise( + Effect.gen(function* () { const end_session_endpoint = 'https://example.com/am/oauth2/alpha/connect/endSession'; const revocation_endpoint = 'https://example.com/am/oauth2/alpha/token/revoke'; let capturedUrl = ''; @@ -165,8 +165,8 @@ describe('signOutRedirectUri', () => { describe('Ping AM', () => { it('logoutµ succeeds with valid wellknown endpoints', () => - Micro.runPromise( - Micro.gen(function* () { + Effect.runPromise( + Effect.gen(function* () { const end_session_endpoint = 'https://example.com/am/oauth2/alpha/connect/endSession'; const revocation_endpoint = 'https://example.com/am/oauth2/alpha/token/revoke'; @@ -191,12 +191,12 @@ describe('Ping AM', () => { )); it('logoutµ fails on bad endSession', () => - Micro.runPromise( - Micro.gen(function* () { + Effect.runPromise( + Effect.gen(function* () { const end_session_endpoint = 'https://example.com/am/oauth2/fake-realm/connect/endSession'; const revocation_endpoint = 'https://example.com/am/oauth2/alpha/token/revoke'; - const result = yield* Micro.exit( + const result = yield* Effect.exit( logoutµ({ tokens, config, @@ -210,30 +210,31 @@ describe('Ping AM', () => { }), ); - deepStrictEqual( - result, - Micro.exitFail({ - error: 'Inner request error', - sessionResponse: { - error: 'End Session failure', - message: 'An error occurred while ending the session', - type: 'auth_error', - status: 400, - }, - revokeResponse: null, - deleteResponse: null, - }), - ); + expect(Exit.isFailure(result)).toBe(true); + if (!Exit.isFailure(result)) return; + const errorOpt = Cause.findErrorOption(result.cause); + if (!Option.isSome(errorOpt)) return; + deepStrictEqual(errorOpt.value, { + error: 'Inner request error', + sessionResponse: { + error: 'End Session failure', + message: 'An error occurred while ending the session', + type: 'auth_error', + status: 400, + }, + revokeResponse: null, + deleteResponse: null, + }); }), )); it('logoutµ fails on bad revoke', () => - Micro.runPromise( - Micro.gen(function* () { + Effect.runPromise( + Effect.gen(function* () { const end_session_endpoint = 'https://example.com/am/oauth2/alpha/connect/endSession'; const revocation_endpoint = 'https://example.com/am/oauth2/fake-realm/token/revoke'; - const result = yield* Micro.exit( + const result = yield* Effect.exit( logoutµ({ tokens, config, @@ -247,20 +248,21 @@ describe('Ping AM', () => { }), ); - deepStrictEqual( - result, - Micro.exitFail({ - error: 'Inner request error', - sessionResponse: null, - revokeResponse: { - error: 'End Session failure', - message: 'An error occurred while ending the session', - type: 'auth_error', - status: 400, - }, - deleteResponse: null, - }), - ); + expect(Exit.isFailure(result)).toBe(true); + if (!Exit.isFailure(result)) return; + const errorOpt = Cause.findErrorOption(result.cause); + if (!Option.isSome(errorOpt)) return; + deepStrictEqual(errorOpt.value, { + error: 'Inner request error', + sessionResponse: null, + revokeResponse: { + error: 'End Session failure', + message: 'An error occurred while ending the session', + type: 'auth_error', + status: 400, + }, + deleteResponse: null, + }); }), )); }); @@ -269,8 +271,8 @@ describe('PingOne', () => { const fakeEndSessionEndpoint = 'https://example.com/endSession'; it('logoutµ succeeds with valid wellknown endpoints', () => - Micro.runPromise( - Micro.gen(function* () { + Effect.runPromise( + Effect.gen(function* () { const ping_end_idp_session_endpoint = 'https://example.com/as/idpSignoff'; const revocation_endpoint = 'https://example.com/as/revoke'; @@ -296,12 +298,12 @@ describe('PingOne', () => { )); it('logoutµ fails on bad endSession', () => - Micro.runPromise( - Micro.gen(function* () { + Effect.runPromise( + Effect.gen(function* () { const ping_end_idp_session_endpoint = 'https://example.com/as/badIdpSignoff'; const revocation_endpoint = 'https://example.com/as/revoke'; - const result = yield* Micro.exit( + const result = yield* Effect.exit( logoutµ({ tokens, config, @@ -316,30 +318,31 @@ describe('PingOne', () => { }), ); - deepStrictEqual( - result, - Micro.exitFail({ - error: 'Inner request error', - sessionResponse: { - error: 'End Session failure', - message: 'An error occurred while ending the session', - type: 'auth_error', - status: 400, - }, - revokeResponse: null, - deleteResponse: null, - }), - ); + expect(Exit.isFailure(result)).toBe(true); + if (!Exit.isFailure(result)) return; + const errorOpt = Cause.findErrorOption(result.cause); + if (!Option.isSome(errorOpt)) return; + deepStrictEqual(errorOpt.value, { + error: 'Inner request error', + sessionResponse: { + error: 'End Session failure', + message: 'An error occurred while ending the session', + type: 'auth_error', + status: 400, + }, + revokeResponse: null, + deleteResponse: null, + }); }), )); it('logoutµ fails on bad revoke', () => - Micro.runPromise( - Micro.gen(function* () { + Effect.runPromise( + Effect.gen(function* () { const ping_end_idp_session_endpoint = 'https://example.com/as/idpSignoff'; const revocation_endpoint = 'https://example.com/as/badRevoke'; - const result = yield* Micro.exit( + const result = yield* Effect.exit( logoutµ({ tokens, config, @@ -354,20 +357,21 @@ describe('PingOne', () => { }), ); - deepStrictEqual( - result, - Micro.exitFail({ - error: 'Inner request error', - sessionResponse: null, - revokeResponse: { - error: 'End Session failure', - message: 'An error occurred while ending the session', - type: 'auth_error', - status: 400, - }, - deleteResponse: null, - }), - ); + expect(Exit.isFailure(result)).toBe(true); + if (!Exit.isFailure(result)) return; + const errorOpt = Cause.findErrorOption(result.cause); + if (!Option.isSome(errorOpt)) return; + deepStrictEqual(errorOpt.value, { + error: 'Inner request error', + sessionResponse: null, + revokeResponse: { + error: 'End Session failure', + message: 'An error occurred while ending the session', + type: 'auth_error', + status: 400, + }, + deleteResponse: null, + }); }), )); }); diff --git a/packages/oidc-client/src/lib/logout.request.ts b/packages/oidc-client/src/lib/logout.request.ts index 636ab5fdd9..caf56f614d 100644 --- a/packages/oidc-client/src/lib/logout.request.ts +++ b/packages/oidc-client/src/lib/logout.request.ts @@ -4,7 +4,7 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { Micro } from 'effect'; +import { Effect } from 'effect'; import { oidcApi } from './oidc.api.js'; import { createLogoutError } from './client.store.utils.js'; @@ -26,9 +26,9 @@ export function logoutµ({ store: ClientStore; storageClient: StorageClient; }) { - return Micro.zip( + return Effect.zip( // End session with the ID token - Micro.promise(() => + Effect.promise(() => store.dispatch( oidcApi.endpoints.endSession.initiate({ idToken: tokens.idToken, @@ -36,10 +36,10 @@ export function logoutµ({ signOutRedirectUri: config.signOutRedirectUri, }), ), - ).pipe(Micro.map(({ data, error }) => createLogoutError(data, error))), + ).pipe(Effect.map(({ data, error }) => createLogoutError(data, error))), // Revoke the access token - Micro.promise(() => + Effect.promise(() => store.dispatch( oidcApi.endpoints.revoke.initiate({ accessToken: tokens.accessToken, @@ -47,12 +47,12 @@ export function logoutµ({ endpoint: wellknown.revocation_endpoint, }), ), - ).pipe(Micro.map(({ data, error }) => createLogoutError(data, error))), + ).pipe(Effect.map(({ data, error }) => createLogoutError(data, error))), ).pipe( // Delete local token and return combined results - Micro.flatMap(([sessionResponse, revokeResponse]) => - Micro.promise(() => storageClient.remove()).pipe( - Micro.flatMap((deleteResponse) => { + Effect.flatMap(([sessionResponse, revokeResponse]) => + Effect.promise(() => storageClient.remove()).pipe( + Effect.flatMap((deleteResponse) => { const isInnerRequestError = (sessionResponse && 'error' in sessionResponse) || (revokeResponse && 'error' in revokeResponse) || @@ -65,14 +65,14 @@ export function logoutµ({ revokeResponse, deleteResponse, }; - return Micro.fail(result); + return Effect.fail(result); } else { const result: LogoutSuccessResult = { sessionResponse: null, revokeResponse: null, deleteResponse: null, }; - return Micro.succeed(result); + return Effect.succeed(result); } }), ), diff --git a/packages/oidc-client/src/lib/session.micros.test.ts b/packages/oidc-client/src/lib/session.micros.test.ts index 581d84d366..3276a9624e 100644 --- a/packages/oidc-client/src/lib/session.micros.test.ts +++ b/packages/oidc-client/src/lib/session.micros.test.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ import { it, expect } from '@effect/vitest'; -import { Micro } from 'effect'; +import { Cause, Effect, Exit, Option } from 'effect'; import { vi, afterEach, describe } from 'vitest'; import * as sdkUtilities from '@forgerock/sdk-utilities'; @@ -181,32 +181,32 @@ describe('buildIdTokenUrl', () => { // ─── sessionCheckNoneµ (iframe path — with redirect_uri) ────────────────────── it.effect('sessionCheckNoneµ uses iframe path and succeeds when redirect_uri is configured', () => - Micro.gen(function* () { + Effect.gen(function* () { const { store, dispatch } = makeDispatchSetup({ data: { params: {} } }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( sessionCheckNoneµ(wellknown, config, store, makeStorageClient(storedTokens), log), ); - expect(Micro.exitIsSuccess(exit)).toBe(true); + expect(Exit.isSuccess(exit)).toBe(true); expect(dispatch).toHaveBeenCalledOnce(); }), ); it.effect('sessionCheckNoneµ iframe path fails with no_id_token_hint when storage is empty', () => - Micro.gen(function* () { + Effect.gen(function* () { const { store, dispatch } = makeDispatchSetup({ data: { params: {} } }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( sessionCheckNoneµ(wellknown, config, store, makeStorageClient(null), log), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('no_id_token_hint'); - expect(exit.cause.error.type).toBe('argument_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('no_id_token_hint'); + expect(errorOpt.value.type).toBe('argument_error'); expect(dispatch).not.toHaveBeenCalled(); }), ); @@ -214,11 +214,11 @@ it.effect('sessionCheckNoneµ iframe path fails with no_id_token_hint when stora // ─── sessionCheckNoneµ (fetch path — without redirect_uri) ─────────────────── it.effect('sessionCheckNoneµ uses fetch path and succeeds when no redirect_uri is configured', () => - Micro.gen(function* () { + Effect.gen(function* () { const configWithoutRedirectUri: OidcConfig = { ...config, redirectUri: '' }; const { store, dispatch } = makeFetchDispatchSetup({ data: { status: 204 } }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( sessionCheckNoneµ( wellknown, configWithoutRedirectUri, @@ -228,36 +228,34 @@ it.effect('sessionCheckNoneµ uses fetch path and succeeds when no redirect_uri ), ); - expect(Micro.exitIsSuccess(exit)).toBe(true); - if (!Micro.exitIsSuccess(exit)) { - return; - } + expect(Exit.isSuccess(exit)).toBe(true); + if (!Exit.isSuccess(exit)) return; expect(exit.value).toStrictEqual({ responseType: 'none' }); expect(dispatch).toHaveBeenCalledOnce(); }), ); it.effect('sessionCheckNoneµ fetch path fails with no_id_token_hint when storage is empty', () => - Micro.gen(function* () { + Effect.gen(function* () { const configWithoutRedirectUri: OidcConfig = { ...config, redirectUri: '' }; const { store, dispatch } = makeFetchDispatchSetup({ data: { status: 204 } }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( sessionCheckNoneµ(wellknown, configWithoutRedirectUri, store, makeStorageClient(null), log), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('no_id_token_hint'); - expect(exit.cause.error.type).toBe('argument_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('no_id_token_hint'); + expect(errorOpt.value.type).toBe('argument_error'); expect(dispatch).not.toHaveBeenCalled(); }), ); it.effect('sessionCheckNoneµ fetch path fails with login_required when AM returns 400', () => - Micro.gen(function* () { + Effect.gen(function* () { const configWithoutRedirectUri: OidcConfig = { ...config, redirectUri: '' }; const errorData: GenericError = { error: 'login_required', @@ -266,7 +264,7 @@ it.effect('sessionCheckNoneµ fetch path fails with login_required when AM retur }; const { store } = makeFetchDispatchSetup({ error: { data: errorData } }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( sessionCheckNoneµ( wellknown, configWithoutRedirectUri, @@ -276,26 +274,26 @@ it.effect('sessionCheckNoneµ fetch path fails with login_required when AM retur ), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('login_required'); - expect(exit.cause.error.type).toBe('auth_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('login_required'); + expect(errorOpt.value.type).toBe('auth_error'); }), ); // ─── dispatchSessionCheckFetchµ ─────────────────────────────────────────────── it.effect('dispatchSessionCheckFetchµ succeeds when dispatch resolves with data', () => - Micro.gen(function* () { + Effect.gen(function* () { const { store, dispatch } = makeFetchDispatchSetup({ data: { status: 204 } }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( dispatchSessionCheckFetchµ(store, 'https://example.com/authorize?prompt=none'), ); - expect(Micro.exitIsSuccess(exit)).toBe(true); + expect(Exit.isSuccess(exit)).toBe(true); expect(dispatch).toHaveBeenCalledOnce(); }), ); @@ -303,7 +301,7 @@ it.effect('dispatchSessionCheckFetchµ succeeds when dispatch resolves with data it.effect( 'dispatchSessionCheckFetchµ fails with auth_error when dispatch resolves with an error result', () => - Micro.gen(function* () { + Effect.gen(function* () { const errorData: GenericError = { error: 'login_required', message: 'The request requires login.', @@ -311,21 +309,21 @@ it.effect( }; const { store } = makeFetchDispatchSetup({ error: { data: errorData } }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( dispatchSessionCheckFetchµ(store, 'https://example.com/authorize?prompt=none'), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('login_required'); - expect(exit.cause.error.type).toBe('auth_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('login_required'); + expect(errorOpt.value.type).toBe('auth_error'); }), ); it.effect('dispatchSessionCheckFetchµ fails with network_error when dispatch rejects', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.spyOn(oidcApi.endpoints.sessionCheckFetch, 'initiate').mockReturnValue( Symbol('sentinel') as unknown as ReturnType< typeof oidcApi.endpoints.sessionCheckFetch.initiate @@ -334,23 +332,23 @@ it.effect('dispatchSessionCheckFetchµ fails with network_error when dispatch re const dispatch = vi.fn().mockRejectedValue(new Error('network failure')); const store: ClientStore = { dispatch } as unknown as ClientStore; - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( dispatchSessionCheckFetchµ(store, 'https://example.com/authorize?prompt=none'), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.type).toBe('network_error'); - expect(exit.cause.error.error).toBe('dispatch_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('network_error'); + expect(errorOpt.value.error).toBe('dispatch_error'); }), ); it.effect( 'dispatchSessionCheckFetchµ fails with network_error when queryFn receives a string-status error (e.g. FETCH_ERROR)', () => - Micro.gen(function* () { + Effect.gen(function* () { const errorData: GenericError = { error: 'session_check_error', message: 'A network error occurred during session check', @@ -358,23 +356,23 @@ it.effect( }; const { store } = makeFetchDispatchSetup({ error: { data: errorData } }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( dispatchSessionCheckFetchµ(store, 'https://example.com/authorize?prompt=none'), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('session_check_error'); - expect(exit.cause.error.type).toBe('network_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('session_check_error'); + expect(errorOpt.value.type).toBe('network_error'); }), ); it.effect( 'dispatchSessionCheckFetchµ fails with network_error when queryFn receives an unexpected 2xx status', () => - Micro.gen(function* () { + Effect.gen(function* () { const errorData: GenericError = { error: 'session_check_error', message: 'Unexpected response status: 200', @@ -382,23 +380,23 @@ it.effect( }; const { store } = makeFetchDispatchSetup({ error: { data: errorData } }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( dispatchSessionCheckFetchµ(store, 'https://example.com/authorize?prompt=none'), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('session_check_error'); - expect(exit.cause.error.type).toBe('network_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('session_check_error'); + expect(errorOpt.value.type).toBe('network_error'); }), ); // ─── sessionCheckIdTokenµ ───────────────────────────────────────────────────── it.effect('sessionCheckIdTokenµ returns claims on valid JWT', () => - Micro.gen(function* () { + Effect.gen(function* () { const knownNonce = 'test-nonce-value-12345678901234'; const knownState = 'known-state-value'; vi.spyOn(sdkUtilities, 'createRandomString').mockReturnValue(knownNonce); @@ -415,72 +413,68 @@ it.effect('sessionCheckIdTokenµ returns claims on valid JWT', () => data: { params: { id_token: validJwt, state: knownState } }, }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( sessionCheckIdTokenµ(wellknown, config, store, makeStorageClient(storedTokens), log), ); - expect(Micro.exitIsSuccess(exit)).toBe(true); - if (!Micro.exitIsSuccess(exit)) { - return; - } + expect(Exit.isSuccess(exit)).toBe(true); + if (!Exit.isSuccess(exit)) return; expect(exit.value.responseType).toBe('id_token'); expect(exit.value.claims).toBeDefined(); - if (!exit.value.claims) { - return; - } + if (!exit.value.claims) return; expect(exit.value.claims['nonce']).toBe(knownNonce); }), ); it.effect('sessionCheckIdTokenµ fails with state_mismatch when response state does not match', () => - Micro.gen(function* () { + Effect.gen(function* () { vi.spyOn(sdkUtilities, 'createState').mockReturnValue('known-state-value'); const { store } = makeDispatchSetup({ data: { params: { id_token: 'some.jwt.token', state: 'tampered-state' } }, }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( sessionCheckIdTokenµ(wellknown, config, store, makeStorageClient(storedTokens), log), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('state_mismatch'); - expect(exit.cause.error.type).toBe('auth_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('state_mismatch'); + expect(errorOpt.value.type).toBe('auth_error'); }), ); it.effect('sessionCheckIdTokenµ fails with no_id_token when iframe returns no id_token param', () => - Micro.gen(function* () { + Effect.gen(function* () { const knownState = 'known-state-value'; vi.spyOn(sdkUtilities, 'createState').mockReturnValue(knownState); const { store } = makeDispatchSetup({ data: { params: { state: knownState } } }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( sessionCheckIdTokenµ(wellknown, config, store, makeStorageClient(storedTokens), log), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('no_id_token'); - expect(exit.cause.error.type).toBe('auth_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('no_id_token'); + expect(errorOpt.value.type).toBe('auth_error'); }), ); it.effect( 'sessionCheckIdTokenµ fails with missing_redirect_uri when no redirect_uri is configured', () => - Micro.gen(function* () { + Effect.gen(function* () { const configWithoutRedirectUri: OidcConfig = { ...config, redirectUri: '' }; const { store, dispatch } = makeDispatchSetup({ data: { params: {} } }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( sessionCheckIdTokenµ( wellknown, configWithoutRedirectUri, @@ -490,12 +484,12 @@ it.effect( ), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('missing_redirect_uri'); - expect(exit.cause.error.type).toBe('argument_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('missing_redirect_uri'); + expect(errorOpt.value.type).toBe('argument_error'); expect(dispatch).not.toHaveBeenCalled(); }), ); @@ -503,33 +497,33 @@ it.effect( // ─── readStoredIdTokenµ ─────────────────────────────────────────────────────── it.effect('readStoredIdTokenµ returns idToken string when tokens are stored', () => - Micro.gen(function* () { + Effect.gen(function* () { const result = yield* readStoredIdTokenµ(makeStorageClient(storedTokens)); expect(result).toBe(storedTokens.idToken); }), ); it.effect('readStoredIdTokenµ returns null when storage is empty', () => - Micro.gen(function* () { + Effect.gen(function* () { const result = yield* readStoredIdTokenµ(makeStorageClient(null)); expect(result).toBeNull(); }), ); it.effect('readStoredIdTokenµ fails with argument_error when storageClient.get rejects', () => - Micro.gen(function* () { + Effect.gen(function* () { const failingStorage: StorageClient = { get: vi.fn().mockRejectedValue(new Error('storage unavailable')), set: vi.fn(), remove: vi.fn(), }; - const exit = yield* Micro.exit(readStoredIdTokenµ(failingStorage)); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.type).toBe('argument_error'); - expect(exit.cause.error.error).toBe('storage_error'); + const exit = yield* Effect.exit(readStoredIdTokenµ(failingStorage)); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('argument_error'); + expect(errorOpt.value.error).toBe('storage_error'); }), ); @@ -538,7 +532,7 @@ it.effect('readStoredIdTokenµ fails with argument_error when storageClient.get it.effect( 'dispatchSessionCheckIframeµ succeeds and returns params when dispatch resolves with data', () => - Micro.gen(function* () { + Effect.gen(function* () { const params = { state: 'ok' }; const dispatch = vi.fn().mockResolvedValue({ data: { params } }); const store: ClientStore = { dispatch } as unknown as ClientStore; @@ -560,7 +554,7 @@ it.effect( it.effect( 'dispatchSessionCheckIframeµ fails with auth_error when dispatch resolves with an error result', () => - Micro.gen(function* () { + Effect.gen(function* () { const errorData: GenericError = { error: 'login_required', message: 'User must authenticate', @@ -574,20 +568,20 @@ it.effect( >, ); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( dispatchSessionCheckIframeµ(store, 'https://example.com/authorize?prompt=none', 'none'), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('login_required'); - expect(exit.cause.error.type).toBe('auth_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('login_required'); + expect(errorOpt.value.type).toBe('auth_error'); }), ); it.effect('dispatchSessionCheckIframeµ fails with network_error when dispatch rejects', () => - Micro.gen(function* () { + Effect.gen(function* () { const dispatch = vi.fn().mockRejectedValue(new Error('network failure')); const store: ClientStore = { dispatch } as unknown as ClientStore; vi.spyOn(oidcApi.endpoints.sessionCheckIframe, 'initiate').mockReturnValue( @@ -596,15 +590,15 @@ it.effect('dispatchSessionCheckIframeµ fails with network_error when dispatch r >, ); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( dispatchSessionCheckIframeµ(store, 'https://example.com/authorize?prompt=none', 'none'), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.type).toBe('network_error'); - expect(exit.cause.error.error).toBe('dispatch_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.type).toBe('network_error'); + expect(errorOpt.value.error).toBe('dispatch_error'); }), ); @@ -621,7 +615,7 @@ function makeJwtWithClaims(claims: JWTPayload): string { it.effect( 'validateSessionCheckResponseµ succeeds and returns claims when state and nonce match', () => - Micro.gen(function* () { + Effect.gen(function* () { const nonce = 'expected-nonce'; const state = 'expected-state'; const jwt = makeJwtWithClaims({ nonce, sub: 'user1' }); @@ -631,7 +625,7 @@ it.effect( ); it.effect('validateSessionCheckResponseµ succeeds when state, nonce, and subject all match', () => - Micro.gen(function* () { + Effect.gen(function* () { const nonce = 'nonce-abc'; const state = 'state-abc'; const jwt = makeJwtWithClaims({ nonce, sub: 'user1' }); @@ -646,81 +640,81 @@ it.effect('validateSessionCheckResponseµ succeeds when state, nonce, and subjec ); it.effect('validateSessionCheckResponseµ fails with state_mismatch when state does not match', () => - Micro.gen(function* () { + Effect.gen(function* () { const jwt = makeJwtWithClaims({ nonce: 'nonce', sub: 'user1' }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( validateSessionCheckResponseµ( { id_token: jwt, state: 'tampered' }, 'expected-state', 'nonce', ), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('state_mismatch'); - expect(exit.cause.error.type).toBe('auth_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('state_mismatch'); + expect(errorOpt.value.type).toBe('auth_error'); }), ); it.effect('validateSessionCheckResponseµ fails with no_id_token when id_token is absent', () => - Micro.gen(function* () { + Effect.gen(function* () { const state = 'expected-state'; - const exit = yield* Micro.exit(validateSessionCheckResponseµ({ state }, state, 'nonce')); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('no_id_token'); - expect(exit.cause.error.type).toBe('auth_error'); + const exit = yield* Effect.exit(validateSessionCheckResponseµ({ state }, state, 'nonce')); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('no_id_token'); + expect(errorOpt.value.type).toBe('auth_error'); }), ); it.effect('validateSessionCheckResponseµ fails with nonce_mismatch when nonce does not match', () => - Micro.gen(function* () { + Effect.gen(function* () { const state = 'expected-state'; const jwt = makeJwtWithClaims({ nonce: 'wrong-nonce', sub: 'user1' }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( validateSessionCheckResponseµ({ id_token: jwt, state }, state, 'expected-nonce'), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('nonce_mismatch'); - expect(exit.cause.error.type).toBe('auth_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('nonce_mismatch'); + expect(errorOpt.value.type).toBe('auth_error'); }), ); it.effect('validateSessionCheckResponseµ fails with subject_mismatch when sub does not match', () => - Micro.gen(function* () { + Effect.gen(function* () { const nonce = 'valid-nonce'; const state = 'expected-state'; const jwt = makeJwtWithClaims({ nonce, sub: 'user2' }); - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( validateSessionCheckResponseµ({ id_token: jwt, state }, state, nonce, 'user1'), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('subject_mismatch'); - expect(exit.cause.error.type).toBe('auth_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('subject_mismatch'); + expect(errorOpt.value.type).toBe('auth_error'); }), ); it.effect('validateSessionCheckResponseµ fails with invalid_jwt when JWT is malformed', () => - Micro.gen(function* () { + Effect.gen(function* () { const state = 'expected-state'; - const exit = yield* Micro.exit( + const exit = yield* Effect.exit( validateSessionCheckResponseµ({ id_token: 'not.a.valid.jwt.payload', state }, state, 'nonce'), ); - expect(Micro.exitIsFailure(exit)).toBe(true); - if (!Micro.exitIsFailure(exit) || !Micro.causeIsFail(exit.cause)) { - return; - } - expect(exit.cause.error.error).toBe('invalid_jwt'); - expect(exit.cause.error.type).toBe('auth_error'); + expect(Exit.isFailure(exit)).toBe(true); + if (!Exit.isFailure(exit)) return; + const errorOpt = Cause.findErrorOption(exit.cause); + if (!Option.isSome(errorOpt)) return; + expect(errorOpt.value.error).toBe('invalid_jwt'); + expect(errorOpt.value.type).toBe('auth_error'); }), ); diff --git a/packages/oidc-client/src/lib/session.micros.ts b/packages/oidc-client/src/lib/session.micros.ts index 561291dce0..650c0a03ad 100644 --- a/packages/oidc-client/src/lib/session.micros.ts +++ b/packages/oidc-client/src/lib/session.micros.ts @@ -4,7 +4,7 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { Micro } from 'effect'; +import { Effect } from 'effect'; import { createRandomString, createState } from '@forgerock/sdk-utilities'; @@ -24,15 +24,15 @@ import type { SessionCheckOptions, SessionCheckSuccess } from './session.types.j export const readStoredIdTokenµ = ( storageClient: StorageClient, -): Micro.Micro => - Micro.tryPromise({ +): Effect.Effect => + Effect.tryPromise({ try: () => storageClient.get(), catch: (): GenericError => ({ error: 'storage_error', message: 'Failed to read tokens from storage', type: 'argument_error', }), - }).pipe(Micro.map((tokens) => (tokens && 'idToken' in tokens ? tokens.idToken : null))); + }).pipe(Effect.map((tokens) => (tokens && 'idToken' in tokens ? tokens.idToken : null))); // ─── Dispatch ──────────────────────────────────────────────────────────────── @@ -40,8 +40,8 @@ export const dispatchSessionCheckIframeµ = ( store: ClientStore, url: string, responseType: 'id_token' | 'none', -): Micro.Micro, GenericError, never> => - Micro.tryPromise({ +): Effect.Effect, GenericError, never> => + Effect.tryPromise({ try: () => store.dispatch(oidcApi.endpoints.sessionCheckIframe.initiate({ url, responseType })), catch: (err): GenericError => ({ error: 'dispatch_error', @@ -49,27 +49,27 @@ export const dispatchSessionCheckIframeµ = ( type: 'network_error', }), }).pipe( - Micro.flatMap((result) => { + Effect.flatMap((result) => { if ('error' in result && result.error) { const errData = result.error as { data?: { error?: string; message?: string; type?: string }; }; - return Micro.fail({ + return Effect.fail({ error: errData.data?.error ?? 'session_check_error', message: errData.data?.message ?? 'An error occurred during session check', type: (errData.data?.type as GenericError['type']) ?? 'network_error', }); } const { params } = (result as { data: { params: Record } }).data; - return Micro.succeed(params); + return Effect.succeed(params); }), ); export const dispatchSessionCheckFetchµ = ( store: ClientStore, url: string, -): Micro.Micro => - Micro.tryPromise({ +): Effect.Effect => + Effect.tryPromise({ try: () => store.dispatch(oidcApi.endpoints.sessionCheckFetch.initiate({ url })), catch: (err): GenericError => ({ error: 'dispatch_error', @@ -77,18 +77,18 @@ export const dispatchSessionCheckFetchµ = ( type: 'network_error', }), }).pipe( - Micro.flatMap((result) => { + Effect.flatMap((result) => { if ('error' in result && result.error) { const errData = result.error as { data?: { error?: string; message?: string; type?: string }; }; - return Micro.fail({ + return Effect.fail({ error: errData.data?.error ?? 'login_required', message: errData.data?.message ?? 'The request requires login.', type: (errData.data?.type as GenericError['type']) ?? 'auth_error', }); } - return Micro.void; + return Effect.void; }), ); @@ -99,10 +99,10 @@ export const validateSessionCheckResponseµ = ( state: string, nonce: string, subject?: string, -): Micro.Micro => { - return Micro.gen(function* () { +): Effect.Effect => { + return Effect.gen(function* () { if (iframeParams.state !== state) { - return yield* Micro.fail({ + return yield* Effect.fail({ error: 'state_mismatch', message: 'State parameter in response does not match the expected value', type: 'auth_error', @@ -111,14 +111,14 @@ export const validateSessionCheckResponseµ = ( const idToken = iframeParams.id_token; if (!idToken) { - return yield* Micro.fail({ + return yield* Effect.fail({ error: 'no_id_token', message: 'No id_token found in iframe response', type: 'auth_error', }); } - const claims = yield* Micro.try({ + const claims = yield* Effect.try({ try: () => decodeJwt(idToken), catch: (): GenericError => ({ error: 'invalid_jwt', @@ -128,7 +128,7 @@ export const validateSessionCheckResponseµ = ( }); if (claims.nonce !== nonce) { - return yield* Micro.fail({ + return yield* Effect.fail({ error: 'nonce_mismatch', message: 'Nonce in id_token does not match the expected value', type: 'auth_error', @@ -136,7 +136,7 @@ export const validateSessionCheckResponseµ = ( } if (subject !== undefined && claims.sub !== subject) { - return yield* Micro.fail({ + return yield* Effect.fail({ error: 'subject_mismatch', message: 'Subject claim in id_token does not match the expected value', type: 'auth_error', @@ -198,11 +198,11 @@ export const sessionCheckNoneµ = ( storageClient: StorageClient, log: CustomLogger, options?: SessionCheckOptions, -): Micro.Micro => { +): Effect.Effect => { return readStoredIdTokenµ(storageClient).pipe( - Micro.flatMap((storedIdToken) => { + Effect.flatMap((storedIdToken) => { if (!storedIdToken) { - return Micro.fail({ + return Effect.fail({ error: 'no_id_token_hint', message: 'response_type=none requires a stored id_token; authenticate first', type: 'argument_error', @@ -224,8 +224,8 @@ export const sessionCheckNoneµ = ( ? dispatchSessionCheckIframeµ(store, url, 'none') : dispatchSessionCheckFetchµ(store, url); }), - Micro.tap(() => log.debug('Session check (none) completed successfully')), - Micro.map((): SessionCheckSuccess => ({ responseType: 'none' })), + Effect.tap(() => Effect.sync(() => log.debug('Session check (none) completed successfully'))), + Effect.map((): SessionCheckSuccess => ({ responseType: 'none' })), ); }; @@ -238,11 +238,11 @@ export const sessionCheckIdTokenµ = ( storageClient: StorageClient, log: CustomLogger, options?: SessionCheckOptions, -): Micro.Micro => { +): Effect.Effect => { const redirectUri = options?.redirectUri ?? config.redirectUri; if (!redirectUri) { - return Micro.fail({ + return Effect.fail({ error: 'missing_redirect_uri', message: 'redirect_uri is required for session check with response_type=id_token', type: 'argument_error', @@ -250,7 +250,7 @@ export const sessionCheckIdTokenµ = ( } return readStoredIdTokenµ(storageClient).pipe( - Micro.flatMap((storedIdToken) => { + Effect.flatMap((storedIdToken) => { const { url, nonce, state } = buildIdTokenUrl( wellknown.authorization_endpoint, config, @@ -259,12 +259,14 @@ export const sessionCheckIdTokenµ = ( options, ); return dispatchSessionCheckIframeµ(store, url, 'id_token').pipe( - Micro.flatMap((iframeParams) => + Effect.flatMap((iframeParams) => validateSessionCheckResponseµ(iframeParams, state, nonce, options?.subject), ), ); }), - Micro.tap(() => log.debug('Session check (id_token) completed successfully')), - Micro.map((claims): SessionCheckSuccess => ({ responseType: 'id_token', claims })), + Effect.tap(() => + Effect.sync(() => log.debug('Session check (id_token) completed successfully')), + ), + Effect.map((claims): SessionCheckSuccess => ({ responseType: 'id_token', claims })), ); }; diff --git a/packages/sdk-utilities/src/lib/config/config.effects.ts b/packages/sdk-utilities/src/lib/config/config.effects.ts index 76defcf49a..c9a05a8908 100644 --- a/packages/sdk-utilities/src/lib/config/config.effects.ts +++ b/packages/sdk-utilities/src/lib/config/config.effects.ts @@ -5,23 +5,23 @@ * of the MIT license. See the LICENSE file for details. */ -import * as Either from 'effect/Either'; +import { Result } from 'effect'; import { parseToOidcConfig, parseToJourneyConfig, parseToDavinciConfig } from './config.utils.js'; import type { OidcConfig, JourneyClientConfig, DaVinciConfig } from './config.types.js'; -function throwOnLeft(result: Either.Either): T { - if (Either.isLeft(result)) { - const messages = result.left.map((e) => `${e.field}: ${e.message}`).join(', '); +function throwOnFail(result: Result.Result): T { + if (Result.isFailure(result)) { + const messages = result.failure.map((e) => `${e.field}: ${e.message}`).join(', '); throw new Error(`Invalid unified SDK config: ${messages}`); } - return result.right; + return result.success; } -export const makeOidcConfig = (json: unknown): OidcConfig => throwOnLeft(parseToOidcConfig(json)); +export const makeOidcConfig = (json: unknown): OidcConfig => throwOnFail(parseToOidcConfig(json)); export const makeJourneyConfig = (json: unknown): JourneyClientConfig => - throwOnLeft(parseToJourneyConfig(json)); + throwOnFail(parseToJourneyConfig(json)); export const makeDavinciConfig = (json: unknown): DaVinciConfig => - throwOnLeft(parseToDavinciConfig(json)); + throwOnFail(parseToDavinciConfig(json)); diff --git a/packages/sdk-utilities/src/lib/config/config.test.ts b/packages/sdk-utilities/src/lib/config/config.test.ts index a48407f9d8..c981091ea8 100644 --- a/packages/sdk-utilities/src/lib/config/config.test.ts +++ b/packages/sdk-utilities/src/lib/config/config.test.ts @@ -6,7 +6,7 @@ */ import { describe, it, expect } from 'vitest'; -import * as Either from 'effect/Either'; +import { Result } from 'effect'; import { parseToOidcConfig, parseToJourneyConfig, @@ -59,31 +59,31 @@ const journeyOnlyConfig = { describe('parseUnifiedSdkConfig', () => { it('parseUnifiedSdkConfig_ValidFullConfig_ReturnsSuccess', () => { - expect(Either.isRight(parseUnifiedSdkConfig(fullConfig))).toBe(true); + expect(Result.isSuccess(parseUnifiedSdkConfig(fullConfig))).toBe(true); }); it('parseUnifiedSdkConfig_JourneyOnlyConfig_ReturnsSuccess', () => { - expect(Either.isRight(parseUnifiedSdkConfig(journeyOnlyConfig))).toBe(true); + expect(Result.isSuccess(parseUnifiedSdkConfig(journeyOnlyConfig))).toBe(true); }); it('parseUnifiedSdkConfig_NoOidcOrJourneySection_ReturnsSuccess', () => { - expect(Either.isRight(parseUnifiedSdkConfig({ timeout: 5000 }))).toBe(true); + expect(Result.isSuccess(parseUnifiedSdkConfig({ timeout: 5000 }))).toBe(true); }); it('parseUnifiedSdkConfig_UnknownTopLevelField_Ignored', () => { - expect(Either.isRight(parseUnifiedSdkConfig({ timeout: 5000, surprise: 'kept' }))).toBe(true); + expect(Result.isSuccess(parseUnifiedSdkConfig({ timeout: 5000, surprise: 'kept' }))).toBe(true); }); it('parseUnifiedSdkConfig_TimeoutNotNumber_ReturnsTypeError', () => { - const errors = Either.getOrThrow( - Either.flip(parseUnifiedSdkConfig({ ...fullConfig, timeout: 'thirty' })), + const errors = Result.getOrThrow( + Result.flip(parseUnifiedSdkConfig({ ...fullConfig, timeout: 'thirty' })), ); expect(errors.some((e) => e.field === 'timeout')).toBe(true); }); it('parseUnifiedSdkConfig_JourneyMissingServerUrl_ReturnsError', () => { - const errors = Either.getOrThrow( - Either.flip( + const errors = Result.getOrThrow( + Result.flip( parseUnifiedSdkConfig({ journey: { realm: 'alpha' }, oidc: { discoveryEndpoint: 'https://example.com/.well-known/openid-configuration' }, @@ -94,15 +94,15 @@ describe('parseUnifiedSdkConfig', () => { }); it('parseUnifiedSdkConfig_InvalidOidcNested_PropagatesErrors', () => { - const errors = Either.getOrThrow( - Either.flip(parseUnifiedSdkConfig({ ...fullConfig, oidc: { ...minimalOidc, clientId: 42 } })), + const errors = Result.getOrThrow( + Result.flip(parseUnifiedSdkConfig({ ...fullConfig, oidc: { ...minimalOidc, clientId: 42 } })), ); expect(errors.some((e) => e.field === 'oidc.clientId')).toBe(true); }); it('parseUnifiedSdkConfig_MultipleErrors_AllAccumulated', () => { - const errors = Either.getOrThrow( - Either.flip(parseUnifiedSdkConfig({ timeout: 'thirty', oidc: { scopes: 'not-an-array' } })), + const errors = Result.getOrThrow( + Result.flip(parseUnifiedSdkConfig({ timeout: 'thirty', oidc: { scopes: 'not-an-array' } })), ); expect(errors.length).toBeGreaterThanOrEqual(2); expect(errors.some((e) => e.field === 'timeout')).toBe(true); @@ -112,14 +112,14 @@ describe('parseUnifiedSdkConfig', () => { describe('parseToOidcConfig', () => { it('parseToOidcConfig_NoOidcBlock_ReturnsFailure', () => { - const errors = Either.getOrThrow( - Either.flip(parseToOidcConfig({ journey: { serverUrl: 'https://example.com/am' } })), + const errors = Result.getOrThrow( + Result.flip(parseToOidcConfig({ journey: { serverUrl: 'https://example.com/am' } })), ); expect(errors.some((e) => e.field === 'oidc')).toBe(true); }); it('parseToOidcConfig_MinimalConfig_MapsRequiredFields', () => { - const data = Either.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })); + const data = Result.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })); expect(data.clientId).toBe('my-client'); expect(data.redirectUri).toBe('https://app.example.com/callback'); expect(data.scope).toBe('openid profile'); @@ -129,14 +129,14 @@ describe('parseToOidcConfig', () => { }); it('parseToOidcConfig_ScopesJoinedWithSpace', () => { - const data = Either.getOrThrow( + const data = Result.getOrThrow( parseToOidcConfig({ oidc: { ...minimalOidc, scopes: ['openid', 'email'] } }), ); expect(data.scope).toBe('openid email'); }); it('parseToOidcConfig_RefreshThresholdConvertedToMs', () => { - const data = Either.getOrThrow( + const data = Result.getOrThrow( parseToOidcConfig({ oidc: { ...minimalOidc, refreshThreshold: 60 } }), ); expect(data.oauthThreshold).toBe(60000); @@ -144,12 +144,12 @@ describe('parseToOidcConfig', () => { it('parseToOidcConfig_NoRefreshThreshold_OauthThresholdAbsent', () => { expect( - Either.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })).oauthThreshold, + Result.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })).oauthThreshold, ).toBeUndefined(); }); it('parseToOidcConfig_RealmMappedToRealmPath', () => { - const data = Either.getOrThrow( + const data = Result.getOrThrow( parseToOidcConfig({ journey: { serverUrl: 'https://example.com/am', realm: 'alpha' }, oidc: minimalOidc, @@ -159,22 +159,22 @@ describe('parseToOidcConfig', () => { }); it('parseToOidcConfig_NoRealm_RealmPathAbsent', () => { - expect(Either.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })).realmPath).toBeUndefined(); + expect(Result.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })).realmPath).toBeUndefined(); }); it('parseToOidcConfig_TimeoutPassedToServerConfig', () => { - const data = Either.getOrThrow(parseToOidcConfig({ timeout: 5000, oidc: minimalOidc })); + const data = Result.getOrThrow(parseToOidcConfig({ timeout: 5000, oidc: minimalOidc })); expect(data.serverConfig.timeout).toBe(5000); }); it('parseToOidcConfig_NoTimeout_TimeoutAbsentInServerConfig', () => { expect( - Either.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })).serverConfig.timeout, + Result.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })).serverConfig.timeout, ).toBeUndefined(); }); it('parseToOidcConfig_AuthorizeParamsMapped', () => { - const data = Either.getOrThrow( + const data = Result.getOrThrow( parseToOidcConfig({ oidc: { ...minimalOidc, @@ -198,22 +198,22 @@ describe('parseToOidcConfig', () => { }); it('parseToOidcConfig_EmptyScopes_ReturnsFailure', () => { - const errors = Either.getOrThrow( - Either.flip(parseToOidcConfig({ oidc: { ...minimalOidc, scopes: [] } })), + const errors = Result.getOrThrow( + Result.flip(parseToOidcConfig({ oidc: { ...minimalOidc, scopes: [] } })), ); expect(errors.some((e) => e.field === 'oidc.scopes')).toBe(true); }); it('parseToOidcConfig_NoAuthorizeParams_AllAbsent', () => { - const data = Either.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })); + const data = Result.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })); expect(data.loginHint).toBeUndefined(); expect(data.nonce).toBeUndefined(); expect(data.query).toBeUndefined(); }); it('parseToOidcConfig_OidcMissingDiscoveryEndpoint_ReturnsFailure', () => { - const errors = Either.getOrThrow( - Either.flip( + const errors = Result.getOrThrow( + Result.flip( parseToOidcConfig({ oidc: { clientId: 'x', redirectUri: 'x', scopes: ['openid'] } }), ), ); @@ -221,34 +221,34 @@ describe('parseToOidcConfig', () => { }); it('parseToOidcConfig_NullInput_ReturnsFailure', () => { - expect(Either.isLeft(parseToOidcConfig(null))).toBe(true); + expect(Result.isFailure(parseToOidcConfig(null))).toBe(true); }); }); describe('parseToJourneyConfig', () => { it('parseToJourneyConfig_NoOidcBlock_ReturnsFailure', () => { - const errors = Either.getOrThrow( - Either.flip(parseToJourneyConfig({ journey: { serverUrl: 'https://example.com/am' } })), + const errors = Result.getOrThrow( + Result.flip(parseToJourneyConfig({ journey: { serverUrl: 'https://example.com/am' } })), ); expect(errors.some((e) => e.field === 'oidc')).toBe(true); }); it('parseToJourneyConfig_MinimalConfig_MapsWellknown', () => { - const data = Either.getOrThrow(parseToJourneyConfig({ oidc: minimalOidc })); + const data = Result.getOrThrow(parseToJourneyConfig({ oidc: minimalOidc })); expect(data.serverConfig.wellknown).toBe( 'https://example.com/.well-known/openid-configuration', ); }); it('parseToJourneyConfig_JourneyOnlyConfig_MapsWellknown', () => { - const data = Either.getOrThrow(parseToJourneyConfig(journeyOnlyConfig)); + const data = Result.getOrThrow(parseToJourneyConfig(journeyOnlyConfig)); expect(data.serverConfig.wellknown).toBe( 'https://example.com/.well-known/openid-configuration', ); }); it('parseToJourneyConfig_RealmMappedToRealmPath', () => { - const data = Either.getOrThrow( + const data = Result.getOrThrow( parseToJourneyConfig({ journey: { serverUrl: 'https://example.com/am', realm: 'beta' }, oidc: minimalOidc, @@ -259,17 +259,17 @@ describe('parseToJourneyConfig', () => { it('parseToJourneyConfig_NoRealm_RealmPathAbsent', () => { expect( - Either.getOrThrow(parseToJourneyConfig({ oidc: minimalOidc })).realmPath, + Result.getOrThrow(parseToJourneyConfig({ oidc: minimalOidc })).realmPath, ).toBeUndefined(); }); it('parseToJourneyConfig_TimeoutPassedToServerConfig', () => { - const data = Either.getOrThrow(parseToJourneyConfig({ timeout: 10000, oidc: minimalOidc })); + const data = Result.getOrThrow(parseToJourneyConfig({ timeout: 10000, oidc: minimalOidc })); expect(data.serverConfig.timeout).toBe(10000); }); it('parseToJourneyConfig_OidcFieldsNotLeakedToResult', () => { - const data = Either.getOrThrow(parseToJourneyConfig(fullConfig)) as unknown as Record< + const data = Result.getOrThrow(parseToJourneyConfig(fullConfig)) as unknown as Record< string, unknown >; @@ -279,27 +279,27 @@ describe('parseToJourneyConfig', () => { }); it('parseToJourneyConfig_OidcMissingDiscoveryEndpoint_ReturnsFailure', () => { - const errors = Either.getOrThrow( - Either.flip(parseToJourneyConfig({ oidc: { realm: 'alpha' } })), + const errors = Result.getOrThrow( + Result.flip(parseToJourneyConfig({ oidc: { realm: 'alpha' } })), ); expect(errors.some((e) => e.field === 'oidc.discoveryEndpoint')).toBe(true); }); it('parseToJourneyConfig_NullInput_ReturnsFailure', () => { - expect(Either.isLeft(parseToJourneyConfig(null))).toBe(true); + expect(Result.isFailure(parseToJourneyConfig(null))).toBe(true); }); }); describe('parseToDavinciConfig', () => { it('parseToDavinciConfig_NoOidcBlock_ReturnsFailure', () => { - const errors = Either.getOrThrow( - Either.flip(parseToDavinciConfig({ journey: { serverUrl: 'https://example.com/am' } })), + const errors = Result.getOrThrow( + Result.flip(parseToDavinciConfig({ journey: { serverUrl: 'https://example.com/am' } })), ); expect(errors.some((e) => e.field === 'oidc')).toBe(true); }); it('parseToDavinciConfig_MinimalConfig_MapsRequiredFields', () => { - const data = Either.getOrThrow(parseToDavinciConfig({ oidc: minimalOidc })); + const data = Result.getOrThrow(parseToDavinciConfig({ oidc: minimalOidc })); expect(data.clientId).toBe('my-client'); expect(data.redirectUri).toBe('https://app.example.com/callback'); expect(data.scope).toBe('openid profile'); @@ -309,21 +309,21 @@ describe('parseToDavinciConfig', () => { }); it('parseToDavinciConfig_ScopesJoinedWithSpace', () => { - const data = Either.getOrThrow( + const data = Result.getOrThrow( parseToDavinciConfig({ oidc: { ...minimalOidc, scopes: ['openid', 'email'] } }), ); expect(data.scope).toBe('openid email'); }); it('parseToDavinciConfig_RefreshThresholdConvertedToMs', () => { - const data = Either.getOrThrow( + const data = Result.getOrThrow( parseToDavinciConfig({ oidc: { ...minimalOidc, refreshThreshold: 30 } }), ); expect(data.oauthThreshold).toBe(30000); }); it('parseToDavinciConfig_RealmMappedToRealmPath', () => { - const data = Either.getOrThrow( + const data = Result.getOrThrow( parseToDavinciConfig({ journey: { serverUrl: 'https://example.com/am', realm: 'alpha' }, oidc: minimalOidc, @@ -333,20 +333,20 @@ describe('parseToDavinciConfig', () => { }); it('parseToDavinciConfig_EmptyScopes_ReturnsFailure', () => { - const errors = Either.getOrThrow( - Either.flip(parseToDavinciConfig({ oidc: { ...minimalOidc, scopes: [] } })), + const errors = Result.getOrThrow( + Result.flip(parseToDavinciConfig({ oidc: { ...minimalOidc, scopes: [] } })), ); expect(errors.some((e) => e.field === 'oidc.scopes')).toBe(true); }); it('parseToDavinciConfig_TimeoutPassedToServerConfig', () => { - const data = Either.getOrThrow(parseToDavinciConfig({ timeout: 7000, oidc: minimalOidc })); + const data = Result.getOrThrow(parseToDavinciConfig({ timeout: 7000, oidc: minimalOidc })); expect(data.serverConfig.timeout).toBe(7000); }); it('parseToDavinciConfig_OidcMissingDiscoveryEndpoint_ReturnsFailure', () => { - const errors = Either.getOrThrow( - Either.flip( + const errors = Result.getOrThrow( + Result.flip( parseToDavinciConfig({ oidc: { clientId: 'x', redirectUri: 'x', scopes: ['openid'] } }), ), ); @@ -354,23 +354,23 @@ describe('parseToDavinciConfig', () => { }); it('parseToDavinciConfig_NullInput_ReturnsFailure', () => { - expect(Either.isLeft(parseToDavinciConfig(null))).toBe(true); + expect(Result.isFailure(parseToDavinciConfig(null))).toBe(true); }); }); describe('parseToOidcConfig log mapping', () => { it('parseToOidcConfig_LogFieldMapped_ToLogLevel', () => { - expect(Either.getOrThrow(parseToOidcConfig({ log: 'DEBUG', oidc: minimalOidc })).log).toBe( + expect(Result.getOrThrow(parseToOidcConfig({ log: 'DEBUG', oidc: minimalOidc })).log).toBe( 'debug', ); }); it('parseToOidcConfig_NoLogField_LogLevelAbsent', () => { - expect(Either.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })).log).toBeUndefined(); + expect(Result.getOrThrow(parseToOidcConfig({ oidc: minimalOidc })).log).toBeUndefined(); }); it('parseToOidcConfig_CookieName_NotMappedToResult', () => { - const data = Either.getOrThrow( + const data = Result.getOrThrow( parseToOidcConfig({ journey: { serverUrl: 'https://example.com/am', cookieName: 'iPlanetDirectoryPro' }, oidc: minimalOidc, @@ -382,17 +382,17 @@ describe('parseToOidcConfig log mapping', () => { describe('parseToJourneyConfig log mapping', () => { it('parseToJourneyConfig_LogFieldMapped_ToLogLevel', () => { - expect(Either.getOrThrow(parseToJourneyConfig({ log: 'WARN', oidc: minimalOidc })).log).toBe( + expect(Result.getOrThrow(parseToJourneyConfig({ log: 'WARN', oidc: minimalOidc })).log).toBe( 'warn', ); }); it('parseToJourneyConfig_NoLogField_LogLevelAbsent', () => { - expect(Either.getOrThrow(parseToJourneyConfig({ oidc: minimalOidc })).log).toBeUndefined(); + expect(Result.getOrThrow(parseToJourneyConfig({ oidc: minimalOidc })).log).toBeUndefined(); }); it('parseToJourneyConfig_CookieName_NotMappedToResult', () => { - const data = Either.getOrThrow( + const data = Result.getOrThrow( parseToJourneyConfig({ journey: { serverUrl: 'https://example.com/am', cookieName: 'iPlanetDirectoryPro' }, oidc: minimalOidc, @@ -404,13 +404,13 @@ describe('parseToJourneyConfig log mapping', () => { describe('parseToDavinciConfig log mapping', () => { it('parseToDavinciConfig_LogFieldMapped_ToLogLevel', () => { - expect(Either.getOrThrow(parseToDavinciConfig({ log: 'ERROR', oidc: minimalOidc })).log).toBe( + expect(Result.getOrThrow(parseToDavinciConfig({ log: 'ERROR', oidc: minimalOidc })).log).toBe( 'error', ); }); it('parseToDavinciConfig_NoLogField_LogLevelAbsent', () => { - expect(Either.getOrThrow(parseToDavinciConfig({ oidc: minimalOidc })).log).toBeUndefined(); + expect(Result.getOrThrow(parseToDavinciConfig({ oidc: minimalOidc })).log).toBeUndefined(); }); }); @@ -520,22 +520,22 @@ describe('makeDavinciConfig', () => { describe('collectErrors', () => { it('collectErrors_AllRight_ReturnsEmpty', () => { - expect(collectErrors([Either.right(1), Either.right('a')])).toEqual([]); + expect(collectErrors([Result.succeed(1), Result.succeed('a')])).toEqual([]); }); it('collectErrors_MultipleLeft_AccumulatesAllErrors', () => { const errors = collectErrors([ - Either.right(1), - Either.left([{ field: 'a', message: 'bad a' }]), - Either.left([{ field: 'b', message: 'bad b' }]), + Result.succeed(1), + Result.fail([{ field: 'a', message: 'bad a' }]), + Result.fail([{ field: 'b', message: 'bad b' }]), ]); expect(errors.map((e) => e.field)).toEqual(['a', 'b']); }); it('collectErrors_DoesNotShortCircuit', () => { const errors = collectErrors([ - Either.left([{ field: 'first', message: 'x' }]), - Either.left([{ field: 'second', message: 'y' }]), + Result.fail([{ field: 'first', message: 'x' }]), + Result.fail([{ field: 'second', message: 'y' }]), ]); expect(errors).toHaveLength(2); }); @@ -548,7 +548,7 @@ describe('parseOidcSection', () => { clientId: 'my-client', scopes: ['openid'], }); - expect(Either.getOrThrow(result).clientId).toBe('my-client'); + expect(Result.getOrThrow(result).clientId).toBe('my-client'); }); it('parseOidcSection_UnknownField_Ignored', () => { @@ -556,11 +556,11 @@ describe('parseOidcSection', () => { discoveryEndpoint: 'https://example.com/.well-known', unknownField: 'kept', }); - expect(Either.isRight(result)).toBe(true); + expect(Result.isSuccess(result)).toBe(true); }); it('parseOidcSection_MissingDiscoveryEndpoint_ReturnsError', () => { - const errors = Either.getOrThrow(Either.flip(parseOidcSection({ clientId: 'my-client' }))); + const errors = Result.getOrThrow(Result.flip(parseOidcSection({ clientId: 'my-client' }))); expect(errors.some((e) => e.field === 'oidc.discoveryEndpoint')).toBe(true); }); }); diff --git a/packages/sdk-utilities/src/lib/config/config.types.ts b/packages/sdk-utilities/src/lib/config/config.types.ts index bbcf2c2be1..3706344f77 100644 --- a/packages/sdk-utilities/src/lib/config/config.types.ts +++ b/packages/sdk-utilities/src/lib/config/config.types.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ -import type * as Either from 'effect/Either'; +import type { Result } from 'effect'; import type { LogLevel, AuthDisplayValue, AuthPromptValue } from '@forgerock/sdk-types'; @@ -50,10 +50,10 @@ export type ConfigValidationError = { }; /** - * A parsed result over the accumulating-error channel. Effect's `Either` is - * `Either`, so the SECOND type parameter is the error channel. + * A parsed result over the accumulating-error channel. Effect's `Result` is + * `Result`, so the SECOND type parameter is the error channel. */ -export type ParseResult = Either.Either; +export type ParseResult = Result.Result; /** Parses a record of unknown values into `A`. Unknown fields are silently ignored. */ export type Parser = (input: Readonly>) => ParseResult; diff --git a/packages/sdk-utilities/src/lib/config/config.utils.ts b/packages/sdk-utilities/src/lib/config/config.utils.ts index 576d1b42f5..d6adad56de 100644 --- a/packages/sdk-utilities/src/lib/config/config.utils.ts +++ b/packages/sdk-utilities/src/lib/config/config.utils.ts @@ -5,8 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ -import { pipe } from 'effect'; -import * as Either from 'effect/Either'; +import { pipe, Result } from 'effect'; import { AUTH_DISPLAY_VALUES, @@ -69,22 +68,22 @@ function isAbsent(value: unknown): value is undefined | null { /** * Gather every error from a list of parsed results without short-circuiting (unlike - * `Either.all`, which stops at the first `Left`). Returns all accumulated errors so a + * `Result.all`, which stops at the first failure). Returns all accumulated errors so a * section parser can report every invalid field in one pass. */ export function collectErrors( results: ReadonlyArray>, ): ConfigValidationError[] { - return results.flatMap((result) => (Either.isLeft(result) ? result.left : [])); + return results.flatMap((result) => (Result.isFailure(result) ? result.failure : [])); } /** * Unwraps a `ParseResult`, then returns `{ [key]: value }` when the value is defined, `{}` otherwise. * Spread into an object literal to conditionally include a property without an inline ternary. - * Safe to call after `collectErrors` — every result is guaranteed `Right` past the error guard. + * Safe to call after `collectErrors` — every result is guaranteed `Success` past the error guard. */ function parsedProp(key: K, result: ParseResult): ParsedProp { - const value = Either.getOrThrow(result); + const value = Result.getOrThrow(result); return (value !== undefined ? { [key]: value } : {}) as ParsedProp; } @@ -94,21 +93,21 @@ function parsedProp(key: K, result: ParseResult): Parsed const requiredString: FieldParser = (value, fieldPath) => { if (isAbsent(value)) { - return Either.left([{ field: fieldPath, message: 'Required field is missing' }]); + return Result.fail([{ field: fieldPath, message: 'Required field is missing' }]); } return typeof value === 'string' - ? Either.right(value) - : Either.left([{ field: fieldPath, message: `Expected string, got ${typeName(value)}` }]); + ? Result.succeed(value) + : Result.fail([{ field: fieldPath, message: `Expected string, got ${typeName(value)}` }]); }; /** Required, non-empty string — treats `''` as missing (a blank value can't satisfy a requirement). */ const requiredNonEmptyString: FieldParser = (value, fieldPath) => { if (isAbsent(value) || value === '') { - return Either.left([{ field: fieldPath, message: 'Required field is missing' }]); + return Result.fail([{ field: fieldPath, message: 'Required field is missing' }]); } return typeof value === 'string' - ? Either.right(value) - : Either.left([{ field: fieldPath, message: `Expected string, got ${typeName(value)}` }]); + ? Result.succeed(value) + : Result.fail([{ field: fieldPath, message: `Expected string, got ${typeName(value)}` }]); }; /** Parse each element of an array as a string, accumulating one error per non-string element. */ @@ -125,46 +124,46 @@ function parseStringElements(value: readonly unknown[], fieldPath: string): Pars }); } }); - return errors.length > 0 ? Either.left(errors) : Either.right(parsed); + return errors.length > 0 ? Result.fail(errors) : Result.succeed(parsed); } /** Required, non-empty array of strings — treats absent or `[]` as missing. */ const requiredNonEmptyStringArray: FieldParser = (value, fieldPath) => { if (isAbsent(value) || (Array.isArray(value) && value.length === 0)) { - return Either.left([{ field: fieldPath, message: 'Required field is missing' }]); + return Result.fail([{ field: fieldPath, message: 'Required field is missing' }]); } if (!Array.isArray(value)) { - return Either.left([{ field: fieldPath, message: `Expected array, got ${typeName(value)}` }]); + return Result.fail([{ field: fieldPath, message: `Expected array, got ${typeName(value)}` }]); } return parseStringElements(value, fieldPath); }; const optionalString: FieldParser = (value, fieldPath) => { - if (isAbsent(value)) return Either.right(undefined); + if (isAbsent(value)) return Result.succeed(undefined); return typeof value === 'string' - ? Either.right(value) - : Either.left([{ field: fieldPath, message: `Expected string, got ${typeName(value)}` }]); + ? Result.succeed(value) + : Result.fail([{ field: fieldPath, message: `Expected string, got ${typeName(value)}` }]); }; /** Finite, non-negative number (rejects NaN, Infinity, negatives). Optional-aware. */ const finiteNonNegativeNumber: FieldParser = (value, fieldPath) => { - if (isAbsent(value)) return Either.right(undefined); + if (isAbsent(value)) return Result.succeed(undefined); if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) { - return Either.left([ + return Result.fail([ { field: fieldPath, message: `Expected a finite, non-negative number, got ${typeName(value)}`, }, ]); } - return Either.right(value); + return Result.succeed(value); }; /** Optional array of strings, accumulating one error per non-string element. */ const optionalStringArray: FieldParser = (value, fieldPath) => { - if (isAbsent(value)) return Either.right(undefined); + if (isAbsent(value)) return Result.succeed(undefined); if (!Array.isArray(value)) { - return Either.left([{ field: fieldPath, message: `Expected array, got ${typeName(value)}` }]); + return Result.fail([{ field: fieldPath, message: `Expected array, got ${typeName(value)}` }]); } return parseStringElements(value, fieldPath); }; @@ -174,9 +173,9 @@ const optionalStringRecord: FieldParser | undefined> = ( value, fieldPath, ) => { - if (isAbsent(value)) return Either.right(undefined); + if (isAbsent(value)) return Result.succeed(undefined); if (typeof value !== 'object' || Array.isArray(value)) { - return Either.left([{ field: fieldPath, message: `Expected object, got ${typeName(value)}` }]); + return Result.fail([{ field: fieldPath, message: `Expected object, got ${typeName(value)}` }]); } const parsed: Record = {}; const errors: ConfigValidationError[] = []; @@ -190,7 +189,7 @@ const optionalStringRecord: FieldParser | undefined> = ( }); } } - return errors.length > 0 ? Either.left(errors) : Either.right(parsed); + return errors.length > 0 ? Result.fail(errors) : Result.succeed(parsed); }; /** @@ -201,16 +200,16 @@ function optionalLiteralUnion( members: Members, ): FieldParser { return (value, fieldPath) => { - if (isAbsent(value)) return Either.right(undefined); + if (isAbsent(value)) return Result.succeed(undefined); if (typeof value !== 'string') { - return Either.left([ + return Result.fail([ { field: fieldPath, message: `Expected string, got ${typeName(value)}` }, ]); } const matched = members.find((member): member is Members[number] => member === value); return matched !== undefined - ? Either.right(matched) - : Either.left([ + ? Result.succeed(matched) + : Result.fail([ { field: fieldPath, message: `Expected one of ${members.join(', ')}, got ${value}` }, ]); }; @@ -260,10 +259,10 @@ export const parseOidcSection: Parser = (input) => { acrValues, additionalParameters, ]); - if (errors.length > 0) return Either.left(errors); + if (errors.length > 0) return Result.fail(errors); const oidc: UnifiedOidcConfig = { - discoveryEndpoint: Either.getOrThrow(discoveryEndpoint), + discoveryEndpoint: Result.getOrThrow(discoveryEndpoint), ...parsedProp('clientId', clientId), ...parsedProp('redirectUri', redirectUri), ...parsedProp('scopes', scopes), @@ -277,7 +276,7 @@ export const parseOidcSection: Parser = (input) => { ...parsedProp('acrValues', acrValues), ...parsedProp('additionalParameters', additionalParameters), }; - return Either.right(oidc); + return Result.succeed(oidc); }; /** Parse the `journey` block. `serverUrl` required; `realm`/`cookieName` optional. */ @@ -287,28 +286,28 @@ export const parseJourneySection: Parser = (input) => { const cookieName = optionalString(input['cookieName'], 'journey.cookieName'); const errors = collectErrors([serverUrl, realm, cookieName]); - if (errors.length > 0) return Either.left(errors); + if (errors.length > 0) return Result.fail(errors); const journey: UnifiedJourneyConfig = { - serverUrl: Either.getOrThrow(serverUrl), + serverUrl: Result.getOrThrow(serverUrl), ...parsedProp('realm', realm), ...parsedProp('cookieName', cookieName), }; - return Either.right(journey); + return Result.succeed(journey); }; /** - * Run a section parser against an optional nested object: absent → `Right(undefined)`; - * present-but-not-an-object → `Left`; present object → delegate to `parser`. + * Run a section parser against an optional nested object: absent → `Result.succeed(undefined)`; + * present-but-not-an-object → failure; present object → delegate to `parser`. */ function parseOptionalSection( value: unknown, prefix: string, parser: Parser, ): ParseResult { - if (isAbsent(value)) return Either.right(undefined); + if (isAbsent(value)) return Result.succeed(undefined); if (typeof value !== 'object' || Array.isArray(value)) { - return Either.left([{ field: prefix, message: `Expected object, got ${typeName(value)}` }]); + return Result.fail([{ field: prefix, message: `Expected object, got ${typeName(value)}` }]); } return parser({ ...value }); } @@ -321,7 +320,7 @@ export const parseUnifiedSdkConfig: Parser = (input) => { const oidc = parseOptionalSection(input['oidc'], 'oidc', parseOidcSection); const errors = collectErrors([timeout, log, journey, oidc]); - if (errors.length > 0) return Either.left(errors); + if (errors.length > 0) return Result.fail(errors); const config: UnifiedSdkConfig = { ...parsedProp('timeout', timeout), @@ -329,7 +328,7 @@ export const parseUnifiedSdkConfig: Parser = (input) => { ...parsedProp('journey', journey), ...parsedProp('oidc', oidc), }; - return Either.right(config); + return Result.succeed(config); }; /* ------------------------------------------------------------------ * @@ -344,14 +343,14 @@ export const parseUnifiedSdkConfig: Parser = (input) => { */ function parseClientSdkConfig(config: UnifiedSdkConfig): ParseResult { if (!config.oidc) { - return Either.left([{ field: 'oidc', message: 'Required block is missing' }]); + return Result.fail([{ field: 'oidc', message: 'Required block is missing' }]); } const oidc = config.oidc; - // All three are required and non-optional, so `Either.all` (first-error) is enough — the + // All three are required and non-optional, so `Result.all` (first-error) is enough — the // struct form keeps field/value paired by key. Section parsers collect errors across many // optional fields instead, so they accumulate via `collectErrors`. - return Either.map( - Either.all({ + return Result.map( + Result.all({ clientId: requiredNonEmptyString(oidc.clientId, 'oidc.clientId'), redirectUri: requiredNonEmptyString(oidc.redirectUri, 'oidc.redirectUri'), scopes: requiredNonEmptyStringArray(oidc.scopes, 'oidc.scopes'), @@ -367,8 +366,8 @@ function parseClientSdkConfig(config: UnifiedSdkConfig): ParseResult { return config.oidc - ? Either.right({ ...config, oidc: config.oidc }) - : Either.left([{ field: 'oidc', message: 'Required block is missing' }]); + ? Result.succeed({ ...config, oidc: config.oidc }) + : Result.fail([{ field: 'oidc', message: 'Required block is missing' }]); } /* ------------------------------------------------------------------ * @@ -440,33 +439,33 @@ function buildDavinciConfig(config: ClientSdkConfig): DaVinciConfig { function assertObject( input: unknown, -): Either.Either>, ConfigValidationError[]> { +): Result.Result>, ConfigValidationError[]> { if (typeof input !== 'object' || input === null || Array.isArray(input)) { - return Either.left([{ field: 'config', message: `Expected object, got ${typeName(input)}` }]); + return Result.fail([{ field: 'config', message: `Expected object, got ${typeName(input)}` }]); } - return Either.right(input as Readonly>); + return Result.succeed(input as Readonly>); } export const parseToOidcConfig = (input: unknown): ParseResult => pipe( assertObject(input), - Either.flatMap(parseUnifiedSdkConfig), - Either.flatMap(parseClientSdkConfig), - Either.map(buildOidcConfig), + Result.flatMap(parseUnifiedSdkConfig), + Result.flatMap(parseClientSdkConfig), + Result.map(buildOidcConfig), ); export const parseToJourneyConfig = (input: unknown): ParseResult => pipe( assertObject(input), - Either.flatMap(parseUnifiedSdkConfig), - Either.flatMap(parseJourneySdkConfig), - Either.map(buildJourneyConfig), + Result.flatMap(parseUnifiedSdkConfig), + Result.flatMap(parseJourneySdkConfig), + Result.map(buildJourneyConfig), ); export const parseToDavinciConfig = (input: unknown): ParseResult => pipe( assertObject(input), - Either.flatMap(parseUnifiedSdkConfig), - Either.flatMap(parseClientSdkConfig), - Either.map(buildDavinciConfig), + Result.flatMap(parseUnifiedSdkConfig), + Result.flatMap(parseClientSdkConfig), + Result.map(buildDavinciConfig), ); diff --git a/packages/sdk-utilities/src/lib/micro.utils.ts b/packages/sdk-utilities/src/lib/micro.utils.ts index f5febe126d..3fc9f73be0 100644 --- a/packages/sdk-utilities/src/lib/micro.utils.ts +++ b/packages/sdk-utilities/src/lib/micro.utils.ts @@ -4,22 +4,32 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { causeIsDie, exitIsFail, exitIsSuccess } from 'effect/Micro'; -import type { MicroExit } from 'effect/Micro'; +import { Cause, Exit } from 'effect'; import type { GenericError } from '@forgerock/sdk-types'; -export function handleMicroExit( - result: MicroExit, +/** + * Unwrap an {@link Exit.Exit} into a plain value. + * + * - **Success** → returns the wrapped value. + * - **Failure with a typed error** → returns the error value from the first `Fail` reason. + * - **Defect / Die** → returns a {@link GenericError} built from the defect message. + * - **Other failure** → returns a {@link GenericError} with an unknown defect message. + */ +export function handleExit( + result: Exit.Exit, defectError: string, defectType: GenericError['type'], ): T | E | GenericError { - if (exitIsSuccess(result)) { + if (Exit.isSuccess(result)) { return result.value; } - if (exitIsFail(result)) { - return result.cause.error; + const reasons = result.cause.reasons; + const failReason = reasons.find(Cause.isFailReason); + if (failReason !== undefined) { + return failReason.error; } - const defect = causeIsDie(result.cause) ? result.cause.defect : undefined; + const dieReason = reasons.find(Cause.isDieReason); + const defect = dieReason?.defect; return { error: defectError, message: defect instanceof Error ? defect.message : String(defect ?? 'Unknown defect'), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 869e7d3f15..5089858708 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,41 +31,38 @@ catalogs: specifier: 4.21.0 version: 4.21.0 effect: - '@effect/cli': - specifier: ^0.69.0 - version: 0.69.2 '@effect/language-service': - specifier: ^0.35.2 - version: 0.35.2 + specifier: 0.87.1 + version: 0.87.1 '@effect/opentelemetry': - specifier: ^0.56.1 - version: 0.56.6 - '@effect/platform': - specifier: ^0.90.0 - version: 0.90.10 + specifier: 4.0.0-beta.103 + version: 4.0.0-beta.103 '@effect/platform-node': - specifier: 0.94.2 - version: 0.94.2 + specifier: 4.0.0-beta.103 + version: 4.0.0-beta.103 '@effect/vitest': - specifier: ^0.27.0 - version: 0.27.0 + specifier: 4.0.0-beta.103 + version: 4.0.0-beta.103 effect: - specifier: ^3.20.0 - version: 3.21.0 + specifier: 4.0.0-beta.103 + version: 4.0.0-beta.103 vite: vite: specifier: ^7.3.6 version: 7.3.6 vitest: '@vitest/coverage-v8': - specifier: ^3.2.6 - version: 3.2.6 + specifier: ^4.1.0 + version: 4.1.10 + '@vitest/ui': + specifier: ^4.1.0 + version: 4.1.10 vitest: - specifier: ^3.2.6 - version: 3.2.6 + specifier: ^4.1.0 + version: 4.1.10 vitest-canvas-mock: - specifier: ^1.1.3 - version: 1.1.3 + specifier: ^1.1.4 + version: 1.1.4 overrides: rollup: ^4.59.0 @@ -102,9 +99,6 @@ importers: '@commitlint/prompt': specifier: ^20.0.0 version: 20.1.0(@types/node@24.9.2)(typescript@5.8.3) - '@effect/cli': - specifier: catalog:effect - version: 0.69.2(@effect/platform@0.90.10(effect@3.21.0))(@effect/printer-ansi@0.45.0(@effect/typeclass@0.36.0(effect@3.21.0))(effect@3.21.0))(@effect/printer@0.45.0(@effect/typeclass@0.36.0(effect@3.21.0))(effect@3.21.0))(effect@3.21.0) '@eslint/eslintrc': specifier: ^3.0.0 version: 3.3.5 @@ -140,13 +134,13 @@ importers: version: 22.7.6(@babel/traverse@7.28.5)(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(@types/node@24.9.2)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.39.4(jiti@2.6.1))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(ts-node@10.9.2(@swc/core@1.15.30(@swc/helpers@0.5.21))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0)) '@nx/vite': specifier: 22.7.6 - version: 22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@3.2.6) + version: 22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.10) '@nx/vitest': specifier: 22.7.6 - version: 22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@3.2.6) + version: 22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.10) '@nx/web': specifier: 22.7.6 - version: 22.7.6(04f16120cd0b4809abbf447c38c7f725) + version: 22.7.6(294da7a21825b430d5914a528d2ef8ee) '@nx/workspace': specifier: 22.7.6 version: 22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)) @@ -191,10 +185,10 @@ importers: version: 8.46.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.8.3) '@vitest/coverage-v8': specifier: catalog:vitest - version: 3.2.6(vitest@3.2.6) + version: 4.1.10(vitest@4.1.10) '@vitest/ui': - specifier: 3.2.6 - version: 3.2.6(vitest@3.2.6) + specifier: catalog:vitest + version: 4.1.10(vitest@4.1.10) conventional-changelog-conventionalcommits: specifier: ^8.0.0 version: 8.0.0 @@ -293,10 +287,10 @@ importers: version: 7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) vitest: specifier: catalog:vitest - version: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) vitest-canvas-mock: specifier: catalog:vitest - version: 1.1.3(vitest@3.2.6) + version: 1.1.4(vitest@4.1.10) e2e/am-mock-api: dependencies: @@ -350,11 +344,11 @@ importers: version: 4.9.0 effect: specifier: catalog:effect - version: 3.21.0 + version: 4.0.0-beta.103 devDependencies: '@effect/language-service': specifier: catalog:effect - version: 0.35.2 + version: 0.87.1 e2e/journey-app: dependencies: @@ -384,16 +378,13 @@ importers: dependencies: '@effect/language-service': specifier: catalog:effect - version: 0.35.2 + version: 0.87.1 '@effect/opentelemetry': specifier: catalog:effect - version: 0.56.6(@effect/platform@0.90.10(effect@3.21.0))(@opentelemetry/api@1.9.0)(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-logs@0.207.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-web@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)(effect@3.21.0) - '@effect/platform': - specifier: catalog:effect - version: 0.90.10(effect@3.21.0) + version: 4.0.0-beta.103(@opentelemetry/api-logs@0.207.0)(@opentelemetry/api@1.9.0)(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-logs@0.207.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-web@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)(effect@4.0.0-beta.103) '@effect/platform-node': specifier: catalog:effect - version: 0.94.2(@effect/cluster@0.46.4(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/workflow@0.8.3(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0) + version: 4.0.0-beta.103(effect@4.0.0-beta.103)(ioredis@5.11.1) '@opentelemetry/sdk-logs': specifier: 0.207.0 version: 0.207.0(@opentelemetry/api@1.9.0) @@ -411,17 +402,17 @@ importers: version: 2.2.0(@opentelemetry/api@1.9.0) effect: specifier: catalog:effect - version: 3.21.0 + version: 4.0.0-beta.103 nanoid: specifier: ^5.1.16 version: 5.1.16 devDependencies: '@effect/vitest': specifier: catalog:effect - version: 0.27.0(effect@3.21.0)(vitest@3.2.6) + version: 4.0.0-beta.103(effect@4.0.0-beta.103)(vitest@4.1.10) vitest: specifier: catalog:vitest - version: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) e2e/oidc-app: dependencies: @@ -465,17 +456,17 @@ importers: version: 2.10.1 effect: specifier: catalog:effect - version: 3.21.0 + version: 4.0.0-beta.103 immer: specifier: 'catalog:' version: 10.2.0 devDependencies: '@effect/vitest': specifier: catalog:effect - version: 0.27.0(effect@3.21.0)(vitest@3.2.6) + version: 4.0.0-beta.103(effect@4.0.0-beta.103)(vitest@4.1.10) vitest: specifier: catalog:vitest - version: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) packages/device-client: dependencies: @@ -515,23 +506,23 @@ importers: version: 2.10.1 effect: specifier: catalog:effect - version: 3.21.0 + version: 4.0.0-beta.103 tslib: specifier: 'catalog:' version: 2.8.1 devDependencies: '@vitest/coverage-v8': specifier: catalog:vitest - version: 3.2.6(vitest@3.2.6) + version: 4.1.10(vitest@4.1.10) vite: specifier: catalog:vite version: 7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) vitest: specifier: catalog:vitest - version: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) vitest-canvas-mock: specifier: catalog:vitest - version: 1.1.3(vitest@3.2.6) + version: 1.1.4(vitest@4.1.10) packages/oidc-client: dependencies: @@ -561,14 +552,14 @@ importers: version: 2.10.1 effect: specifier: catalog:effect - version: 3.21.0 + version: 4.0.0-beta.103 jose: specifier: 'catalog:' version: 6.2.3 devDependencies: '@effect/vitest': specifier: catalog:effect - version: 0.27.0(effect@3.21.0)(vitest@3.2.6) + version: 4.0.0-beta.103(effect@4.0.0-beta.103)(vitest@4.1.10) msw: specifier: 'catalog:' version: 2.12.1(@types/node@24.9.2)(typescript@5.9.3) @@ -623,7 +614,7 @@ importers: version: link:../sdk-types effect: specifier: catalog:effect - version: 3.21.0 + version: 4.0.0-beta.103 scratchpad: dependencies: @@ -654,7 +645,7 @@ importers: version: 28.0.0 vitest: specifier: catalog:vitest - version: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) devDependencies: '@forgerock/javascript-sdk': specifier: 'catalog:' @@ -662,37 +653,31 @@ importers: tools/release: dependencies: - '@effect/platform': - specifier: catalog:effect - version: 0.90.10(effect@3.21.0) '@effect/platform-node': specifier: catalog:effect - version: 0.94.2(@effect/cluster@0.46.4(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/workflow@0.8.3(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0) + version: 4.0.0-beta.103(effect@4.0.0-beta.103)(ioredis@5.11.1) effect: specifier: catalog:effect - version: 3.21.0 + version: 4.0.0-beta.103 tools/user-scripts: dependencies: - '@effect/platform': - specifier: catalog:effect - version: 0.90.10(effect@3.21.0) '@effect/platform-node': specifier: catalog:effect - version: 0.94.2(@effect/cluster@0.46.4(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/workflow@0.8.3(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0) + version: 4.0.0-beta.103(effect@4.0.0-beta.103)(ioredis@5.11.1) effect: specifier: catalog:effect - version: 3.21.0 + version: 4.0.0-beta.103 vitest: specifier: catalog:vitest - version: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) devDependencies: '@effect/language-service': specifier: catalog:effect - version: 0.35.2 + version: 0.87.1 '@effect/vitest': specifier: catalog:effect - version: 0.27.0(effect@3.21.0)(vitest@3.2.6) + version: 4.0.0-beta.103(effect@4.0.0-beta.103)(vitest@4.1.10) packages: @@ -714,10 +699,6 @@ packages: '@altano/repository-tools@2.0.3': resolution: {integrity: sha512-cSR/ZYDF6Wp9OeAJMyLYYN1GenAAhV17W+w38ELP+3c5Ltsy9jkkCymi33nz/qnXyef3n6Fbr1h2yt3dvUN5sQ==} - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - '@aracna/core@1.5.0': resolution: {integrity: sha512-eU7xRvSl0I5XBp9VEOZUgrkDzd9Vew/umDj/pL3nrbmpaXEU662mIfC/2jtUbbW16mazXCCb2McCKtVQWNkqXg==} @@ -834,10 +815,18 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.28.5': resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.27.1': resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} @@ -855,6 +844,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} engines: {node: '>=6.9.0'} @@ -1357,6 +1351,10 @@ packages: resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} @@ -1549,56 +1547,29 @@ packages: resolution: {integrity: sha512-Y6+WUMsTFWE5jb20IFP4YGa5IrGY/+a/FbOSjDF/wz9gepU2hwCYSXRHP/vPwBvwcY3SVMASt4yXxbXNXigmZQ==} engines: {node: '>=18'} - '@effect/cli@0.69.2': - resolution: {integrity: sha512-1xYfEzW5f6jGWDb6V6DWTsWbtdp8DgQcchbewnCwKOXnJzF5VsTcfo4lYM4TXk/RAHA1owyq7OaEmeZ+qIt1/w==} - peerDependencies: - '@effect/platform': ^0.90.5 - '@effect/printer': ^0.45.0 - '@effect/printer-ansi': ^0.45.0 - effect: ^3.17.8 - - '@effect/cluster@0.46.4': - resolution: {integrity: sha512-81nWw5ABtRZZFmQTrWvfsUnqTg9LybIFYvmsiIL7xQ2t+g6746IZe9Tcv9bSmMdioJLgeuO4CiRg0FfDP2qCWA==} - peerDependencies: - '@effect/platform': ^0.90.0 - '@effect/rpc': ^0.68.3 - '@effect/sql': ^0.44.1 - '@effect/workflow': ^0.8.3 - effect: ^3.17.6 - - '@effect/experimental@0.54.6': - resolution: {integrity: sha512-UqHMvCQmrZT6kUVoUC0lqyno4Yad+j9hBGCdUjW84zkLwAq08tPqySiZUKRwY+Ae5B2Ab8rISYJH7nQvct9DMQ==} - peerDependencies: - '@effect/platform': ^0.90.2 - effect: ^3.17.7 - ioredis: ^5 - lmdb: ^3 - peerDependenciesMeta: - ioredis: - optional: true - lmdb: - optional: true - - '@effect/language-service@0.35.2': - resolution: {integrity: sha512-J7GbtthuYeruD4kYUHn3QEZtbl9v7OX9+ElD20mDBGBMA+Q6W4KnVMxZc+yDvKQBBYvfXImVUSzBbXzbrZJpyg==} + '@effect/language-service@0.87.1': + resolution: {integrity: sha512-kcljlJmEgqg5mFAM6UShJYJjMqJb3TbHHxrK8Qoubvwugc0aVWpRkbdgQvK5b17puOt3BKXXKOmcV+oQt0oQqQ==} hasBin: true - '@effect/opentelemetry@0.56.6': - resolution: {integrity: sha512-cBi9frXujTIEGXChkl4VdQfvDe7QvzC18SM8wK0CKYSgH9ZL7v/F5f5/3fTSTfEdO9ZyBk73s5Jbbogab0Q01g==} + '@effect/opentelemetry@4.0.0-beta.103': + resolution: {integrity: sha512-nGen5/SeuCkSII+X71YjCUsT/r1AqfS6eWyzCTzXv0NqyLxtnpWJxSYBGy5LtwZFMQsTmQKC7R426IzXbsxOXg==} + engines: {node: '>=18.0.0'} peerDependencies: - '@effect/platform': ^0.90.8 '@opentelemetry/api': ^1.9 + '@opentelemetry/api-logs': '>=0.203.0 <0.300.0' '@opentelemetry/resources': ^2.0.0 - '@opentelemetry/sdk-logs': ^0.203.0 + '@opentelemetry/sdk-logs': '>=0.203.0 <0.300.0' '@opentelemetry/sdk-metrics': ^2.0.0 '@opentelemetry/sdk-trace-base': ^2.0.0 '@opentelemetry/sdk-trace-node': ^2.0.0 '@opentelemetry/sdk-trace-web': ^2.0.0 '@opentelemetry/semantic-conventions': ^1.33.0 - effect: ^3.17.13 + effect: ^4.0.0-beta.103 peerDependenciesMeta: '@opentelemetry/api': optional: true + '@opentelemetry/api-logs': + optional: true '@opentelemetry/resources': optional: true '@opentelemetry/sdk-logs': @@ -1612,71 +1583,24 @@ packages: '@opentelemetry/sdk-trace-web': optional: true - '@effect/platform-node-shared@0.47.2': - resolution: {integrity: sha512-mtXNAx7Rzbfmp8hsMnyYebIkdCoKKOMa61uRLfOgbOV0p/ksO99YHYZSE/UTE2fFeoF9f2oi0mwOj/G7EMqzng==} - peerDependencies: - '@effect/cluster': ^0.46.4 - '@effect/platform': ^0.90.0 - '@effect/rpc': ^0.68.3 - '@effect/sql': ^0.44.1 - effect: ^3.17.6 - - '@effect/platform-node@0.94.2': - resolution: {integrity: sha512-iI7vUjNqd1DOFCa/9Tyf6Cu00Y4oLKMrpa2lx8+bUIHxtYbk696Yd9VFIDLMXVWrKFUru4Fw7WgWaA/YDor/sw==} - peerDependencies: - '@effect/cluster': ^0.46.4 - '@effect/platform': ^0.90.0 - '@effect/rpc': ^0.68.3 - '@effect/sql': ^0.44.1 - effect: ^3.17.6 - - '@effect/platform@0.90.10': - resolution: {integrity: sha512-QhDPgCaLfIMQKOCoCPQvRUS+Y34iYJ07jdZ/CBAvYFvg/iUBebsmFuHL63RCD/YZH9BuK/kqqLYAA3M0fmUEgg==} - peerDependencies: - effect: ^3.17.13 - - '@effect/printer-ansi@0.45.0': - resolution: {integrity: sha512-3MS02RP83eZaBJX98PRI4f5kyoEVyNfg2Qu/XUWQMFRp4wvmgNwEy18RjO9G6s7uB8NaYXTpQVDmtUoKARx7fA==} - peerDependencies: - '@effect/typeclass': ^0.36.0 - effect: ^3.17.0 - - '@effect/printer@0.45.0': - resolution: {integrity: sha512-UpFBH2JKAgakSWpue6yKkIAXMq+3md/CPb9s/NGl28vDu1P33cvDeeDL/1EOzFk8WqhIs3oKwPMDnd3jUhjzdg==} - peerDependencies: - '@effect/typeclass': ^0.36.0 - effect: ^3.17.0 - - '@effect/rpc@0.68.4': - resolution: {integrity: sha512-iFGqBtZjjatNWwgDCCajYZvQSHc55XyZEdmHGqrKS6UfdRsV7qUSPgnplMf++tIIyGme7IbAjD/3VJdbHI5Gzg==} - peerDependencies: - '@effect/platform': ^0.90.2 - effect: ^3.17.7 - - '@effect/sql@0.44.2': - resolution: {integrity: sha512-DEcvriHvj88zu7keruH9NcHQzam7yQzLNLJO6ucDXMCAwWzYZSJOsmkxBznRFv8ylFtccSclKH2fuj+wRKPjCQ==} - peerDependencies: - '@effect/experimental': ^0.54.6 - '@effect/platform': ^0.90.4 - effect: ^3.17.7 - - '@effect/typeclass@0.36.0': - resolution: {integrity: sha512-+8xYvX4tjD7gKwGYzOyFh90I+ptdXzoNHLQTSa8kGh/xOVZMIGYb0VgLoNHE02UsuVrB+JJJuBmKLdd5TeDTPg==} + '@effect/platform-node-shared@4.0.0-beta.103': + resolution: {integrity: sha512-0aCZMBid5ifqmY55TkfCDLaGTIM8qu3bNFUW7qL9vh/7jFOkaIAMX2MA8muG4deqW17XWxawddWu4v0fK+UW3g==} + engines: {node: '>=18.0.0'} peerDependencies: - effect: ^3.17.0 + effect: ^4.0.0-beta.103 - '@effect/vitest@0.27.0': - resolution: {integrity: sha512-8bM7n9xlMUYw9GqPIVgXFwFm2jf27m/R7psI64PGpwU5+26iwyxp9eAXEsfT5S6lqztYfpQQ1Ubp5o6HfNYzJQ==} + '@effect/platform-node@4.0.0-beta.103': + resolution: {integrity: sha512-VD8fbpendwFokMwzC7/MxazjhEVDihPC5NZtomYEyZwGaA1LXMvwP1y8pfXwfshUkG56TN4EMQqzu72c0B9FhA==} + engines: {node: '>=18.0.0'} peerDependencies: - effect: ^3.19.0 - vitest: ^3.2.0 + effect: ^4.0.0-beta.103 + ioredis: ^5.7.0 - '@effect/workflow@0.8.3': - resolution: {integrity: sha512-8X5IOemCb6I66GMd84w6NSmaQ+Ya3oXwItCUMelQAEuRtGzwqsw8PNNunQgK/poSRkmpszlsKOb6kEVNjSdFiQ==} + '@effect/vitest@4.0.0-beta.103': + resolution: {integrity: sha512-Kz3gemVuJNAZ3e4V6A7BwAP87x2Av8LyHOlCjy9jbZzlncwJXO7Olk1Sje3hdKaet3wEl51A/0/89xJ2IYSgNg==} peerDependencies: - '@effect/platform': ^0.90.0 - '@effect/rpc': ^0.68.3 - effect: ^3.17.6 + effect: ^4.0.0-beta.103 + vitest: ^4.1.0 '@emnapi/core@1.4.5': resolution: {integrity: sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==} @@ -1984,6 +1908,9 @@ packages: '@types/node': optional: true + '@ioredis/commands@1.10.0': + resolution: {integrity: sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q==} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -2123,33 +2050,33 @@ packages: '@microsoft/tsdoc@0.16.0': resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': - resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': + resolution: {integrity: sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==} cpu: [arm64] os: [darwin] - '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': - resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==} + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4': + resolution: {integrity: sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==} cpu: [x64] os: [darwin] - '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': - resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==} + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4': + resolution: {integrity: sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==} cpu: [arm64] os: [linux] - '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': - resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==} + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4': + resolution: {integrity: sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==} cpu: [arm] os: [linux] - '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': - resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==} + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4': + resolution: {integrity: sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==} cpu: [x64] os: [linux] - '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': - resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==} + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4': + resolution: {integrity: sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==} cpu: [x64] os: [win32] @@ -2677,88 +2604,6 @@ packages: '@paralleldrive/cuid2@2.2.2': resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} - '@parcel/watcher-android-arm64@2.5.1': - resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [android] - - '@parcel/watcher-darwin-arm64@2.5.1': - resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [darwin] - - '@parcel/watcher-darwin-x64@2.5.1': - resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [darwin] - - '@parcel/watcher-freebsd-x64@2.5.1': - resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [freebsd] - - '@parcel/watcher-linux-arm-glibc@2.5.1': - resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} - engines: {node: '>= 10.0.0'} - cpu: [arm] - os: [linux] - - '@parcel/watcher-linux-arm-musl@2.5.1': - resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} - engines: {node: '>= 10.0.0'} - cpu: [arm] - os: [linux] - - '@parcel/watcher-linux-arm64-glibc@2.5.1': - resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [linux] - - '@parcel/watcher-linux-arm64-musl@2.5.1': - resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [linux] - - '@parcel/watcher-linux-x64-glibc@2.5.1': - resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [linux] - - '@parcel/watcher-linux-x64-musl@2.5.1': - resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [linux] - - '@parcel/watcher-win32-arm64@2.5.1': - resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [win32] - - '@parcel/watcher-win32-ia32@2.5.1': - resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} - engines: {node: '>= 10.0.0'} - cpu: [ia32] - os: [win32] - - '@parcel/watcher-win32-x64@2.5.1': - resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [win32] - - '@parcel/watcher@2.5.1': - resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} - engines: {node: '>= 10.0.0'} - '@phenomnomnominal/tsquery@6.2.0': resolution: {integrity: sha512-Vo9nkhfZxDB/sBiqIY3pjDC4mOSyure+AFlEW5hcy/tRE82MqCXjRN4InnVNMldinRt0dLYqg4HAU2XPq5e1LA==} peerDependencies: @@ -3267,6 +3112,9 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} @@ -3528,48 +3376,48 @@ packages: resolution: {integrity: sha512-wfwn3z5M+w2KOV+xJFVv8tM8aOB4Ok5emfBDrDHrHMPDJ/fn3dEo6HoOra654PJ+zNwbTiMDvE5oAg/PLtnsUw==} engines: {node: '>=18'} - '@vitest/coverage-v8@3.2.6': - resolution: {integrity: sha512-LsAdmUapA0qSN306d8+zOyawM0hFm2m2Hg9IwVNIKBm+qJV8cijiq2c+gxKZcB1HCfIWAy+0qEZDCUQA58A1cw==} + '@vitest/coverage-v8@4.1.10': + resolution: {integrity: sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==} peerDependencies: - '@vitest/browser': 3.2.6 - vitest: 3.2.6 + '@vitest/browser': 4.1.10 + vitest: 4.1.10 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@3.2.6': - resolution: {integrity: sha512-1+7q9BtaKzEmO+fmNT3kYvoNn5Y71XWAx2Q5HRim4tTVRQVRv4uJFAQ5FbK0OPUeNP/WmVCpxYxoJdvuHVjzBQ==} + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} - '@vitest/mocker@3.2.6': - resolution: {integrity: sha512-EZOrpDbkKotFAP7wPAQV1UIyoGOk4oX7ynWhBhLB7v+meMHbQhU16oPpIYGTTe4oFlhpryGpgpcZP/sin3hYuw==} + '@vitest/mocker@4.1.10': + resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@3.2.6': - resolution: {integrity: sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==} + '@vitest/pretty-format@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} - '@vitest/runner@3.2.6': - resolution: {integrity: sha512-HYcoSj1w5tcgUnzoF0HcyaAQjpA1gj9ftUJ7iSJSuipc02jW9gKkigwZbjFldAfYHA1fa8UZVRftdMY5msWM9Q==} + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} - '@vitest/snapshot@3.2.6': - resolution: {integrity: sha512-H+ZjNTWGpObenh0YnlBctAPnJSI20P81PL8BPzWpx54YXLLTm8hEsWawtcYLMrwvpK48hGxLLbCS+1KRXhsKhw==} + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} - '@vitest/spy@3.2.6': - resolution: {integrity: sha512-oq6BbH68WzcWmwtBrU9nqLeaXTR4XwJF7FSLkKEZo4i6eoXcrxjcwSuTvWBIRUTC6VC72nXYunzqgZA+IKdtxg==} + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} - '@vitest/ui@3.2.6': - resolution: {integrity: sha512-mATfG3zVdhobE9U1rIpvtYD3DGuSSxqZ3Aj/8ityGqKXy8YDJ9BoAjZmAz6dZ1IZ1xI5V+MerkCczvVa+3QK9Q==} + '@vitest/ui@4.1.10': + resolution: {integrity: sha512-EOUqfXHTXtpSHsyLHH40ts3Ue+hRhSGwzwzMlK0dTEOLSDYyOXLyr5JDGmHQWhN2DYI30gw6dVx3cdgM9FZl+Q==} peerDependencies: - vitest: 3.2.6 + vitest: 4.1.10 - '@vitest/utils@3.2.6': - resolution: {integrity: sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==} + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} '@vue/compiler-core@3.5.24': resolution: {integrity: sha512-eDl5H57AOpNakGNAkFDH+y7kTqrQpJkZFXhWZQGyx/5Wh7B1uQYvcWkvZi11BDhscPgj8N7XV3oRwiPnx1Vrig==} @@ -3888,8 +3736,8 @@ packages: resolution: {integrity: sha512-WHw67kLXYbZuHTmcdbIrVArCq5wxo6NEuj3hiYAWr8mwJeC+C2mMCIBIWCiDoCye/OF/xelc+teJ1ERoWmnEIA==} engines: {node: '>=18'} - ast-v8-to-istanbul@0.3.8: - resolution: {integrity: sha512-szgSZqUxI5T8mLKvS7WTjF9is+MVbOeLADU73IseOcrqhxr/VAvy6wfoVE39KnKzA7JRhjF5eUagNlHwvZPlKQ==} + ast-v8-to-istanbul@1.0.5: + resolution: {integrity: sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==} async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} @@ -4101,10 +3949,6 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - cacheable-lookup@6.1.0: resolution: {integrity: sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww==} engines: {node: '>=10.6.0'} @@ -4162,8 +4006,8 @@ packages: caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} chalk@2.4.2: @@ -4191,10 +4035,6 @@ packages: chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} - check-error@2.1.3: - resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} - engines: {node: '>= 16'} - chrome-trace-event@1.0.4: resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} @@ -4245,6 +4085,10 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} + cluster-key-slot@1.1.1: + resolution: {integrity: sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==} + engines: {node: '>=0.10.0'} + co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -4387,10 +4231,6 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} - cookie@1.0.2: - resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} - engines: {node: '>=18'} - cookie@1.1.1: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} @@ -4569,10 +4409,6 @@ packages: babel-plugin-macros: optional: true - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -4607,6 +4443,10 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -4635,11 +4475,6 @@ packages: resolution: {integrity: sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==} engines: {node: '>=12.20'} - detect-libc@1.0.3: - resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} - engines: {node: '>=0.10'} - hasBin: true - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -4764,8 +4599,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - effect@3.21.0: - resolution: {integrity: sha512-PPN80qRokCd1f015IANNhrwOnLO7GrrMQfk4/lnZRE/8j7UPWrNNjPV0uBrZutI/nHzernbW+J0hdqQysHiSnQ==} + effect@4.0.0-beta.103: + resolution: {integrity: sha512-pE8TxF4m2tQzVI+77dIlm3s+81TACV1AiX1JEkvY+zVuxgQQ8aGSkqXNJF6b/ST+coCSk5cUdbULpQ7sm4oHyw==} ejs@5.0.1: resolution: {integrity: sha512-COqBPFMxuPTPspXl2DkVYaDS3HtrD1GpzOGkNTJ1IYkifq/r9h8SVEFrjA3D9/VJGOEoMQcrlhpntcSUrM8k6A==} @@ -4847,6 +4682,9 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-module-lexer@2.3.1: + resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -5072,8 +4910,8 @@ packages: resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} engines: {node: '>=0.10.0'} - expect-type@1.2.2: - resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} expect@30.2.0: @@ -5113,14 +4951,14 @@ packages: resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} engines: {'0': node >=0.6.0} - fast-check@3.23.2: - resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} - engines: {node: '>=8.0.0'} - fast-check@4.7.0: resolution: {integrity: sha512-NsZRtqvSSoCP0HbNjUD+r1JH8zqZalyp6gLY9e7OYs7NK9b6AHOs2baBFeBG7bVNsuoukh89x2Yg3rPsul8ziQ==} engines: {node: '>=12.17.0'} + fast-check@4.9.0: + resolution: {integrity: sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg==} + engines: {node: '>=12.17.0'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -5684,6 +5522,10 @@ packages: resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + ini@7.0.0: + resolution: {integrity: sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + inquirer@8.2.5: resolution: {integrity: sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==} engines: {node: '>=12.0.0'} @@ -5703,6 +5545,10 @@ packages: resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} engines: {node: '>= 0.10'} + ioredis@5.11.1: + resolution: {integrity: sha512-ehuGcf94bQXhfagULNXrJdfnWO38v070jxSx/qE87Kjzmu2fU7ro5EFAb+OPituLqgfyuQaym5DlrNydW2sJ9A==} + engines: {node: '>=12.22.0'} + ip-regex@4.3.0: resolution: {integrity: sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==} engines: {node: '>=8'} @@ -6084,12 +5930,12 @@ packages: jose@6.2.3: resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-tokens@9.0.1: - resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} - js-yaml@3.14.2: resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true @@ -6190,6 +6036,9 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} + kubernetes-types@1.30.0: + resolution: {integrity: sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==} + leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -6301,9 +6150,6 @@ packages: resolution: {integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==} engines: {node: '>=0.10.0'} - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - lowdb@1.0.0: resolution: {integrity: sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==} engines: {node: '>=4'} @@ -6350,8 +6196,8 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magicast@0.3.5: - resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + magicast@0.5.4: + resolution: {integrity: sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==} make-asynchronous@1.1.0: resolution: {integrity: sha512-ayF7iT+44LXdxJLTrTd3TLQpFDDvPCBxXxbv+pMUSuHA5Q8zyAfwkRP6aHHwNVFBUFWtxAHqwNJxF8vMZLAbVg==} @@ -6449,6 +6295,11 @@ packages: engines: {node: '>=10.0.0'} hasBin: true + mime@4.1.0: + resolution: {integrity: sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==} + engines: {node: '>=16'} + hasBin: true + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -6540,12 +6391,12 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - msgpackr-extract@3.0.3: - resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==} + msgpackr-extract@3.0.4: + resolution: {integrity: sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==} hasBin: true - msgpackr@1.11.5: - resolution: {integrity: sha512-UjkUHN0yqp9RWKy0Lplhh+wlpdt9oQBYgULZOiFhV3VclSF1JnSQWZ5r9gORQlNYaUKQoR8itv7g7z1xDDuACA==} + msgpackr@2.0.5: + resolution: {integrity: sha512-cef05H/dSYpLpqp3sj/qyZh5vhUYCalnaLO7j1yOmpsR0y/XwLVtK7r5gn+U/F7CTEfMowcGhlUQJDLcLf7jcA==} msw@2.12.1: resolution: {integrity: sha512-arzsi9IZjjByiEw21gSUP82qHM8zkV69nNpWV6W4z72KiLvsDWoOp678ORV6cNfU/JGhlX0SsnD4oXo9gI6I2A==} @@ -6557,8 +6408,8 @@ packages: typescript: optional: true - multipasta@0.2.7: - resolution: {integrity: sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==} + multipasta@0.2.8: + resolution: {integrity: sha512-ZPWuMKyv0cSO29f7hozp+k6+crZbQijV8ipMvxNxRf2SwtYGTX1ZX89Kd20VV4H9Znonx+EQn+iy1wGQsJ+b+Q==} mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} @@ -6602,9 +6453,6 @@ packages: nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} - node-addon-api@7.1.1: - resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} - node-fetch@2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} @@ -6709,6 +6557,10 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} + obug@2.1.4: + resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} + engines: {node: '>=12.20.0'} + on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -6915,10 +6767,6 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} - peek-stream@1.1.3: resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==} @@ -7087,9 +6935,6 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - pure-rand@7.0.1: resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} @@ -7175,6 +7020,14 @@ packages: resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} engines: {node: '>= 0.10'} + redis-errors@1.2.0: + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} + engines: {node: '>=4'} + + redis-parser@3.0.0: + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} + engines: {node: '>=4'} + redux-thunk@3.1.0: resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==} peerDependencies: @@ -7571,6 +7424,9 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + standard-as-callback@2.1.0: + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -7579,8 +7435,8 @@ packages: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.2.0: + resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} steno@0.4.4: resolution: {integrity: sha512-EEHMVYHNXFHfGtgjNITnka0aHhiAlo93F7z2/Pwd+g0teG9CnM3JIINM7hVVB5/rhw9voufD7Wukwgtw2uqh6w==} @@ -7678,9 +7534,6 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-literal@3.1.0: - resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} - strtok3@10.3.4: resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==} engines: {node: '>=18'} @@ -7845,10 +7698,6 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} - test-exclude@7.0.1: - resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} - engines: {node: '>=18'} - text-decoder@1.2.3: resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} @@ -7872,9 +7721,6 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@0.3.2: - resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyexec@1.0.2: resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} engines: {node: '>=18'} @@ -7883,16 +7729,8 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} - tinypool@1.1.1: - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} - engines: {node: '>=14.0.0'} - - tinyspy@4.0.4: - resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + tinyrainbow@3.1.1: + resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==} engines: {node: '>=14.0.0'} tldts-core@6.1.86: @@ -7932,8 +7770,9 @@ packages: resolution: {integrity: sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==} engines: {node: '>=14.16'} - toml@3.0.0: - resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} + toml@4.3.0: + resolution: {integrity: sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A==} + engines: {node: '>=20'} totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} @@ -8204,14 +8043,14 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} - uuid@11.1.1: - resolution: {integrity: sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==} - hasBin: true - uuid@14.0.0: resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} hasBin: true + uuid@14.0.1: + resolution: {integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==} + hasBin: true + uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). @@ -8260,11 +8099,6 @@ packages: resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} engines: {'0': node >=0.6.0} - vite-node@3.2.4: - resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - vite@7.3.6: resolution: {integrity: sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8305,31 +8139,44 @@ packages: yaml: optional: true - vitest-canvas-mock@1.1.3: - resolution: {integrity: sha512-zlKJR776Qgd+bcACPh0Pq5MG3xWq+CdkACKY/wX4Jyija0BSz8LH3aCCgwFKYFwtm565+050YFEGG9Ki0gE/Hw==} + vitest-canvas-mock@1.1.4: + resolution: {integrity: sha512-4boWHY+STwAxGl1+uwakNNoQky5EjPLC8HuponXNoAscYyT1h/F7RUvTkl4IyF/MiWr3V8Q626je3Iel3eArqA==} peerDependencies: vitest: ^3.0.0 || ^4.0.0 - vitest@3.2.6: - resolution: {integrity: sha512-xejya+bT/j/+R/AGa1XOfRxLmNUlLtlwjRsFUILF+xHfzElmGcmFydy2gqqIrd62ptIEfwVMofd19uNWD9L7Nw==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vitest@4.1.10: + resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/debug': ^4.1.12 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.2.6 - '@vitest/ui': 3.2.6 + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.10 + '@vitest/browser-preview': 4.1.10 + '@vitest/browser-webdriverio': 4.1.10 + '@vitest/coverage-istanbul': 4.1.10 + '@vitest/coverage-v8': 4.1.10 + '@vitest/ui': 4.1.10 happy-dom: '*' jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true - '@types/debug': + '@opentelemetry/api': optional: true '@types/node': optional: true - '@vitest/browser': + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': optional: true '@vitest/ui': optional: true @@ -8574,11 +8421,6 @@ snapshots: '@altano/repository-tools@2.0.3': {} - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - '@aracna/core@1.5.0': dependencies: cookie: 1.1.1 @@ -8755,8 +8597,12 @@ snapshots: '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-string-parser@7.29.7': {} + '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-identifier@7.29.7': {} + '@babel/helper-validator-option@7.27.1': {} '@babel/helper-wrap-function@7.28.3': @@ -8776,6 +8622,10 @@ snapshots: dependencies: '@babel/types': 7.28.5 + '@babel/parser@7.29.8': + dependencies: + '@babel/types': 7.29.8 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.28.5)': dependencies: '@babel/core': 7.28.5 @@ -9400,6 +9250,11 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@bcoe/v8-coverage@0.2.3': {} '@bcoe/v8-coverage@1.0.2': {} @@ -9739,39 +9594,15 @@ snapshots: gonzales-pe: 4.3.0 node-source-walk: 7.0.1 - '@effect/cli@0.69.2(@effect/platform@0.90.10(effect@3.21.0))(@effect/printer-ansi@0.45.0(@effect/typeclass@0.36.0(effect@3.21.0))(effect@3.21.0))(@effect/printer@0.45.0(@effect/typeclass@0.36.0(effect@3.21.0))(effect@3.21.0))(effect@3.21.0)': - dependencies: - '@effect/platform': 0.90.10(effect@3.21.0) - '@effect/printer': 0.45.0(@effect/typeclass@0.36.0(effect@3.21.0))(effect@3.21.0) - '@effect/printer-ansi': 0.45.0(@effect/typeclass@0.36.0(effect@3.21.0))(effect@3.21.0) - effect: 3.21.0 - ini: 4.1.3 - toml: 3.0.0 - yaml: 2.9.0 - - '@effect/cluster@0.46.4(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/workflow@0.8.3(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(effect@3.21.0)': - dependencies: - '@effect/platform': 0.90.10(effect@3.21.0) - '@effect/rpc': 0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0) - '@effect/sql': 0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0) - '@effect/workflow': 0.8.3(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0) - effect: 3.21.0 + '@effect/language-service@0.87.1': {} - '@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0)': + '@effect/opentelemetry@4.0.0-beta.103(@opentelemetry/api-logs@0.207.0)(@opentelemetry/api@1.9.0)(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-logs@0.207.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-web@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)(effect@4.0.0-beta.103)': dependencies: - '@effect/platform': 0.90.10(effect@3.21.0) - effect: 3.21.0 - uuid: 11.1.1 - - '@effect/language-service@0.35.2': {} - - '@effect/opentelemetry@0.56.6(@effect/platform@0.90.10(effect@3.21.0))(@opentelemetry/api@1.9.0)(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-logs@0.207.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-web@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)(effect@3.21.0)': - dependencies: - '@effect/platform': 0.90.10(effect@3.21.0) '@opentelemetry/semantic-conventions': 1.38.0 - effect: 3.21.0 + effect: 4.0.0-beta.103 optionalDependencies: '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.207.0 '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-logs': 0.207.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': 2.2.0(@opentelemetry/api@1.9.0) @@ -9779,79 +9610,30 @@ snapshots: '@opentelemetry/sdk-trace-node': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-web': 2.2.0(@opentelemetry/api@1.9.0) - '@effect/platform-node-shared@0.47.2(@effect/cluster@0.46.4(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/workflow@0.8.3(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0)': + '@effect/platform-node-shared@4.0.0-beta.103(effect@4.0.0-beta.103)': dependencies: - '@effect/cluster': 0.46.4(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/workflow@0.8.3(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(effect@3.21.0) - '@effect/platform': 0.90.10(effect@3.21.0) - '@effect/rpc': 0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0) - '@effect/sql': 0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0) - '@parcel/watcher': 2.5.1 - effect: 3.21.0 - multipasta: 0.2.7 + '@types/ws': 8.18.1 + effect: 4.0.0-beta.103 ws: 8.21.1 transitivePeerDependencies: - bufferutil - utf-8-validate - '@effect/platform-node@0.94.2(@effect/cluster@0.46.4(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/workflow@0.8.3(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0)': + '@effect/platform-node@4.0.0-beta.103(effect@4.0.0-beta.103)(ioredis@5.11.1)': dependencies: - '@effect/cluster': 0.46.4(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/workflow@0.8.3(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(effect@3.21.0) - '@effect/platform': 0.90.10(effect@3.21.0) - '@effect/platform-node-shared': 0.47.2(@effect/cluster@0.46.4(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/workflow@0.8.3(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0) - '@effect/rpc': 0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0) - '@effect/sql': 0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0) - effect: 3.21.0 - mime: 3.0.0 + '@effect/platform-node-shared': 4.0.0-beta.103(effect@4.0.0-beta.103) + effect: 4.0.0-beta.103 + ioredis: 5.11.1 + mime: 4.1.0 undici: 7.29.0 - ws: 8.21.1 transitivePeerDependencies: - bufferutil - utf-8-validate - '@effect/platform@0.90.10(effect@3.21.0)': - dependencies: - effect: 3.21.0 - find-my-way-ts: 0.1.6 - msgpackr: 1.11.5 - multipasta: 0.2.7 - - '@effect/printer-ansi@0.45.0(@effect/typeclass@0.36.0(effect@3.21.0))(effect@3.21.0)': - dependencies: - '@effect/printer': 0.45.0(@effect/typeclass@0.36.0(effect@3.21.0))(effect@3.21.0) - '@effect/typeclass': 0.36.0(effect@3.21.0) - effect: 3.21.0 - - '@effect/printer@0.45.0(@effect/typeclass@0.36.0(effect@3.21.0))(effect@3.21.0)': - dependencies: - '@effect/typeclass': 0.36.0(effect@3.21.0) - effect: 3.21.0 - - '@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0)': - dependencies: - '@effect/platform': 0.90.10(effect@3.21.0) - effect: 3.21.0 - - '@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0)': + '@effect/vitest@4.0.0-beta.103(effect@4.0.0-beta.103)(vitest@4.1.10)': dependencies: - '@effect/experimental': 0.54.6(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0) - '@effect/platform': 0.90.10(effect@3.21.0) - effect: 3.21.0 - uuid: 11.1.1 - - '@effect/typeclass@0.36.0(effect@3.21.0)': - dependencies: - effect: 3.21.0 - - '@effect/vitest@0.27.0(effect@3.21.0)(vitest@3.2.6)': - dependencies: - effect: 3.21.0 - vitest: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) - - '@effect/workflow@0.8.3(@effect/platform@0.90.10(effect@3.21.0))(@effect/rpc@0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0))(effect@3.21.0)': - dependencies: - '@effect/platform': 0.90.10(effect@3.21.0) - '@effect/rpc': 0.68.4(@effect/platform@0.90.10(effect@3.21.0))(effect@3.21.0) - effect: 3.21.0 + effect: 4.0.0-beta.103 + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) '@emnapi/core@1.4.5': dependencies: @@ -10085,6 +9867,8 @@ snapshots: optionalDependencies: '@types/node': 24.9.2 + '@ioredis/commands@1.10.0': {} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -10343,22 +10127,22 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4': optional: true '@mswjs/interceptors@0.40.0': @@ -10739,11 +10523,11 @@ snapshots: - typescript - verdaccio - '@nx/vite@22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@3.2.6)': + '@nx/vite@22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.10)': dependencies: '@nx/devkit': 22.7.6(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))) '@nx/js': 22.7.6(@babel/traverse@7.28.5)(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(verdaccio@6.5.2(typanion@3.14.0)) - '@nx/vitest': 22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@3.2.6) + '@nx/vitest': 22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.10) '@phenomnomnominal/tsquery': 6.2.0(typescript@5.8.3) ajv: 8.20.0 enquirer: 2.3.6 @@ -10752,7 +10536,7 @@ snapshots: tsconfig-paths: 4.2.0 tslib: 2.8.1 vite: 7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) - vitest: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) transitivePeerDependencies: - '@babel/traverse' - '@nx/eslint' @@ -10764,7 +10548,7 @@ snapshots: - typescript - verdaccio - '@nx/vitest@22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@3.2.6)': + '@nx/vitest@22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.10)': dependencies: '@nx/devkit': 22.7.6(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))) '@nx/js': 22.7.6(@babel/traverse@7.28.5)(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(verdaccio@6.5.2(typanion@3.14.0)) @@ -10774,7 +10558,7 @@ snapshots: optionalDependencies: '@nx/eslint': 22.7.6(03cdb71bd33024bc72407dcf2fd22241) vite: 7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) - vitest: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -10785,7 +10569,7 @@ snapshots: - typescript - verdaccio - '@nx/web@22.7.6(04f16120cd0b4809abbf447c38c7f725)': + '@nx/web@22.7.6(294da7a21825b430d5914a528d2ef8ee)': dependencies: '@nx/devkit': 22.7.6(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))) '@nx/js': 22.7.6(@babel/traverse@7.28.5)(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(verdaccio@6.5.2(typanion@3.14.0)) @@ -10797,7 +10581,7 @@ snapshots: '@nx/eslint': 22.7.6(03cdb71bd33024bc72407dcf2fd22241) '@nx/jest': 22.7.6(@babel/traverse@7.28.5)(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(@types/node@24.9.2)(babel-plugin-macros@3.1.0)(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(ts-node@10.9.2(@swc/core@1.15.30(@swc/helpers@0.5.21))(@types/node@24.9.2)(typescript@5.8.3))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0)) '@nx/playwright': 22.7.6(2adf0f06d3a79ef992d45b4845c9b15e) - '@nx/vite': 22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@3.2.6) + '@nx/vite': 22.7.6(@babel/traverse@7.28.5)(@nx/eslint@22.7.6(03cdb71bd33024bc72407dcf2fd22241))(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21))(nx@22.7.6(@swc-node/register@1.11.1(@emnapi/core@1.7.0)(@emnapi/runtime@1.7.0)(@swc/core@1.15.30(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.8.3))(@swc/core@1.15.30(@swc/helpers@0.5.21)))(typescript@5.8.3)(verdaccio@6.5.2(typanion@3.14.0))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))(vitest@4.1.10) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -11029,66 +10813,6 @@ snapshots: dependencies: '@noble/hashes': 1.8.0 - '@parcel/watcher-android-arm64@2.5.1': - optional: true - - '@parcel/watcher-darwin-arm64@2.5.1': - optional: true - - '@parcel/watcher-darwin-x64@2.5.1': - optional: true - - '@parcel/watcher-freebsd-x64@2.5.1': - optional: true - - '@parcel/watcher-linux-arm-glibc@2.5.1': - optional: true - - '@parcel/watcher-linux-arm-musl@2.5.1': - optional: true - - '@parcel/watcher-linux-arm64-glibc@2.5.1': - optional: true - - '@parcel/watcher-linux-arm64-musl@2.5.1': - optional: true - - '@parcel/watcher-linux-x64-glibc@2.5.1': - optional: true - - '@parcel/watcher-linux-x64-musl@2.5.1': - optional: true - - '@parcel/watcher-win32-arm64@2.5.1': - optional: true - - '@parcel/watcher-win32-ia32@2.5.1': - optional: true - - '@parcel/watcher-win32-x64@2.5.1': - optional: true - - '@parcel/watcher@2.5.1': - dependencies: - detect-libc: 1.0.3 - is-glob: 4.0.3 - micromatch: 4.0.8 - node-addon-api: 7.1.1 - optionalDependencies: - '@parcel/watcher-android-arm64': 2.5.1 - '@parcel/watcher-darwin-arm64': 2.5.1 - '@parcel/watcher-darwin-x64': 2.5.1 - '@parcel/watcher-freebsd-x64': 2.5.1 - '@parcel/watcher-linux-arm-glibc': 2.5.1 - '@parcel/watcher-linux-arm-musl': 2.5.1 - '@parcel/watcher-linux-arm64-glibc': 2.5.1 - '@parcel/watcher-linux-arm64-musl': 2.5.1 - '@parcel/watcher-linux-x64-glibc': 2.5.1 - '@parcel/watcher-linux-x64-musl': 2.5.1 - '@parcel/watcher-win32-arm64': 2.5.1 - '@parcel/watcher-win32-ia32': 2.5.1 - '@parcel/watcher-win32-x64': 2.5.1 - '@phenomnomnominal/tsquery@6.2.0(typescript@5.8.3)': dependencies: '@types/esquery': 1.5.4 @@ -11556,6 +11280,10 @@ snapshots: '@types/unist@3.0.3': {} + '@types/ws@8.18.1': + dependencies: + '@types/node': 24.9.2 + '@types/yargs-parser@21.0.3': {} '@types/yargs@17.0.34': @@ -11906,87 +11634,81 @@ snapshots: lodash: 4.18.1 minimatch: 7.4.9 - '@vitest/coverage-v8@3.2.6(vitest@3.2.6)': + '@vitest/coverage-v8@4.1.10(vitest@4.1.10)': dependencies: - '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 - ast-v8-to-istanbul: 0.3.8 - debug: 4.4.3 + '@vitest/utils': 4.1.10 + ast-v8-to-istanbul: 1.0.5 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.6 istanbul-reports: 3.2.0 - magic-string: 0.30.21 - magicast: 0.3.5 - std-env: 3.10.0 - test-exclude: 7.0.1 - tinyrainbow: 2.0.0 - vitest: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) - transitivePeerDependencies: - - supports-color + magicast: 0.5.4 + obug: 2.1.4 + std-env: 4.2.0 + tinyrainbow: 3.1.1 + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) - '@vitest/expect@3.2.6': + '@vitest/expect@4.1.10': dependencies: + '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 3.2.6 - '@vitest/utils': 3.2.6 - chai: 5.3.3 - tinyrainbow: 2.0.0 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + chai: 6.2.2 + tinyrainbow: 3.1.1 - '@vitest/mocker@3.2.6(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))': dependencies: - '@vitest/spy': 3.2.6 + '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.12.1(@types/node@24.9.2)(typescript@5.8.3) vite: 7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) - '@vitest/mocker@3.2.6(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0))': dependencies: - '@vitest/spy': 3.2.6 + '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.12.1(@types/node@24.9.2)(typescript@5.9.3) vite: 7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) - '@vitest/pretty-format@3.2.6': + '@vitest/pretty-format@4.1.10': dependencies: - tinyrainbow: 2.0.0 + tinyrainbow: 3.1.1 - '@vitest/runner@3.2.6': + '@vitest/runner@4.1.10': dependencies: - '@vitest/utils': 3.2.6 + '@vitest/utils': 4.1.10 pathe: 2.0.3 - strip-literal: 3.1.0 - '@vitest/snapshot@3.2.6': + '@vitest/snapshot@4.1.10': dependencies: - '@vitest/pretty-format': 3.2.6 + '@vitest/pretty-format': 4.1.10 + '@vitest/utils': 4.1.10 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@3.2.6': - dependencies: - tinyspy: 4.0.4 + '@vitest/spy@4.1.10': {} - '@vitest/ui@3.2.6(vitest@3.2.6)': + '@vitest/ui@4.1.10(vitest@4.1.10)': dependencies: - '@vitest/utils': 3.2.6 + '@vitest/utils': 4.1.10 fflate: 0.8.2 flatted: 3.4.2 pathe: 2.0.3 sirv: 3.0.2 tinyglobby: 0.2.15 - tinyrainbow: 2.0.0 - vitest: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) + tinyrainbow: 3.1.1 + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) - '@vitest/utils@3.2.6': + '@vitest/utils@4.1.10': dependencies: - '@vitest/pretty-format': 3.2.6 - loupe: 3.2.1 - tinyrainbow: 2.0.0 + '@vitest/pretty-format': 4.1.10 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.1 '@vue/compiler-core@3.5.24': dependencies: @@ -12401,11 +12123,11 @@ snapshots: ast-module-types@6.0.1: {} - ast-v8-to-istanbul@0.3.8: + ast-v8-to-istanbul@1.0.5: dependencies: '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 - js-tokens: 9.0.1 + js-tokens: 10.0.0 async-function@1.0.0: {} @@ -12666,8 +12388,6 @@ snapshots: bytes@3.1.2: {} - cac@6.7.14: {} - cacheable-lookup@6.1.0: {} cacheable-lookup@7.0.0: {} @@ -12725,13 +12445,7 @@ snapshots: caseless@0.12.0: {} - chai@5.3.3: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.3 - deep-eql: 5.0.2 - loupe: 3.2.1 - pathval: 2.0.1 + chai@6.2.2: {} chalk@2.4.2: dependencies: @@ -12754,8 +12468,6 @@ snapshots: chardet@2.1.1: {} - check-error@2.1.3: {} - chrome-trace-event@1.0.4: {} ci-info@4.3.1: {} @@ -12796,6 +12508,8 @@ snapshots: clone@1.0.4: {} + cluster-key-slot@1.1.1: {} + co@4.6.0: {} code-block-writer@13.0.3: {} @@ -12932,8 +12646,6 @@ snapshots: cookie@0.7.2: {} - cookie@1.0.2: {} - cookie@1.1.1: {} cookiejar@2.1.4: {} @@ -13096,8 +12808,6 @@ snapshots: optionalDependencies: babel-plugin-macros: 3.1.0 - deep-eql@5.0.2: {} - deep-extend@0.6.0: {} deep-is@0.1.4: {} @@ -13126,6 +12836,8 @@ snapshots: delayed-stream@1.0.0: {} + denque@2.1.0: {} + depd@2.0.0: {} dependency-tree@11.2.0: @@ -13147,8 +12859,6 @@ snapshots: detect-indent@7.0.2: {} - detect-libc@1.0.3: {} - detect-libc@2.1.2: optional: true @@ -13279,10 +12989,18 @@ snapshots: ee-first@1.1.1: {} - effect@3.21.0: + effect@4.0.0-beta.103: dependencies: '@standard-schema/spec': 1.1.0 - fast-check: 3.23.2 + fast-check: 4.9.0 + find-my-way-ts: 0.1.6 + ini: 7.0.0 + kubernetes-types: 1.30.0 + msgpackr: 2.0.5 + multipasta: 0.2.8 + toml: 4.3.0 + uuid: 14.0.1 + yaml: 2.9.0 ejs@5.0.1: {} @@ -13396,6 +13114,8 @@ snapshots: es-module-lexer@1.7.0: {} + es-module-lexer@2.3.1: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -13699,7 +13419,7 @@ snapshots: dependencies: homedir-polyfill: 1.0.3 - expect-type@1.2.2: {} + expect-type@1.4.0: {} expect@30.2.0: dependencies: @@ -13802,11 +13522,11 @@ snapshots: extsprintf@1.3.0: {} - fast-check@3.23.2: + fast-check@4.7.0: dependencies: - pure-rand: 6.1.0 + pure-rand: 8.4.0 - fast-check@4.7.0: + fast-check@4.9.0: dependencies: pure-rand: 8.4.0 @@ -14440,6 +14160,8 @@ snapshots: ini@4.1.3: {} + ini@7.0.0: {} + inquirer@8.2.5: dependencies: ansi-escapes: 4.3.2 @@ -14487,6 +14209,18 @@ snapshots: interpret@1.4.0: {} + ioredis@5.11.1: + dependencies: + '@ioredis/commands': 1.10.0 + cluster-key-slot: 1.1.1 + debug: 4.4.3 + denque: 2.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + ip-regex@4.3.0: {} ipaddr.js@1.9.1: {} @@ -14999,9 +14733,9 @@ snapshots: jose@6.2.3: {} - js-tokens@4.0.0: {} + js-tokens@10.0.0: {} - js-tokens@9.0.1: {} + js-tokens@4.0.0: {} js-yaml@3.14.2: dependencies: @@ -15131,6 +14865,8 @@ snapshots: kind-of@6.0.3: {} + kubernetes-types@1.30.0: {} + leven@3.1.0: {} levn@0.4.1: @@ -15225,8 +14961,6 @@ snapshots: longest@2.0.1: {} - loupe@3.2.1: {} - lowdb@1.0.0: dependencies: graceful-fs: 4.2.11 @@ -15278,10 +15012,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magicast@0.3.5: + magicast@0.5.4: dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 source-map-js: 1.2.1 make-asynchronous@1.1.0: @@ -15356,6 +15090,8 @@ snapshots: mime@3.0.0: {} + mime@4.1.0: {} + mimic-fn@2.1.0: {} mimic-fn@4.0.0: {} @@ -15431,21 +15167,21 @@ snapshots: ms@2.1.3: {} - msgpackr-extract@3.0.3: + msgpackr-extract@3.0.4: dependencies: node-gyp-build-optional-packages: 5.2.2 optionalDependencies: - '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.4 optional: true - msgpackr@1.11.5: + msgpackr@2.0.5: optionalDependencies: - msgpackr-extract: 3.0.3 + msgpackr-extract: 3.0.4 msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3): dependencies: @@ -15453,7 +15189,7 @@ snapshots: '@mswjs/interceptors': 0.40.0 '@open-draft/deferred-promise': 2.2.0 '@types/statuses': 2.0.6 - cookie: 1.0.2 + cookie: 1.1.1 graphql: 16.12.0 headers-polyfill: 4.0.3 is-node-process: 1.2.0 @@ -15479,7 +15215,7 @@ snapshots: '@mswjs/interceptors': 0.40.0 '@open-draft/deferred-promise': 2.2.0 '@types/statuses': 2.0.6 - cookie: 1.0.2 + cookie: 1.1.1 graphql: 16.12.0 headers-polyfill: 4.0.3 is-node-process: 1.2.0 @@ -15498,7 +15234,7 @@ snapshots: transitivePeerDependencies: - '@types/node' - multipasta@0.2.7: {} + multipasta@0.2.8: {} mute-stream@0.0.8: {} @@ -15522,8 +15258,6 @@ snapshots: nice-try@1.0.5: {} - node-addon-api@7.1.1: {} - node-fetch@2.6.7: dependencies: whatwg-url: 5.0.0 @@ -15738,6 +15472,8 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + obug@2.1.4: {} + on-exit-leak-free@2.1.2: {} on-finished@2.4.1: @@ -15949,8 +15685,6 @@ snapshots: pathe@2.0.3: {} - pathval@2.0.1: {} - peek-stream@1.1.3: dependencies: buffer-from: 1.1.2 @@ -16134,8 +15868,6 @@ snapshots: punycode@2.3.1: {} - pure-rand@6.1.0: {} - pure-rand@7.0.1: {} pure-rand@8.4.0: {} @@ -16240,6 +15972,12 @@ snapshots: dependencies: resolve: 1.22.11 + redis-errors@1.2.0: {} + + redis-parser@3.0.0: + dependencies: + redis-errors: 1.2.0 + redux-thunk@3.1.0(redux@5.0.1): dependencies: redux: 5.0.1 @@ -16708,11 +16446,13 @@ snapshots: stackback@0.0.2: {} + standard-as-callback@2.1.0: {} + statuses@2.0.1: {} statuses@2.0.2: {} - std-env@3.10.0: {} + std-env@4.2.0: {} steno@0.4.4: dependencies: @@ -16823,10 +16563,6 @@ snapshots: strip-json-comments@3.1.1: {} - strip-literal@3.1.0: - dependencies: - js-tokens: 9.0.1 - strtok3@10.3.4: dependencies: '@tokenizer/token': 0.3.0 @@ -16970,12 +16706,6 @@ snapshots: glob: 7.2.3 minimatch: 3.1.5 - test-exclude@7.0.1: - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 10.4.5 - minimatch: 9.0.9 - text-decoder@1.2.3: dependencies: b4a: 1.7.3 @@ -17001,8 +16731,6 @@ snapshots: tinybench@2.9.0: {} - tinyexec@0.3.2: {} - tinyexec@1.0.2: {} tinyglobby@0.2.15: @@ -17010,11 +16738,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 - tinypool@1.1.1: {} - - tinyrainbow@2.0.0: {} - - tinyspy@4.0.4: {} + tinyrainbow@3.1.1: {} tldts-core@6.1.86: {} @@ -17048,7 +16772,7 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 - toml@3.0.0: {} + toml@4.3.0: {} totalist@3.0.1: {} @@ -17338,10 +17062,10 @@ snapshots: utils-merge@1.0.1: {} - uuid@11.1.1: {} - uuid@14.0.0: {} + uuid@14.0.1: {} + uuid@8.3.2: {} v8-compile-cache-lib@3.0.1: {} @@ -17434,27 +17158,6 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite-node@3.2.4(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0): - dependencies: - cac: 6.7.14 - debug: 4.4.3 - es-module-lexer: 1.7.0 - pathe: 2.0.3 - vite: 7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) - transitivePeerDependencies: - - '@types/node' - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0): dependencies: esbuild: 0.27.2 @@ -17471,97 +17174,73 @@ snapshots: tsx: 4.21.0 yaml: 2.9.0 - vitest-canvas-mock@1.1.3(vitest@3.2.6): + vitest-canvas-mock@1.1.4(vitest@4.1.10): dependencies: cssfontparser: 1.2.1 moo-color: 1.0.3 - vitest: 3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) - - vitest@3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0): - dependencies: - '@types/chai': 5.2.3 - '@vitest/expect': 3.2.6 - '@vitest/mocker': 3.2.6(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) - '@vitest/pretty-format': 3.2.6 - '@vitest/runner': 3.2.6 - '@vitest/snapshot': 3.2.6 - '@vitest/spy': 3.2.6 - '@vitest/utils': 3.2.6 - chai: 5.3.3 - debug: 4.4.3 - expect-type: 1.2.2 + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) + + vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)): + dependencies: + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(msw@2.12.1(@types/node@24.9.2)(typescript@5.8.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + es-module-lexer: 2.3.1 + expect-type: 1.4.0 magic-string: 0.30.21 + obug: 2.1.4 pathe: 2.0.3 picomatch: 4.0.4 - std-env: 3.10.0 + std-env: 4.2.0 tinybench: 2.9.0 - tinyexec: 0.3.2 + tinyexec: 1.0.2 tinyglobby: 0.2.15 - tinypool: 1.1.1 - tinyrainbow: 2.0.0 + tinyrainbow: 3.1.1 vite: 7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) - vite-node: 3.2.4(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: + '@opentelemetry/api': 1.9.0 '@types/node': 24.9.2 - '@vitest/ui': 3.2.6(vitest@3.2.6) + '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) + '@vitest/ui': 4.1.10(vitest@4.1.10) jsdom: 27.4.0(@noble/hashes@1.8.0) transitivePeerDependencies: - - jiti - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - vitest@3.2.6(@types/node@24.9.2)(@vitest/ui@3.2.6)(jiti@2.6.1)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0): - dependencies: - '@types/chai': 5.2.3 - '@vitest/expect': 3.2.6 - '@vitest/mocker': 3.2.6(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) - '@vitest/pretty-format': 3.2.6 - '@vitest/runner': 3.2.6 - '@vitest/snapshot': 3.2.6 - '@vitest/spy': 3.2.6 - '@vitest/utils': 3.2.6 - chai: 5.3.3 - debug: 4.4.3 - expect-type: 1.2.2 + vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)): + dependencies: + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + es-module-lexer: 2.3.1 + expect-type: 1.4.0 magic-string: 0.30.21 + obug: 2.1.4 pathe: 2.0.3 picomatch: 4.0.4 - std-env: 3.10.0 + std-env: 4.2.0 tinybench: 2.9.0 - tinyexec: 0.3.2 + tinyexec: 1.0.2 tinyglobby: 0.2.15 - tinypool: 1.1.1 - tinyrainbow: 2.0.0 + tinyrainbow: 3.1.1 vite: 7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) - vite-node: 3.2.4(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: + '@opentelemetry/api': 1.9.0 '@types/node': 24.9.2 - '@vitest/ui': 3.2.6(vitest@3.2.6) + '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) + '@vitest/ui': 4.1.10(vitest@4.1.10) jsdom: 27.4.0(@noble/hashes@1.8.0) transitivePeerDependencies: - - jiti - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml w3c-xmlserializer@5.0.0: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index d00cd28562..1e9c1073e3 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -17,17 +17,16 @@ catalog: tsx: '4.21.0' catalogs: effect: - effect: '^3.20.0' - '@effect/cli': '^0.69.0' - '@effect/language-service': '^0.35.2' - '@effect/platform': '^0.90.0' - '@effect/platform-node': '0.94.2' - '@effect/vitest': '^0.27.0' - '@effect/opentelemetry': '^0.56.1' + effect: '4.0.0-beta.103' + '@effect/language-service': '0.87.1' + '@effect/platform-node': '4.0.0-beta.103' + '@effect/vitest': '4.0.0-beta.103' + '@effect/opentelemetry': '4.0.0-beta.103' vitest: - vitest: '^3.2.6' - '@vitest/coverage-v8': '^3.2.6' - 'vitest-canvas-mock': '^1.1.3' + vitest: '^4.1.0' + '@vitest/coverage-v8': '^4.1.0' + '@vitest/ui': '^4.1.0' + 'vitest-canvas-mock': '^1.1.4' vite: vite: '^7.3.6' diff --git a/tools/release/package.json b/tools/release/package.json index 5925c21ecb..7cebf9aef2 100644 --- a/tools/release/package.json +++ b/tools/release/package.json @@ -9,7 +9,6 @@ "main": "index.js", "scripts": {}, "dependencies": { - "@effect/platform": "catalog:effect", "@effect/platform-node": "catalog:effect", "effect": "catalog:effect" } diff --git a/tools/user-scripts/package.json b/tools/user-scripts/package.json index cd9a532cab..6f2ca980c2 100644 --- a/tools/user-scripts/package.json +++ b/tools/user-scripts/package.json @@ -16,7 +16,6 @@ "test:watch": "pnpm nx nxTest --watch" }, "dependencies": { - "@effect/platform": "catalog:effect", "@effect/platform-node": "catalog:effect", "effect": "catalog:effect", "vitest": "catalog:vitest" From 4dc47f20667424f4519b48fddf146db32be09143 Mon Sep 17 00:00:00 2001 From: Ryan Bas Date: Thu, 6 Aug 2026 08:26:11 -0600 Subject: [PATCH 02/11] fix: replace Effect.sleep with direct setTimeout in polling effects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Effect.sleep in v4 beta.103 hangs in Vite-bundled browser environments due to ClockRef/withFiber/clockWith indirection chain. Replace with delayMs helper using Effect.callback + plain setTimeout to match v3 Micro.sleep behavior. Also fix: - pollStatus: use Effect.runPromiseExit(effect) direct call (not pipe) - pollStatus: add Cause.squash fallback for defect errors - password-policy.rules.ts: Result.failVoid → Result.fail(undefined) --- .../src/lib/client.store.effects.ts | 15 +++++++++-- .../davinci-client/src/lib/client.store.ts | 9 +++++-- .../src/lib/password-policy.rules.ts | 4 +-- tools/user-scripts/src/lib/user-scripts.ts | 27 +++++++------------ 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/packages/davinci-client/src/lib/client.store.effects.ts b/packages/davinci-client/src/lib/client.store.effects.ts index 8546e4d089..0356044e57 100644 --- a/packages/davinci-client/src/lib/client.store.effects.ts +++ b/packages/davinci-client/src/lib/client.store.effects.ts @@ -20,6 +20,17 @@ import { createInternalError, isInternalError } from './client.store.utils.js'; import { davinciApi } from './davinci.api.js'; import { nodeSlice } from './node.slice.js'; +/** + * Plain-`setTimeout` delay that bypasses Effect's ClockRef/withFiber chain. + * Required in Vite-bundled browser environments where Effect.sleep can hang + * due to the ClockRef scheduler not draining in a browser event loop. + */ +const delayMs = (ms: number): Effect.Effect => + Effect.callback((resume) => { + const handle = setTimeout(() => resume(Effect.void), ms); + return Effect.sync(() => clearTimeout(handle)); + }); + /** * Shape returned by RTK Query's dispatch for the poll endpoint. */ @@ -265,7 +276,7 @@ function challengePollingµ({ let response: PollDispatchResult = yield* doPoll(); for (let i = 0; i < maxRetries - 1 && isChallengeStillPending(response); i++) { - yield* Effect.sleep(pollInterval); + yield* delayMs(pollInterval); response = yield* doPoll(); } @@ -290,7 +301,7 @@ function continuePollingµ( if (mode.retriesRemaining <= 0) { return Effect.succeed('timedOut' as PollingStatus); } - return Effect.sleep(mode.pollInterval).pipe(Effect.map(() => 'continue' as PollingStatus)); + return delayMs(mode.pollInterval).pipe(Effect.map(() => 'continue' as PollingStatus)); } /** diff --git a/packages/davinci-client/src/lib/client.store.ts b/packages/davinci-client/src/lib/client.store.ts index e8fcdb3715..570f8f6dd3 100644 --- a/packages/davinci-client/src/lib/client.store.ts +++ b/packages/davinci-client/src/lib/client.store.ts @@ -451,14 +451,15 @@ export async function davinci({ */ pollStatus: (collector: PollingCollector): Poller => { return async () => { - const result = await getPollingModeµ(collector).pipe( + const pollingEffect = getPollingModeµ(collector).pipe( Effect.flatMap((mode: PollingMode) => pollingµ({ mode, collector, store, log })), Effect.tapError((err: InternalErrorResponse) => Effect.sync(() => log.error(err.error.message)), ), - Effect.runPromiseExit, ); + const result = await Effect.runPromiseExit(pollingEffect); + if (Exit.isSuccess(result)) { return result.value; } @@ -468,6 +469,10 @@ export async function davinci({ if (Option.isSome(maybeError)) { return maybeError.value; } + // Handle defects (unexpected thrown errors) + const defect = Cause.squash(result.cause); + const message = defect instanceof Error ? defect.message : String(defect); + return createInternalError(message, 'unknown_error'); } return createInternalError( diff --git a/packages/davinci-client/src/lib/password-policy.rules.ts b/packages/davinci-client/src/lib/password-policy.rules.ts index 7a74d91616..9dcaab1d31 100644 --- a/packages/davinci-client/src/lib/password-policy.rules.ts +++ b/packages/davinci-client/src/lib/password-policy.rules.ts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Ping Identity Corporation. All rights reserved. + * Copyright (c) 2025 - 2026 Ping Identity Corporation. All rights reserved. * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. @@ -67,7 +67,7 @@ const minCharactersRule: PasswordPolicyRule = (policy, value) => { for (const ch of value) if (members.has(ch)) hits += 1; return hits < min ? Result.succeed(`Password must contain at least ${min} character(s) from "${charset}"`) - : Result.failVoid; + : Result.fail(undefined); }), ); }; diff --git a/tools/user-scripts/src/lib/user-scripts.ts b/tools/user-scripts/src/lib/user-scripts.ts index 18e657634f..1de32aced8 100644 --- a/tools/user-scripts/src/lib/user-scripts.ts +++ b/tools/user-scripts/src/lib/user-scripts.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpClientRequest, HttpClientResponse } from '@effect/platform'; -import { Config, Data, Effect, ManagedRuntime } from 'effect'; +import { HttpClient, HttpClientRequest, HttpClientResponse } from 'effect/unstable/http'; +import { Context, Config, Data, Effect, Layer, ManagedRuntime } from 'effect'; import { NodeHttpClient } from '@effect/platform-node'; import { getUsersResponse, TokenResponse } from './schemas.js'; @@ -28,9 +28,8 @@ export class FailureToAcquireToken extends Data.TaggedError('FailureToAcquireTok cause: string; }> {} -export class UserService extends Effect.Service()('@users/service', { - dependencies: [NodeHttpClient.layerUndici], - effect: Effect.gen(function* () { +export class UserService extends Context.Service()('@users/service', { + make: Effect.gen(function* () { const client = yield* HttpClient.HttpClient; const clientId = yield* Config.string('CLIENT_ID'); const clientSecret = yield* Config.string('CLIENT_SECRET'); @@ -51,23 +50,15 @@ export class UserService extends Effect.Service()('@users/service', return { deleteUser: (userId: string) => Effect.gen(function* () { - const response = yield* HttpClientRequest.del(API_URL).pipe( + const response = yield* HttpClientRequest.delete(API_URL).pipe( HttpClientRequest.appendUrl(`/v1/environments/${envId}/users/${userId}`), HttpClientRequest.bearerToken(tokenResponse.access_token), client.execute, Effect.flatMap(HttpClientResponse.filterStatusOk), - Effect.catchTag('ResponseError', (e) => + Effect.catchTag('HttpClientError', (e) => Effect.fail( new DeleteUserError({ - message: `Failed to delete user, error in response: ${e}`, - cause: e.message, - }), - ), - ), - Effect.catchTag('RequestError', (e) => - Effect.fail( - new DeleteUserError({ - message: `Failed to delete user, error in request: ${e}`, + message: `Failed to delete user: ${e}`, cause: e.message, }), ), @@ -102,4 +93,6 @@ export class UserService extends Effect.Service()('@users/service', }), }) {} -export const UserRuntime = ManagedRuntime.make(UserService.Default); +export const UserRuntime = ManagedRuntime.make( + Layer.provide(Layer.effect(UserService, UserService.make), NodeHttpClient.layerUndici), +); From 91af3270a30c4091ce3e62d5eca6af34a0a81db5 Mon Sep 17 00:00:00 2001 From: Ryan Bas Date: Thu, 6 Aug 2026 08:54:01 -0600 Subject: [PATCH 03/11] refactor(davinci-client): simplify maxRepeatedCharacters and remove redundant casts --- packages/davinci-client/src/lib/client.store.effects.ts | 4 ++-- packages/davinci-client/src/lib/password-policy.rules.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/davinci-client/src/lib/client.store.effects.ts b/packages/davinci-client/src/lib/client.store.effects.ts index 0356044e57..a67ed185fb 100644 --- a/packages/davinci-client/src/lib/client.store.effects.ts +++ b/packages/davinci-client/src/lib/client.store.effects.ts @@ -299,9 +299,9 @@ function continuePollingµ( mode: Extract, ): Effect.Effect { if (mode.retriesRemaining <= 0) { - return Effect.succeed('timedOut' as PollingStatus); + return Effect.succeed('timedOut'); } - return delayMs(mode.pollInterval).pipe(Effect.map(() => 'continue' as PollingStatus)); + return delayMs(mode.pollInterval).pipe(Effect.map(() => 'continue')); } /** diff --git a/packages/davinci-client/src/lib/password-policy.rules.ts b/packages/davinci-client/src/lib/password-policy.rules.ts index 9dcaab1d31..69ce0b1c35 100644 --- a/packages/davinci-client/src/lib/password-policy.rules.ts +++ b/packages/davinci-client/src/lib/password-policy.rules.ts @@ -52,7 +52,7 @@ const maxRepeatedCharactersRule: PasswordPolicyRule = (policy, value) => { const maxCount = pipe( countChars(value), (counts) => Array.from(counts.values()), - Arr.reduce(0, (acc, n) => (n > acc ? n : acc)), + (values) => Math.max(0, ...values), ); return maxCount > max ? [`Password cannot repeat any character more than ${max} times`] : []; }; From 5fcd80c3122b382a5b7a8d5515ff4518b124403f Mon Sep 17 00:00:00 2001 From: Ryan Bas Date: Fri, 24 Jul 2026 14:07:24 -0600 Subject: [PATCH 04/11] feat: extract wellknownApi to shared @forgerock/sdk-wellknown package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Single canonical RTK Query instance used by davinci-client, journey-client, and oidc-client — prerequisite for shared Redux store cache deduplication. --- .../centralize-redux-store/facts-result.json | 109 ++++++++++ .../centralize-redux-store/facts-review.json | 103 ++++++++++ goals/centralize-redux-store/facts.md | 14 ++ goals/centralize-redux-store/facts.meta.json | 86 ++++++++ goals/centralize-redux-store/goal.md | 22 +++ .../interview-result.json | 53 +++++ goals/centralize-redux-store/interview.json | 113 +++++++++++ goals/centralize-redux-store/plan.md | 187 ++++++++++++++++++ packages/davinci-client/package.json | 1 + .../davinci-client/src/lib/client.store.ts | 2 +- .../src/lib/client.store.utils.ts | 2 +- .../davinci-client/src/lib/wellknown.api.ts | 57 ------ packages/davinci-client/tsconfig.json | 3 + packages/davinci-client/tsconfig.lib.json | 3 + packages/journey-client/package.json | 1 + .../journey-client/src/lib/client.store.ts | 2 +- .../src/lib/client.store.utils.ts | 2 +- .../journey-client/src/lib/wellknown.api.ts | 43 ---- packages/journey-client/tsconfig.lib.json | 3 + packages/oidc-client/package.json | 1 + packages/oidc-client/src/lib/client.store.ts | 2 +- .../oidc-client/src/lib/client.store.utils.ts | 2 +- packages/oidc-client/tsconfig.lib.json | 3 + .../sdk-effects/wellknown/eslint.config.mjs | 22 +++ packages/sdk-effects/wellknown/package.json | 41 ++++ packages/sdk-effects/wellknown/src/index.ts | 9 + .../wellknown}/src/lib/wellknown.api.ts | 20 +- packages/sdk-effects/wellknown/tsconfig.json | 16 ++ .../sdk-effects/wellknown/tsconfig.lib.json | 37 ++++ .../sdk-effects/wellknown/tsconfig.spec.json | 41 ++++ packages/sdk-effects/wellknown/vite.config.ts | 43 ++++ pnpm-lock.yaml | 21 ++ tsconfig.json | 3 + 33 files changed, 953 insertions(+), 114 deletions(-) create mode 100644 goals/centralize-redux-store/facts-result.json create mode 100644 goals/centralize-redux-store/facts-review.json create mode 100644 goals/centralize-redux-store/facts.md create mode 100644 goals/centralize-redux-store/facts.meta.json create mode 100644 goals/centralize-redux-store/goal.md create mode 100644 goals/centralize-redux-store/interview-result.json create mode 100644 goals/centralize-redux-store/interview.json create mode 100644 goals/centralize-redux-store/plan.md delete mode 100644 packages/davinci-client/src/lib/wellknown.api.ts delete mode 100644 packages/journey-client/src/lib/wellknown.api.ts create mode 100644 packages/sdk-effects/wellknown/eslint.config.mjs create mode 100644 packages/sdk-effects/wellknown/package.json create mode 100644 packages/sdk-effects/wellknown/src/index.ts rename packages/{oidc-client => sdk-effects/wellknown}/src/lib/wellknown.api.ts (78%) create mode 100644 packages/sdk-effects/wellknown/tsconfig.json create mode 100644 packages/sdk-effects/wellknown/tsconfig.lib.json create mode 100644 packages/sdk-effects/wellknown/tsconfig.spec.json create mode 100644 packages/sdk-effects/wellknown/vite.config.ts diff --git a/goals/centralize-redux-store/facts-result.json b/goals/centralize-redux-store/facts-result.json new file mode 100644 index 0000000000..1628a1d9d7 --- /dev/null +++ b/goals/centralize-redux-store/facts-result.json @@ -0,0 +1,109 @@ +{ + "decision": "submitted", + "stage": "facts", + "result": { + "stage": "facts", + "title": "Centralize Redux Store Across Client Packages", + "goalSlug": "centralize-redux-store", + "facts": [ + { + "id": "fact-1", + "text": "`davinci()` returns an object with a `store` property typed as an opaque `SdkStore` handle (not the raw Redux `Store` type).", + "accepted": true, + "removed": false, + "automatedVerification": true, + "recommendedAutomatedVerification": true + }, + { + "id": "fact-2", + "text": "`journey()` returns an object with a `store` property typed as an opaque `SdkStore` handle.", + "accepted": true, + "removed": false, + "automatedVerification": true, + "recommendedAutomatedVerification": true + }, + { + "id": "fact-3", + "text": "`oidc()` accepts an optional second argument — an `SdkStore` — and uses it instead of creating a new store when provided.", + "accepted": true, + "removed": false, + "automatedVerification": true, + "recommendedAutomatedVerification": true + }, + { + "id": "fact-4", + "text": "When `oidc()` is called without a second argument, it creates its own store exactly as it does today (no behavioral change for standalone usage).", + "accepted": true, + "removed": false, + "automatedVerification": true, + "recommendedAutomatedVerification": true + }, + { + "id": "fact-5", + "text": "The davinci/journey store is pre-provisioned with oidc's reducers (`oidcApi`) so that when `oidc()` receives the shared store, it can dispatch and select from its own slice without any runtime injection.", + "accepted": false, + "removed": false, + "comment": "I don't think we want `oidc` pre-provisioned. We only want `oidc` when it's been used as the oidc client.", + "automatedVerification": true, + "recommendedAutomatedVerification": true + }, + { + "id": "fact-6", + "text": "`wellknownApi` is extracted from `davinci-client`, `journey-client`, and `oidc-client` into `sdk-effects` (or an appropriate shared effects package) so all three import the same instance.", + "accepted": true, + "removed": false, + "automatedVerification": true, + "recommendedAutomatedVerification": true + }, + { + "id": "fact-7", + "text": "When `oidc()` shares a store with `davinci()`, there is only one `wellknown` cache entry — a second call to the same wellknown URL returns from cache without a network request.", + "accepted": true, + "removed": false, + "automatedVerification": true, + "recommendedAutomatedVerification": true + }, + { + "id": "fact-8", + "text": "A single `store.subscribe()` call on the davinci/journey client fires for state changes from both the flow client and oidc client when a shared store is in use.", + "accepted": true, + "removed": false, + "automatedVerification": true, + "recommendedAutomatedVerification": true + }, + { + "id": "fact-9", + "text": "All existing call sites (`davinci({ config })`, `journey({ config })`, `oidc({ config })`) continue to work without modification.", + "accepted": true, + "removed": false, + "automatedVerification": true, + "recommendedAutomatedVerification": true + }, + { + "id": "fact-10", + "text": "TypeScript consumers cannot access internal Redux primitives (dispatch, getState, etc.) through the exposed `SdkStore` type — it is opaque by design.", + "accepted": true, + "removed": false, + "automatedVerification": true, + "recommendedAutomatedVerification": true + }, + { + "id": "fact-11", + "text": "The `requestMiddleware` and `logger` passed to `davinci()`/`journey()` are inherited by oidc when using a shared store — oidc does not need to re-declare them.", + "accepted": true, + "removed": false, + "automatedVerification": false, + "recommendedAutomatedVerification": false + }, + { + "id": "fact-12", + "text": "All affected packages pass `pnpm lint`, `pnpm build`, and `pnpm test` after the changes.", + "accepted": true, + "removed": false, + "automatedVerification": true, + "recommendedAutomatedVerification": true + } + ], + "factsMarkdown": "# Facts\n\n- `davinci()` returns an object with a `store` property typed as an opaque `SdkStore` handle (not the raw Redux `Store` type).\n- `journey()` returns an object with a `store` property typed as an opaque `SdkStore` handle.\n- `oidc()` accepts an optional second argument — an `SdkStore` — and uses it instead of creating a new store when provided.\n- When `oidc()` is called without a second argument, it creates its own store exactly as it does today (no behavioral change for standalone usage).\n- `wellknownApi` is extracted from `davinci-client`, `journey-client`, and `oidc-client` into `sdk-effects` (or an appropriate shared effects package) so all three import the same instance.\n- When `oidc()` shares a store with `davinci()`, there is only one `wellknown` cache entry — a second call to the same wellknown URL returns from cache without a network request.\n- A single `store.subscribe()` call on the davinci/journey client fires for state changes from both the flow client and oidc client when a shared store is in use.\n- All existing call sites (`davinci({ config })`, `journey({ config })`, `oidc({ config })`) continue to work without modification.\n- TypeScript consumers cannot access internal Redux primitives (dispatch, getState, etc.) through the exposed `SdkStore` type — it is opaque by design.\n- The `requestMiddleware` and `logger` passed to `davinci()`/`journey()` are inherited by oidc when using a shared store — oidc does not need to re-declare them.\n- All affected packages pass `pnpm lint`, `pnpm build`, and `pnpm test` after the changes." + } +} diff --git a/goals/centralize-redux-store/facts-review.json b/goals/centralize-redux-store/facts-review.json new file mode 100644 index 0000000000..d7653b6042 --- /dev/null +++ b/goals/centralize-redux-store/facts-review.json @@ -0,0 +1,103 @@ +{ + "stage": "facts", + "title": "Centralize Redux Store Across Client Packages", + "goalSlug": "centralize-redux-store", + "facts": [ + { + "id": "fact-1", + "text": "`davinci()` returns an object with a `store` property typed as an opaque `SdkStore` handle (not the raw Redux `Store` type).", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-2", + "text": "`journey()` returns an object with a `store` property typed as an opaque `SdkStore` handle.", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-3", + "text": "`oidc()` accepts an optional second argument — an `SdkStore` — and uses it instead of creating a new store when provided.", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-4", + "text": "When `oidc()` is called without a second argument, it creates its own store exactly as it does today (no behavioral change for standalone usage).", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-5", + "text": "The davinci/journey store is pre-provisioned with oidc's reducers (`oidcApi`) so that when `oidc()` receives the shared store, it can dispatch and select from its own slice without any runtime injection.", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-6", + "text": "`wellknownApi` is extracted from `davinci-client`, `journey-client`, and `oidc-client` into `sdk-effects` (or an appropriate shared effects package) so all three import the same instance.", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-7", + "text": "When `oidc()` shares a store with `davinci()`, there is only one `wellknown` cache entry — a second call to the same wellknown URL returns from cache without a network request.", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-8", + "text": "A single `store.subscribe()` call on the davinci/journey client fires for state changes from both the flow client and oidc client when a shared store is in use.", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-9", + "text": "All existing call sites (`davinci({ config })`, `journey({ config })`, `oidc({ config })`) continue to work without modification.", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-10", + "text": "TypeScript consumers cannot access internal Redux primitives (dispatch, getState, etc.) through the exposed `SdkStore` type — it is opaque by design.", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-11", + "text": "The `requestMiddleware` and `logger` passed to `davinci()`/`journey()` are inherited by oidc when using a shared store — oidc does not need to re-declare them.", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": false, + "automatedVerification": false + }, + { + "id": "fact-12", + "text": "All affected packages pass `pnpm lint`, `pnpm build`, and `pnpm test` after the changes.", + "accepted": false, + "removed": false, + "recommendedAutomatedVerification": true, + "automatedVerification": true + } + ] +} diff --git a/goals/centralize-redux-store/facts.md b/goals/centralize-redux-store/facts.md new file mode 100644 index 0000000000..49d466e6df --- /dev/null +++ b/goals/centralize-redux-store/facts.md @@ -0,0 +1,14 @@ +# Facts + +- `davinci()` returns an object with a `store` property typed as an opaque `SdkStore` handle (not the raw Redux `Store` type). +- `journey()` returns an object with a `store` property typed as an opaque `SdkStore` handle. +- `oidc()` accepts an optional second argument — an `SdkStore` — and uses it instead of creating a new store when provided. +- When `oidc()` is called without a second argument, it creates its own store exactly as it does today (no behavioral change for standalone usage). +- `oidc` lazily injects its own reducers (`oidcApi`) into the shared store at `oidc()` init time — the owning store (davinci/journey) does NOT pre-provision oidc reducers. +- `wellknownApi` is extracted from `davinci-client`, `journey-client`, and `oidc-client` into `sdk-effects` (or an appropriate shared effects package) so all three import the same instance. +- When `oidc()` shares a store with `davinci()`, there is only one `wellknown` cache entry — a second call to the same wellknown URL returns from cache without a network request. +- A single `store.subscribe()` call on the davinci/journey client fires for state changes from both the flow client and oidc client when a shared store is in use. +- All existing call sites (`davinci({ config })`, `journey({ config })`, `oidc({ config })`) continue to work without modification. +- TypeScript consumers cannot access internal Redux primitives (dispatch, getState, etc.) through the exposed `SdkStore` type — it is opaque by design. +- The `requestMiddleware` and `logger` passed to `davinci()`/`journey()` are inherited by oidc when using a shared store — oidc does not need to re-declare them. +- All affected packages pass `pnpm lint`, `pnpm build`, and `pnpm test` after the changes. diff --git a/goals/centralize-redux-store/facts.meta.json b/goals/centralize-redux-store/facts.meta.json new file mode 100644 index 0000000000..49896c66b7 --- /dev/null +++ b/goals/centralize-redux-store/facts.meta.json @@ -0,0 +1,86 @@ +[ + { + "id": "fact-1", + "text": "`davinci()` returns an object with a `store` property typed as an opaque `SdkStore` handle (not the raw Redux `Store` type).", + "comment": "", + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-2", + "text": "`journey()` returns an object with a `store` property typed as an opaque `SdkStore` handle.", + "comment": "", + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-3", + "text": "`oidc()` accepts an optional second argument — an `SdkStore` — and uses it instead of creating a new store when provided.", + "comment": "", + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-4", + "text": "When `oidc()` is called without a second argument, it creates its own store exactly as it does today (no behavioral change for standalone usage).", + "comment": "", + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-5-revised", + "text": "`oidc` lazily injects its own reducers (`oidcApi`) into the shared store at `oidc()` init time — the owning store (davinci/journey) does NOT pre-provision oidc reducers.", + "comment": "User rejected pre-provisioning: 'I don't think we want oidc pre-provisioned. We only want oidc when it's been used as the oidc client.'", + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-6", + "text": "`wellknownApi` is extracted from `davinci-client`, `journey-client`, and `oidc-client` into `sdk-effects` (or an appropriate shared effects package) so all three import the same instance.", + "comment": "", + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-7", + "text": "When `oidc()` shares a store with `davinci()`, there is only one `wellknown` cache entry — a second call to the same wellknown URL returns from cache without a network request.", + "comment": "", + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-8", + "text": "A single `store.subscribe()` call on the davinci/journey client fires for state changes from both the flow client and oidc client when a shared store is in use.", + "comment": "", + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-9", + "text": "All existing call sites (`davinci({ config })`, `journey({ config })`, `oidc({ config })`) continue to work without modification.", + "comment": "", + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-10", + "text": "TypeScript consumers cannot access internal Redux primitives (dispatch, getState, etc.) through the exposed `SdkStore` type — it is opaque by design.", + "comment": "", + "recommendedAutomatedVerification": true, + "automatedVerification": true + }, + { + "id": "fact-11", + "text": "The `requestMiddleware` and `logger` passed to `davinci()`/`journey()` are inherited by oidc when using a shared store — oidc does not need to re-declare them.", + "comment": "", + "recommendedAutomatedVerification": false, + "automatedVerification": false + }, + { + "id": "fact-12", + "text": "All affected packages pass `pnpm lint`, `pnpm build`, and `pnpm test` after the changes.", + "comment": "", + "recommendedAutomatedVerification": true, + "automatedVerification": true + } +] diff --git a/goals/centralize-redux-store/goal.md b/goals/centralize-redux-store/goal.md new file mode 100644 index 0000000000..fa4942d99d --- /dev/null +++ b/goals/centralize-redux-store/goal.md @@ -0,0 +1,22 @@ +# Goal: Centralize Redux Store Across Client Packages + +## Articulated Goal + +Expose an opaque `SdkStore` handle from `davinci()` and `journey()`, and allow `oidc()` to accept that handle as an optional second argument. When provided, `oidc` lazily injects its own reducers and middleware into the shared store rather than creating a new one — eliminating the dual-store problem when pairing oidc with a flow client. All existing call sites remain unchanged. + +## Shared Understanding + +See [`facts.md`](./facts.md) for the full list of accepted facts defining correct behavior. + +## Execution Plan + +See [`plan.md`](./plan.md) for the ordered steps, files touched, and verification commands. + +## Done Condition + +- `davinci()` and `journey()` return objects include a `store: SdkStore` property +- `oidc(opts, sharedStore?)` accepts the optional second argument and injects into it when provided +- `wellknownApi` lives in a new `@forgerock/sdk-wellknown` package imported by all three clients +- A shared store results in one wellknown cache entry and a single unified `subscribe` +- All existing call sites work without modification +- `pnpm nx run-many -t build lint test` passes across all affected packages diff --git a/goals/centralize-redux-store/interview-result.json b/goals/centralize-redux-store/interview-result.json new file mode 100644 index 0000000000..63fea5dd15 --- /dev/null +++ b/goals/centralize-redux-store/interview-result.json @@ -0,0 +1,53 @@ +{ + "decision": "submitted", + "stage": "interview", + "result": { + "stage": "interview", + "title": "Centralize Redux Store Across Client Packages", + "goalSlug": "centralize-redux-store", + "answers": [ + { + "questionId": "store-exposure", + "selectedOptionIds": ["opaque-property"], + "customAnswer": "", + "answer": "store property (opaque SdkStore type)", + "completed": true + }, + { + "questionId": "oidc-injection", + "selectedOptionIds": ["second-arg"], + "customAnswer": "", + "answer": "Second argument to oidc()", + "completed": true + }, + { + "questionId": "wellknown-dedup", + "selectedOptionIds": ["extract-now"], + "customAnswer": "", + "answer": "Extract wellknownApi to sdk-effects in this PR", + "completed": true + }, + { + "questionId": "reducer-injection-strategy", + "selectedOptionIds": ["pre-register"], + "customAnswer": "", + "answer": "Pre-register oidc reducers in davinci/journey store upfront", + "completed": true + }, + { + "questionId": "scope", + "selectedOptionIds": ["davinci", "journey", "oidc", "sdk-effects"], + "customAnswer": "", + "answer": "davinci-client\njourney-client\noidc-client\nsdk-effects (wellknown extraction)", + "completed": true + }, + { + "questionId": "breaking-changes", + "selectedOptionIds": ["minor-ok"], + "customAnswer": "", + "answer": "Minor breaking changes acceptable (semver minor)", + "completed": true + } + ] + } +} diff --git a/goals/centralize-redux-store/interview.json b/goals/centralize-redux-store/interview.json new file mode 100644 index 0000000000..78c7badb5c --- /dev/null +++ b/goals/centralize-redux-store/interview.json @@ -0,0 +1,113 @@ +{ + "stage": "interview", + "title": "Centralize Redux Store Across Client Packages", + "goalSlug": "centralize-redux-store", + "questions": [ + { + "id": "store-exposure", + "prompt": "How should `davinci()`/`journey()` expose the store to consumers?", + "description": "The store is currently fully private. The simplest approach is adding a `store` property to the returned client object. An alternative is a dedicated `getStore()` method. A third option is exposing only an opaque handle typed as `SdkStore` (not the full Redux `Store` type) to discourage direct Redux usage.", + "answerMode": "single-custom", + "recommendedAnswer": "Add a `store` property typed as an opaque `SdkStore` handle on the return object — additive, zero breaking changes, consumers can pass it to oidc() but can't easily misuse the raw Redux API.", + "recommendedOptionIds": ["opaque-property"], + "options": [ + { + "id": "opaque-property", + "label": "store property (opaque SdkStore type)" + }, + { + "id": "full-property", + "label": "store property (full Redux Store type)" + }, + { "id": "getter-method", "label": "getStore() method" } + ], + "required": true + }, + { + "id": "oidc-injection", + "prompt": "How should `oidc()` accept the shared store?", + "description": "Option A: add an optional `store` param to the existing config object — `oidc({ config, store: client.store })`. Option B: add it as a second argument — `oidc({ config }, client.store)`. The survey shows oidc() already takes a single destructured options bag.", + "answerMode": "single-custom", + "recommendedAnswer": "Optional `store` field inside the existing options object — consistent with how requestMiddleware and logger are passed today.", + "recommendedOptionIds": ["options-bag"], + "options": [ + { + "id": "options-bag", + "label": "Optional field in existing options object" + }, + { "id": "second-arg", "label": "Second argument to oidc()" } + ], + "required": true + }, + { + "id": "wellknown-dedup", + "prompt": "Should `wellknownApi` be deduplicated as part of this work?", + "description": "All three packages each define their own `wellknownApi` RTK Query slice with the same reducerPath ('wellknown') and endpoint. With a shared store, both registrations would collide on the same reducer key. We could: (A) keep them separate and let RTK Query's cache dedup on-the-fly (they share the same reducerPath so this actually works), (B) extract `wellknownApi` to `sdk-effects` so both packages import the same instance, or (C) defer this to a follow-up.", + "answerMode": "single-custom", + "recommendedAnswer": "Extract wellknownApi to sdk-effects as part of this PR — the same-key collision is a latent bug we'd hit immediately when testing shared store, and extraction is straightforward.", + "recommendedOptionIds": ["extract-now"], + "options": [ + { + "id": "extract-now", + "label": "Extract wellknownApi to sdk-effects in this PR" + }, + { + "id": "rtk-dedup", + "label": "Rely on RTK Query same-key dedup (same reducerPath)" + }, + { "id": "defer", "label": "Defer to a follow-up" } + ], + "required": true + }, + { + "id": "reducer-injection-strategy", + "prompt": "How should oidc inject its reducers into a shared store?", + "description": "RTK 2.0 ships `combineSlices` and lazy reducer injection. Two clean approaches: (A) use `store.dispatch(oidcApi.util.updateSubscriptionOptions(...))` + manually add reducer via `store.injectReducers` if RTK exposes it, or (B) design `createClientStore` / `createJourneyStore` to pre-register all possible reducers with their slices (oidc's included) so the store is fully wired before oidc() receives it. Option B is simpler but slightly over-provisions; Option A is lazy but requires RTK 2.0 `combineSlices`.", + "answerMode": "single-custom", + "recommendedAnswer": "Pre-register all reducers in the owning store (davinci/journey) — avoids runtime injection complexity, reducer keys don't collide (config/node/davinci/journeyReducer/oidc/wellknown are all unique), and the extra state is negligible.", + "recommendedOptionIds": ["pre-register"], + "options": [ + { + "id": "pre-register", + "label": "Pre-register oidc reducers in davinci/journey store upfront" + }, + { + "id": "lazy-inject", + "label": "Lazy inject via RTK combineSlices at oidc() init time" + } + ], + "required": true + }, + { + "id": "scope", + "prompt": "Which packages are in scope for this change?", + "description": "davinci-client and journey-client are the store owners; oidc-client is the joiner. protect and device-client don't use Redux stores currently.", + "answerMode": "multi-custom", + "recommendedAnswer": "davinci-client, journey-client, oidc-client only.", + "recommendedOptionIds": ["davinci", "journey", "oidc"], + "options": [ + { "id": "davinci", "label": "davinci-client" }, + { "id": "journey", "label": "journey-client" }, + { "id": "oidc", "label": "oidc-client" }, + { "id": "sdk-effects", "label": "sdk-effects (wellknown extraction)" } + ], + "required": true + }, + { + "id": "breaking-changes", + "prompt": "Are any breaking changes acceptable?", + "description": "Exposing `store` on the return object is purely additive. Adding `store?` to oidc's options bag is additive. The only potential breaking change is if `wellknownApi` is extracted to sdk-effects and packages previously imported it directly — but that's an internal import path change, not a public API change.", + "answerMode": "single", + "recommendedAnswer": "No breaking changes to public API — internal import path changes are acceptable.", + "recommendedOptionIds": ["no-breaking"], + "options": [ + { "id": "no-breaking", "label": "No breaking public API changes" }, + { + "id": "minor-ok", + "label": "Minor breaking changes acceptable (semver minor)" + } + ], + "required": true + } + ] +} diff --git a/goals/centralize-redux-store/plan.md b/goals/centralize-redux-store/plan.md new file mode 100644 index 0000000000..449aaea4fe --- /dev/null +++ b/goals/centralize-redux-store/plan.md @@ -0,0 +1,187 @@ +# Plan: Centralize Redux Store Across Client Packages + +## Solution Approach + +Migrate all three stores from `configureStore` + `combineReducers` to RTK 2.0 `combineSlices`, which enables lazy reducer injection. `davinci()` and `journey()` expose an opaque `SdkStore` handle on their return object. `oidc()` accepts that handle as an optional second argument and injects its own reducers into it at init time. `wellknownApi` is extracted to a new `sdk-effects/wellknown` package so all three clients share the same RTK Query instance — critical for cache deduplication on a shared store. + +## Ordered Steps + +### Step 1 — Extract `wellknownApi` to `@forgerock/sdk-wellknown` + +**Why first:** The shared store relies on a single `wellknownApi` instance. If each package keeps its own copy, `createApi` creates distinct RTK Query reducers with distinct internal state — sharing the store won't deduplicate the cache. This must land before any store changes. + +**Files to create:** + +- `packages/sdk-effects/wellknown/package.json` — follow `packages/sdk-effects/logger/package.json` as template, name `@forgerock/sdk-wellknown` +- `packages/sdk-effects/wellknown/src/index.ts` — re-exports from `lib/wellknown.api.ts` +- `packages/sdk-effects/wellknown/src/lib/wellknown.api.ts` — canonical implementation (merge `davinci-client`'s version + oidc's `wellknownSelector`/`createWellknownSelector`) +- `packages/sdk-effects/wellknown/vite.config.ts` — copy from `logger/vite.config.ts` +- `packages/sdk-effects/wellknown/project.json` — Nx project config +- `packages/sdk-effects/wellknown/tsconfig.json` / `tsconfig.lib.json` / `tsconfig.spec.json` + +**Files to modify:** + +- `packages/davinci-client/package.json` — add `@forgerock/sdk-wellknown: workspace:*` dep +- `packages/journey-client/package.json` — same +- `packages/oidc-client/package.json` — same +- `packages/davinci-client/src/lib/wellknown.api.ts` — delete file, update all imports to `@forgerock/sdk-wellknown` +- `packages/journey-client/src/lib/wellknown.api.ts` — delete file, update all imports +- `packages/oidc-client/src/lib/wellknown.api.ts` — delete file, update all imports (note: oidc has `wellknownSelector` — move to the shared package) + +**Verification:** + +```bash +pnpm nx build @forgerock/sdk-wellknown +pnpm nx build @forgerock/davinci-client +pnpm nx build @forgerock/journey-client +pnpm nx build @forgerock/oidc-client +pnpm nx test @forgerock/davinci-client +pnpm nx test @forgerock/journey-client +pnpm nx test @forgerock/oidc-client +``` + +--- + +### Step 2 — Introduce `SdkStore` opaque type in a shared location + +**Files to create/modify:** + +- `packages/sdk-types/src/lib/store.types.ts` — define the opaque `SdkStore` interface: + + ```ts + // Opaque handle — consumers can pass it around but cannot access Redux internals + export interface SdkStore { + readonly __brand: unique symbol; + } + ``` + + Internally, the concrete type will extend this. Consumers only ever see `SdkStore`. + +- `packages/sdk-types/src/index.ts` — export `SdkStore` + +**Why here:** `sdk-types` is the shared contracts layer with no runtime code. `SdkStore` is purely a type contract between the packages. Keeping it here avoids a circular dependency (davinci → sdk-types is already valid; oidc → sdk-types is already valid). + +**Verification:** + +```bash +pnpm nx build @forgerock/sdk-types +``` + +--- + +### Step 3 — Migrate `davinci-client` store to `combineSlices` + expose `SdkStore` + +**Files to modify:** + +- `packages/davinci-client/src/lib/client.store.utils.ts`: + - Replace `configureStore` + inline `reducer: {}` with `combineSlices(configSlice, nodeSlice, davinciApi, wellknownApi).withLazyLoadedSlices()` + - Create `const dynamicMiddleware = createDynamicMiddleware()` and add `dynamicMiddleware.middleware` to the `configureStore` middleware chain alongside `davinciApi.middleware` and `wellknownApi.middleware` + - Attach `__dynamicMiddleware: dynamicMiddleware` to the store (or carry it alongside) so `oidc()` can call `addMiddleware` at inject time + - Export the `rootReducer` so the store can be typed + - Export `InjectableStore` type (internal, extends the RTK store type, carries `__dynamicMiddleware` and the `combineSlices` `.inject()` method) +- `packages/davinci-client/src/lib/client.store.ts`: + - Add `store: store as SdkStore` to the return object of `davinci()` + - The local `store` variable remains typed as `InjectableStore` — the cast to `SdkStore` happens only at the return boundary + +- `packages/davinci-client/src/types.ts` — export `DavinciClient` type update picks up `store: SdkStore` automatically via `Awaited>` + +**Verification:** + +```bash +pnpm nx build @forgerock/davinci-client +pnpm nx test @forgerock/davinci-client +# Type check: verify DavinciClient has store: SdkStore +# Type check: verify store.dispatch / store.getState are NOT accessible on SdkStore +``` + +--- + +### Step 4 — Migrate `journey-client` store to `combineSlices` + expose `SdkStore` + +Mirrors Step 3. + +**Files to modify:** + +- `packages/journey-client/src/lib/client.store.utils.ts` — same `combineSlices` migration +- `packages/journey-client/src/lib/client.store.ts` — add `store: store as SdkStore` to return object +- `packages/journey-client/src/types.ts` (or `index.ts`) — `JourneyClient` interface gains `store: SdkStore` + +**Verification:** + +```bash +pnpm nx build @forgerock/journey-client +pnpm nx test @forgerock/journey-client +``` + +--- + +### Step 5 — Migrate `oidc-client` to accept optional `SdkStore` second argument + lazy inject + +**Files to modify:** + +- `packages/oidc-client/src/lib/client.store.utils.ts`: + - Keep `createClientStore` for standalone usage (no change) + - Add `injectIntoStore(store: SdkStore): void` helper — casts back to `InjectableStore`, calls `.inject(oidcApi)` and `.inject(wellknownApi)` + +- `packages/oidc-client/src/lib/client.store.ts` — `oidc()` signature becomes: + + ```ts + export async function oidc(options: OidcOptions, sharedStore?: SdkStore); + ``` + + Inside: + - If `sharedStore` is provided: call `injectIntoStore(sharedStore)`, use `sharedStore` as the internal store (cast to `InjectableStore`) + - If not provided: call `createClientStore(...)` as today + - All methods below are unchanged — they close over `store`, so the injection is transparent + +- `packages/oidc-client/src/types.ts` — `OidcClient` type picks up automatically; export `SdkStore` re-export for consumer convenience + +**Verification:** + +```bash +pnpm nx build @forgerock/oidc-client +pnpm nx test @forgerock/oidc-client +# Integration test: create davinci() → pass client.store to oidc() → assert single wellknown fetch +``` + +--- + +### Step 6 — Write integration tests proving shared-store behavior + +**Files to create/modify:** + +- `packages/oidc-client/src/lib/shared-store.test.ts` (or add to existing integration test file): + - Test: `oidc(opts, davinciClient.store)` — `wellknownApi` cache has exactly one entry, no second network call + - Test: `store.subscribe` on davinci client fires when oidc dispatches + - Test: `oidc(opts)` standalone still creates its own store (existing behavior) + - Test: TypeScript compile-time: `davinciClient.store.dispatch` should be a type error + +**Verification:** + +```bash +pnpm nx test @forgerock/oidc-client +pnpm nx test @forgerock/davinci-client +``` + +--- + +### Step 7 — Verify full suite + type check + +```bash +pnpm nx run-many -t build --no-agents +pnpm nx run-many -t lint +pnpm nx run-many -t test +pnpm tsc --noEmit # or pnpm nx run-many -t typecheck +``` + +--- + +## Risks and Open Questions + +1. **RTK Query middleware — use `createDynamicMiddleware`**: RTK Query API slices need their `.middleware` in the store's middleware chain. For lazy-injected slices like `oidcApi`, we use RTK 2.0's `createDynamicMiddleware`. The owning store (davinci/journey) registers `dynamicMiddleware.middleware` in `configureStore`; the `DynamicMiddlewareInstance` is included in the `InjectableStore` internal type. When `oidc()` injects its reducers via `combineSlices`, it also calls `store.__dynamicMiddleware.addMiddleware(oidcApi.middleware)`. No downside — this is RTK's designed use case for lazy middleware registration. + +2. **`wellknownApi` selector `RootState` coupling**: `oidc-client`'s `wellknownSelector` is typed against oidc's own `RootState`. After extraction to `sdk-wellknown`, it needs a generic state type or the `wellknown` slice state shape directly. Use `wellknownApi.endpoints.configuration.select(url)` directly — it returns a state selector that only requires the `wellknown` key, not a full `RootState`. + +3. **`SdkStore` cast fidelity**: The internal `InjectableStore` → `SdkStore` cast must be verifiably safe. Add a helper that asserts the store has `inject` available at runtime before accepting it in `oidc()`. + +4. **Package creation friction**: Creating a new `sdk-effects/wellknown` sub-package requires Nx project registration. Check `packages/sdk-effects/logger/project.json` and `nx.json` for the exact scaffolding pattern to avoid CI graph errors. diff --git a/packages/davinci-client/package.json b/packages/davinci-client/package.json index 1d6e1bd1bb..26beda8ed7 100644 --- a/packages/davinci-client/package.json +++ b/packages/davinci-client/package.json @@ -31,6 +31,7 @@ "@forgerock/sdk-request-middleware": "workspace:*", "@forgerock/sdk-types": "workspace:*", "@forgerock/sdk-utilities": "workspace:*", + "@forgerock/sdk-wellknown": "workspace:*", "@forgerock/storage": "workspace:*", "@reduxjs/toolkit": "catalog:", "effect": "catalog:effect", diff --git a/packages/davinci-client/src/lib/client.store.ts b/packages/davinci-client/src/lib/client.store.ts index 570f8f6dd3..82b8480400 100644 --- a/packages/davinci-client/src/lib/client.store.ts +++ b/packages/davinci-client/src/lib/client.store.ts @@ -24,7 +24,7 @@ import { pollingµ, getPollingModeµ, type PollingMode } from './client.store.ef import { nodeSlice } from './node.slice.js'; import { davinciApi } from './davinci.api.js'; import { configSlice } from './config.slice.js'; -import { wellknownApi } from './wellknown.api.js'; +import { wellknownApi } from '@forgerock/sdk-wellknown'; import type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; /** diff --git a/packages/davinci-client/src/lib/client.store.utils.ts b/packages/davinci-client/src/lib/client.store.utils.ts index ae6034f246..d92ba36667 100644 --- a/packages/davinci-client/src/lib/client.store.utils.ts +++ b/packages/davinci-client/src/lib/client.store.utils.ts @@ -29,7 +29,7 @@ import type { import { configSlice } from './config.slice.js'; import { nodeSlice } from './node.slice.js'; import { davinciApi } from './davinci.api.js'; -import { wellknownApi } from './wellknown.api.js'; +import { wellknownApi } from '@forgerock/sdk-wellknown'; export function createClientStore({ requestMiddleware, diff --git a/packages/davinci-client/src/lib/wellknown.api.ts b/packages/davinci-client/src/lib/wellknown.api.ts deleted file mode 100644 index 8b9772094e..0000000000 --- a/packages/davinci-client/src/lib/wellknown.api.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2025 - 2026 Ping Identity Corporation. All rights reserved. - * - * This software may be modified and distributed under the terms - * of the MIT license. See the LICENSE file for details. - */ - -import { createSelector } from '@reduxjs/toolkit'; -import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'; -import { initWellknownQuery } from '@forgerock/sdk-oidc'; - -import type { WellknownResponse } from '@forgerock/sdk-types'; -import type { - FetchBaseQueryError, - FetchBaseQueryMeta, - QueryReturnValue, -} from '@reduxjs/toolkit/query'; - -/** - * RTK Query API for well-known endpoint discovery. - * - * Uses the `initWellknownQuery` builder pattern from `@forgerock/sdk-oidc`. - * The builder constructs the request and validates the response; - * `fetchBaseQuery` handles the HTTP transport through RTK Query's pipeline. - */ -export const wellknownApi = createApi({ - reducerPath: 'wellknown', - baseQuery: fetchBaseQuery(), - endpoints: (builder) => ({ - configuration: builder.query({ - queryFn: async (url, _api, _extra, baseQuery) => { - const result = await initWellknownQuery(url).applyQuery(async (req) => { - const queryResult = await baseQuery(req); - return queryResult as QueryReturnValue; - }); - return result as QueryReturnValue< - WellknownResponse, - FetchBaseQueryError, - FetchBaseQueryMeta - >; - }, - }), - }), -}); - -/** - * Creates a memoized selector for cached well-known data. - * - * @param wellknownUrl - The well-known endpoint URL used as the cache key - * @returns A memoized selector that extracts the WellknownResponse from state, or undefined if not yet fetched - */ -export function createWellknownSelector(wellknownUrl: string) { - return createSelector( - wellknownApi.endpoints.configuration.select(wellknownUrl), - (result) => result?.data, - ); -} diff --git a/packages/davinci-client/tsconfig.json b/packages/davinci-client/tsconfig.json index 141b4ebf5f..4b134f1186 100644 --- a/packages/davinci-client/tsconfig.json +++ b/packages/davinci-client/tsconfig.json @@ -23,6 +23,9 @@ { "path": "../sdk-effects/sdk-request-middleware" }, + { + "path": "../sdk-effects/wellknown" + }, { "path": "../sdk-effects/oidc" }, diff --git a/packages/davinci-client/tsconfig.lib.json b/packages/davinci-client/tsconfig.lib.json index 6c7bbdefef..c0645d65ac 100644 --- a/packages/davinci-client/tsconfig.lib.json +++ b/packages/davinci-client/tsconfig.lib.json @@ -48,6 +48,9 @@ }, { "path": "../sdk-effects/logger/tsconfig.lib.json" + }, + { + "path": "../sdk-effects/wellknown/tsconfig.lib.json" } ] } diff --git a/packages/journey-client/package.json b/packages/journey-client/package.json index 285cb707cb..eec3748ede 100644 --- a/packages/journey-client/package.json +++ b/packages/journey-client/package.json @@ -37,6 +37,7 @@ "@forgerock/sdk-request-middleware": "workspace:*", "@forgerock/sdk-types": "workspace:*", "@forgerock/sdk-utilities": "workspace:*", + "@forgerock/sdk-wellknown": "workspace:*", "@forgerock/storage": "workspace:*", "@reduxjs/toolkit": "catalog:", "effect": "catalog:effect", diff --git a/packages/journey-client/src/lib/client.store.ts b/packages/journey-client/src/lib/client.store.ts index 353e5ef973..28acdbc233 100644 --- a/packages/journey-client/src/lib/client.store.ts +++ b/packages/journey-client/src/lib/client.store.ts @@ -23,7 +23,7 @@ import { createStorage } from '@forgerock/storage'; import * as Result from 'effect/Result'; import { createJourneyObject, parseJourneyResponse } from './journey.utils.js'; import type { JourneyResult } from './journey.utils.js'; -import { wellknownApi } from './wellknown.api.js'; +import { wellknownApi } from '@forgerock/sdk-wellknown'; import type { JourneyStep } from './step.utils.js'; import type { JourneyClientConfig } from './config.types.js'; diff --git a/packages/journey-client/src/lib/client.store.utils.ts b/packages/journey-client/src/lib/client.store.utils.ts index 7c08201f87..5588c66c42 100644 --- a/packages/journey-client/src/lib/client.store.utils.ts +++ b/packages/journey-client/src/lib/client.store.utils.ts @@ -11,7 +11,7 @@ import { combineReducers, configureStore } from '@reduxjs/toolkit'; import { configSlice } from './config.slice.js'; import { journeyApi } from './journey.api.js'; -import { wellknownApi } from './wellknown.api.js'; +import { wellknownApi } from '@forgerock/sdk-wellknown'; const rootReducer = combineReducers({ [journeyApi.reducerPath]: journeyApi.reducer, diff --git a/packages/journey-client/src/lib/wellknown.api.ts b/packages/journey-client/src/lib/wellknown.api.ts deleted file mode 100644 index d8f2dde936..0000000000 --- a/packages/journey-client/src/lib/wellknown.api.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2025 - 2026 Ping Identity Corporation. All rights reserved. - * - * This software may be modified and distributed under the terms - * of the MIT license. See the LICENSE file for details. - */ - -import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'; -import { initWellknownQuery } from '@forgerock/sdk-oidc'; - -import type { WellknownResponse } from '@forgerock/sdk-types'; -import type { - FetchBaseQueryError, - FetchBaseQueryMeta, - QueryReturnValue, -} from '@reduxjs/toolkit/query'; - -/** - * RTK Query API for well-known endpoint discovery. - * - * Uses the `initWellknownQuery` builder pattern from `@forgerock/sdk-oidc`. - * The builder constructs the request and validates the response; - * `fetchBaseQuery` handles the HTTP transport through RTK Query's pipeline. - */ -export const wellknownApi = createApi({ - reducerPath: 'wellknown', - baseQuery: fetchBaseQuery(), - endpoints: (builder) => ({ - configuration: builder.query({ - queryFn: async (url, _api, _extra, baseQuery) => { - const result = await initWellknownQuery(url).applyQuery(async (req) => { - const queryResult = await baseQuery(req); - return queryResult as QueryReturnValue; - }); - return result as QueryReturnValue< - WellknownResponse, - FetchBaseQueryError, - FetchBaseQueryMeta - >; - }, - }), - }), -}); diff --git a/packages/journey-client/tsconfig.lib.json b/packages/journey-client/tsconfig.lib.json index ca3f899b8d..ae23b14b06 100644 --- a/packages/journey-client/tsconfig.lib.json +++ b/packages/journey-client/tsconfig.lib.json @@ -35,6 +35,9 @@ }, { "path": "../sdk-effects/logger/tsconfig.lib.json" + }, + { + "path": "../sdk-effects/wellknown/tsconfig.lib.json" } ] } diff --git a/packages/oidc-client/package.json b/packages/oidc-client/package.json index 0f245c228f..2bab653d2e 100644 --- a/packages/oidc-client/package.json +++ b/packages/oidc-client/package.json @@ -33,6 +33,7 @@ "@forgerock/sdk-request-middleware": "workspace:*", "@forgerock/sdk-types": "workspace:*", "@forgerock/sdk-utilities": "workspace:*", + "@forgerock/sdk-wellknown": "workspace:*", "@forgerock/storage": "workspace:*", "@reduxjs/toolkit": "catalog:", "effect": "catalog:effect", diff --git a/packages/oidc-client/src/lib/client.store.ts b/packages/oidc-client/src/lib/client.store.ts index d93fce9c1b..c3ebeb15cd 100644 --- a/packages/oidc-client/src/lib/client.store.ts +++ b/packages/oidc-client/src/lib/client.store.ts @@ -17,7 +17,7 @@ import { isExpiryWithinThreshold } from './token.utils.js'; import { logoutµ } from './logout.request.js'; import { oidcApi } from './oidc.api.js'; import { sessionCheckNoneµ, sessionCheckIdTokenµ } from './session.micros.js'; -import { wellknownApi, wellknownSelector } from './wellknown.api.js'; +import { wellknownApi, wellknownSelector } from '@forgerock/sdk-wellknown'; import type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; import type { GenericError, GetAuthorizationUrlOptions } from '@forgerock/sdk-types'; diff --git a/packages/oidc-client/src/lib/client.store.utils.ts b/packages/oidc-client/src/lib/client.store.utils.ts index a011974bf6..c58d13b6ab 100644 --- a/packages/oidc-client/src/lib/client.store.utils.ts +++ b/packages/oidc-client/src/lib/client.store.utils.ts @@ -9,7 +9,7 @@ import { logger as loggerFn } from '@forgerock/sdk-logger'; import { configureStore, type SerializedError } from '@reduxjs/toolkit'; import { oidcApi } from './oidc.api.js'; -import { wellknownApi } from './wellknown.api.js'; +import { wellknownApi } from '@forgerock/sdk-wellknown'; import type { GenericError } from '@forgerock/sdk-types'; import type { FetchBaseQueryError } from '@reduxjs/toolkit/query'; diff --git a/packages/oidc-client/tsconfig.lib.json b/packages/oidc-client/tsconfig.lib.json index d689866941..920e9ccdc8 100644 --- a/packages/oidc-client/tsconfig.lib.json +++ b/packages/oidc-client/tsconfig.lib.json @@ -39,6 +39,9 @@ }, { "path": "../sdk-effects/iframe-manager/tsconfig.lib.json" + }, + { + "path": "../sdk-effects/wellknown/tsconfig.lib.json" } ], "exclude": [ diff --git a/packages/sdk-effects/wellknown/eslint.config.mjs b/packages/sdk-effects/wellknown/eslint.config.mjs new file mode 100644 index 0000000000..980b6a3e9d --- /dev/null +++ b/packages/sdk-effects/wellknown/eslint.config.mjs @@ -0,0 +1,22 @@ +import baseConfig from '../../../eslint.config.mjs'; + +export default [ + ...baseConfig, + { + files: ['**/*.json'], + rules: { + '@nx/dependency-checks': [ + 'warn', + { + ignoredFiles: [ + '{projectRoot}/eslint.config.{js,cjs,mjs}', + '{projectRoot}/vite.config.{js,ts,mjs,mts}', + ], + }, + ], + }, + languageOptions: { + parser: (await import('jsonc-eslint-parser')).default, + }, + }, +]; diff --git a/packages/sdk-effects/wellknown/package.json b/packages/sdk-effects/wellknown/package.json new file mode 100644 index 0000000000..18e9feff21 --- /dev/null +++ b/packages/sdk-effects/wellknown/package.json @@ -0,0 +1,41 @@ +{ + "name": "@forgerock/sdk-wellknown", + "version": "1.0.0", + "private": false, + "repository": { + "type": "git", + "url": "git+https://github.com/ForgeRock/ping-javascript-sdk.git", + "directory": "packages/sdk-effects/wellknown" + }, + "description": "Shared wellknown/OpenID Connect discovery API for the Ping JavaScript SDK", + "license": "MIT", + "author": "ForgeRock", + "sideEffects": false, + "type": "module", + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js", + "default": "./dist/src/index.js" + }, + "./package.json": "./package.json" + }, + "main": "./dist/src/index.js", + "module": "./dist/src/index.js", + "types": "./dist/src/index.d.ts", + "files": ["dist"], + "scripts": { + "build": "pnpm nx nxBuild", + "lint": "pnpm nx nxLint", + "test": "pnpm nx nxTest", + "test:watch": "pnpm nx nxTest --watch" + }, + "dependencies": { + "@forgerock/sdk-oidc": "workspace:*", + "@forgerock/sdk-types": "workspace:*", + "@reduxjs/toolkit": "catalog:" + }, + "nx": { + "tags": ["scope:sdk-effects"] + } +} diff --git a/packages/sdk-effects/wellknown/src/index.ts b/packages/sdk-effects/wellknown/src/index.ts new file mode 100644 index 0000000000..04f4e2c35b --- /dev/null +++ b/packages/sdk-effects/wellknown/src/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2025 - 2026 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +export { wellknownApi, wellknownSelector, createWellknownSelector } from './lib/wellknown.api.js'; +export type { WellknownState } from './lib/wellknown.api.js'; diff --git a/packages/oidc-client/src/lib/wellknown.api.ts b/packages/sdk-effects/wellknown/src/lib/wellknown.api.ts similarity index 78% rename from packages/oidc-client/src/lib/wellknown.api.ts rename to packages/sdk-effects/wellknown/src/lib/wellknown.api.ts index ddcd254d4d..e2f5f12074 100644 --- a/packages/oidc-client/src/lib/wellknown.api.ts +++ b/packages/sdk-effects/wellknown/src/lib/wellknown.api.ts @@ -15,7 +15,6 @@ import type { FetchBaseQueryMeta, QueryReturnValue, } from '@reduxjs/toolkit/query'; -import type { RootState } from './client.types.js'; /** * RTK Query API for well-known endpoint discovery. @@ -23,6 +22,9 @@ import type { RootState } from './client.types.js'; * Uses the `initWellknownQuery` builder pattern from `@forgerock/sdk-oidc`. * The builder constructs the request and validates the response; * `fetchBaseQuery` handles the HTTP transport through RTK Query's pipeline. + * + * This is the canonical single instance — all SDK client packages import from here + * so that a shared Redux store gets a single cache entry per URL. */ export const wellknownApi = createApi({ reducerPath: 'wellknown', @@ -44,6 +46,11 @@ export const wellknownApi = createApi({ }), }); +/** Minimum state shape required to use wellknown selectors. */ +export type WellknownState = { + [wellknownApi.reducerPath]: ReturnType; +}; + /** * Creates a memoized selector for cached well-known data. * @@ -58,19 +65,16 @@ export function createWellknownSelector(wellknownUrl: string) { } /** - * Convenience selector for oidc-client's RootState type. + * Convenience selector for any state that contains the wellknown slice. * * Unlike {@link createWellknownSelector}, this immediately evaluates the * selector against the provided state rather than returning a reusable selector. * * @param wellknownUrl - The well-known endpoint URL used as the cache key - * @param state - The oidc-client Redux root state + * @param state - Any Redux state that includes the wellknown slice * @returns The cached WellknownResponse or undefined if not yet fetched */ -export function wellknownSelector(wellknownUrl: string, state: RootState) { - const selector = createSelector( - wellknownApi.endpoints.configuration.select(wellknownUrl), - (result) => result?.data, - ); +export function wellknownSelector(wellknownUrl: string, state: S) { + const selector = createWellknownSelector(wellknownUrl); return selector(state); } diff --git a/packages/sdk-effects/wellknown/tsconfig.json b/packages/sdk-effects/wellknown/tsconfig.json new file mode 100644 index 0000000000..3a5af05d8e --- /dev/null +++ b/packages/sdk-effects/wellknown/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "nx": { + "addTypecheckTarget": false + } +} diff --git a/packages/sdk-effects/wellknown/tsconfig.lib.json b/packages/sdk-effects/wellknown/tsconfig.lib.json new file mode 100644 index 0000000000..3ded621972 --- /dev/null +++ b/packages/sdk-effects/wellknown/tsconfig.lib.json @@ -0,0 +1,37 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "baseUrl": ".", + "outDir": "dist", + "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo", + "emitDeclarationOnly": false, + "module": "nodenext", + "moduleResolution": "nodenext", + "forceConsistentCasingInFileNames": true, + "strict": true, + "importHelpers": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "types": ["node"] + }, + "include": ["src/**/*.ts"], + "references": [ + { "path": "../../sdk-types/tsconfig.lib.json" }, + { "path": "../oidc/tsconfig.lib.json" } + ], + "exclude": [ + "vite.config.ts", + "vite.config.mts", + "vitest.config.ts", + "vitest.config.mts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx" + ] +} diff --git a/packages/sdk-effects/wellknown/tsconfig.spec.json b/packages/sdk-effects/wellknown/tsconfig.spec.json new file mode 100644 index 0000000000..c8fc6b21fa --- /dev/null +++ b/packages/sdk-effects/wellknown/tsconfig.spec.json @@ -0,0 +1,41 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./out-tsc/vitest", + "types": [ + "vitest/globals", + "vitest/importMeta", + "vite/client", + "node", + "vitest" + ], + "module": "nodenext", + "moduleResolution": "nodenext", + "forceConsistentCasingInFileNames": true, + "strict": true, + "importHelpers": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "include": [ + "vite.config.ts", + "vite.config.mts", + "vitest.config.ts", + "vitest.config.mts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ] +} diff --git a/packages/sdk-effects/wellknown/vite.config.ts b/packages/sdk-effects/wellknown/vite.config.ts new file mode 100644 index 0000000000..dd352b8bbd --- /dev/null +++ b/packages/sdk-effects/wellknown/vite.config.ts @@ -0,0 +1,43 @@ +import { defineConfig } from 'vite'; + +export default defineConfig(() => ({ + root: __dirname, + cacheDir: '../../../node_modules/.vite/packages/effects/wellknown', + plugins: [], + test: { + watch: false, + globals: true, + environment: 'node', + include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + reporters: ['default'], + coverage: { + include: ['src/**/*.{js,ts}'], + exclude: [ + 'src/**/*.mock.{js,ts}', + 'src/**/*.data.{js,ts}', + 'src/**/*.test.{js,ts}', + 'coverage/**', + 'dist/**', + '**/node_modules/**', + '**/[.]**', + 'packages/*/test?(s)/**', + '**/*.d.ts', + '**/virtual:*', + '**/__x00__*', + '**/ *', + 'cypress/**', + 'test?(s)/**', + 'test?(-*).?(c|m)[jt]s?(x)', + '**/*{.,-}{test,spec,bench,benchmark}?(-d).?(c|m)[jt]s?(x)', + '**/__tests__/**', + '**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*', + '**/vitest.{workspace,projects}.[jt]s?(on)', + '**/.{eslint,mocha,prettier}rc.{?(c|m)js,yml}', + ], + reporter: ['text', 'html', 'json'], + enabled: Boolean(process.env['CI']), + reportsDirectory: './coverage', + provider: 'v8' as const, + }, + }, +})); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5089858708..1bb49164ea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -448,6 +448,9 @@ importers: '@forgerock/sdk-utilities': specifier: workspace:* version: link:../sdk-utilities + '@forgerock/sdk-wellknown': + specifier: workspace:* + version: link:../sdk-effects/wellknown '@forgerock/storage': specifier: workspace:* version: link:../sdk-effects/storage @@ -498,6 +501,9 @@ importers: '@forgerock/sdk-utilities': specifier: workspace:* version: link:../sdk-utilities + '@forgerock/sdk-wellknown': + specifier: workspace:* + version: link:../sdk-effects/wellknown '@forgerock/storage': specifier: workspace:* version: link:../sdk-effects/storage @@ -544,6 +550,9 @@ importers: '@forgerock/sdk-utilities': specifier: workspace:* version: link:../sdk-utilities + '@forgerock/sdk-wellknown': + specifier: workspace:* + version: link:../sdk-effects/wellknown '@forgerock/storage': specifier: workspace:* version: link:../sdk-effects/storage @@ -605,6 +614,18 @@ importers: specifier: workspace:* version: link:../../sdk-types + packages/sdk-effects/wellknown: + dependencies: + '@forgerock/sdk-oidc': + specifier: workspace:* + version: link:../oidc + '@forgerock/sdk-types': + specifier: workspace:* + version: link:../../sdk-types + '@reduxjs/toolkit': + specifier: 'catalog:' + version: 2.10.1 + packages/sdk-types: {} packages/sdk-utilities: diff --git a/tsconfig.json b/tsconfig.json index 5bac2012e8..19174a5565 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -79,6 +79,9 @@ { "path": "./tools/api-report" }, + { + "path": "./packages/sdk-effects/wellknown" + }, { "path": "./packages/recognize" }, From 3385e6b007b0a0eef8d39c0ab593c4f321b7f46a Mon Sep 17 00:00:00 2001 From: Ryan Bas Date: Mon, 27 Jul 2026 12:32:11 -0600 Subject: [PATCH 05/11] =?UTF-8?q?feat:=20centralize=20Redux=20stores=20?= =?UTF-8?q?=E2=80=94=20expose=20SdkStore=20from=20davinci/journey,=20injec?= =?UTF-8?q?t=20into=20oidc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api-report/davinci-client.api.md | 4458 +++++++++-------- .../api-report/davinci-client.types.api.md | 4452 ++++++++-------- .../src/lib/client.store.effects.ts | 6 +- .../davinci-client/src/lib/client.store.ts | 7 +- .../src/lib/client.store.utils.ts | 113 +- .../api-report/journey-client.api.md | 3 + .../api-report/journey-client.types.api.md | 3 + .../journey-client/src/lib/client.store.ts | 9 +- .../src/lib/client.store.utils.ts | 52 +- .../oidc-client/api-report/oidc-client.api.md | 3 +- .../api-report/oidc-client.types.api.md | 3 +- packages/oidc-client/src/lib/client.store.ts | 39 +- .../oidc-client/src/lib/client.store.utils.ts | 31 + .../oidc-client/src/lib/shared-store.test.ts | 236 + packages/sdk-effects/wellknown/vite.config.ts | 1 + packages/sdk-types/src/index.ts | 1 + packages/sdk-types/src/lib/store.types.ts | 16 + 17 files changed, 5325 insertions(+), 4108 deletions(-) create mode 100644 packages/oidc-client/src/lib/shared-store.test.ts create mode 100644 packages/sdk-types/src/lib/store.types.ts diff --git a/packages/davinci-client/api-report/davinci-client.api.md b/packages/davinci-client/api-report/davinci-client.api.md index 2dc2071de1..4c9616c1f5 100644 --- a/packages/davinci-client/api-report/davinci-client.api.md +++ b/packages/davinci-client/api-report/davinci-client.api.md @@ -1,2016 +1,2442 @@ -## API Report File for "@forgerock/davinci-client" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts - -import { ActionCreatorWithPayload } from '@reduxjs/toolkit'; -import { ActionTypes } from '@forgerock/sdk-request-middleware'; -import { CustomLogger } from '@forgerock/sdk-logger'; -import type { DaVinciConfig } from '@forgerock/sdk-types'; -import { FetchBaseQueryError } from '@reduxjs/toolkit/query'; -import type { FetchBaseQueryMeta } from '@reduxjs/toolkit/query'; -import { GenericError } from '@forgerock/sdk-types'; -import { LogLevel } from '@forgerock/sdk-logger'; -import type { MutationResultSelectorResult } from '@reduxjs/toolkit/query'; -import { QueryStatus } from '@reduxjs/toolkit/query'; -import { Reducer } from '@reduxjs/toolkit'; -import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; -import { SerializedError } from '@reduxjs/toolkit'; -import { Unsubscribe } from '@reduxjs/toolkit'; - -// @public (undocumented) -export type ActionCollector = ActionCollectorNoUrl | ActionCollectorWithUrl; - -// @public (undocumented) -export interface ActionCollectorNoUrl { - // (undocumented) - category: 'ActionCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ActionCollectors = ActionCollectorWithUrl<'IdpCollector'> | ActionCollectorNoUrl<'ActionCollector'> | ActionCollectorNoUrl<'FlowCollector'> | ActionCollectorNoUrl<'SubmitCollector'>; - -// @public -export type ActionCollectorTypes = 'FlowCollector' | 'SubmitCollector' | 'IdpCollector' | 'ActionCollector'; - -// @public (undocumented) -export interface ActionCollectorWithUrl { - // (undocumented) - category: 'ActionCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - url?: string | null; - }; - // (undocumented) - type: T; -} - -export { ActionTypes } - -// @public (undocumented) -export type AgreementField = { - type: 'AGREEMENT'; - key: string; - content: string; - titleEnabled: boolean; - title?: string; - agreement: { - id: string; - useDynamicAgreement: boolean; - }; - enabled: boolean; -}; - -// @public (undocumented) -export interface AssertionValue extends Omit { - // (undocumented) - rawId: string; - // (undocumented) - response: { - clientDataJSON: string; - authenticatorData: string; - signature: string; - userHandle: string | null; - }; -} - -// @public (undocumented) -export interface AttestationValue extends Omit { - // (undocumented) - rawId: string; - // (undocumented) - response: { - clientDataJSON: string; - attestationObject: string; - }; -} - -// @public (undocumented) -export interface AutoCollector> { - // (undocumented) - category: C; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: IV; - type: string; - validation?: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - type: string; - config: OV; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type AutoCollectorCategories = 'SingleValueAutoCollector' | 'ObjectValueAutoCollector'; - -// @public (undocumented) -export type AutoCollectors = ProtectCollector | FidoRegistrationCollector | FidoAuthenticationCollector | MetadataCollector | PollingCollector | SingleValueAutoCollector | ObjectValueAutoCollector; - -// @public (undocumented) -export type AutoCollectorTypes = SingleValueAutoCollectorTypes | ObjectValueAutoCollectorTypes; - -// @public (undocumented) -export interface BooleanCollector extends SingleValueCollectorWithValue<'BooleanCollector', boolean> { - // (undocumented) - output: SingleValueCollectorWithValue<'BooleanCollector', boolean>['output'] & { - appearance: string; - richContent?: CollectorRichContent; - }; -} - -// @public (undocumented) -export type CollectorCategory = Collectors['category']; - -// @public (undocumented) -export interface CollectorErrors { - // (undocumented) - code: string; - // (undocumented) - message: string; - // (undocumented) - target: string; -} - -// @public -export interface CollectorRichContent { - // (undocumented) - content: string; - // (undocumented) - replacements: RichContentLink[]; -} - -// @public (undocumented) -export type Collectors = FlowCollector | MetadataCollector | PasswordCollector | ValidatedPasswordCollector | TextCollector | BooleanCollector | ValidatedBooleanCollector | SingleSelectCollector | IdpCollector | SubmitCollector | ActionCollector<'ActionCollector'> | SingleValueCollector<'SingleValueCollector'> | MultiSelectCollector | DeviceAuthenticationCollector | DeviceRegistrationCollector | PhoneNumberCollector | PhoneNumberExtensionCollector | ReadOnlyCollector | RichTextCollector | ValidatedTextCollector | ProtectCollector | PollingCollector | FidoRegistrationCollector | FidoAuthenticationCollector | QrCodeCollector | ImageCollector | UnknownCollector; - -// @public -export type CollectorValueType = T extends { - type: 'PasswordCollector'; -} | { - type: 'ValidatedPasswordCollector'; -} | { - type: 'SingleSelectCollector'; -} | { - type: 'DeviceRegistrationCollector'; -} | { - type: 'DeviceAuthenticationCollector'; -} | { - type: 'ProtectCollector'; -} | { - type: 'PollingCollector'; -} ? string : T extends { - type: 'TextCollector'; - category: 'SingleValueCollector'; -} ? string : T extends { - type: 'TextCollector'; - category: 'ValidatedSingleValueCollector'; -} ? string : T extends { - type: 'BooleanCollector'; -} | { - type: 'ValidatedBooleanCollector'; -} ? boolean : T extends { - type: 'MultiSelectCollector'; -} ? string | string[] : T extends { - type: 'PhoneNumberCollector'; -} ? PhoneNumberInputValue : T extends { - type: 'PhoneNumberExtensionCollector'; -} ? PhoneNumberExtensionInputValue : T extends { - type: 'FidoRegistrationCollector'; -} ? FidoRegistrationInputValue | GenericError : T extends { - type: 'FidoAuthenticationCollector'; -} ? FidoAuthenticationInputValue | GenericError : T extends { - type: 'MetadataCollector'; -} ? Record | MetadataError : T extends { - category: 'SingleValueCollector'; -} ? string : T extends { - category: 'ValidatedSingleValueCollector'; -} ? string : T extends { - category: 'SingleValueAutoCollector'; -} ? string : T extends { - category: 'MultiValueCollector'; -} ? string | string[] : T extends { - category: 'ActionCollector'; -} ? never : T extends { - category: 'NoValueCollector'; -} ? never : CollectorValueTypes; - -// @public -export type CollectorValueTypes = string | string[] | boolean | PhoneNumberInputValue | PhoneNumberExtensionInputValue | FidoRegistrationInputValue | FidoAuthenticationInputValue | MetadataError | GenericError; - -// @public (undocumented) -export type ComplexValueFields = DeviceAuthenticationField | DeviceRegistrationField | PhoneNumberField | PhoneNumberExtensionField | FidoRegistrationField | FidoAuthenticationField | PollingField | MetadataField; - -// @public (undocumented) -export interface ContinueNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'continue'; - }; - // (undocumented) - error: null; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - eventName?: string; - status: 'continue'; - }; - // (undocumented) - status: 'continue'; -} - -export { CustomLogger } - -// @public -export type CustomPollingStatus = string & {}; - -// @public -export function davinci(input: { - config: DaVinciConfig; - requestMiddleware?: RequestMiddleware[]; - logger?: { - level: LogLevel; - custom?: CustomLogger; - }; -}): Promise<{ - subscribe: (listener: () => void) => Unsubscribe; - externalIdp: () => (() => Promise); - flow: (action: DaVinciAction) => InitFlow; - next: (args?: DaVinciRequest) => Promise; - resume: (input: { - continueToken: string; - }) => Promise; - start: (options?: StartOptions | undefined) => Promise; - update: (collector: T) => Updater; - validate: (collector: SingleValueCollectors | ObjectValueCollectors | MultiValueCollectors | AutoCollectors) => Validator; - pollStatus: (collector: PollingCollector) => Poller; - getClient: () => { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: "continue"; - } | { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: "error"; - } | { - status: "failure"; - } | { - status: "start"; - } | { - authorization?: { - code?: string; - state?: string; - }; - status: "success"; - } | null; - getCollectors: () => Collectors[]; - getError: () => DaVinciError | null; - getErrorCollectors: () => CollectorErrors[]; - getNode: () => ContinueNode | ErrorNode | FailureNode | StartNode | SuccessNode; - getServer: () => { - _links?: Links; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - eventName?: string; - status: "continue"; - } | { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: "error"; - } | { - _links?: Links; - eventName?: string; - href?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: "failure"; - } | { - status: "start"; - } | { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - session?: string; - status: "success"; - } | null; - cache: { - getLatestResponse: () => ({ - status: QueryStatus.fulfilled; - } & Omit<{ - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, "data" | "fulfilledTimeStamp"> & Required> & { - error: undefined; - } & { - status: QueryStatus.fulfilled; - isUninitialized: false; - isLoading: false; - isSuccess: true; - isError: false; - }) | ({ - status: QueryStatus.rejected; - } & Omit<{ - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, "error"> & Required> & { - status: QueryStatus.rejected; - isUninitialized: false; - isLoading: false; - isSuccess: false; - isError: true; - }) | { - error: { - message: string; - type: string; - }; - }; - getResponseWithId: (requestId: string) => ({ - status: QueryStatus.fulfilled; - } & Omit<{ - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, "data" | "fulfilledTimeStamp"> & Required> & { - error: undefined; - } & { - status: QueryStatus.fulfilled; - isUninitialized: false; - isLoading: false; - isSuccess: true; - isError: false; - }) | ({ - status: QueryStatus.rejected; - } & Omit<{ - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, "error"> & Required> & { - status: QueryStatus.rejected; - isUninitialized: false; - isLoading: false; - isSuccess: false; - isError: true; - }) | { - error: { - message: string; - type: string; - }; - }; - }; -}>; - -// @public -export interface DaVinciAction { - // (undocumented) - action: string; -} - -// @public -export interface DaVinciBaseResponse { - // (undocumented) - capabilityName?: string; - // (undocumented) - companyId?: string; - // (undocumented) - connectionId?: string; - // (undocumented) - connectorId?: string; - // (undocumented) - id?: string; - // (undocumented) - interactionId?: string; - // (undocumented) - interactionToken?: string; - // (undocumented) - isResponseCompatibleWithMobileAndWebSdks?: boolean; - // (undocumented) - status?: string; -} - -// @public -export type DaVinciCacheEntry = { - data?: DaVinciBaseResponse; - error?: { - data: DaVinciBaseResponse; - status: number; - }; -} & { - data?: any; - error?: any; -} & MutationResultSelectorResult; - -// @public (undocumented) -export type DavinciClient = Awaited>; - -export { DaVinciConfig } - -// @public (undocumented) -export interface DaVinciError extends Omit { - // (undocumented) - collectors?: CollectorErrors[]; - // (undocumented) - internalHttpStatus?: number; - // (undocumented) - message: string; - // (undocumented) - status: 'error' | 'failure' | 'unknown'; -} - -// @public (undocumented) -export interface DaVinciErrorCacheEntry { - // (undocumented) - endpointName: 'next' | 'flow' | 'start'; - // (undocumented) - error: { - data: T; - }; - // (undocumented) - fulfilledTimeStamp: number; - // (undocumented) - isError: boolean; - // (undocumented) - isLoading: boolean; - // (undocumented) - isSuccess: boolean; - // (undocumented) - isUninitialized: boolean; - // (undocumented) - requestId: string; - // (undocumented) - startedTimeStamp: number; - // (undocumented) - status: 'fulfilled' | 'pending' | 'rejected'; -} - -// @public (undocumented) -export interface DavinciErrorResponse extends DaVinciBaseResponse { - // (undocumented) - cause?: string | null; - // (undocumented) - code: string | number; - // (undocumented) - details?: ErrorDetail[]; - // (undocumented) - doNotSendToOE?: boolean; - // (undocumented) - error?: { - code?: string; - message?: string; - }; - // (undocumented) - errorCategory?: string; - // (undocumented) - errorMessage?: string; - // (undocumented) - expected?: boolean; - // (undocumented) - httpResponseCode: number; - // (undocumented) - isErrorCustomized?: boolean; - // (undocumented) - message: string; - // (undocumented) - metricAttributes?: { - [key: string]: unknown; - }; -} - -// @public (undocumented) -export interface DaVinciFailureResponse extends DaVinciBaseResponse { - // (undocumented) - error?: { - code?: string; - message?: string; - [key: string]: unknown; - }; -} - -// @public (undocumented) -export type DaVinciField = ComplexValueFields | MultiValueFields | ReadOnlyFields | RedirectFields | SingleValueFields; - -// @public -export interface DaVinciNextResponse extends DaVinciBaseResponse { - // (undocumented) - eventName?: string; - // (undocumented) - form?: { - name?: string; - description?: string; - components?: { - fields?: DaVinciField[]; - }; - }; - // (undocumented) - formData?: { - value?: { - [key: string]: string; - }; - }; - // (undocumented) - _links?: Links; -} - -// @public -export interface DaVinciPollResponse extends DaVinciBaseResponse { - // (undocumented) - eventName?: string; - // (undocumented) - _links?: Links; - // (undocumented) - success?: boolean; -} - -// @public (undocumented) -export interface DaVinciRequest { - // (undocumented) - eventName: string; - // (undocumented) - id: string; - // (undocumented) - interactionId: string; - // (undocumented) - parameters: { - eventType: 'submit' | 'action' | 'polling'; - data: { - actionKey: string; - formData?: Record; - }; - }; -} - -// @public -export type DaVinciRequestValueTypes = string | number | boolean | (string | number | boolean)[] | DeviceValue | PhoneNumberInputValue | FidoRegistrationInputValue | FidoAuthenticationInputValue | MetadataError | GenericError; - -// @public (undocumented) -export interface DaVinciSuccessResponse extends DaVinciBaseResponse { - // (undocumented) - authorizeResponse?: OAuthDetails; - // (undocumented) - environment: { - id: string; - [key: string]: unknown; - }; - // (undocumented) - _links?: Links; - // (undocumented) - resetCookie?: boolean; - // (undocumented) - session?: { - id?: string; - [key: string]: unknown; - }; - // (undocumented) - sessionToken?: string; - // (undocumented) - sessionTokenMaxAge?: number; - // (undocumented) - status: string; - // (undocumented) - subFlowSettings?: { - cssLinks?: unknown[]; - cssUrl?: unknown; - jsLinks?: unknown[]; - loadingScreenSettings?: unknown; - reactSkUrl?: unknown; - }; - // (undocumented) - success: true; -} - -// @public (undocumented) -export type DeviceAuthenticationCollector = ObjectOptionsCollectorWithObjectValue<'DeviceAuthenticationCollector', DeviceValue>; - -// @public (undocumented) -export type DeviceAuthenticationField = { - type: 'DEVICE_AUTHENTICATION'; - key: string; - label: string; - options: { - type: string; - iconSrc: string; - title: string; - id: string; - default: boolean; - description: string; - }[]; - required: boolean; -}; - -// @public (undocumented) -export interface DeviceOptionNoDefault { - // (undocumented) - content: string; - // (undocumented) - key: string; - // (undocumented) - label: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export interface DeviceOptionWithDefault { - // (undocumented) - content: string; - // (undocumented) - default: boolean; - // (undocumented) - key: string; - // (undocumented) - label: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export type DeviceRegistrationCollector = ObjectOptionsCollectorWithStringValue<'DeviceRegistrationCollector', string>; - -// @public (undocumented) -export type DeviceRegistrationField = { - type: 'DEVICE_REGISTRATION'; - key: string; - label: string; - options: { - type: string; - iconSrc: string; - title: string; - description: string; - }[]; - required: boolean; -}; - -// @public (undocumented) -export interface DeviceValue { - // (undocumented) - id: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export interface ErrorDetail { - // (undocumented) - message?: string; - // (undocumented) - rawResponse?: { - _embedded?: { - users?: Array; - }; - code?: string; - count?: number; - details?: NestedErrorDetails[]; - id?: string; - message?: string; - size?: number; - userFilter?: string; - [key: string]: unknown; - }; - // (undocumented) - statusCode?: number; -} - -// @public (undocumented) -export interface ErrorNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'error'; - }; - // (undocumented) - error: DaVinciError; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'error'; - } | null; - // (undocumented) - status: 'error'; -} - -// @public (undocumented) -export interface FailureNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - status: 'failure'; - }; - // (undocumented) - error: DaVinciError; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - href?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'failure'; - } | null; - // (undocumented) - status: 'failure'; -} - -// @public -export function fido(): FidoClient; - -// @public (undocumented) -export type FidoAuthenticationCollector = AutoCollector<'ObjectValueAutoCollector', 'FidoAuthenticationCollector', FidoAuthenticationInputValue | GenericError, FidoAuthenticationOutputValue>; - -// @public (undocumented) -export type FidoAuthenticationField = { - type: 'FIDO2'; - key: string; - label: string; - publicKeyCredentialRequestOptions: FidoAuthenticationOptions; - action: 'AUTHENTICATE'; - trigger: string; - required: boolean; -}; - -// @public (undocumented) -export interface FidoAuthenticationInputValue { - // (undocumented) - assertionValue?: AssertionValue; -} - -// @public (undocumented) -export interface FidoAuthenticationOptions extends Omit { - // (undocumented) - allowCredentials?: { - id: number[]; - transports?: AuthenticatorTransport[]; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - challenge: number[]; -} - -// @public (undocumented) -export interface FidoAuthenticationOutputValue { - // (undocumented) - action: 'AUTHENTICATE'; - // (undocumented) - publicKeyCredentialRequestOptions: FidoAuthenticationOptions; - // (undocumented) - trigger: string; -} - -// @public (undocumented) -export interface FidoClient { - authenticate: (options: FidoAuthenticationOptions) => Promise; - register: (options: FidoRegistrationOptions) => Promise; -} - -// @public -export type FidoErrorCode = 'NotAllowedError' | 'AbortError' | 'InvalidStateError' | 'NotSupportedError' | 'SecurityError' | 'TimeoutError' | 'UnknownError'; - -// @public (undocumented) -export type FidoRegistrationCollector = AutoCollector<'ObjectValueAutoCollector', 'FidoRegistrationCollector', FidoRegistrationInputValue | GenericError, FidoRegistrationOutputValue>; - -// @public (undocumented) -export type FidoRegistrationField = { - type: 'FIDO2'; - key: string; - label: string; - publicKeyCredentialCreationOptions: FidoRegistrationOptions; - action: 'REGISTER'; - trigger: string; - required: boolean; -}; - -// @public (undocumented) -export interface FidoRegistrationInputValue { - // (undocumented) - attestationValue?: AttestationValue; -} - -// @public (undocumented) -export interface FidoRegistrationOptions extends Omit { - // (undocumented) - challenge: number[]; - // (undocumented) - excludeCredentials?: { - id: number[]; - transports?: AuthenticatorTransport[]; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - pubKeyCredParams: { - alg: string | number; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - user: { - id: number[]; - name: string; - displayName: string; - }; -} - -// @public (undocumented) -export interface FidoRegistrationOutputValue { - // (undocumented) - action: 'REGISTER'; - // (undocumented) - publicKeyCredentialCreationOptions: FidoRegistrationOptions; - // (undocumented) - trigger: string; -} - -// @public (undocumented) -export type FlowCollector = ActionCollectorNoUrl<'FlowCollector'>; - -// @public (undocumented) -export type FlowNode = ContinueNode | ErrorNode | StartNode | SuccessNode | FailureNode; - -// @public -export type GetClient = StartNode['client'] | ContinueNode['client'] | ErrorNode['client'] | SuccessNode['client'] | FailureNode['client']; - -// @public (undocumented) -export type IdpCollector = ActionCollectorWithUrl<'IdpCollector'>; - -// @public -export interface ImageCollector extends NoValueCollectorBase<'ImageCollector'> { - // (undocumented) - output: NoValueCollectorBase<'ImageCollector'>['output'] & { - src: string; - alt: string; - href?: string; - }; -} - -// @public (undocumented) -export type ImageField = { - type: 'IMAGE'; - key: string; - description: string; - imageUrl: string; - hyperlinkUrl?: string; -}; - -// @public (undocumented) -export type InferActionCollectorType = T extends 'IdpCollector' ? IdpCollector : T extends 'SubmitCollector' ? SubmitCollector : T extends 'FlowCollector' ? FlowCollector : ActionCollectorWithUrl<'ActionCollector'> | ActionCollectorNoUrl<'ActionCollector'>; - -// @public -export type InferAutoCollectorType = T extends 'ProtectCollector' ? ProtectCollector : T extends 'PollingCollector' ? PollingCollector : T extends 'FidoRegistrationCollector' ? FidoRegistrationCollector : T extends 'FidoAuthenticationCollector' ? FidoAuthenticationCollector : T extends 'MetadataCollector' ? MetadataCollector : T extends 'ObjectValueAutoCollector' ? ObjectValueAutoCollector : SingleValueAutoCollector; - -// @public -export type InferMultiValueCollectorType = T extends 'MultiSelectCollector' ? MultiValueCollectorWithValue<'MultiSelectCollector'> : MultiValueCollectorWithValue<'MultiValueCollector'> | MultiValueCollectorNoValue<'MultiValueCollector'>; - -// @public -export type InferNoValueCollectorType = T extends 'ReadOnlyCollector' ? ReadOnlyCollector : T extends 'RichTextCollector' ? RichTextCollector : T extends 'QrCodeCollector' ? QrCodeCollector : T extends 'ImageCollector' ? ImageCollector : NoValueCollectorBase<'NoValueCollector'>; - -// @public -export type InferSingleValueCollectorType = T extends 'TextCollector' ? TextCollector : T extends 'SingleSelectCollector' ? SingleSelectCollector : T extends 'ValidatedTextCollector' ? ValidatedTextCollector : T extends 'PasswordCollector' ? PasswordCollector : T extends 'ValidatedPasswordCollector' ? ValidatedPasswordCollector : T extends 'BooleanCollector' ? BooleanCollector : T extends 'ValidatedBooleanCollector' ? ValidatedBooleanCollector : SingleValueCollectorWithValue<'SingleValueCollector'> | SingleValueCollectorNoValue<'SingleValueCollector'>; - -// @public (undocumented) -export type InferValueObjectCollectorType = T extends 'DeviceAuthenticationCollector' ? DeviceAuthenticationCollector : T extends 'DeviceRegistrationCollector' ? DeviceRegistrationCollector : T extends 'PhoneNumberCollector' ? PhoneNumberCollector : T extends 'PhoneNumberExtensionCollector' ? PhoneNumberExtensionCollector : ObjectOptionsCollectorWithObjectValue<'ObjectValueCollector'> | ObjectOptionsCollectorWithStringValue<'ObjectValueCollector'>; - -// @public (undocumented) -export type InitFlow = () => Promise; - -// @public (undocumented) -export interface InternalErrorResponse { - // (undocumented) - error: Omit & { - message: string; - }; - // (undocumented) - type: 'internal_error'; -} - -// @public (undocumented) -export interface Links { - // (undocumented) - [key: string]: { - href?: string; - }; -} - -export { LogLevel } - -// @public (undocumented) -export type MetadataCollector = AutoCollector<'ObjectValueAutoCollector', 'MetadataCollector', MetadataCollectorInputValue, Record>; - -// @public (undocumented) -export type MetadataCollectorInputValue = Record | MetadataError; - -// @public -export interface MetadataError { - // (undocumented) - code: string; - // (undocumented) - message: string; -} - -// @public (undocumented) -export type MetadataField = { - type: 'METADATA'; - key: string; - payload: Record; -}; - -// @public (undocumented) -export type MultiSelectCollector = MultiValueCollectorWithValue<'MultiSelectCollector'>; - -// @public (undocumented) -export type MultiSelectField = { - inputType: 'MULTI_SELECT'; - key: string; - label: string; - options: { - label: string; - value: string; - }[]; - required?: boolean; - type: 'CHECKBOX' | 'COMBOBOX'; -}; - -// @public (undocumented) -export type MultiValueCollector = MultiValueCollectorWithValue | MultiValueCollectorNoValue; - -// @public (undocumented) -export interface MultiValueCollectorNoValue { - // (undocumented) - category: 'MultiValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string[]; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type MultiValueCollectors = MultiValueCollectorWithValue<'MultiValueCollector'> | MultiValueCollectorWithValue<'MultiSelectCollector'>; - -// @public -export type MultiValueCollectorTypes = 'MultiSelectCollector' | 'MultiValueCollector'; - -// @public (undocumented) -export interface MultiValueCollectorWithValue { - // (undocumented) - category: 'MultiValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string[]; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: string[]; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type MultiValueFields = MultiSelectField; - -// @public -export interface NestedErrorDetails { - // (undocumented) - code?: string; - // (undocumented) - innerError?: { - history?: string; - unsatisfiedRequirements?: string[]; - failuresRemaining?: number; - }; - // (undocumented) - message?: string; - // (undocumented) - target?: string; -} - -// @public -export const nextCollectorValues: ActionCreatorWithPayload< { -fields: DaVinciField[]; -formData: { -value: Record; -}; -}, string>; - -// @public -export const nodeCollectorReducer: Reducer & { - getInitialState: () => Collectors[]; -}; - -// @public (undocumented) -export type NodeStates = StartNode | ContinueNode | ErrorNode | SuccessNode | FailureNode; - -// @public (undocumented) -export type NoValueCollector = InferNoValueCollectorType; - -// @public (undocumented) -export interface NoValueCollectorBase { - // (undocumented) - category: 'NoValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type NoValueCollectors = NoValueCollectorBase<'NoValueCollector'> | ReadOnlyCollector | RichTextCollector | QrCodeCollector | ImageCollector; - -// @public -export type NoValueCollectorTypes = 'ReadOnlyCollector' | 'RichTextCollector' | 'NoValueCollector' | 'QrCodeCollector' | 'ImageCollector'; - -// @public -export interface OAuthDetails { - // (undocumented) - [key: string]: unknown; - // (undocumented) - code?: string; - // (undocumented) - state?: string; -} - -// @public (undocumented) -export interface ObjectOptionsCollectorWithObjectValue, D = Record> { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: DeviceOptionWithDefault[]; - value?: D | null; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface ObjectOptionsCollectorWithStringValue { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: DeviceOptionNoDefault[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ObjectValueAutoCollector = AutoCollector<'ObjectValueAutoCollector', 'ObjectValueAutoCollector', Record>; - -// @public (undocumented) -export type ObjectValueAutoCollectorTypes = 'ObjectValueAutoCollector' | 'FidoRegistrationCollector' | 'FidoAuthenticationCollector' | 'MetadataCollector'; - -// @public (undocumented) -export type ObjectValueCollector = ObjectOptionsCollectorWithObjectValue | ObjectOptionsCollectorWithStringValue | ObjectValueCollectorWithObjectValue; - -// @public (undocumented) -export type ObjectValueCollectors = DeviceAuthenticationCollector | DeviceRegistrationCollector | PhoneNumberCollector | PhoneNumberExtensionCollector | ObjectOptionsCollectorWithObjectValue<'ObjectSelectCollector'> | ObjectOptionsCollectorWithStringValue<'ObjectSelectCollector'>; - -// @public -export type ObjectValueCollectorTypes = 'DeviceAuthenticationCollector' | 'DeviceRegistrationCollector' | 'PhoneNumberCollector' | 'PhoneNumberExtensionCollector' | 'ObjectOptionsCollector' | 'ObjectValueCollector' | 'ObjectSelectCollector'; - -// @public (undocumented) -export interface ObjectValueCollectorWithObjectValue, OV = Record> { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: IV; - type: string; - validation: (ValidationRequired | ValidationPhoneNumber)[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value?: OV | null; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface OutgoingQueryParams { - // (undocumented) - [key: string]: string | string[]; -} - -// @public (undocumented) -export interface PasswordCollector { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - verify: boolean; - }; - // (undocumented) - type: 'PasswordCollector'; -} - -// @public -export type PasswordField = { - type: 'PASSWORD' | 'PASSWORD_VERIFY'; - key: string; - label: string; - required?: boolean; - verify?: boolean; - passwordPolicy?: PasswordPolicy; -}; - -// @public -export interface PasswordPolicy { - // (undocumented) - createdAt?: string; - // (undocumented) - default?: boolean; - // (undocumented) - description?: string; - // (undocumented) - excludesCommonlyUsed?: boolean; - // (undocumented) - excludesProfileData?: boolean; - // (undocumented) - history?: { - count?: number; - retentionDays?: number; - }; - // (undocumented) - id?: string; - // (undocumented) - length?: { - min?: number; - max?: number; - }; - // (undocumented) - lockout?: { - failureCount?: number; - durationSeconds?: number; - }; - // (undocumented) - maxAgeDays?: number; - // (undocumented) - maxRepeatedCharacters?: number; - // (undocumented) - minAgeDays?: number; - // (undocumented) - minCharacters?: Record; - // (undocumented) - minUniqueCharacters?: number; - // (undocumented) - name?: string; - // (undocumented) - notSimilarToCurrent?: boolean; - // (undocumented) - populationCount?: number; - // (undocumented) - updatedAt?: string; -} - -// @public (undocumented) -export type PhoneNumberCollector = ObjectValueCollectorWithObjectValue<'PhoneNumberCollector', PhoneNumberInputValue, PhoneNumberOutputValue>; - -// @public (undocumented) -export interface PhoneNumberExtensionCollector { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: PhoneNumberExtensionInputValue; - type: string; - validation: (ValidationRequired | ValidationPhoneNumber)[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - extensionLabel: string; - value: PhoneNumberExtensionOutputValue; - }; - // (undocumented) - type: 'PhoneNumberExtensionCollector'; -} - -// @public (undocumented) -export type PhoneNumberExtensionField = PhoneNumberField & { - showExtension: boolean; - extensionLabel: string; -}; - -// @public (undocumented) -export interface PhoneNumberExtensionInputValue { - // (undocumented) - countryCode: string; - // (undocumented) - extension: string; - // (undocumented) - phoneNumber: string; -} - -// @public (undocumented) -export interface PhoneNumberExtensionOutputValue { - // (undocumented) - countryCode?: string; - // (undocumented) - extension?: string; - // (undocumented) - phoneNumber?: string; -} - -// @public (undocumented) -export type PhoneNumberField = { - type: 'PHONE_NUMBER'; - key: string; - label: string; - required: boolean; - defaultCountryCode: string | null; - validatePhoneNumber: boolean; -}; - -// @public (undocumented) -export interface PhoneNumberInputValue { - // (undocumented) - countryCode: string; - // (undocumented) - phoneNumber: string; -} - -// @public (undocumented) -export interface PhoneNumberOutputValue { - // (undocumented) - countryCode?: string; - // (undocumented) - phoneNumber?: string; -} - -// @public -export type Poller = () => Promise; - -// @public (undocumented) -export type PollingCollector = AutoCollector<'SingleValueAutoCollector', 'PollingCollector', string, PollingOutputValue>; - -// @public (undocumented) -export type PollingField = { - type: 'POLLING'; - key: string; - pollInterval: number; - pollRetries: number; - pollChallengeStatus?: boolean; - challenge?: string; -}; - -// @public (undocumented) -export interface PollingOutputValue { - // (undocumented) - challenge?: string; - // (undocumented) - pollChallengeStatus?: boolean; - // (undocumented) - pollInterval: number; - // (undocumented) - pollRetries: number; - // (undocumented) - retriesRemaining?: number; -} - -// @public (undocumented) -export type PollingStatus = PollingStatusContinue | PollingStatusChallenge; - -// @public (undocumented) -export type PollingStatusChallenge = PollingStatusChallengeComplete | 'expired' | 'timedOut' | 'error'; - -// @public (undocumented) -export type PollingStatusChallengeComplete = 'approved' | 'denied' | 'continue' | CustomPollingStatus; - -// @public (undocumented) -export type PollingStatusContinue = 'continue' | 'timedOut'; - -// @public (undocumented) -export type ProtectCollector = AutoCollector<'SingleValueAutoCollector', 'ProtectCollector', string, ProtectOutputValue>; - -// @public (undocumented) -export type ProtectField = { - type: 'PROTECT'; - key: string; - behavioralDataCollection: boolean; - universalDeviceIdentification: boolean; -}; - -// @public -export interface ProtectOutputValue { - // (undocumented) - behavioralDataCollection: boolean; - // (undocumented) - universalDeviceIdentification: boolean; -} - -// @public -export interface QrCodeCollector extends NoValueCollectorBase<'QrCodeCollector'> { - // (undocumented) - output: NoValueCollectorBase<'QrCodeCollector'>['output'] & { - src: string; - }; -} - -// @public (undocumented) -export type QrCodeField = { - type: 'QR_CODE'; - key: string; - content: string; - fallbackText?: string; -}; - -// @public -export interface ReadOnlyCollector extends NoValueCollectorBase<'ReadOnlyCollector'> { - // (undocumented) - output: NoValueCollectorBase<'ReadOnlyCollector'>['output'] & { - content: string; - title?: string; - }; -} - -// @public (undocumented) -export type ReadOnlyField = { - type: 'LABEL'; - content: string; - richContent?: RichContent; - key?: string; -}; - -// @public (undocumented) -export type ReadOnlyFields = ReadOnlyField | QrCodeField | AgreementField | ImageField; - -// @public (undocumented) -export type RedirectField = { - type: 'SOCIAL_LOGIN_BUTTON'; - key: string; - label: string; - links: Links; -}; - -// @public (undocumented) -export type RedirectFields = RedirectField; - -export { RequestMiddleware } - -// @public -export type RichContent = { - content: string; - replacements?: Record; -}; - -// @public -export interface RichContentLink { - // (undocumented) - href: string; - // (undocumented) - key: string; - // (undocumented) - target?: '_self' | '_blank'; - // (undocumented) - type: 'link'; - // (undocumented) - value: string; -} - -// @public -export type RichContentReplacement = { - type: 'link'; - value: string; - href: string; - target?: '_self' | '_blank'; -}; - -// @public -export interface RichTextCollector extends NoValueCollectorBase<'RichTextCollector'> { - // (undocumented) - output: NoValueCollectorBase<'RichTextCollector'>['output'] & { - content: string; - richContent: CollectorRichContent; - }; -} - -// @public (undocumented) -export interface SelectorOption { - // (undocumented) - label: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export type SingleCheckboxField = { - type: 'SINGLE_CHECKBOX'; - inputType: 'BOOLEAN'; - key: string; - label: string; - required?: boolean; - errorMessage?: string; - appearance: string; - richContent?: RichContent; -}; - -// @public (undocumented) -export type SingleSelectCollector = SingleSelectCollectorWithValue<'SingleSelectCollector'>; - -// @public (undocumented) -export interface SingleSelectCollectorNoValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface SingleSelectCollectorWithValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: string | number | boolean; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleSelectField = { - inputType: 'SINGLE_SELECT'; - key: string; - label: string; - options: { - label: string; - value: string; - }[]; - required?: boolean; - type: 'RADIO' | 'DROPDOWN'; -}; - -// @public (undocumented) -export type SingleValueAutoCollector = AutoCollector<'SingleValueAutoCollector', 'SingleValueAutoCollector', string>; - -// @public (undocumented) -export type SingleValueAutoCollectorTypes = 'SingleValueAutoCollector' | 'ProtectCollector' | 'PollingCollector'; - -// @public -export type SingleValueCollector = SingleValueCollectorWithValue | SingleValueCollectorNoValue; - -// @public (undocumented) -export interface SingleValueCollectorNoValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleValueCollectors = PasswordCollector | ValidatedPasswordCollector | SingleSelectCollector | TextCollector | ValidatedTextCollector | BooleanCollector | ValidatedBooleanCollector | SingleValueCollectorWithValue<'SingleValueCollector'>; - -// @public -export type SingleValueCollectorTypes = 'PasswordCollector' | 'ValidatedPasswordCollector' | 'BooleanCollector' | 'ValidatedBooleanCollector' | 'SingleValueCollector' | 'SingleSelectCollector' | 'SingleSelectObjectCollector' | 'TextCollector' | 'ValidatedTextCollector'; - -// @public (undocumented) -export interface SingleValueCollectorWithValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: V; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleValueFields = StandardField | PasswordField | ValidatedField | SingleCheckboxField | SingleSelectField | ProtectField; - -// @public (undocumented) -export type StandardField = { - type: 'TEXT' | 'SUBMIT_BUTTON' | 'FLOW_BUTTON' | 'FLOW_LINK' | 'BUTTON'; - key: string; - label: string; - required?: boolean; -}; - -// @public (undocumented) -export interface StartNode { - // (undocumented) - cache: null; - // (undocumented) - client: { - status: 'start'; - }; - // (undocumented) - error: DaVinciError | null; - // (undocumented) - server: { - status: 'start'; - }; - // (undocumented) - status: 'start'; -} - -// @public (undocumented) -export interface StartOptions { - // (undocumented) - query: Query; -} - -// @public (undocumented) -export type SubmitCollector = ActionCollectorNoUrl<'SubmitCollector'>; - -// @public (undocumented) -export interface SuccessNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - authorization?: { - code?: string; - state?: string; - }; - status: 'success'; - } | null; - // (undocumented) - error: null; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - session?: string; - status: 'success'; - }; - // (undocumented) - status: 'success'; -} - -// @public (undocumented) -export type TextCollector = SingleValueCollectorWithValue<'TextCollector'>; - -// @public (undocumented) -export interface ThrownQueryError { - // (undocumented) - error: FetchBaseQueryError; - // (undocumented) - isHandledError: boolean; - // (undocumented) - meta: FetchBaseQueryMeta; -} - -// @public -export type UnknownCollector = { - category: 'UnknownCollector'; - error: string | null; - type: 'UnknownCollector'; - id: string; - name: string; - output: { - key: string; - label: string; - type: string; - }; -}; - -// @public (undocumented) -export type UnknownField = Record; - -// @public -export type UpdatableCollectors = SingleValueCollectors | MultiSelectCollector | ObjectValueCollectors | AutoCollectors; - -// @public (undocumented) -export const updateCollectorValues: ActionCreatorWithPayload< { -id: string; -value: CollectorValueTypes; -index?: number; -}, string>; - -// @public -export type Updater = (value: CollectorValueType, index?: number) => InternalErrorResponse | null; - -// @public (undocumented) -export interface ValidatedBooleanCollector extends ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean> { - // (undocumented) - output: ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean>['output'] & { - appearance: string; - richContent?: CollectorRichContent; - }; -} - -// @public -export type ValidatedCollectors = ValidatedTextCollector | ValidatedBooleanCollector | ValidatedPasswordCollector | ObjectValueCollectors | MultiValueCollectors | AutoCollectors; - -// @public (undocumented) -export type ValidatedField = { - type: 'TEXT'; - key: string; - label: string; - required: boolean; - validation: { - regex: string; - errorMessage: string; - }; -}; - -// @public (undocumented) -export interface ValidatedPasswordCollector { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - validation: PasswordPolicy; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - verify: boolean; - }; - // (undocumented) - type: 'ValidatedPasswordCollector'; -} - -// @public (undocumented) -export interface ValidatedSingleValueCollectorWithValue { - // (undocumented) - category: 'ValidatedSingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - type: string; - validation: (ValidationRequired | ValidationRegex)[]; - value: V; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: V; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ValidatedTextCollector = ValidatedSingleValueCollectorWithValue<'TextCollector'>; - -// @public (undocumented) -export interface ValidationPhoneNumber { - // (undocumented) - message: string; - // (undocumented) - rule: boolean; - // (undocumented) - type: 'validatePhoneNumber'; -} - -// @public (undocumented) -export interface ValidationRegex { - // (undocumented) - message: string; - // (undocumented) - rule: string; - // (undocumented) - type: 'regex'; -} - -// @public (undocumented) -export interface ValidationRequired { - // (undocumented) - message: string; - // (undocumented) - rule: boolean; - // (undocumented) - type: 'required'; -} - -// @public -export type Validator = (value: CollectorValueType) => string[] | { - error: { - message: string; - type: string; - }; - type: string; -}; - -// (No @packageDocumentation comment for this package) - -``` +## API Report File for "@forgerock/davinci-client" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ActionCreatorWithPayload } from '@reduxjs/toolkit'; +import { ActionTypes } from '@forgerock/sdk-request-middleware'; +import { CustomLogger } from '@forgerock/sdk-logger'; +import type { DaVinciConfig } from '@forgerock/sdk-types'; +import { FetchBaseQueryError } from '@reduxjs/toolkit/query'; +import type { FetchBaseQueryMeta } from '@reduxjs/toolkit/query'; +import { GenericError } from '@forgerock/sdk-types'; +import { LogLevel } from '@forgerock/sdk-logger'; +import type { MutationResultSelectorResult } from '@reduxjs/toolkit/query'; +import { QueryStatus } from '@reduxjs/toolkit/query'; +import { Reducer } from '@reduxjs/toolkit'; +import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; +import type { SdkStore } from '@forgerock/sdk-types'; +import { SerializedError } from '@reduxjs/toolkit'; +import { Unsubscribe } from '@reduxjs/toolkit'; + +// @public (undocumented) +export type ActionCollector = + | ActionCollectorNoUrl + | ActionCollectorWithUrl; + +// @public (undocumented) +export interface ActionCollectorNoUrl { + // (undocumented) + category: 'ActionCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ActionCollectors = + | ActionCollectorWithUrl<'IdpCollector'> + | ActionCollectorNoUrl<'ActionCollector'> + | ActionCollectorNoUrl<'FlowCollector'> + | ActionCollectorNoUrl<'SubmitCollector'>; + +// @public +export type ActionCollectorTypes = + | 'FlowCollector' + | 'SubmitCollector' + | 'IdpCollector' + | 'ActionCollector'; + +// @public (undocumented) +export interface ActionCollectorWithUrl { + // (undocumented) + category: 'ActionCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + url?: string | null; + }; + // (undocumented) + type: T; +} + +export { ActionTypes }; + +// @public (undocumented) +export type AgreementField = { + type: 'AGREEMENT'; + key: string; + content: string; + titleEnabled: boolean; + title?: string; + agreement: { + id: string; + useDynamicAgreement: boolean; + }; + enabled: boolean; +}; + +// @public (undocumented) +export interface AssertionValue extends Omit< + PublicKeyCredential, + 'rawId' | 'response' | 'getClientExtensionResults' | 'toJSON' +> { + // (undocumented) + rawId: string; + // (undocumented) + response: { + clientDataJSON: string; + authenticatorData: string; + signature: string; + userHandle: string | null; + }; +} + +// @public (undocumented) +export interface AttestationValue extends Omit< + PublicKeyCredential, + 'rawId' | 'response' | 'getClientExtensionResults' | 'toJSON' +> { + // (undocumented) + rawId: string; + // (undocumented) + response: { + clientDataJSON: string; + attestationObject: string; + }; +} + +// @public (undocumented) +export interface AutoCollector< + C extends AutoCollectorCategories, + T extends AutoCollectorTypes, + IV = string, + OV = Record, +> { + // (undocumented) + category: C; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: IV; + type: string; + validation?: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + type: string; + config: OV; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type AutoCollectorCategories = 'SingleValueAutoCollector' | 'ObjectValueAutoCollector'; + +// @public (undocumented) +export type AutoCollectors = + | ProtectCollector + | FidoRegistrationCollector + | FidoAuthenticationCollector + | MetadataCollector + | PollingCollector + | SingleValueAutoCollector + | ObjectValueAutoCollector; + +// @public (undocumented) +export type AutoCollectorTypes = SingleValueAutoCollectorTypes | ObjectValueAutoCollectorTypes; + +// @public (undocumented) +export interface BooleanCollector extends SingleValueCollectorWithValue< + 'BooleanCollector', + boolean +> { + // (undocumented) + output: SingleValueCollectorWithValue<'BooleanCollector', boolean>['output'] & { + appearance: string; + richContent?: CollectorRichContent; + }; +} + +// @public (undocumented) +export type CollectorCategory = Collectors['category']; + +// @public (undocumented) +export interface CollectorErrors { + // (undocumented) + code: string; + // (undocumented) + message: string; + // (undocumented) + target: string; +} + +// @public +export interface CollectorRichContent { + // (undocumented) + content: string; + // (undocumented) + replacements: RichContentLink[]; +} + +// @public (undocumented) +export type Collectors = + | FlowCollector + | MetadataCollector + | PasswordCollector + | ValidatedPasswordCollector + | TextCollector + | BooleanCollector + | ValidatedBooleanCollector + | SingleSelectCollector + | IdpCollector + | SubmitCollector + | ActionCollector<'ActionCollector'> + | SingleValueCollector<'SingleValueCollector'> + | MultiSelectCollector + | DeviceAuthenticationCollector + | DeviceRegistrationCollector + | PhoneNumberCollector + | PhoneNumberExtensionCollector + | ReadOnlyCollector + | RichTextCollector + | ValidatedTextCollector + | ProtectCollector + | PollingCollector + | FidoRegistrationCollector + | FidoAuthenticationCollector + | QrCodeCollector + | ImageCollector + | UnknownCollector; + +// @public +export type CollectorValueType = T extends + | { + type: 'PasswordCollector'; + } + | { + type: 'ValidatedPasswordCollector'; + } + | { + type: 'SingleSelectCollector'; + } + | { + type: 'DeviceRegistrationCollector'; + } + | { + type: 'DeviceAuthenticationCollector'; + } + | { + type: 'ProtectCollector'; + } + | { + type: 'PollingCollector'; + } + ? string + : T extends { + type: 'TextCollector'; + category: 'SingleValueCollector'; + } + ? string + : T extends { + type: 'TextCollector'; + category: 'ValidatedSingleValueCollector'; + } + ? string + : T extends + | { + type: 'BooleanCollector'; + } + | { + type: 'ValidatedBooleanCollector'; + } + ? boolean + : T extends { + type: 'MultiSelectCollector'; + } + ? string | string[] + : T extends { + type: 'PhoneNumberCollector'; + } + ? PhoneNumberInputValue + : T extends { + type: 'PhoneNumberExtensionCollector'; + } + ? PhoneNumberExtensionInputValue + : T extends { + type: 'FidoRegistrationCollector'; + } + ? FidoRegistrationInputValue | GenericError + : T extends { + type: 'FidoAuthenticationCollector'; + } + ? FidoAuthenticationInputValue | GenericError + : T extends { + type: 'MetadataCollector'; + } + ? Record | MetadataError + : T extends { + category: 'SingleValueCollector'; + } + ? string + : T extends { + category: 'ValidatedSingleValueCollector'; + } + ? string + : T extends { + category: 'SingleValueAutoCollector'; + } + ? string + : T extends { + category: 'MultiValueCollector'; + } + ? string | string[] + : T extends { + category: 'ActionCollector'; + } + ? never + : T extends { + category: 'NoValueCollector'; + } + ? never + : CollectorValueTypes; + +// @public +export type CollectorValueTypes = + | string + | string[] + | boolean + | PhoneNumberInputValue + | PhoneNumberExtensionInputValue + | FidoRegistrationInputValue + | FidoAuthenticationInputValue + | MetadataError + | GenericError; + +// @public (undocumented) +export type ComplexValueFields = + | DeviceAuthenticationField + | DeviceRegistrationField + | PhoneNumberField + | PhoneNumberExtensionField + | FidoRegistrationField + | FidoAuthenticationField + | PollingField + | MetadataField; + +// @public (undocumented) +export interface ContinueNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'continue'; + }; + // (undocumented) + error: null; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + eventName?: string; + status: 'continue'; + }; + // (undocumented) + status: 'continue'; +} + +export { CustomLogger }; + +// @public +export type CustomPollingStatus = string & {}; + +// @public +export function davinci(input: { + config: DaVinciConfig; + requestMiddleware?: RequestMiddleware[]; + logger?: { + level: LogLevel; + custom?: CustomLogger; + }; +}): Promise<{ + store: SdkStore; + subscribe: (listener: () => void) => Unsubscribe; + externalIdp: () => () => Promise; + flow: (action: DaVinciAction) => InitFlow; + next: (args?: DaVinciRequest) => Promise; + resume: (input: { continueToken: string }) => Promise; + start: ( + options?: StartOptions | undefined, + ) => Promise; + update: (collector: T) => Updater; + validate: ( + collector: + | SingleValueCollectors + | ObjectValueCollectors + | MultiValueCollectors + | AutoCollectors, + ) => Validator; + pollStatus: (collector: PollingCollector) => Poller; + getClient: () => + | { + status: 'start'; + } + | { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'error'; + } + | { + status: 'failure'; + } + | { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'continue'; + } + | { + authorization?: { + code?: string; + state?: string; + }; + status: 'success'; + } + | null; + getCollectors: () => Collectors[]; + getError: () => DaVinciError | null; + getErrorCollectors: () => CollectorErrors[]; + getNode: () => StartNode | ErrorNode | FailureNode | ContinueNode | SuccessNode; + getServer: () => + | { + status: 'start'; + } + | { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'error'; + } + | { + _links?: Links; + eventName?: string; + href?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'failure'; + } + | { + _links?: Links; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + eventName?: string; + status: 'continue'; + } + | { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + session?: string; + status: 'success'; + } + | null; + cache: { + getLatestResponse: () => + | ({ + status: QueryStatus.fulfilled; + } & Omit< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'data' | 'fulfilledTimeStamp' + > & + Required< + Pick< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'data' | 'fulfilledTimeStamp' + > + > & { + error: undefined; + } & { + status: QueryStatus.fulfilled; + isUninitialized: false; + isLoading: false; + isSuccess: true; + isError: false; + }) + | ({ + status: QueryStatus.rejected; + } & Omit< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'error' + > & + Required< + Pick< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'error' + > + > & { + status: QueryStatus.rejected; + isUninitialized: false; + isLoading: false; + isSuccess: false; + isError: true; + }) + | { + error: { + message: string; + type: string; + }; + }; + getResponseWithId: (requestId: string) => + | ({ + status: QueryStatus.fulfilled; + } & Omit< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'data' | 'fulfilledTimeStamp' + > & + Required< + Pick< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'data' | 'fulfilledTimeStamp' + > + > & { + error: undefined; + } & { + status: QueryStatus.fulfilled; + isUninitialized: false; + isLoading: false; + isSuccess: true; + isError: false; + }) + | ({ + status: QueryStatus.rejected; + } & Omit< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'error' + > & + Required< + Pick< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'error' + > + > & { + status: QueryStatus.rejected; + isUninitialized: false; + isLoading: false; + isSuccess: false; + isError: true; + }) + | { + error: { + message: string; + type: string; + }; + }; + }; +}>; + +// @public +export interface DaVinciAction { + // (undocumented) + action: string; +} + +// @public +export interface DaVinciBaseResponse { + // (undocumented) + capabilityName?: string; + // (undocumented) + companyId?: string; + // (undocumented) + connectionId?: string; + // (undocumented) + connectorId?: string; + // (undocumented) + id?: string; + // (undocumented) + interactionId?: string; + // (undocumented) + interactionToken?: string; + // (undocumented) + isResponseCompatibleWithMobileAndWebSdks?: boolean; + // (undocumented) + status?: string; +} + +// @public +export type DaVinciCacheEntry = { + data?: DaVinciBaseResponse; + error?: { + data: DaVinciBaseResponse; + status: number; + }; +} & { + data?: any; + error?: any; +} & MutationResultSelectorResult; + +// @public (undocumented) +export type DavinciClient = Awaited>; + +export { DaVinciConfig }; + +// @public (undocumented) +export interface DaVinciError extends Omit { + // (undocumented) + collectors?: CollectorErrors[]; + // (undocumented) + internalHttpStatus?: number; + // (undocumented) + message: string; + // (undocumented) + status: 'error' | 'failure' | 'unknown'; +} + +// @public (undocumented) +export interface DaVinciErrorCacheEntry { + // (undocumented) + endpointName: 'next' | 'flow' | 'start'; + // (undocumented) + error: { + data: T; + }; + // (undocumented) + fulfilledTimeStamp: number; + // (undocumented) + isError: boolean; + // (undocumented) + isLoading: boolean; + // (undocumented) + isSuccess: boolean; + // (undocumented) + isUninitialized: boolean; + // (undocumented) + requestId: string; + // (undocumented) + startedTimeStamp: number; + // (undocumented) + status: 'fulfilled' | 'pending' | 'rejected'; +} + +// @public (undocumented) +export interface DavinciErrorResponse extends DaVinciBaseResponse { + // (undocumented) + cause?: string | null; + // (undocumented) + code: string | number; + // (undocumented) + details?: ErrorDetail[]; + // (undocumented) + doNotSendToOE?: boolean; + // (undocumented) + error?: { + code?: string; + message?: string; + }; + // (undocumented) + errorCategory?: string; + // (undocumented) + errorMessage?: string; + // (undocumented) + expected?: boolean; + // (undocumented) + httpResponseCode: number; + // (undocumented) + isErrorCustomized?: boolean; + // (undocumented) + message: string; + // (undocumented) + metricAttributes?: { + [key: string]: unknown; + }; +} + +// @public (undocumented) +export interface DaVinciFailureResponse extends DaVinciBaseResponse { + // (undocumented) + error?: { + code?: string; + message?: string; + [key: string]: unknown; + }; +} + +// @public (undocumented) +export type DaVinciField = + | ComplexValueFields + | MultiValueFields + | ReadOnlyFields + | RedirectFields + | SingleValueFields; + +// @public +export interface DaVinciNextResponse extends DaVinciBaseResponse { + // (undocumented) + eventName?: string; + // (undocumented) + form?: { + name?: string; + description?: string; + components?: { + fields?: DaVinciField[]; + }; + }; + // (undocumented) + formData?: { + value?: { + [key: string]: string; + }; + }; + // (undocumented) + _links?: Links; +} + +// @public +export interface DaVinciPollResponse extends DaVinciBaseResponse { + // (undocumented) + eventName?: string; + // (undocumented) + _links?: Links; + // (undocumented) + success?: boolean; +} + +// @public (undocumented) +export interface DaVinciRequest { + // (undocumented) + eventName: string; + // (undocumented) + id: string; + // (undocumented) + interactionId: string; + // (undocumented) + parameters: { + eventType: 'submit' | 'action' | 'polling'; + data: { + actionKey: string; + formData?: Record; + }; + }; +} + +// @public +export type DaVinciRequestValueTypes = + | string + | number + | boolean + | (string | number | boolean)[] + | DeviceValue + | PhoneNumberInputValue + | FidoRegistrationInputValue + | FidoAuthenticationInputValue + | MetadataError + | GenericError; + +// @public (undocumented) +export interface DaVinciSuccessResponse extends DaVinciBaseResponse { + // (undocumented) + authorizeResponse?: OAuthDetails; + // (undocumented) + environment: { + id: string; + [key: string]: unknown; + }; + // (undocumented) + _links?: Links; + // (undocumented) + resetCookie?: boolean; + // (undocumented) + session?: { + id?: string; + [key: string]: unknown; + }; + // (undocumented) + sessionToken?: string; + // (undocumented) + sessionTokenMaxAge?: number; + // (undocumented) + status: string; + // (undocumented) + subFlowSettings?: { + cssLinks?: unknown[]; + cssUrl?: unknown; + jsLinks?: unknown[]; + loadingScreenSettings?: unknown; + reactSkUrl?: unknown; + }; + // (undocumented) + success: true; +} + +// @public (undocumented) +export type DeviceAuthenticationCollector = ObjectOptionsCollectorWithObjectValue< + 'DeviceAuthenticationCollector', + DeviceValue +>; + +// @public (undocumented) +export type DeviceAuthenticationField = { + type: 'DEVICE_AUTHENTICATION'; + key: string; + label: string; + options: { + type: string; + iconSrc: string; + title: string; + id: string; + default: boolean; + description: string; + }[]; + required: boolean; +}; + +// @public (undocumented) +export interface DeviceOptionNoDefault { + // (undocumented) + content: string; + // (undocumented) + key: string; + // (undocumented) + label: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export interface DeviceOptionWithDefault { + // (undocumented) + content: string; + // (undocumented) + default: boolean; + // (undocumented) + key: string; + // (undocumented) + label: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export type DeviceRegistrationCollector = ObjectOptionsCollectorWithStringValue< + 'DeviceRegistrationCollector', + string +>; + +// @public (undocumented) +export type DeviceRegistrationField = { + type: 'DEVICE_REGISTRATION'; + key: string; + label: string; + options: { + type: string; + iconSrc: string; + title: string; + description: string; + }[]; + required: boolean; +}; + +// @public (undocumented) +export interface DeviceValue { + // (undocumented) + id: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export interface ErrorDetail { + // (undocumented) + message?: string; + // (undocumented) + rawResponse?: { + _embedded?: { + users?: Array; + }; + code?: string; + count?: number; + details?: NestedErrorDetails[]; + id?: string; + message?: string; + size?: number; + userFilter?: string; + [key: string]: unknown; + }; + // (undocumented) + statusCode?: number; +} + +// @public (undocumented) +export interface ErrorNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'error'; + }; + // (undocumented) + error: DaVinciError; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'error'; + } | null; + // (undocumented) + status: 'error'; +} + +// @public (undocumented) +export interface FailureNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + status: 'failure'; + }; + // (undocumented) + error: DaVinciError; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + href?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'failure'; + } | null; + // (undocumented) + status: 'failure'; +} + +// @public +export function fido(): FidoClient; + +// @public (undocumented) +export type FidoAuthenticationCollector = AutoCollector< + 'ObjectValueAutoCollector', + 'FidoAuthenticationCollector', + FidoAuthenticationInputValue | GenericError, + FidoAuthenticationOutputValue +>; + +// @public (undocumented) +export type FidoAuthenticationField = { + type: 'FIDO2'; + key: string; + label: string; + publicKeyCredentialRequestOptions: FidoAuthenticationOptions; + action: 'AUTHENTICATE'; + trigger: string; + required: boolean; +}; + +// @public (undocumented) +export interface FidoAuthenticationInputValue { + // (undocumented) + assertionValue?: AssertionValue; +} + +// @public (undocumented) +export interface FidoAuthenticationOptions extends Omit< + PublicKeyCredentialRequestOptions, + 'challenge' | 'allowCredentials' +> { + // (undocumented) + allowCredentials?: { + id: number[]; + transports?: AuthenticatorTransport[]; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + challenge: number[]; +} + +// @public (undocumented) +export interface FidoAuthenticationOutputValue { + // (undocumented) + action: 'AUTHENTICATE'; + // (undocumented) + publicKeyCredentialRequestOptions: FidoAuthenticationOptions; + // (undocumented) + trigger: string; +} + +// @public (undocumented) +export interface FidoClient { + authenticate: ( + options: FidoAuthenticationOptions, + ) => Promise; + register: ( + options: FidoRegistrationOptions, + ) => Promise; +} + +// @public +export type FidoErrorCode = + | 'NotAllowedError' + | 'AbortError' + | 'InvalidStateError' + | 'NotSupportedError' + | 'SecurityError' + | 'TimeoutError' + | 'UnknownError'; + +// @public (undocumented) +export type FidoRegistrationCollector = AutoCollector< + 'ObjectValueAutoCollector', + 'FidoRegistrationCollector', + FidoRegistrationInputValue | GenericError, + FidoRegistrationOutputValue +>; + +// @public (undocumented) +export type FidoRegistrationField = { + type: 'FIDO2'; + key: string; + label: string; + publicKeyCredentialCreationOptions: FidoRegistrationOptions; + action: 'REGISTER'; + trigger: string; + required: boolean; +}; + +// @public (undocumented) +export interface FidoRegistrationInputValue { + // (undocumented) + attestationValue?: AttestationValue; +} + +// @public (undocumented) +export interface FidoRegistrationOptions extends Omit< + PublicKeyCredentialCreationOptions, + 'challenge' | 'user' | 'pubKeyCredParams' | 'excludeCredentials' +> { + // (undocumented) + challenge: number[]; + // (undocumented) + excludeCredentials?: { + id: number[]; + transports?: AuthenticatorTransport[]; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + pubKeyCredParams: { + alg: string | number; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + user: { + id: number[]; + name: string; + displayName: string; + }; +} + +// @public (undocumented) +export interface FidoRegistrationOutputValue { + // (undocumented) + action: 'REGISTER'; + // (undocumented) + publicKeyCredentialCreationOptions: FidoRegistrationOptions; + // (undocumented) + trigger: string; +} + +// @public (undocumented) +export type FlowCollector = ActionCollectorNoUrl<'FlowCollector'>; + +// @public (undocumented) +export type FlowNode = ContinueNode | ErrorNode | StartNode | SuccessNode | FailureNode; + +// @public +export type GetClient = + | StartNode['client'] + | ContinueNode['client'] + | ErrorNode['client'] + | SuccessNode['client'] + | FailureNode['client']; + +// @public (undocumented) +export type IdpCollector = ActionCollectorWithUrl<'IdpCollector'>; + +// @public +export interface ImageCollector extends NoValueCollectorBase<'ImageCollector'> { + // (undocumented) + output: NoValueCollectorBase<'ImageCollector'>['output'] & { + src: string; + alt: string; + href?: string; + }; +} + +// @public (undocumented) +export type ImageField = { + type: 'IMAGE'; + key: string; + description: string; + imageUrl: string; + hyperlinkUrl?: string; +}; + +// @public (undocumented) +export type InferActionCollectorType = T extends 'IdpCollector' + ? IdpCollector + : T extends 'SubmitCollector' + ? SubmitCollector + : T extends 'FlowCollector' + ? FlowCollector + : ActionCollectorWithUrl<'ActionCollector'> | ActionCollectorNoUrl<'ActionCollector'>; + +// @public +export type InferAutoCollectorType = T extends 'ProtectCollector' + ? ProtectCollector + : T extends 'PollingCollector' + ? PollingCollector + : T extends 'FidoRegistrationCollector' + ? FidoRegistrationCollector + : T extends 'FidoAuthenticationCollector' + ? FidoAuthenticationCollector + : T extends 'MetadataCollector' + ? MetadataCollector + : T extends 'ObjectValueAutoCollector' + ? ObjectValueAutoCollector + : SingleValueAutoCollector; + +// @public +export type InferMultiValueCollectorType = + T extends 'MultiSelectCollector' + ? MultiValueCollectorWithValue<'MultiSelectCollector'> + : + | MultiValueCollectorWithValue<'MultiValueCollector'> + | MultiValueCollectorNoValue<'MultiValueCollector'>; + +// @public +export type InferNoValueCollectorType = + T extends 'ReadOnlyCollector' + ? ReadOnlyCollector + : T extends 'RichTextCollector' + ? RichTextCollector + : T extends 'QrCodeCollector' + ? QrCodeCollector + : T extends 'ImageCollector' + ? ImageCollector + : NoValueCollectorBase<'NoValueCollector'>; + +// @public +export type InferSingleValueCollectorType = + T extends 'TextCollector' + ? TextCollector + : T extends 'SingleSelectCollector' + ? SingleSelectCollector + : T extends 'ValidatedTextCollector' + ? ValidatedTextCollector + : T extends 'PasswordCollector' + ? PasswordCollector + : T extends 'ValidatedPasswordCollector' + ? ValidatedPasswordCollector + : T extends 'BooleanCollector' + ? BooleanCollector + : T extends 'ValidatedBooleanCollector' + ? ValidatedBooleanCollector + : + | SingleValueCollectorWithValue<'SingleValueCollector'> + | SingleValueCollectorNoValue<'SingleValueCollector'>; + +// @public (undocumented) +export type InferValueObjectCollectorType = + T extends 'DeviceAuthenticationCollector' + ? DeviceAuthenticationCollector + : T extends 'DeviceRegistrationCollector' + ? DeviceRegistrationCollector + : T extends 'PhoneNumberCollector' + ? PhoneNumberCollector + : T extends 'PhoneNumberExtensionCollector' + ? PhoneNumberExtensionCollector + : + | ObjectOptionsCollectorWithObjectValue<'ObjectValueCollector'> + | ObjectOptionsCollectorWithStringValue<'ObjectValueCollector'>; + +// @public (undocumented) +export type InitFlow = () => Promise; + +// @public (undocumented) +export interface InternalErrorResponse { + // (undocumented) + error: Omit & { + message: string; + }; + // (undocumented) + type: 'internal_error'; +} + +// @public (undocumented) +export interface Links { + // (undocumented) + [key: string]: { + href?: string; + }; +} + +export { LogLevel }; + +// @public (undocumented) +export type MetadataCollector = AutoCollector< + 'ObjectValueAutoCollector', + 'MetadataCollector', + MetadataCollectorInputValue, + Record +>; + +// @public (undocumented) +export type MetadataCollectorInputValue = Record | MetadataError; + +// @public +export interface MetadataError { + // (undocumented) + code: string; + // (undocumented) + message: string; +} + +// @public (undocumented) +export type MetadataField = { + type: 'METADATA'; + key: string; + payload: Record; +}; + +// @public (undocumented) +export type MultiSelectCollector = MultiValueCollectorWithValue<'MultiSelectCollector'>; + +// @public (undocumented) +export type MultiSelectField = { + inputType: 'MULTI_SELECT'; + key: string; + label: string; + options: { + label: string; + value: string; + }[]; + required?: boolean; + type: 'CHECKBOX' | 'COMBOBOX'; +}; + +// @public (undocumented) +export type MultiValueCollector = + | MultiValueCollectorWithValue + | MultiValueCollectorNoValue; + +// @public (undocumented) +export interface MultiValueCollectorNoValue { + // (undocumented) + category: 'MultiValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string[]; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type MultiValueCollectors = + | MultiValueCollectorWithValue<'MultiValueCollector'> + | MultiValueCollectorWithValue<'MultiSelectCollector'>; + +// @public +export type MultiValueCollectorTypes = 'MultiSelectCollector' | 'MultiValueCollector'; + +// @public (undocumented) +export interface MultiValueCollectorWithValue { + // (undocumented) + category: 'MultiValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string[]; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: string[]; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type MultiValueFields = MultiSelectField; + +// @public +export interface NestedErrorDetails { + // (undocumented) + code?: string; + // (undocumented) + innerError?: { + history?: string; + unsatisfiedRequirements?: string[]; + failuresRemaining?: number; + }; + // (undocumented) + message?: string; + // (undocumented) + target?: string; +} + +// @public +export const nextCollectorValues: ActionCreatorWithPayload< + { + fields: DaVinciField[]; + formData: { + value: Record; + }; + }, + string +>; + +// @public +export const nodeCollectorReducer: Reducer & { + getInitialState: () => Collectors[]; +}; + +// @public (undocumented) +export type NodeStates = StartNode | ContinueNode | ErrorNode | SuccessNode | FailureNode; + +// @public (undocumented) +export type NoValueCollector = InferNoValueCollectorType; + +// @public (undocumented) +export interface NoValueCollectorBase { + // (undocumented) + category: 'NoValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type NoValueCollectors = + | NoValueCollectorBase<'NoValueCollector'> + | ReadOnlyCollector + | RichTextCollector + | QrCodeCollector + | ImageCollector; + +// @public +export type NoValueCollectorTypes = + | 'ReadOnlyCollector' + | 'RichTextCollector' + | 'NoValueCollector' + | 'QrCodeCollector' + | 'ImageCollector'; + +// @public +export interface OAuthDetails { + // (undocumented) + [key: string]: unknown; + // (undocumented) + code?: string; + // (undocumented) + state?: string; +} + +// @public (undocumented) +export interface ObjectOptionsCollectorWithObjectValue< + T extends ObjectValueCollectorTypes, + V = Record, + D = Record, +> { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: DeviceOptionWithDefault[]; + value?: D | null; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface ObjectOptionsCollectorWithStringValue< + T extends ObjectValueCollectorTypes, + V = string, +> { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: DeviceOptionNoDefault[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ObjectValueAutoCollector = AutoCollector< + 'ObjectValueAutoCollector', + 'ObjectValueAutoCollector', + Record +>; + +// @public (undocumented) +export type ObjectValueAutoCollectorTypes = + | 'ObjectValueAutoCollector' + | 'FidoRegistrationCollector' + | 'FidoAuthenticationCollector' + | 'MetadataCollector'; + +// @public (undocumented) +export type ObjectValueCollector = + | ObjectOptionsCollectorWithObjectValue + | ObjectOptionsCollectorWithStringValue + | ObjectValueCollectorWithObjectValue; + +// @public (undocumented) +export type ObjectValueCollectors = + | DeviceAuthenticationCollector + | DeviceRegistrationCollector + | PhoneNumberCollector + | PhoneNumberExtensionCollector + | ObjectOptionsCollectorWithObjectValue<'ObjectSelectCollector'> + | ObjectOptionsCollectorWithStringValue<'ObjectSelectCollector'>; + +// @public +export type ObjectValueCollectorTypes = + | 'DeviceAuthenticationCollector' + | 'DeviceRegistrationCollector' + | 'PhoneNumberCollector' + | 'PhoneNumberExtensionCollector' + | 'ObjectOptionsCollector' + | 'ObjectValueCollector' + | 'ObjectSelectCollector'; + +// @public (undocumented) +export interface ObjectValueCollectorWithObjectValue< + T extends ObjectValueCollectorTypes, + IV = Record, + OV = Record, +> { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: IV; + type: string; + validation: (ValidationRequired | ValidationPhoneNumber)[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value?: OV | null; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface OutgoingQueryParams { + // (undocumented) + [key: string]: string | string[]; +} + +// @public (undocumented) +export interface PasswordCollector { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + verify: boolean; + }; + // (undocumented) + type: 'PasswordCollector'; +} + +// @public +export type PasswordField = { + type: 'PASSWORD' | 'PASSWORD_VERIFY'; + key: string; + label: string; + required?: boolean; + verify?: boolean; + passwordPolicy?: PasswordPolicy; +}; + +// @public +export interface PasswordPolicy { + // (undocumented) + createdAt?: string; + // (undocumented) + default?: boolean; + // (undocumented) + description?: string; + // (undocumented) + excludesCommonlyUsed?: boolean; + // (undocumented) + excludesProfileData?: boolean; + // (undocumented) + history?: { + count?: number; + retentionDays?: number; + }; + // (undocumented) + id?: string; + // (undocumented) + length?: { + min?: number; + max?: number; + }; + // (undocumented) + lockout?: { + failureCount?: number; + durationSeconds?: number; + }; + // (undocumented) + maxAgeDays?: number; + // (undocumented) + maxRepeatedCharacters?: number; + // (undocumented) + minAgeDays?: number; + // (undocumented) + minCharacters?: Record; + // (undocumented) + minUniqueCharacters?: number; + // (undocumented) + name?: string; + // (undocumented) + notSimilarToCurrent?: boolean; + // (undocumented) + populationCount?: number; + // (undocumented) + updatedAt?: string; +} + +// @public (undocumented) +export type PhoneNumberCollector = ObjectValueCollectorWithObjectValue< + 'PhoneNumberCollector', + PhoneNumberInputValue, + PhoneNumberOutputValue +>; + +// @public (undocumented) +export interface PhoneNumberExtensionCollector { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: PhoneNumberExtensionInputValue; + type: string; + validation: (ValidationRequired | ValidationPhoneNumber)[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + extensionLabel: string; + value: PhoneNumberExtensionOutputValue; + }; + // (undocumented) + type: 'PhoneNumberExtensionCollector'; +} + +// @public (undocumented) +export type PhoneNumberExtensionField = PhoneNumberField & { + showExtension: boolean; + extensionLabel: string; +}; + +// @public (undocumented) +export interface PhoneNumberExtensionInputValue { + // (undocumented) + countryCode: string; + // (undocumented) + extension: string; + // (undocumented) + phoneNumber: string; +} + +// @public (undocumented) +export interface PhoneNumberExtensionOutputValue { + // (undocumented) + countryCode?: string; + // (undocumented) + extension?: string; + // (undocumented) + phoneNumber?: string; +} + +// @public (undocumented) +export type PhoneNumberField = { + type: 'PHONE_NUMBER'; + key: string; + label: string; + required: boolean; + defaultCountryCode: string | null; + validatePhoneNumber: boolean; +}; + +// @public (undocumented) +export interface PhoneNumberInputValue { + // (undocumented) + countryCode: string; + // (undocumented) + phoneNumber: string; +} + +// @public (undocumented) +export interface PhoneNumberOutputValue { + // (undocumented) + countryCode?: string; + // (undocumented) + phoneNumber?: string; +} + +// @public +export type Poller = () => Promise; + +// @public (undocumented) +export type PollingCollector = AutoCollector< + 'SingleValueAutoCollector', + 'PollingCollector', + string, + PollingOutputValue +>; + +// @public (undocumented) +export type PollingField = { + type: 'POLLING'; + key: string; + pollInterval: number; + pollRetries: number; + pollChallengeStatus?: boolean; + challenge?: string; +}; + +// @public (undocumented) +export interface PollingOutputValue { + // (undocumented) + challenge?: string; + // (undocumented) + pollChallengeStatus?: boolean; + // (undocumented) + pollInterval: number; + // (undocumented) + pollRetries: number; + // (undocumented) + retriesRemaining?: number; +} + +// @public (undocumented) +export type PollingStatus = PollingStatusContinue | PollingStatusChallenge; + +// @public (undocumented) +export type PollingStatusChallenge = + | PollingStatusChallengeComplete + | 'expired' + | 'timedOut' + | 'error'; + +// @public (undocumented) +export type PollingStatusChallengeComplete = + | 'approved' + | 'denied' + | 'continue' + | CustomPollingStatus; + +// @public (undocumented) +export type PollingStatusContinue = 'continue' | 'timedOut'; + +// @public (undocumented) +export type ProtectCollector = AutoCollector< + 'SingleValueAutoCollector', + 'ProtectCollector', + string, + ProtectOutputValue +>; + +// @public (undocumented) +export type ProtectField = { + type: 'PROTECT'; + key: string; + behavioralDataCollection: boolean; + universalDeviceIdentification: boolean; +}; + +// @public +export interface ProtectOutputValue { + // (undocumented) + behavioralDataCollection: boolean; + // (undocumented) + universalDeviceIdentification: boolean; +} + +// @public +export interface QrCodeCollector extends NoValueCollectorBase<'QrCodeCollector'> { + // (undocumented) + output: NoValueCollectorBase<'QrCodeCollector'>['output'] & { + src: string; + }; +} + +// @public (undocumented) +export type QrCodeField = { + type: 'QR_CODE'; + key: string; + content: string; + fallbackText?: string; +}; + +// @public +export interface ReadOnlyCollector extends NoValueCollectorBase<'ReadOnlyCollector'> { + // (undocumented) + output: NoValueCollectorBase<'ReadOnlyCollector'>['output'] & { + content: string; + title?: string; + }; +} + +// @public (undocumented) +export type ReadOnlyField = { + type: 'LABEL'; + content: string; + richContent?: RichContent; + key?: string; +}; + +// @public (undocumented) +export type ReadOnlyFields = ReadOnlyField | QrCodeField | AgreementField | ImageField; + +// @public (undocumented) +export type RedirectField = { + type: 'SOCIAL_LOGIN_BUTTON'; + key: string; + label: string; + links: Links; +}; + +// @public (undocumented) +export type RedirectFields = RedirectField; + +export { RequestMiddleware }; + +// @public +export type RichContent = { + content: string; + replacements?: Record; +}; + +// @public +export interface RichContentLink { + // (undocumented) + href: string; + // (undocumented) + key: string; + // (undocumented) + target?: '_self' | '_blank'; + // (undocumented) + type: 'link'; + // (undocumented) + value: string; +} + +// @public +export type RichContentReplacement = { + type: 'link'; + value: string; + href: string; + target?: '_self' | '_blank'; +}; + +// @public +export interface RichTextCollector extends NoValueCollectorBase<'RichTextCollector'> { + // (undocumented) + output: NoValueCollectorBase<'RichTextCollector'>['output'] & { + content: string; + richContent: CollectorRichContent; + }; +} + +// @public (undocumented) +export interface SelectorOption { + // (undocumented) + label: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export type SingleCheckboxField = { + type: 'SINGLE_CHECKBOX'; + inputType: 'BOOLEAN'; + key: string; + label: string; + required?: boolean; + errorMessage?: string; + appearance: string; + richContent?: RichContent; +}; + +// @public (undocumented) +export type SingleSelectCollector = SingleSelectCollectorWithValue<'SingleSelectCollector'>; + +// @public (undocumented) +export interface SingleSelectCollectorNoValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface SingleSelectCollectorWithValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: string | number | boolean; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleSelectField = { + inputType: 'SINGLE_SELECT'; + key: string; + label: string; + options: { + label: string; + value: string; + }[]; + required?: boolean; + type: 'RADIO' | 'DROPDOWN'; +}; + +// @public (undocumented) +export type SingleValueAutoCollector = AutoCollector< + 'SingleValueAutoCollector', + 'SingleValueAutoCollector', + string +>; + +// @public (undocumented) +export type SingleValueAutoCollectorTypes = + | 'SingleValueAutoCollector' + | 'ProtectCollector' + | 'PollingCollector'; + +// @public +export type SingleValueCollector = + | SingleValueCollectorWithValue + | SingleValueCollectorNoValue; + +// @public (undocumented) +export interface SingleValueCollectorNoValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleValueCollectors = + | PasswordCollector + | ValidatedPasswordCollector + | SingleSelectCollector + | TextCollector + | ValidatedTextCollector + | BooleanCollector + | ValidatedBooleanCollector + | SingleValueCollectorWithValue<'SingleValueCollector'>; + +// @public +export type SingleValueCollectorTypes = + | 'PasswordCollector' + | 'ValidatedPasswordCollector' + | 'BooleanCollector' + | 'ValidatedBooleanCollector' + | 'SingleValueCollector' + | 'SingleSelectCollector' + | 'SingleSelectObjectCollector' + | 'TextCollector' + | 'ValidatedTextCollector'; + +// @public (undocumented) +export interface SingleValueCollectorWithValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: V; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleValueFields = + | StandardField + | PasswordField + | ValidatedField + | SingleCheckboxField + | SingleSelectField + | ProtectField; + +// @public (undocumented) +export type StandardField = { + type: 'TEXT' | 'SUBMIT_BUTTON' | 'FLOW_BUTTON' | 'FLOW_LINK' | 'BUTTON'; + key: string; + label: string; + required?: boolean; +}; + +// @public (undocumented) +export interface StartNode { + // (undocumented) + cache: null; + // (undocumented) + client: { + status: 'start'; + }; + // (undocumented) + error: DaVinciError | null; + // (undocumented) + server: { + status: 'start'; + }; + // (undocumented) + status: 'start'; +} + +// @public (undocumented) +export interface StartOptions { + // (undocumented) + query: Query; +} + +// @public (undocumented) +export type SubmitCollector = ActionCollectorNoUrl<'SubmitCollector'>; + +// @public (undocumented) +export interface SuccessNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + authorization?: { + code?: string; + state?: string; + }; + status: 'success'; + } | null; + // (undocumented) + error: null; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + session?: string; + status: 'success'; + }; + // (undocumented) + status: 'success'; +} + +// @public (undocumented) +export type TextCollector = SingleValueCollectorWithValue<'TextCollector'>; + +// @public (undocumented) +export interface ThrownQueryError { + // (undocumented) + error: FetchBaseQueryError; + // (undocumented) + isHandledError: boolean; + // (undocumented) + meta: FetchBaseQueryMeta; +} + +// @public +export type UnknownCollector = { + category: 'UnknownCollector'; + error: string | null; + type: 'UnknownCollector'; + id: string; + name: string; + output: { + key: string; + label: string; + type: string; + }; +}; + +// @public (undocumented) +export type UnknownField = Record; + +// @public +export type UpdatableCollectors = + | SingleValueCollectors + | MultiSelectCollector + | ObjectValueCollectors + | AutoCollectors; + +// @public (undocumented) +export const updateCollectorValues: ActionCreatorWithPayload< + { + id: string; + value: CollectorValueTypes; + index?: number; + }, + string +>; + +// @public +export type Updater = ( + value: CollectorValueType, + index?: number, +) => InternalErrorResponse | null; + +// @public (undocumented) +export interface ValidatedBooleanCollector extends ValidatedSingleValueCollectorWithValue< + 'ValidatedBooleanCollector', + boolean +> { + // (undocumented) + output: ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean>['output'] & { + appearance: string; + richContent?: CollectorRichContent; + }; +} + +// @public +export type ValidatedCollectors = + | ValidatedTextCollector + | ValidatedBooleanCollector + | ValidatedPasswordCollector + | ObjectValueCollectors + | MultiValueCollectors + | AutoCollectors; + +// @public (undocumented) +export type ValidatedField = { + type: 'TEXT'; + key: string; + label: string; + required: boolean; + validation: { + regex: string; + errorMessage: string; + }; +}; + +// @public (undocumented) +export interface ValidatedPasswordCollector { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + validation: PasswordPolicy; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + verify: boolean; + }; + // (undocumented) + type: 'ValidatedPasswordCollector'; +} + +// @public (undocumented) +export interface ValidatedSingleValueCollectorWithValue< + T extends SingleValueCollectorTypes, + V = string, +> { + // (undocumented) + category: 'ValidatedSingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + type: string; + validation: (ValidationRequired | ValidationRegex)[]; + value: V; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: V; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ValidatedTextCollector = ValidatedSingleValueCollectorWithValue<'TextCollector'>; + +// @public (undocumented) +export interface ValidationPhoneNumber { + // (undocumented) + message: string; + // (undocumented) + rule: boolean; + // (undocumented) + type: 'validatePhoneNumber'; +} + +// @public (undocumented) +export interface ValidationRegex { + // (undocumented) + message: string; + // (undocumented) + rule: string; + // (undocumented) + type: 'regex'; +} + +// @public (undocumented) +export interface ValidationRequired { + // (undocumented) + message: string; + // (undocumented) + rule: boolean; + // (undocumented) + type: 'required'; +} + +// @public +export type Validator = ( + value: CollectorValueType, +) => + | string[] + | { + error: { + message: string; + type: string; + }; + type: string; + }; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/davinci-client/api-report/davinci-client.types.api.md b/packages/davinci-client/api-report/davinci-client.types.api.md index d498f3a14f..79eac2bd49 100644 --- a/packages/davinci-client/api-report/davinci-client.types.api.md +++ b/packages/davinci-client/api-report/davinci-client.types.api.md @@ -1,2013 +1,2439 @@ -## API Report File for "@forgerock/davinci-client" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts - -import { ActionCreatorWithPayload } from '@reduxjs/toolkit'; -import { ActionTypes } from '@forgerock/sdk-request-middleware'; -import { CustomLogger } from '@forgerock/sdk-logger'; -import type { DaVinciConfig } from '@forgerock/sdk-types'; -import { FetchBaseQueryError } from '@reduxjs/toolkit/query'; -import type { FetchBaseQueryMeta } from '@reduxjs/toolkit/query'; -import { GenericError } from '@forgerock/sdk-types'; -import { LogLevel } from '@forgerock/sdk-logger'; -import type { MutationResultSelectorResult } from '@reduxjs/toolkit/query'; -import { QueryStatus } from '@reduxjs/toolkit/query'; -import { Reducer } from '@reduxjs/toolkit'; -import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; -import { SerializedError } from '@reduxjs/toolkit'; -import { Unsubscribe } from '@reduxjs/toolkit'; - -// @public (undocumented) -export type ActionCollector = ActionCollectorNoUrl | ActionCollectorWithUrl; - -// @public (undocumented) -export interface ActionCollectorNoUrl { - // (undocumented) - category: 'ActionCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ActionCollectors = ActionCollectorWithUrl<'IdpCollector'> | ActionCollectorNoUrl<'ActionCollector'> | ActionCollectorNoUrl<'FlowCollector'> | ActionCollectorNoUrl<'SubmitCollector'>; - -// @public -export type ActionCollectorTypes = 'FlowCollector' | 'SubmitCollector' | 'IdpCollector' | 'ActionCollector'; - -// @public (undocumented) -export interface ActionCollectorWithUrl { - // (undocumented) - category: 'ActionCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - url?: string | null; - }; - // (undocumented) - type: T; -} - -export { ActionTypes } - -// @public (undocumented) -export type AgreementField = { - type: 'AGREEMENT'; - key: string; - content: string; - titleEnabled: boolean; - title?: string; - agreement: { - id: string; - useDynamicAgreement: boolean; - }; - enabled: boolean; -}; - -// @public (undocumented) -export interface AssertionValue extends Omit { - // (undocumented) - rawId: string; - // (undocumented) - response: { - clientDataJSON: string; - authenticatorData: string; - signature: string; - userHandle: string | null; - }; -} - -// @public (undocumented) -export interface AttestationValue extends Omit { - // (undocumented) - rawId: string; - // (undocumented) - response: { - clientDataJSON: string; - attestationObject: string; - }; -} - -// @public (undocumented) -export interface AutoCollector> { - // (undocumented) - category: C; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: IV; - type: string; - validation?: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - type: string; - config: OV; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type AutoCollectorCategories = 'SingleValueAutoCollector' | 'ObjectValueAutoCollector'; - -// @public (undocumented) -export type AutoCollectors = ProtectCollector | FidoRegistrationCollector | FidoAuthenticationCollector | MetadataCollector | PollingCollector | SingleValueAutoCollector | ObjectValueAutoCollector; - -// @public (undocumented) -export type AutoCollectorTypes = SingleValueAutoCollectorTypes | ObjectValueAutoCollectorTypes; - -// @public (undocumented) -export interface BooleanCollector extends SingleValueCollectorWithValue<'BooleanCollector', boolean> { - // (undocumented) - output: SingleValueCollectorWithValue<'BooleanCollector', boolean>['output'] & { - appearance: string; - richContent?: CollectorRichContent; - }; -} - -// @public (undocumented) -export type CollectorCategory = Collectors['category']; - -// @public (undocumented) -export interface CollectorErrors { - // (undocumented) - code: string; - // (undocumented) - message: string; - // (undocumented) - target: string; -} - -// @public -export interface CollectorRichContent { - // (undocumented) - content: string; - // (undocumented) - replacements: RichContentLink[]; -} - -// @public (undocumented) -export type Collectors = FlowCollector | MetadataCollector | PasswordCollector | ValidatedPasswordCollector | TextCollector | BooleanCollector | ValidatedBooleanCollector | SingleSelectCollector | IdpCollector | SubmitCollector | ActionCollector<'ActionCollector'> | SingleValueCollector<'SingleValueCollector'> | MultiSelectCollector | DeviceAuthenticationCollector | DeviceRegistrationCollector | PhoneNumberCollector | PhoneNumberExtensionCollector | ReadOnlyCollector | RichTextCollector | ValidatedTextCollector | ProtectCollector | PollingCollector | FidoRegistrationCollector | FidoAuthenticationCollector | QrCodeCollector | ImageCollector | UnknownCollector; - -// @public -export type CollectorValueType = T extends { - type: 'PasswordCollector'; -} | { - type: 'ValidatedPasswordCollector'; -} | { - type: 'SingleSelectCollector'; -} | { - type: 'DeviceRegistrationCollector'; -} | { - type: 'DeviceAuthenticationCollector'; -} | { - type: 'ProtectCollector'; -} | { - type: 'PollingCollector'; -} ? string : T extends { - type: 'TextCollector'; - category: 'SingleValueCollector'; -} ? string : T extends { - type: 'TextCollector'; - category: 'ValidatedSingleValueCollector'; -} ? string : T extends { - type: 'BooleanCollector'; -} | { - type: 'ValidatedBooleanCollector'; -} ? boolean : T extends { - type: 'MultiSelectCollector'; -} ? string | string[] : T extends { - type: 'PhoneNumberCollector'; -} ? PhoneNumberInputValue : T extends { - type: 'PhoneNumberExtensionCollector'; -} ? PhoneNumberExtensionInputValue : T extends { - type: 'FidoRegistrationCollector'; -} ? FidoRegistrationInputValue | GenericError : T extends { - type: 'FidoAuthenticationCollector'; -} ? FidoAuthenticationInputValue | GenericError : T extends { - type: 'MetadataCollector'; -} ? Record | MetadataError : T extends { - category: 'SingleValueCollector'; -} ? string : T extends { - category: 'ValidatedSingleValueCollector'; -} ? string : T extends { - category: 'SingleValueAutoCollector'; -} ? string : T extends { - category: 'MultiValueCollector'; -} ? string | string[] : T extends { - category: 'ActionCollector'; -} ? never : T extends { - category: 'NoValueCollector'; -} ? never : CollectorValueTypes; - -// @public -export type CollectorValueTypes = string | string[] | boolean | PhoneNumberInputValue | PhoneNumberExtensionInputValue | FidoRegistrationInputValue | FidoAuthenticationInputValue | MetadataError | GenericError; - -// @public (undocumented) -export type ComplexValueFields = DeviceAuthenticationField | DeviceRegistrationField | PhoneNumberField | PhoneNumberExtensionField | FidoRegistrationField | FidoAuthenticationField | PollingField | MetadataField; - -// @public (undocumented) -export interface ContinueNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'continue'; - }; - // (undocumented) - error: null; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - eventName?: string; - status: 'continue'; - }; - // (undocumented) - status: 'continue'; -} - -export { CustomLogger } - -// @public -export type CustomPollingStatus = string & {}; - -// @public -export function davinci(input: { - config: DaVinciConfig; - requestMiddleware?: RequestMiddleware[]; - logger?: { - level: LogLevel; - custom?: CustomLogger; - }; -}): Promise<{ - subscribe: (listener: () => void) => Unsubscribe; - externalIdp: () => (() => Promise); - flow: (action: DaVinciAction) => InitFlow; - next: (args?: DaVinciRequest) => Promise; - resume: (input: { - continueToken: string; - }) => Promise; - start: (options?: StartOptions | undefined) => Promise; - update: (collector: T) => Updater; - validate: (collector: SingleValueCollectors | ObjectValueCollectors | MultiValueCollectors | AutoCollectors) => Validator; - pollStatus: (collector: PollingCollector) => Poller; - getClient: () => { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: "continue"; - } | { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: "error"; - } | { - status: "failure"; - } | { - status: "start"; - } | { - authorization?: { - code?: string; - state?: string; - }; - status: "success"; - } | null; - getCollectors: () => Collectors[]; - getError: () => DaVinciError | null; - getErrorCollectors: () => CollectorErrors[]; - getNode: () => ContinueNode | ErrorNode | FailureNode | StartNode | SuccessNode; - getServer: () => { - _links?: Links; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - eventName?: string; - status: "continue"; - } | { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: "error"; - } | { - _links?: Links; - eventName?: string; - href?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: "failure"; - } | { - status: "start"; - } | { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - session?: string; - status: "success"; - } | null; - cache: { - getLatestResponse: () => ({ - status: QueryStatus.fulfilled; - } & Omit<{ - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, "data" | "fulfilledTimeStamp"> & Required> & { - error: undefined; - } & { - status: QueryStatus.fulfilled; - isUninitialized: false; - isLoading: false; - isSuccess: true; - isError: false; - }) | ({ - status: QueryStatus.rejected; - } & Omit<{ - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, "error"> & Required> & { - status: QueryStatus.rejected; - isUninitialized: false; - isLoading: false; - isSuccess: false; - isError: true; - }) | { - error: { - message: string; - type: string; - }; - }; - getResponseWithId: (requestId: string) => ({ - status: QueryStatus.fulfilled; - } & Omit<{ - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, "data" | "fulfilledTimeStamp"> & Required> & { - error: undefined; - } & { - status: QueryStatus.fulfilled; - isUninitialized: false; - isLoading: false; - isSuccess: true; - isError: false; - }) | ({ - status: QueryStatus.rejected; - } & Omit<{ - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, "error"> & Required> & { - status: QueryStatus.rejected; - isUninitialized: false; - isLoading: false; - isSuccess: false; - isError: true; - }) | { - error: { - message: string; - type: string; - }; - }; - }; -}>; - -// @public -export interface DaVinciAction { - // (undocumented) - action: string; -} - -// @public -export interface DaVinciBaseResponse { - // (undocumented) - capabilityName?: string; - // (undocumented) - companyId?: string; - // (undocumented) - connectionId?: string; - // (undocumented) - connectorId?: string; - // (undocumented) - id?: string; - // (undocumented) - interactionId?: string; - // (undocumented) - interactionToken?: string; - // (undocumented) - isResponseCompatibleWithMobileAndWebSdks?: boolean; - // (undocumented) - status?: string; -} - -// @public -export type DaVinciCacheEntry = { - data?: DaVinciBaseResponse; - error?: { - data: DaVinciBaseResponse; - status: number; - }; -} & { - data?: any; - error?: any; -} & MutationResultSelectorResult; - -// @public (undocumented) -export type DavinciClient = Awaited>; - -export { DaVinciConfig } - -// @public (undocumented) -export interface DaVinciError extends Omit { - // (undocumented) - collectors?: CollectorErrors[]; - // (undocumented) - internalHttpStatus?: number; - // (undocumented) - message: string; - // (undocumented) - status: 'error' | 'failure' | 'unknown'; -} - -// @public (undocumented) -export interface DaVinciErrorCacheEntry { - // (undocumented) - endpointName: 'next' | 'flow' | 'start'; - // (undocumented) - error: { - data: T; - }; - // (undocumented) - fulfilledTimeStamp: number; - // (undocumented) - isError: boolean; - // (undocumented) - isLoading: boolean; - // (undocumented) - isSuccess: boolean; - // (undocumented) - isUninitialized: boolean; - // (undocumented) - requestId: string; - // (undocumented) - startedTimeStamp: number; - // (undocumented) - status: 'fulfilled' | 'pending' | 'rejected'; -} - -// @public (undocumented) -export interface DavinciErrorResponse extends DaVinciBaseResponse { - // (undocumented) - cause?: string | null; - // (undocumented) - code: string | number; - // (undocumented) - details?: ErrorDetail[]; - // (undocumented) - doNotSendToOE?: boolean; - // (undocumented) - error?: { - code?: string; - message?: string; - }; - // (undocumented) - errorCategory?: string; - // (undocumented) - errorMessage?: string; - // (undocumented) - expected?: boolean; - // (undocumented) - httpResponseCode: number; - // (undocumented) - isErrorCustomized?: boolean; - // (undocumented) - message: string; - // (undocumented) - metricAttributes?: { - [key: string]: unknown; - }; -} - -// @public (undocumented) -export interface DaVinciFailureResponse extends DaVinciBaseResponse { - // (undocumented) - error?: { - code?: string; - message?: string; - [key: string]: unknown; - }; -} - -// @public (undocumented) -export type DaVinciField = ComplexValueFields | MultiValueFields | ReadOnlyFields | RedirectFields | SingleValueFields; - -// @public -export interface DaVinciNextResponse extends DaVinciBaseResponse { - // (undocumented) - eventName?: string; - // (undocumented) - form?: { - name?: string; - description?: string; - components?: { - fields?: DaVinciField[]; - }; - }; - // (undocumented) - formData?: { - value?: { - [key: string]: string; - }; - }; - // (undocumented) - _links?: Links; -} - -// @public -export interface DaVinciPollResponse extends DaVinciBaseResponse { - // (undocumented) - eventName?: string; - // (undocumented) - _links?: Links; - // (undocumented) - success?: boolean; -} - -// @public (undocumented) -export interface DaVinciRequest { - // (undocumented) - eventName: string; - // (undocumented) - id: string; - // (undocumented) - interactionId: string; - // (undocumented) - parameters: { - eventType: 'submit' | 'action' | 'polling'; - data: { - actionKey: string; - formData?: Record; - }; - }; -} - -// @public -export type DaVinciRequestValueTypes = string | number | boolean | (string | number | boolean)[] | DeviceValue | PhoneNumberInputValue | FidoRegistrationInputValue | FidoAuthenticationInputValue | MetadataError | GenericError; - -// @public (undocumented) -export interface DaVinciSuccessResponse extends DaVinciBaseResponse { - // (undocumented) - authorizeResponse?: OAuthDetails; - // (undocumented) - environment: { - id: string; - [key: string]: unknown; - }; - // (undocumented) - _links?: Links; - // (undocumented) - resetCookie?: boolean; - // (undocumented) - session?: { - id?: string; - [key: string]: unknown; - }; - // (undocumented) - sessionToken?: string; - // (undocumented) - sessionTokenMaxAge?: number; - // (undocumented) - status: string; - // (undocumented) - subFlowSettings?: { - cssLinks?: unknown[]; - cssUrl?: unknown; - jsLinks?: unknown[]; - loadingScreenSettings?: unknown; - reactSkUrl?: unknown; - }; - // (undocumented) - success: true; -} - -// @public (undocumented) -export type DeviceAuthenticationCollector = ObjectOptionsCollectorWithObjectValue<'DeviceAuthenticationCollector', DeviceValue>; - -// @public (undocumented) -export type DeviceAuthenticationField = { - type: 'DEVICE_AUTHENTICATION'; - key: string; - label: string; - options: { - type: string; - iconSrc: string; - title: string; - id: string; - default: boolean; - description: string; - }[]; - required: boolean; -}; - -// @public (undocumented) -export interface DeviceOptionNoDefault { - // (undocumented) - content: string; - // (undocumented) - key: string; - // (undocumented) - label: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export interface DeviceOptionWithDefault { - // (undocumented) - content: string; - // (undocumented) - default: boolean; - // (undocumented) - key: string; - // (undocumented) - label: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export type DeviceRegistrationCollector = ObjectOptionsCollectorWithStringValue<'DeviceRegistrationCollector', string>; - -// @public (undocumented) -export type DeviceRegistrationField = { - type: 'DEVICE_REGISTRATION'; - key: string; - label: string; - options: { - type: string; - iconSrc: string; - title: string; - description: string; - }[]; - required: boolean; -}; - -// @public (undocumented) -export interface DeviceValue { - // (undocumented) - id: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export interface ErrorDetail { - // (undocumented) - message?: string; - // (undocumented) - rawResponse?: { - _embedded?: { - users?: Array; - }; - code?: string; - count?: number; - details?: NestedErrorDetails[]; - id?: string; - message?: string; - size?: number; - userFilter?: string; - [key: string]: unknown; - }; - // (undocumented) - statusCode?: number; -} - -// @public (undocumented) -export interface ErrorNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'error'; - }; - // (undocumented) - error: DaVinciError; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'error'; - } | null; - // (undocumented) - status: 'error'; -} - -// @public (undocumented) -export interface FailureNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - status: 'failure'; - }; - // (undocumented) - error: DaVinciError; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - href?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'failure'; - } | null; - // (undocumented) - status: 'failure'; -} - -// @public (undocumented) -export type FidoAuthenticationCollector = AutoCollector<'ObjectValueAutoCollector', 'FidoAuthenticationCollector', FidoAuthenticationInputValue | GenericError, FidoAuthenticationOutputValue>; - -// @public (undocumented) -export type FidoAuthenticationField = { - type: 'FIDO2'; - key: string; - label: string; - publicKeyCredentialRequestOptions: FidoAuthenticationOptions; - action: 'AUTHENTICATE'; - trigger: string; - required: boolean; -}; - -// @public (undocumented) -export interface FidoAuthenticationInputValue { - // (undocumented) - assertionValue?: AssertionValue; -} - -// @public (undocumented) -export interface FidoAuthenticationOptions extends Omit { - // (undocumented) - allowCredentials?: { - id: number[]; - transports?: AuthenticatorTransport[]; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - challenge: number[]; -} - -// @public (undocumented) -export interface FidoAuthenticationOutputValue { - // (undocumented) - action: 'AUTHENTICATE'; - // (undocumented) - publicKeyCredentialRequestOptions: FidoAuthenticationOptions; - // (undocumented) - trigger: string; -} - -// @public (undocumented) -export interface FidoClient { - authenticate: (options: FidoAuthenticationOptions) => Promise; - register: (options: FidoRegistrationOptions) => Promise; -} - -// @public -export type FidoErrorCode = 'NotAllowedError' | 'AbortError' | 'InvalidStateError' | 'NotSupportedError' | 'SecurityError' | 'TimeoutError' | 'UnknownError'; - -// @public (undocumented) -export type FidoRegistrationCollector = AutoCollector<'ObjectValueAutoCollector', 'FidoRegistrationCollector', FidoRegistrationInputValue | GenericError, FidoRegistrationOutputValue>; - -// @public (undocumented) -export type FidoRegistrationField = { - type: 'FIDO2'; - key: string; - label: string; - publicKeyCredentialCreationOptions: FidoRegistrationOptions; - action: 'REGISTER'; - trigger: string; - required: boolean; -}; - -// @public (undocumented) -export interface FidoRegistrationInputValue { - // (undocumented) - attestationValue?: AttestationValue; -} - -// @public (undocumented) -export interface FidoRegistrationOptions extends Omit { - // (undocumented) - challenge: number[]; - // (undocumented) - excludeCredentials?: { - id: number[]; - transports?: AuthenticatorTransport[]; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - pubKeyCredParams: { - alg: string | number; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - user: { - id: number[]; - name: string; - displayName: string; - }; -} - -// @public (undocumented) -export interface FidoRegistrationOutputValue { - // (undocumented) - action: 'REGISTER'; - // (undocumented) - publicKeyCredentialCreationOptions: FidoRegistrationOptions; - // (undocumented) - trigger: string; -} - -// @public (undocumented) -export type FlowCollector = ActionCollectorNoUrl<'FlowCollector'>; - -// @public (undocumented) -export type FlowNode = ContinueNode | ErrorNode | StartNode | SuccessNode | FailureNode; - -// @public -export type GetClient = StartNode['client'] | ContinueNode['client'] | ErrorNode['client'] | SuccessNode['client'] | FailureNode['client']; - -// @public (undocumented) -export type IdpCollector = ActionCollectorWithUrl<'IdpCollector'>; - -// @public -export interface ImageCollector extends NoValueCollectorBase<'ImageCollector'> { - // (undocumented) - output: NoValueCollectorBase<'ImageCollector'>['output'] & { - src: string; - alt: string; - href?: string; - }; -} - -// @public (undocumented) -export type ImageField = { - type: 'IMAGE'; - key: string; - description: string; - imageUrl: string; - hyperlinkUrl?: string; -}; - -// @public (undocumented) -export type InferActionCollectorType = T extends 'IdpCollector' ? IdpCollector : T extends 'SubmitCollector' ? SubmitCollector : T extends 'FlowCollector' ? FlowCollector : ActionCollectorWithUrl<'ActionCollector'> | ActionCollectorNoUrl<'ActionCollector'>; - -// @public -export type InferAutoCollectorType = T extends 'ProtectCollector' ? ProtectCollector : T extends 'PollingCollector' ? PollingCollector : T extends 'FidoRegistrationCollector' ? FidoRegistrationCollector : T extends 'FidoAuthenticationCollector' ? FidoAuthenticationCollector : T extends 'MetadataCollector' ? MetadataCollector : T extends 'ObjectValueAutoCollector' ? ObjectValueAutoCollector : SingleValueAutoCollector; - -// @public -export type InferMultiValueCollectorType = T extends 'MultiSelectCollector' ? MultiValueCollectorWithValue<'MultiSelectCollector'> : MultiValueCollectorWithValue<'MultiValueCollector'> | MultiValueCollectorNoValue<'MultiValueCollector'>; - -// @public -export type InferNoValueCollectorType = T extends 'ReadOnlyCollector' ? ReadOnlyCollector : T extends 'RichTextCollector' ? RichTextCollector : T extends 'QrCodeCollector' ? QrCodeCollector : T extends 'ImageCollector' ? ImageCollector : NoValueCollectorBase<'NoValueCollector'>; - -// @public -export type InferSingleValueCollectorType = T extends 'TextCollector' ? TextCollector : T extends 'SingleSelectCollector' ? SingleSelectCollector : T extends 'ValidatedTextCollector' ? ValidatedTextCollector : T extends 'PasswordCollector' ? PasswordCollector : T extends 'ValidatedPasswordCollector' ? ValidatedPasswordCollector : T extends 'BooleanCollector' ? BooleanCollector : T extends 'ValidatedBooleanCollector' ? ValidatedBooleanCollector : SingleValueCollectorWithValue<'SingleValueCollector'> | SingleValueCollectorNoValue<'SingleValueCollector'>; - -// @public (undocumented) -export type InferValueObjectCollectorType = T extends 'DeviceAuthenticationCollector' ? DeviceAuthenticationCollector : T extends 'DeviceRegistrationCollector' ? DeviceRegistrationCollector : T extends 'PhoneNumberCollector' ? PhoneNumberCollector : T extends 'PhoneNumberExtensionCollector' ? PhoneNumberExtensionCollector : ObjectOptionsCollectorWithObjectValue<'ObjectValueCollector'> | ObjectOptionsCollectorWithStringValue<'ObjectValueCollector'>; - -// @public (undocumented) -export type InitFlow = () => Promise; - -// @public (undocumented) -export interface InternalErrorResponse { - // (undocumented) - error: Omit & { - message: string; - }; - // (undocumented) - type: 'internal_error'; -} - -// @public (undocumented) -export interface Links { - // (undocumented) - [key: string]: { - href?: string; - }; -} - -export { LogLevel } - -// @public (undocumented) -export type MetadataCollector = AutoCollector<'ObjectValueAutoCollector', 'MetadataCollector', MetadataCollectorInputValue, Record>; - -// @public (undocumented) -export type MetadataCollectorInputValue = Record | MetadataError; - -// @public -export interface MetadataError { - // (undocumented) - code: string; - // (undocumented) - message: string; -} - -// @public (undocumented) -export type MetadataField = { - type: 'METADATA'; - key: string; - payload: Record; -}; - -// @public (undocumented) -export type MultiSelectCollector = MultiValueCollectorWithValue<'MultiSelectCollector'>; - -// @public (undocumented) -export type MultiSelectField = { - inputType: 'MULTI_SELECT'; - key: string; - label: string; - options: { - label: string; - value: string; - }[]; - required?: boolean; - type: 'CHECKBOX' | 'COMBOBOX'; -}; - -// @public (undocumented) -export type MultiValueCollector = MultiValueCollectorWithValue | MultiValueCollectorNoValue; - -// @public (undocumented) -export interface MultiValueCollectorNoValue { - // (undocumented) - category: 'MultiValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string[]; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type MultiValueCollectors = MultiValueCollectorWithValue<'MultiValueCollector'> | MultiValueCollectorWithValue<'MultiSelectCollector'>; - -// @public -export type MultiValueCollectorTypes = 'MultiSelectCollector' | 'MultiValueCollector'; - -// @public (undocumented) -export interface MultiValueCollectorWithValue { - // (undocumented) - category: 'MultiValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string[]; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: string[]; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type MultiValueFields = MultiSelectField; - -// @public -export interface NestedErrorDetails { - // (undocumented) - code?: string; - // (undocumented) - innerError?: { - history?: string; - unsatisfiedRequirements?: string[]; - failuresRemaining?: number; - }; - // (undocumented) - message?: string; - // (undocumented) - target?: string; -} - -// @public -export const nextCollectorValues: ActionCreatorWithPayload< { -fields: DaVinciField[]; -formData: { -value: Record; -}; -}, string>; - -// @public -export const nodeCollectorReducer: Reducer & { - getInitialState: () => Collectors[]; -}; - -// @public (undocumented) -export type NodeStates = StartNode | ContinueNode | ErrorNode | SuccessNode | FailureNode; - -// @public (undocumented) -export type NoValueCollector = InferNoValueCollectorType; - -// @public (undocumented) -export interface NoValueCollectorBase { - // (undocumented) - category: 'NoValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type NoValueCollectors = NoValueCollectorBase<'NoValueCollector'> | ReadOnlyCollector | RichTextCollector | QrCodeCollector | ImageCollector; - -// @public -export type NoValueCollectorTypes = 'ReadOnlyCollector' | 'RichTextCollector' | 'NoValueCollector' | 'QrCodeCollector' | 'ImageCollector'; - -// @public -export interface OAuthDetails { - // (undocumented) - [key: string]: unknown; - // (undocumented) - code?: string; - // (undocumented) - state?: string; -} - -// @public (undocumented) -export interface ObjectOptionsCollectorWithObjectValue, D = Record> { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: DeviceOptionWithDefault[]; - value?: D | null; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface ObjectOptionsCollectorWithStringValue { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: DeviceOptionNoDefault[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ObjectValueAutoCollector = AutoCollector<'ObjectValueAutoCollector', 'ObjectValueAutoCollector', Record>; - -// @public (undocumented) -export type ObjectValueAutoCollectorTypes = 'ObjectValueAutoCollector' | 'FidoRegistrationCollector' | 'FidoAuthenticationCollector' | 'MetadataCollector'; - -// @public (undocumented) -export type ObjectValueCollector = ObjectOptionsCollectorWithObjectValue | ObjectOptionsCollectorWithStringValue | ObjectValueCollectorWithObjectValue; - -// @public (undocumented) -export type ObjectValueCollectors = DeviceAuthenticationCollector | DeviceRegistrationCollector | PhoneNumberCollector | PhoneNumberExtensionCollector | ObjectOptionsCollectorWithObjectValue<'ObjectSelectCollector'> | ObjectOptionsCollectorWithStringValue<'ObjectSelectCollector'>; - -// @public -export type ObjectValueCollectorTypes = 'DeviceAuthenticationCollector' | 'DeviceRegistrationCollector' | 'PhoneNumberCollector' | 'PhoneNumberExtensionCollector' | 'ObjectOptionsCollector' | 'ObjectValueCollector' | 'ObjectSelectCollector'; - -// @public (undocumented) -export interface ObjectValueCollectorWithObjectValue, OV = Record> { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: IV; - type: string; - validation: (ValidationRequired | ValidationPhoneNumber)[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value?: OV | null; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface OutgoingQueryParams { - // (undocumented) - [key: string]: string | string[]; -} - -// @public (undocumented) -export interface PasswordCollector { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - verify: boolean; - }; - // (undocumented) - type: 'PasswordCollector'; -} - -// @public -export type PasswordField = { - type: 'PASSWORD' | 'PASSWORD_VERIFY'; - key: string; - label: string; - required?: boolean; - verify?: boolean; - passwordPolicy?: PasswordPolicy; -}; - -// @public -export interface PasswordPolicy { - // (undocumented) - createdAt?: string; - // (undocumented) - default?: boolean; - // (undocumented) - description?: string; - // (undocumented) - excludesCommonlyUsed?: boolean; - // (undocumented) - excludesProfileData?: boolean; - // (undocumented) - history?: { - count?: number; - retentionDays?: number; - }; - // (undocumented) - id?: string; - // (undocumented) - length?: { - min?: number; - max?: number; - }; - // (undocumented) - lockout?: { - failureCount?: number; - durationSeconds?: number; - }; - // (undocumented) - maxAgeDays?: number; - // (undocumented) - maxRepeatedCharacters?: number; - // (undocumented) - minAgeDays?: number; - // (undocumented) - minCharacters?: Record; - // (undocumented) - minUniqueCharacters?: number; - // (undocumented) - name?: string; - // (undocumented) - notSimilarToCurrent?: boolean; - // (undocumented) - populationCount?: number; - // (undocumented) - updatedAt?: string; -} - -// @public (undocumented) -export type PhoneNumberCollector = ObjectValueCollectorWithObjectValue<'PhoneNumberCollector', PhoneNumberInputValue, PhoneNumberOutputValue>; - -// @public (undocumented) -export interface PhoneNumberExtensionCollector { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: PhoneNumberExtensionInputValue; - type: string; - validation: (ValidationRequired | ValidationPhoneNumber)[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - extensionLabel: string; - value: PhoneNumberExtensionOutputValue; - }; - // (undocumented) - type: 'PhoneNumberExtensionCollector'; -} - -// @public (undocumented) -export type PhoneNumberExtensionField = PhoneNumberField & { - showExtension: boolean; - extensionLabel: string; -}; - -// @public (undocumented) -export interface PhoneNumberExtensionInputValue { - // (undocumented) - countryCode: string; - // (undocumented) - extension: string; - // (undocumented) - phoneNumber: string; -} - -// @public (undocumented) -export interface PhoneNumberExtensionOutputValue { - // (undocumented) - countryCode?: string; - // (undocumented) - extension?: string; - // (undocumented) - phoneNumber?: string; -} - -// @public (undocumented) -export type PhoneNumberField = { - type: 'PHONE_NUMBER'; - key: string; - label: string; - required: boolean; - defaultCountryCode: string | null; - validatePhoneNumber: boolean; -}; - -// @public (undocumented) -export interface PhoneNumberInputValue { - // (undocumented) - countryCode: string; - // (undocumented) - phoneNumber: string; -} - -// @public (undocumented) -export interface PhoneNumberOutputValue { - // (undocumented) - countryCode?: string; - // (undocumented) - phoneNumber?: string; -} - -// @public -export type Poller = () => Promise; - -// @public (undocumented) -export type PollingCollector = AutoCollector<'SingleValueAutoCollector', 'PollingCollector', string, PollingOutputValue>; - -// @public (undocumented) -export type PollingField = { - type: 'POLLING'; - key: string; - pollInterval: number; - pollRetries: number; - pollChallengeStatus?: boolean; - challenge?: string; -}; - -// @public (undocumented) -export interface PollingOutputValue { - // (undocumented) - challenge?: string; - // (undocumented) - pollChallengeStatus?: boolean; - // (undocumented) - pollInterval: number; - // (undocumented) - pollRetries: number; - // (undocumented) - retriesRemaining?: number; -} - -// @public (undocumented) -export type PollingStatus = PollingStatusContinue | PollingStatusChallenge; - -// @public (undocumented) -export type PollingStatusChallenge = PollingStatusChallengeComplete | 'expired' | 'timedOut' | 'error'; - -// @public (undocumented) -export type PollingStatusChallengeComplete = 'approved' | 'denied' | 'continue' | CustomPollingStatus; - -// @public (undocumented) -export type PollingStatusContinue = 'continue' | 'timedOut'; - -// @public (undocumented) -export type ProtectCollector = AutoCollector<'SingleValueAutoCollector', 'ProtectCollector', string, ProtectOutputValue>; - -// @public (undocumented) -export type ProtectField = { - type: 'PROTECT'; - key: string; - behavioralDataCollection: boolean; - universalDeviceIdentification: boolean; -}; - -// @public -export interface ProtectOutputValue { - // (undocumented) - behavioralDataCollection: boolean; - // (undocumented) - universalDeviceIdentification: boolean; -} - -// @public -export interface QrCodeCollector extends NoValueCollectorBase<'QrCodeCollector'> { - // (undocumented) - output: NoValueCollectorBase<'QrCodeCollector'>['output'] & { - src: string; - }; -} - -// @public (undocumented) -export type QrCodeField = { - type: 'QR_CODE'; - key: string; - content: string; - fallbackText?: string; -}; - -// @public -export interface ReadOnlyCollector extends NoValueCollectorBase<'ReadOnlyCollector'> { - // (undocumented) - output: NoValueCollectorBase<'ReadOnlyCollector'>['output'] & { - content: string; - title?: string; - }; -} - -// @public (undocumented) -export type ReadOnlyField = { - type: 'LABEL'; - content: string; - richContent?: RichContent; - key?: string; -}; - -// @public (undocumented) -export type ReadOnlyFields = ReadOnlyField | QrCodeField | AgreementField | ImageField; - -// @public (undocumented) -export type RedirectField = { - type: 'SOCIAL_LOGIN_BUTTON'; - key: string; - label: string; - links: Links; -}; - -// @public (undocumented) -export type RedirectFields = RedirectField; - -export { RequestMiddleware } - -// @public -export type RichContent = { - content: string; - replacements?: Record; -}; - -// @public -export interface RichContentLink { - // (undocumented) - href: string; - // (undocumented) - key: string; - // (undocumented) - target?: '_self' | '_blank'; - // (undocumented) - type: 'link'; - // (undocumented) - value: string; -} - -// @public -export type RichContentReplacement = { - type: 'link'; - value: string; - href: string; - target?: '_self' | '_blank'; -}; - -// @public -export interface RichTextCollector extends NoValueCollectorBase<'RichTextCollector'> { - // (undocumented) - output: NoValueCollectorBase<'RichTextCollector'>['output'] & { - content: string; - richContent: CollectorRichContent; - }; -} - -// @public (undocumented) -export interface SelectorOption { - // (undocumented) - label: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export type SingleCheckboxField = { - type: 'SINGLE_CHECKBOX'; - inputType: 'BOOLEAN'; - key: string; - label: string; - required?: boolean; - errorMessage?: string; - appearance: string; - richContent?: RichContent; -}; - -// @public (undocumented) -export type SingleSelectCollector = SingleSelectCollectorWithValue<'SingleSelectCollector'>; - -// @public (undocumented) -export interface SingleSelectCollectorNoValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface SingleSelectCollectorWithValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: string | number | boolean; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleSelectField = { - inputType: 'SINGLE_SELECT'; - key: string; - label: string; - options: { - label: string; - value: string; - }[]; - required?: boolean; - type: 'RADIO' | 'DROPDOWN'; -}; - -// @public (undocumented) -export type SingleValueAutoCollector = AutoCollector<'SingleValueAutoCollector', 'SingleValueAutoCollector', string>; - -// @public (undocumented) -export type SingleValueAutoCollectorTypes = 'SingleValueAutoCollector' | 'ProtectCollector' | 'PollingCollector'; - -// @public -export type SingleValueCollector = SingleValueCollectorWithValue | SingleValueCollectorNoValue; - -// @public (undocumented) -export interface SingleValueCollectorNoValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleValueCollectors = PasswordCollector | ValidatedPasswordCollector | SingleSelectCollector | TextCollector | ValidatedTextCollector | BooleanCollector | ValidatedBooleanCollector | SingleValueCollectorWithValue<'SingleValueCollector'>; - -// @public -export type SingleValueCollectorTypes = 'PasswordCollector' | 'ValidatedPasswordCollector' | 'BooleanCollector' | 'ValidatedBooleanCollector' | 'SingleValueCollector' | 'SingleSelectCollector' | 'SingleSelectObjectCollector' | 'TextCollector' | 'ValidatedTextCollector'; - -// @public (undocumented) -export interface SingleValueCollectorWithValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: V; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleValueFields = StandardField | PasswordField | ValidatedField | SingleCheckboxField | SingleSelectField | ProtectField; - -// @public (undocumented) -export type StandardField = { - type: 'TEXT' | 'SUBMIT_BUTTON' | 'FLOW_BUTTON' | 'FLOW_LINK' | 'BUTTON'; - key: string; - label: string; - required?: boolean; -}; - -// @public (undocumented) -export interface StartNode { - // (undocumented) - cache: null; - // (undocumented) - client: { - status: 'start'; - }; - // (undocumented) - error: DaVinciError | null; - // (undocumented) - server: { - status: 'start'; - }; - // (undocumented) - status: 'start'; -} - -// @public (undocumented) -export interface StartOptions { - // (undocumented) - query: Query; -} - -// @public (undocumented) -export type SubmitCollector = ActionCollectorNoUrl<'SubmitCollector'>; - -// @public (undocumented) -export interface SuccessNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - authorization?: { - code?: string; - state?: string; - }; - status: 'success'; - } | null; - // (undocumented) - error: null; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - session?: string; - status: 'success'; - }; - // (undocumented) - status: 'success'; -} - -// @public (undocumented) -export type TextCollector = SingleValueCollectorWithValue<'TextCollector'>; - -// @public (undocumented) -export interface ThrownQueryError { - // (undocumented) - error: FetchBaseQueryError; - // (undocumented) - isHandledError: boolean; - // (undocumented) - meta: FetchBaseQueryMeta; -} - -// @public -export type UnknownCollector = { - category: 'UnknownCollector'; - error: string | null; - type: 'UnknownCollector'; - id: string; - name: string; - output: { - key: string; - label: string; - type: string; - }; -}; - -// @public (undocumented) -export type UnknownField = Record; - -// @public -export type UpdatableCollectors = SingleValueCollectors | MultiSelectCollector | ObjectValueCollectors | AutoCollectors; - -// @public (undocumented) -export const updateCollectorValues: ActionCreatorWithPayload< { -id: string; -value: CollectorValueTypes; -index?: number; -}, string>; - -// @public -export type Updater = (value: CollectorValueType, index?: number) => InternalErrorResponse | null; - -// @public (undocumented) -export interface ValidatedBooleanCollector extends ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean> { - // (undocumented) - output: ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean>['output'] & { - appearance: string; - richContent?: CollectorRichContent; - }; -} - -// @public -export type ValidatedCollectors = ValidatedTextCollector | ValidatedBooleanCollector | ValidatedPasswordCollector | ObjectValueCollectors | MultiValueCollectors | AutoCollectors; - -// @public (undocumented) -export type ValidatedField = { - type: 'TEXT'; - key: string; - label: string; - required: boolean; - validation: { - regex: string; - errorMessage: string; - }; -}; - -// @public (undocumented) -export interface ValidatedPasswordCollector { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - validation: PasswordPolicy; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - verify: boolean; - }; - // (undocumented) - type: 'ValidatedPasswordCollector'; -} - -// @public (undocumented) -export interface ValidatedSingleValueCollectorWithValue { - // (undocumented) - category: 'ValidatedSingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - type: string; - validation: (ValidationRequired | ValidationRegex)[]; - value: V; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: V; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ValidatedTextCollector = ValidatedSingleValueCollectorWithValue<'TextCollector'>; - -// @public (undocumented) -export interface ValidationPhoneNumber { - // (undocumented) - message: string; - // (undocumented) - rule: boolean; - // (undocumented) - type: 'validatePhoneNumber'; -} - -// @public (undocumented) -export interface ValidationRegex { - // (undocumented) - message: string; - // (undocumented) - rule: string; - // (undocumented) - type: 'regex'; -} - -// @public (undocumented) -export interface ValidationRequired { - // (undocumented) - message: string; - // (undocumented) - rule: boolean; - // (undocumented) - type: 'required'; -} - -// @public -export type Validator = (value: CollectorValueType) => string[] | { - error: { - message: string; - type: string; - }; - type: string; -}; - -// (No @packageDocumentation comment for this package) - -``` +## API Report File for "@forgerock/davinci-client" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ActionCreatorWithPayload } from '@reduxjs/toolkit'; +import { ActionTypes } from '@forgerock/sdk-request-middleware'; +import { CustomLogger } from '@forgerock/sdk-logger'; +import type { DaVinciConfig } from '@forgerock/sdk-types'; +import { FetchBaseQueryError } from '@reduxjs/toolkit/query'; +import type { FetchBaseQueryMeta } from '@reduxjs/toolkit/query'; +import { GenericError } from '@forgerock/sdk-types'; +import { LogLevel } from '@forgerock/sdk-logger'; +import type { MutationResultSelectorResult } from '@reduxjs/toolkit/query'; +import { QueryStatus } from '@reduxjs/toolkit/query'; +import { Reducer } from '@reduxjs/toolkit'; +import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; +import type { SdkStore } from '@forgerock/sdk-types'; +import { SerializedError } from '@reduxjs/toolkit'; +import { Unsubscribe } from '@reduxjs/toolkit'; + +// @public (undocumented) +export type ActionCollector = + | ActionCollectorNoUrl + | ActionCollectorWithUrl; + +// @public (undocumented) +export interface ActionCollectorNoUrl { + // (undocumented) + category: 'ActionCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ActionCollectors = + | ActionCollectorWithUrl<'IdpCollector'> + | ActionCollectorNoUrl<'ActionCollector'> + | ActionCollectorNoUrl<'FlowCollector'> + | ActionCollectorNoUrl<'SubmitCollector'>; + +// @public +export type ActionCollectorTypes = + | 'FlowCollector' + | 'SubmitCollector' + | 'IdpCollector' + | 'ActionCollector'; + +// @public (undocumented) +export interface ActionCollectorWithUrl { + // (undocumented) + category: 'ActionCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + url?: string | null; + }; + // (undocumented) + type: T; +} + +export { ActionTypes }; + +// @public (undocumented) +export type AgreementField = { + type: 'AGREEMENT'; + key: string; + content: string; + titleEnabled: boolean; + title?: string; + agreement: { + id: string; + useDynamicAgreement: boolean; + }; + enabled: boolean; +}; + +// @public (undocumented) +export interface AssertionValue extends Omit< + PublicKeyCredential, + 'rawId' | 'response' | 'getClientExtensionResults' | 'toJSON' +> { + // (undocumented) + rawId: string; + // (undocumented) + response: { + clientDataJSON: string; + authenticatorData: string; + signature: string; + userHandle: string | null; + }; +} + +// @public (undocumented) +export interface AttestationValue extends Omit< + PublicKeyCredential, + 'rawId' | 'response' | 'getClientExtensionResults' | 'toJSON' +> { + // (undocumented) + rawId: string; + // (undocumented) + response: { + clientDataJSON: string; + attestationObject: string; + }; +} + +// @public (undocumented) +export interface AutoCollector< + C extends AutoCollectorCategories, + T extends AutoCollectorTypes, + IV = string, + OV = Record, +> { + // (undocumented) + category: C; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: IV; + type: string; + validation?: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + type: string; + config: OV; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type AutoCollectorCategories = 'SingleValueAutoCollector' | 'ObjectValueAutoCollector'; + +// @public (undocumented) +export type AutoCollectors = + | ProtectCollector + | FidoRegistrationCollector + | FidoAuthenticationCollector + | MetadataCollector + | PollingCollector + | SingleValueAutoCollector + | ObjectValueAutoCollector; + +// @public (undocumented) +export type AutoCollectorTypes = SingleValueAutoCollectorTypes | ObjectValueAutoCollectorTypes; + +// @public (undocumented) +export interface BooleanCollector extends SingleValueCollectorWithValue< + 'BooleanCollector', + boolean +> { + // (undocumented) + output: SingleValueCollectorWithValue<'BooleanCollector', boolean>['output'] & { + appearance: string; + richContent?: CollectorRichContent; + }; +} + +// @public (undocumented) +export type CollectorCategory = Collectors['category']; + +// @public (undocumented) +export interface CollectorErrors { + // (undocumented) + code: string; + // (undocumented) + message: string; + // (undocumented) + target: string; +} + +// @public +export interface CollectorRichContent { + // (undocumented) + content: string; + // (undocumented) + replacements: RichContentLink[]; +} + +// @public (undocumented) +export type Collectors = + | FlowCollector + | MetadataCollector + | PasswordCollector + | ValidatedPasswordCollector + | TextCollector + | BooleanCollector + | ValidatedBooleanCollector + | SingleSelectCollector + | IdpCollector + | SubmitCollector + | ActionCollector<'ActionCollector'> + | SingleValueCollector<'SingleValueCollector'> + | MultiSelectCollector + | DeviceAuthenticationCollector + | DeviceRegistrationCollector + | PhoneNumberCollector + | PhoneNumberExtensionCollector + | ReadOnlyCollector + | RichTextCollector + | ValidatedTextCollector + | ProtectCollector + | PollingCollector + | FidoRegistrationCollector + | FidoAuthenticationCollector + | QrCodeCollector + | ImageCollector + | UnknownCollector; + +// @public +export type CollectorValueType = T extends + | { + type: 'PasswordCollector'; + } + | { + type: 'ValidatedPasswordCollector'; + } + | { + type: 'SingleSelectCollector'; + } + | { + type: 'DeviceRegistrationCollector'; + } + | { + type: 'DeviceAuthenticationCollector'; + } + | { + type: 'ProtectCollector'; + } + | { + type: 'PollingCollector'; + } + ? string + : T extends { + type: 'TextCollector'; + category: 'SingleValueCollector'; + } + ? string + : T extends { + type: 'TextCollector'; + category: 'ValidatedSingleValueCollector'; + } + ? string + : T extends + | { + type: 'BooleanCollector'; + } + | { + type: 'ValidatedBooleanCollector'; + } + ? boolean + : T extends { + type: 'MultiSelectCollector'; + } + ? string | string[] + : T extends { + type: 'PhoneNumberCollector'; + } + ? PhoneNumberInputValue + : T extends { + type: 'PhoneNumberExtensionCollector'; + } + ? PhoneNumberExtensionInputValue + : T extends { + type: 'FidoRegistrationCollector'; + } + ? FidoRegistrationInputValue | GenericError + : T extends { + type: 'FidoAuthenticationCollector'; + } + ? FidoAuthenticationInputValue | GenericError + : T extends { + type: 'MetadataCollector'; + } + ? Record | MetadataError + : T extends { + category: 'SingleValueCollector'; + } + ? string + : T extends { + category: 'ValidatedSingleValueCollector'; + } + ? string + : T extends { + category: 'SingleValueAutoCollector'; + } + ? string + : T extends { + category: 'MultiValueCollector'; + } + ? string | string[] + : T extends { + category: 'ActionCollector'; + } + ? never + : T extends { + category: 'NoValueCollector'; + } + ? never + : CollectorValueTypes; + +// @public +export type CollectorValueTypes = + | string + | string[] + | boolean + | PhoneNumberInputValue + | PhoneNumberExtensionInputValue + | FidoRegistrationInputValue + | FidoAuthenticationInputValue + | MetadataError + | GenericError; + +// @public (undocumented) +export type ComplexValueFields = + | DeviceAuthenticationField + | DeviceRegistrationField + | PhoneNumberField + | PhoneNumberExtensionField + | FidoRegistrationField + | FidoAuthenticationField + | PollingField + | MetadataField; + +// @public (undocumented) +export interface ContinueNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'continue'; + }; + // (undocumented) + error: null; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + eventName?: string; + status: 'continue'; + }; + // (undocumented) + status: 'continue'; +} + +export { CustomLogger }; + +// @public +export type CustomPollingStatus = string & {}; + +// @public +export function davinci(input: { + config: DaVinciConfig; + requestMiddleware?: RequestMiddleware[]; + logger?: { + level: LogLevel; + custom?: CustomLogger; + }; +}): Promise<{ + store: SdkStore; + subscribe: (listener: () => void) => Unsubscribe; + externalIdp: () => () => Promise; + flow: (action: DaVinciAction) => InitFlow; + next: (args?: DaVinciRequest) => Promise; + resume: (input: { continueToken: string }) => Promise; + start: ( + options?: StartOptions | undefined, + ) => Promise; + update: (collector: T) => Updater; + validate: ( + collector: + | SingleValueCollectors + | ObjectValueCollectors + | MultiValueCollectors + | AutoCollectors, + ) => Validator; + pollStatus: (collector: PollingCollector) => Poller; + getClient: () => + | { + status: 'start'; + } + | { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'error'; + } + | { + status: 'failure'; + } + | { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'continue'; + } + | { + authorization?: { + code?: string; + state?: string; + }; + status: 'success'; + } + | null; + getCollectors: () => Collectors[]; + getError: () => DaVinciError | null; + getErrorCollectors: () => CollectorErrors[]; + getNode: () => StartNode | ErrorNode | FailureNode | ContinueNode | SuccessNode; + getServer: () => + | { + status: 'start'; + } + | { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'error'; + } + | { + _links?: Links; + eventName?: string; + href?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'failure'; + } + | { + _links?: Links; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + eventName?: string; + status: 'continue'; + } + | { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + session?: string; + status: 'success'; + } + | null; + cache: { + getLatestResponse: () => + | ({ + status: QueryStatus.fulfilled; + } & Omit< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'data' | 'fulfilledTimeStamp' + > & + Required< + Pick< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'data' | 'fulfilledTimeStamp' + > + > & { + error: undefined; + } & { + status: QueryStatus.fulfilled; + isUninitialized: false; + isLoading: false; + isSuccess: true; + isError: false; + }) + | ({ + status: QueryStatus.rejected; + } & Omit< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'error' + > & + Required< + Pick< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'error' + > + > & { + status: QueryStatus.rejected; + isUninitialized: false; + isLoading: false; + isSuccess: false; + isError: true; + }) + | { + error: { + message: string; + type: string; + }; + }; + getResponseWithId: (requestId: string) => + | ({ + status: QueryStatus.fulfilled; + } & Omit< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'data' | 'fulfilledTimeStamp' + > & + Required< + Pick< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'data' | 'fulfilledTimeStamp' + > + > & { + error: undefined; + } & { + status: QueryStatus.fulfilled; + isUninitialized: false; + isLoading: false; + isSuccess: true; + isError: false; + }) + | ({ + status: QueryStatus.rejected; + } & Omit< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'error' + > & + Required< + Pick< + { + requestId: string; + data?: unknown; + error?: FetchBaseQueryError | SerializedError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, + 'error' + > + > & { + status: QueryStatus.rejected; + isUninitialized: false; + isLoading: false; + isSuccess: false; + isError: true; + }) + | { + error: { + message: string; + type: string; + }; + }; + }; +}>; + +// @public +export interface DaVinciAction { + // (undocumented) + action: string; +} + +// @public +export interface DaVinciBaseResponse { + // (undocumented) + capabilityName?: string; + // (undocumented) + companyId?: string; + // (undocumented) + connectionId?: string; + // (undocumented) + connectorId?: string; + // (undocumented) + id?: string; + // (undocumented) + interactionId?: string; + // (undocumented) + interactionToken?: string; + // (undocumented) + isResponseCompatibleWithMobileAndWebSdks?: boolean; + // (undocumented) + status?: string; +} + +// @public +export type DaVinciCacheEntry = { + data?: DaVinciBaseResponse; + error?: { + data: DaVinciBaseResponse; + status: number; + }; +} & { + data?: any; + error?: any; +} & MutationResultSelectorResult; + +// @public (undocumented) +export type DavinciClient = Awaited>; + +export { DaVinciConfig }; + +// @public (undocumented) +export interface DaVinciError extends Omit { + // (undocumented) + collectors?: CollectorErrors[]; + // (undocumented) + internalHttpStatus?: number; + // (undocumented) + message: string; + // (undocumented) + status: 'error' | 'failure' | 'unknown'; +} + +// @public (undocumented) +export interface DaVinciErrorCacheEntry { + // (undocumented) + endpointName: 'next' | 'flow' | 'start'; + // (undocumented) + error: { + data: T; + }; + // (undocumented) + fulfilledTimeStamp: number; + // (undocumented) + isError: boolean; + // (undocumented) + isLoading: boolean; + // (undocumented) + isSuccess: boolean; + // (undocumented) + isUninitialized: boolean; + // (undocumented) + requestId: string; + // (undocumented) + startedTimeStamp: number; + // (undocumented) + status: 'fulfilled' | 'pending' | 'rejected'; +} + +// @public (undocumented) +export interface DavinciErrorResponse extends DaVinciBaseResponse { + // (undocumented) + cause?: string | null; + // (undocumented) + code: string | number; + // (undocumented) + details?: ErrorDetail[]; + // (undocumented) + doNotSendToOE?: boolean; + // (undocumented) + error?: { + code?: string; + message?: string; + }; + // (undocumented) + errorCategory?: string; + // (undocumented) + errorMessage?: string; + // (undocumented) + expected?: boolean; + // (undocumented) + httpResponseCode: number; + // (undocumented) + isErrorCustomized?: boolean; + // (undocumented) + message: string; + // (undocumented) + metricAttributes?: { + [key: string]: unknown; + }; +} + +// @public (undocumented) +export interface DaVinciFailureResponse extends DaVinciBaseResponse { + // (undocumented) + error?: { + code?: string; + message?: string; + [key: string]: unknown; + }; +} + +// @public (undocumented) +export type DaVinciField = + | ComplexValueFields + | MultiValueFields + | ReadOnlyFields + | RedirectFields + | SingleValueFields; + +// @public +export interface DaVinciNextResponse extends DaVinciBaseResponse { + // (undocumented) + eventName?: string; + // (undocumented) + form?: { + name?: string; + description?: string; + components?: { + fields?: DaVinciField[]; + }; + }; + // (undocumented) + formData?: { + value?: { + [key: string]: string; + }; + }; + // (undocumented) + _links?: Links; +} + +// @public +export interface DaVinciPollResponse extends DaVinciBaseResponse { + // (undocumented) + eventName?: string; + // (undocumented) + _links?: Links; + // (undocumented) + success?: boolean; +} + +// @public (undocumented) +export interface DaVinciRequest { + // (undocumented) + eventName: string; + // (undocumented) + id: string; + // (undocumented) + interactionId: string; + // (undocumented) + parameters: { + eventType: 'submit' | 'action' | 'polling'; + data: { + actionKey: string; + formData?: Record; + }; + }; +} + +// @public +export type DaVinciRequestValueTypes = + | string + | number + | boolean + | (string | number | boolean)[] + | DeviceValue + | PhoneNumberInputValue + | FidoRegistrationInputValue + | FidoAuthenticationInputValue + | MetadataError + | GenericError; + +// @public (undocumented) +export interface DaVinciSuccessResponse extends DaVinciBaseResponse { + // (undocumented) + authorizeResponse?: OAuthDetails; + // (undocumented) + environment: { + id: string; + [key: string]: unknown; + }; + // (undocumented) + _links?: Links; + // (undocumented) + resetCookie?: boolean; + // (undocumented) + session?: { + id?: string; + [key: string]: unknown; + }; + // (undocumented) + sessionToken?: string; + // (undocumented) + sessionTokenMaxAge?: number; + // (undocumented) + status: string; + // (undocumented) + subFlowSettings?: { + cssLinks?: unknown[]; + cssUrl?: unknown; + jsLinks?: unknown[]; + loadingScreenSettings?: unknown; + reactSkUrl?: unknown; + }; + // (undocumented) + success: true; +} + +// @public (undocumented) +export type DeviceAuthenticationCollector = ObjectOptionsCollectorWithObjectValue< + 'DeviceAuthenticationCollector', + DeviceValue +>; + +// @public (undocumented) +export type DeviceAuthenticationField = { + type: 'DEVICE_AUTHENTICATION'; + key: string; + label: string; + options: { + type: string; + iconSrc: string; + title: string; + id: string; + default: boolean; + description: string; + }[]; + required: boolean; +}; + +// @public (undocumented) +export interface DeviceOptionNoDefault { + // (undocumented) + content: string; + // (undocumented) + key: string; + // (undocumented) + label: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export interface DeviceOptionWithDefault { + // (undocumented) + content: string; + // (undocumented) + default: boolean; + // (undocumented) + key: string; + // (undocumented) + label: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export type DeviceRegistrationCollector = ObjectOptionsCollectorWithStringValue< + 'DeviceRegistrationCollector', + string +>; + +// @public (undocumented) +export type DeviceRegistrationField = { + type: 'DEVICE_REGISTRATION'; + key: string; + label: string; + options: { + type: string; + iconSrc: string; + title: string; + description: string; + }[]; + required: boolean; +}; + +// @public (undocumented) +export interface DeviceValue { + // (undocumented) + id: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export interface ErrorDetail { + // (undocumented) + message?: string; + // (undocumented) + rawResponse?: { + _embedded?: { + users?: Array; + }; + code?: string; + count?: number; + details?: NestedErrorDetails[]; + id?: string; + message?: string; + size?: number; + userFilter?: string; + [key: string]: unknown; + }; + // (undocumented) + statusCode?: number; +} + +// @public (undocumented) +export interface ErrorNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'error'; + }; + // (undocumented) + error: DaVinciError; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'error'; + } | null; + // (undocumented) + status: 'error'; +} + +// @public (undocumented) +export interface FailureNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + status: 'failure'; + }; + // (undocumented) + error: DaVinciError; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + href?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'failure'; + } | null; + // (undocumented) + status: 'failure'; +} + +// @public (undocumented) +export type FidoAuthenticationCollector = AutoCollector< + 'ObjectValueAutoCollector', + 'FidoAuthenticationCollector', + FidoAuthenticationInputValue | GenericError, + FidoAuthenticationOutputValue +>; + +// @public (undocumented) +export type FidoAuthenticationField = { + type: 'FIDO2'; + key: string; + label: string; + publicKeyCredentialRequestOptions: FidoAuthenticationOptions; + action: 'AUTHENTICATE'; + trigger: string; + required: boolean; +}; + +// @public (undocumented) +export interface FidoAuthenticationInputValue { + // (undocumented) + assertionValue?: AssertionValue; +} + +// @public (undocumented) +export interface FidoAuthenticationOptions extends Omit< + PublicKeyCredentialRequestOptions, + 'challenge' | 'allowCredentials' +> { + // (undocumented) + allowCredentials?: { + id: number[]; + transports?: AuthenticatorTransport[]; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + challenge: number[]; +} + +// @public (undocumented) +export interface FidoAuthenticationOutputValue { + // (undocumented) + action: 'AUTHENTICATE'; + // (undocumented) + publicKeyCredentialRequestOptions: FidoAuthenticationOptions; + // (undocumented) + trigger: string; +} + +// @public (undocumented) +export interface FidoClient { + authenticate: ( + options: FidoAuthenticationOptions, + ) => Promise; + register: ( + options: FidoRegistrationOptions, + ) => Promise; +} + +// @public +export type FidoErrorCode = + | 'NotAllowedError' + | 'AbortError' + | 'InvalidStateError' + | 'NotSupportedError' + | 'SecurityError' + | 'TimeoutError' + | 'UnknownError'; + +// @public (undocumented) +export type FidoRegistrationCollector = AutoCollector< + 'ObjectValueAutoCollector', + 'FidoRegistrationCollector', + FidoRegistrationInputValue | GenericError, + FidoRegistrationOutputValue +>; + +// @public (undocumented) +export type FidoRegistrationField = { + type: 'FIDO2'; + key: string; + label: string; + publicKeyCredentialCreationOptions: FidoRegistrationOptions; + action: 'REGISTER'; + trigger: string; + required: boolean; +}; + +// @public (undocumented) +export interface FidoRegistrationInputValue { + // (undocumented) + attestationValue?: AttestationValue; +} + +// @public (undocumented) +export interface FidoRegistrationOptions extends Omit< + PublicKeyCredentialCreationOptions, + 'challenge' | 'user' | 'pubKeyCredParams' | 'excludeCredentials' +> { + // (undocumented) + challenge: number[]; + // (undocumented) + excludeCredentials?: { + id: number[]; + transports?: AuthenticatorTransport[]; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + pubKeyCredParams: { + alg: string | number; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + user: { + id: number[]; + name: string; + displayName: string; + }; +} + +// @public (undocumented) +export interface FidoRegistrationOutputValue { + // (undocumented) + action: 'REGISTER'; + // (undocumented) + publicKeyCredentialCreationOptions: FidoRegistrationOptions; + // (undocumented) + trigger: string; +} + +// @public (undocumented) +export type FlowCollector = ActionCollectorNoUrl<'FlowCollector'>; + +// @public (undocumented) +export type FlowNode = ContinueNode | ErrorNode | StartNode | SuccessNode | FailureNode; + +// @public +export type GetClient = + | StartNode['client'] + | ContinueNode['client'] + | ErrorNode['client'] + | SuccessNode['client'] + | FailureNode['client']; + +// @public (undocumented) +export type IdpCollector = ActionCollectorWithUrl<'IdpCollector'>; + +// @public +export interface ImageCollector extends NoValueCollectorBase<'ImageCollector'> { + // (undocumented) + output: NoValueCollectorBase<'ImageCollector'>['output'] & { + src: string; + alt: string; + href?: string; + }; +} + +// @public (undocumented) +export type ImageField = { + type: 'IMAGE'; + key: string; + description: string; + imageUrl: string; + hyperlinkUrl?: string; +}; + +// @public (undocumented) +export type InferActionCollectorType = T extends 'IdpCollector' + ? IdpCollector + : T extends 'SubmitCollector' + ? SubmitCollector + : T extends 'FlowCollector' + ? FlowCollector + : ActionCollectorWithUrl<'ActionCollector'> | ActionCollectorNoUrl<'ActionCollector'>; + +// @public +export type InferAutoCollectorType = T extends 'ProtectCollector' + ? ProtectCollector + : T extends 'PollingCollector' + ? PollingCollector + : T extends 'FidoRegistrationCollector' + ? FidoRegistrationCollector + : T extends 'FidoAuthenticationCollector' + ? FidoAuthenticationCollector + : T extends 'MetadataCollector' + ? MetadataCollector + : T extends 'ObjectValueAutoCollector' + ? ObjectValueAutoCollector + : SingleValueAutoCollector; + +// @public +export type InferMultiValueCollectorType = + T extends 'MultiSelectCollector' + ? MultiValueCollectorWithValue<'MultiSelectCollector'> + : + | MultiValueCollectorWithValue<'MultiValueCollector'> + | MultiValueCollectorNoValue<'MultiValueCollector'>; + +// @public +export type InferNoValueCollectorType = + T extends 'ReadOnlyCollector' + ? ReadOnlyCollector + : T extends 'RichTextCollector' + ? RichTextCollector + : T extends 'QrCodeCollector' + ? QrCodeCollector + : T extends 'ImageCollector' + ? ImageCollector + : NoValueCollectorBase<'NoValueCollector'>; + +// @public +export type InferSingleValueCollectorType = + T extends 'TextCollector' + ? TextCollector + : T extends 'SingleSelectCollector' + ? SingleSelectCollector + : T extends 'ValidatedTextCollector' + ? ValidatedTextCollector + : T extends 'PasswordCollector' + ? PasswordCollector + : T extends 'ValidatedPasswordCollector' + ? ValidatedPasswordCollector + : T extends 'BooleanCollector' + ? BooleanCollector + : T extends 'ValidatedBooleanCollector' + ? ValidatedBooleanCollector + : + | SingleValueCollectorWithValue<'SingleValueCollector'> + | SingleValueCollectorNoValue<'SingleValueCollector'>; + +// @public (undocumented) +export type InferValueObjectCollectorType = + T extends 'DeviceAuthenticationCollector' + ? DeviceAuthenticationCollector + : T extends 'DeviceRegistrationCollector' + ? DeviceRegistrationCollector + : T extends 'PhoneNumberCollector' + ? PhoneNumberCollector + : T extends 'PhoneNumberExtensionCollector' + ? PhoneNumberExtensionCollector + : + | ObjectOptionsCollectorWithObjectValue<'ObjectValueCollector'> + | ObjectOptionsCollectorWithStringValue<'ObjectValueCollector'>; + +// @public (undocumented) +export type InitFlow = () => Promise; + +// @public (undocumented) +export interface InternalErrorResponse { + // (undocumented) + error: Omit & { + message: string; + }; + // (undocumented) + type: 'internal_error'; +} + +// @public (undocumented) +export interface Links { + // (undocumented) + [key: string]: { + href?: string; + }; +} + +export { LogLevel }; + +// @public (undocumented) +export type MetadataCollector = AutoCollector< + 'ObjectValueAutoCollector', + 'MetadataCollector', + MetadataCollectorInputValue, + Record +>; + +// @public (undocumented) +export type MetadataCollectorInputValue = Record | MetadataError; + +// @public +export interface MetadataError { + // (undocumented) + code: string; + // (undocumented) + message: string; +} + +// @public (undocumented) +export type MetadataField = { + type: 'METADATA'; + key: string; + payload: Record; +}; + +// @public (undocumented) +export type MultiSelectCollector = MultiValueCollectorWithValue<'MultiSelectCollector'>; + +// @public (undocumented) +export type MultiSelectField = { + inputType: 'MULTI_SELECT'; + key: string; + label: string; + options: { + label: string; + value: string; + }[]; + required?: boolean; + type: 'CHECKBOX' | 'COMBOBOX'; +}; + +// @public (undocumented) +export type MultiValueCollector = + | MultiValueCollectorWithValue + | MultiValueCollectorNoValue; + +// @public (undocumented) +export interface MultiValueCollectorNoValue { + // (undocumented) + category: 'MultiValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string[]; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type MultiValueCollectors = + | MultiValueCollectorWithValue<'MultiValueCollector'> + | MultiValueCollectorWithValue<'MultiSelectCollector'>; + +// @public +export type MultiValueCollectorTypes = 'MultiSelectCollector' | 'MultiValueCollector'; + +// @public (undocumented) +export interface MultiValueCollectorWithValue { + // (undocumented) + category: 'MultiValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string[]; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: string[]; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type MultiValueFields = MultiSelectField; + +// @public +export interface NestedErrorDetails { + // (undocumented) + code?: string; + // (undocumented) + innerError?: { + history?: string; + unsatisfiedRequirements?: string[]; + failuresRemaining?: number; + }; + // (undocumented) + message?: string; + // (undocumented) + target?: string; +} + +// @public +export const nextCollectorValues: ActionCreatorWithPayload< + { + fields: DaVinciField[]; + formData: { + value: Record; + }; + }, + string +>; + +// @public +export const nodeCollectorReducer: Reducer & { + getInitialState: () => Collectors[]; +}; + +// @public (undocumented) +export type NodeStates = StartNode | ContinueNode | ErrorNode | SuccessNode | FailureNode; + +// @public (undocumented) +export type NoValueCollector = InferNoValueCollectorType; + +// @public (undocumented) +export interface NoValueCollectorBase { + // (undocumented) + category: 'NoValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type NoValueCollectors = + | NoValueCollectorBase<'NoValueCollector'> + | ReadOnlyCollector + | RichTextCollector + | QrCodeCollector + | ImageCollector; + +// @public +export type NoValueCollectorTypes = + | 'ReadOnlyCollector' + | 'RichTextCollector' + | 'NoValueCollector' + | 'QrCodeCollector' + | 'ImageCollector'; + +// @public +export interface OAuthDetails { + // (undocumented) + [key: string]: unknown; + // (undocumented) + code?: string; + // (undocumented) + state?: string; +} + +// @public (undocumented) +export interface ObjectOptionsCollectorWithObjectValue< + T extends ObjectValueCollectorTypes, + V = Record, + D = Record, +> { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: DeviceOptionWithDefault[]; + value?: D | null; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface ObjectOptionsCollectorWithStringValue< + T extends ObjectValueCollectorTypes, + V = string, +> { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: DeviceOptionNoDefault[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ObjectValueAutoCollector = AutoCollector< + 'ObjectValueAutoCollector', + 'ObjectValueAutoCollector', + Record +>; + +// @public (undocumented) +export type ObjectValueAutoCollectorTypes = + | 'ObjectValueAutoCollector' + | 'FidoRegistrationCollector' + | 'FidoAuthenticationCollector' + | 'MetadataCollector'; + +// @public (undocumented) +export type ObjectValueCollector = + | ObjectOptionsCollectorWithObjectValue + | ObjectOptionsCollectorWithStringValue + | ObjectValueCollectorWithObjectValue; + +// @public (undocumented) +export type ObjectValueCollectors = + | DeviceAuthenticationCollector + | DeviceRegistrationCollector + | PhoneNumberCollector + | PhoneNumberExtensionCollector + | ObjectOptionsCollectorWithObjectValue<'ObjectSelectCollector'> + | ObjectOptionsCollectorWithStringValue<'ObjectSelectCollector'>; + +// @public +export type ObjectValueCollectorTypes = + | 'DeviceAuthenticationCollector' + | 'DeviceRegistrationCollector' + | 'PhoneNumberCollector' + | 'PhoneNumberExtensionCollector' + | 'ObjectOptionsCollector' + | 'ObjectValueCollector' + | 'ObjectSelectCollector'; + +// @public (undocumented) +export interface ObjectValueCollectorWithObjectValue< + T extends ObjectValueCollectorTypes, + IV = Record, + OV = Record, +> { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: IV; + type: string; + validation: (ValidationRequired | ValidationPhoneNumber)[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value?: OV | null; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface OutgoingQueryParams { + // (undocumented) + [key: string]: string | string[]; +} + +// @public (undocumented) +export interface PasswordCollector { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + verify: boolean; + }; + // (undocumented) + type: 'PasswordCollector'; +} + +// @public +export type PasswordField = { + type: 'PASSWORD' | 'PASSWORD_VERIFY'; + key: string; + label: string; + required?: boolean; + verify?: boolean; + passwordPolicy?: PasswordPolicy; +}; + +// @public +export interface PasswordPolicy { + // (undocumented) + createdAt?: string; + // (undocumented) + default?: boolean; + // (undocumented) + description?: string; + // (undocumented) + excludesCommonlyUsed?: boolean; + // (undocumented) + excludesProfileData?: boolean; + // (undocumented) + history?: { + count?: number; + retentionDays?: number; + }; + // (undocumented) + id?: string; + // (undocumented) + length?: { + min?: number; + max?: number; + }; + // (undocumented) + lockout?: { + failureCount?: number; + durationSeconds?: number; + }; + // (undocumented) + maxAgeDays?: number; + // (undocumented) + maxRepeatedCharacters?: number; + // (undocumented) + minAgeDays?: number; + // (undocumented) + minCharacters?: Record; + // (undocumented) + minUniqueCharacters?: number; + // (undocumented) + name?: string; + // (undocumented) + notSimilarToCurrent?: boolean; + // (undocumented) + populationCount?: number; + // (undocumented) + updatedAt?: string; +} + +// @public (undocumented) +export type PhoneNumberCollector = ObjectValueCollectorWithObjectValue< + 'PhoneNumberCollector', + PhoneNumberInputValue, + PhoneNumberOutputValue +>; + +// @public (undocumented) +export interface PhoneNumberExtensionCollector { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: PhoneNumberExtensionInputValue; + type: string; + validation: (ValidationRequired | ValidationPhoneNumber)[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + extensionLabel: string; + value: PhoneNumberExtensionOutputValue; + }; + // (undocumented) + type: 'PhoneNumberExtensionCollector'; +} + +// @public (undocumented) +export type PhoneNumberExtensionField = PhoneNumberField & { + showExtension: boolean; + extensionLabel: string; +}; + +// @public (undocumented) +export interface PhoneNumberExtensionInputValue { + // (undocumented) + countryCode: string; + // (undocumented) + extension: string; + // (undocumented) + phoneNumber: string; +} + +// @public (undocumented) +export interface PhoneNumberExtensionOutputValue { + // (undocumented) + countryCode?: string; + // (undocumented) + extension?: string; + // (undocumented) + phoneNumber?: string; +} + +// @public (undocumented) +export type PhoneNumberField = { + type: 'PHONE_NUMBER'; + key: string; + label: string; + required: boolean; + defaultCountryCode: string | null; + validatePhoneNumber: boolean; +}; + +// @public (undocumented) +export interface PhoneNumberInputValue { + // (undocumented) + countryCode: string; + // (undocumented) + phoneNumber: string; +} + +// @public (undocumented) +export interface PhoneNumberOutputValue { + // (undocumented) + countryCode?: string; + // (undocumented) + phoneNumber?: string; +} + +// @public +export type Poller = () => Promise; + +// @public (undocumented) +export type PollingCollector = AutoCollector< + 'SingleValueAutoCollector', + 'PollingCollector', + string, + PollingOutputValue +>; + +// @public (undocumented) +export type PollingField = { + type: 'POLLING'; + key: string; + pollInterval: number; + pollRetries: number; + pollChallengeStatus?: boolean; + challenge?: string; +}; + +// @public (undocumented) +export interface PollingOutputValue { + // (undocumented) + challenge?: string; + // (undocumented) + pollChallengeStatus?: boolean; + // (undocumented) + pollInterval: number; + // (undocumented) + pollRetries: number; + // (undocumented) + retriesRemaining?: number; +} + +// @public (undocumented) +export type PollingStatus = PollingStatusContinue | PollingStatusChallenge; + +// @public (undocumented) +export type PollingStatusChallenge = + | PollingStatusChallengeComplete + | 'expired' + | 'timedOut' + | 'error'; + +// @public (undocumented) +export type PollingStatusChallengeComplete = + | 'approved' + | 'denied' + | 'continue' + | CustomPollingStatus; + +// @public (undocumented) +export type PollingStatusContinue = 'continue' | 'timedOut'; + +// @public (undocumented) +export type ProtectCollector = AutoCollector< + 'SingleValueAutoCollector', + 'ProtectCollector', + string, + ProtectOutputValue +>; + +// @public (undocumented) +export type ProtectField = { + type: 'PROTECT'; + key: string; + behavioralDataCollection: boolean; + universalDeviceIdentification: boolean; +}; + +// @public +export interface ProtectOutputValue { + // (undocumented) + behavioralDataCollection: boolean; + // (undocumented) + universalDeviceIdentification: boolean; +} + +// @public +export interface QrCodeCollector extends NoValueCollectorBase<'QrCodeCollector'> { + // (undocumented) + output: NoValueCollectorBase<'QrCodeCollector'>['output'] & { + src: string; + }; +} + +// @public (undocumented) +export type QrCodeField = { + type: 'QR_CODE'; + key: string; + content: string; + fallbackText?: string; +}; + +// @public +export interface ReadOnlyCollector extends NoValueCollectorBase<'ReadOnlyCollector'> { + // (undocumented) + output: NoValueCollectorBase<'ReadOnlyCollector'>['output'] & { + content: string; + title?: string; + }; +} + +// @public (undocumented) +export type ReadOnlyField = { + type: 'LABEL'; + content: string; + richContent?: RichContent; + key?: string; +}; + +// @public (undocumented) +export type ReadOnlyFields = ReadOnlyField | QrCodeField | AgreementField | ImageField; + +// @public (undocumented) +export type RedirectField = { + type: 'SOCIAL_LOGIN_BUTTON'; + key: string; + label: string; + links: Links; +}; + +// @public (undocumented) +export type RedirectFields = RedirectField; + +export { RequestMiddleware }; + +// @public +export type RichContent = { + content: string; + replacements?: Record; +}; + +// @public +export interface RichContentLink { + // (undocumented) + href: string; + // (undocumented) + key: string; + // (undocumented) + target?: '_self' | '_blank'; + // (undocumented) + type: 'link'; + // (undocumented) + value: string; +} + +// @public +export type RichContentReplacement = { + type: 'link'; + value: string; + href: string; + target?: '_self' | '_blank'; +}; + +// @public +export interface RichTextCollector extends NoValueCollectorBase<'RichTextCollector'> { + // (undocumented) + output: NoValueCollectorBase<'RichTextCollector'>['output'] & { + content: string; + richContent: CollectorRichContent; + }; +} + +// @public (undocumented) +export interface SelectorOption { + // (undocumented) + label: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export type SingleCheckboxField = { + type: 'SINGLE_CHECKBOX'; + inputType: 'BOOLEAN'; + key: string; + label: string; + required?: boolean; + errorMessage?: string; + appearance: string; + richContent?: RichContent; +}; + +// @public (undocumented) +export type SingleSelectCollector = SingleSelectCollectorWithValue<'SingleSelectCollector'>; + +// @public (undocumented) +export interface SingleSelectCollectorNoValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface SingleSelectCollectorWithValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: string | number | boolean; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleSelectField = { + inputType: 'SINGLE_SELECT'; + key: string; + label: string; + options: { + label: string; + value: string; + }[]; + required?: boolean; + type: 'RADIO' | 'DROPDOWN'; +}; + +// @public (undocumented) +export type SingleValueAutoCollector = AutoCollector< + 'SingleValueAutoCollector', + 'SingleValueAutoCollector', + string +>; + +// @public (undocumented) +export type SingleValueAutoCollectorTypes = + | 'SingleValueAutoCollector' + | 'ProtectCollector' + | 'PollingCollector'; + +// @public +export type SingleValueCollector = + | SingleValueCollectorWithValue + | SingleValueCollectorNoValue; + +// @public (undocumented) +export interface SingleValueCollectorNoValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleValueCollectors = + | PasswordCollector + | ValidatedPasswordCollector + | SingleSelectCollector + | TextCollector + | ValidatedTextCollector + | BooleanCollector + | ValidatedBooleanCollector + | SingleValueCollectorWithValue<'SingleValueCollector'>; + +// @public +export type SingleValueCollectorTypes = + | 'PasswordCollector' + | 'ValidatedPasswordCollector' + | 'BooleanCollector' + | 'ValidatedBooleanCollector' + | 'SingleValueCollector' + | 'SingleSelectCollector' + | 'SingleSelectObjectCollector' + | 'TextCollector' + | 'ValidatedTextCollector'; + +// @public (undocumented) +export interface SingleValueCollectorWithValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: V; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleValueFields = + | StandardField + | PasswordField + | ValidatedField + | SingleCheckboxField + | SingleSelectField + | ProtectField; + +// @public (undocumented) +export type StandardField = { + type: 'TEXT' | 'SUBMIT_BUTTON' | 'FLOW_BUTTON' | 'FLOW_LINK' | 'BUTTON'; + key: string; + label: string; + required?: boolean; +}; + +// @public (undocumented) +export interface StartNode { + // (undocumented) + cache: null; + // (undocumented) + client: { + status: 'start'; + }; + // (undocumented) + error: DaVinciError | null; + // (undocumented) + server: { + status: 'start'; + }; + // (undocumented) + status: 'start'; +} + +// @public (undocumented) +export interface StartOptions { + // (undocumented) + query: Query; +} + +// @public (undocumented) +export type SubmitCollector = ActionCollectorNoUrl<'SubmitCollector'>; + +// @public (undocumented) +export interface SuccessNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + authorization?: { + code?: string; + state?: string; + }; + status: 'success'; + } | null; + // (undocumented) + error: null; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + session?: string; + status: 'success'; + }; + // (undocumented) + status: 'success'; +} + +// @public (undocumented) +export type TextCollector = SingleValueCollectorWithValue<'TextCollector'>; + +// @public (undocumented) +export interface ThrownQueryError { + // (undocumented) + error: FetchBaseQueryError; + // (undocumented) + isHandledError: boolean; + // (undocumented) + meta: FetchBaseQueryMeta; +} + +// @public +export type UnknownCollector = { + category: 'UnknownCollector'; + error: string | null; + type: 'UnknownCollector'; + id: string; + name: string; + output: { + key: string; + label: string; + type: string; + }; +}; + +// @public (undocumented) +export type UnknownField = Record; + +// @public +export type UpdatableCollectors = + | SingleValueCollectors + | MultiSelectCollector + | ObjectValueCollectors + | AutoCollectors; + +// @public (undocumented) +export const updateCollectorValues: ActionCreatorWithPayload< + { + id: string; + value: CollectorValueTypes; + index?: number; + }, + string +>; + +// @public +export type Updater = ( + value: CollectorValueType, + index?: number, +) => InternalErrorResponse | null; + +// @public (undocumented) +export interface ValidatedBooleanCollector extends ValidatedSingleValueCollectorWithValue< + 'ValidatedBooleanCollector', + boolean +> { + // (undocumented) + output: ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean>['output'] & { + appearance: string; + richContent?: CollectorRichContent; + }; +} + +// @public +export type ValidatedCollectors = + | ValidatedTextCollector + | ValidatedBooleanCollector + | ValidatedPasswordCollector + | ObjectValueCollectors + | MultiValueCollectors + | AutoCollectors; + +// @public (undocumented) +export type ValidatedField = { + type: 'TEXT'; + key: string; + label: string; + required: boolean; + validation: { + regex: string; + errorMessage: string; + }; +}; + +// @public (undocumented) +export interface ValidatedPasswordCollector { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + validation: PasswordPolicy; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + verify: boolean; + }; + // (undocumented) + type: 'ValidatedPasswordCollector'; +} + +// @public (undocumented) +export interface ValidatedSingleValueCollectorWithValue< + T extends SingleValueCollectorTypes, + V = string, +> { + // (undocumented) + category: 'ValidatedSingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + type: string; + validation: (ValidationRequired | ValidationRegex)[]; + value: V; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: V; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ValidatedTextCollector = ValidatedSingleValueCollectorWithValue<'TextCollector'>; + +// @public (undocumented) +export interface ValidationPhoneNumber { + // (undocumented) + message: string; + // (undocumented) + rule: boolean; + // (undocumented) + type: 'validatePhoneNumber'; +} + +// @public (undocumented) +export interface ValidationRegex { + // (undocumented) + message: string; + // (undocumented) + rule: string; + // (undocumented) + type: 'regex'; +} + +// @public (undocumented) +export interface ValidationRequired { + // (undocumented) + message: string; + // (undocumented) + rule: boolean; + // (undocumented) + type: 'required'; +} + +// @public +export type Validator = ( + value: CollectorValueType, +) => + | string[] + | { + error: { + message: string; + type: string; + }; + type: string; + }; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/davinci-client/src/lib/client.store.effects.ts b/packages/davinci-client/src/lib/client.store.effects.ts index a67ed185fb..519fb1a04b 100644 --- a/packages/davinci-client/src/lib/client.store.effects.ts +++ b/packages/davinci-client/src/lib/client.store.effects.ts @@ -11,7 +11,7 @@ import { FetchBaseQueryError } from '@reduxjs/toolkit/query/react'; import type { logger as loggerFn } from '@forgerock/sdk-logger'; -import type { ClientStore, RootState } from './client.store.utils.js'; +import type { DavinciStore, RootState } from './client.store.utils.js'; import type { PollingStatus, InternalErrorResponse } from './client.types.js'; import type { PollingCollector } from './collector.types.js'; import type { ContinueNode } from './node.types.js'; @@ -251,7 +251,7 @@ function challengePollingµ({ }: { collector: PollingCollector; challenge: string; - store: ReturnType; + store: DavinciStore; log: ReturnType; }): Effect.Effect { const maxRetries = collector.output.config.pollRetries ?? 60; @@ -316,7 +316,7 @@ export function pollingµ({ }: { mode: PollingMode; collector: PollingCollector; - store: ReturnType; + store: DavinciStore; log: ReturnType; }): Effect.Effect { if (mode._tag === 'challenge') { diff --git a/packages/davinci-client/src/lib/client.store.ts b/packages/davinci-client/src/lib/client.store.ts index 82b8480400..32f45d9865 100644 --- a/packages/davinci-client/src/lib/client.store.ts +++ b/packages/davinci-client/src/lib/client.store.ts @@ -18,6 +18,7 @@ import { handleUpdateValidateError, isValidCollectorCategory, resolveCollectorUpdateValue, + toSdkStore, type RootState, } from './client.store.utils.js'; import { pollingµ, getPollingModeµ, type PollingMode } from './client.store.effects.js'; @@ -27,6 +28,7 @@ import { configSlice } from './config.slice.js'; import { wellknownApi } from '@forgerock/sdk-wellknown'; import type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; +import type { SdkStore } from '@forgerock/sdk-types'; /** * Import the DaVinciRequest types */ @@ -82,7 +84,8 @@ export async function davinci({ level: logger?.level ?? config.log ?? 'error', custom: logger?.custom, }); - const store = createClientStore({ requestMiddleware, logger: log }); + const injectable = createClientStore({ requestMiddleware, logger: log }); + const store = injectable.store; const serverInfo = createStorage({ type: 'localStorage', name: 'serverInfo', @@ -114,6 +117,8 @@ export async function davinci({ store.dispatch(configSlice.actions.set({ ...config, wellknownResponse: openIdResponse })); return { + // Opaque store handle — pass to oidc() to share this store + store: toSdkStore(injectable) as SdkStore, // Pass store methods to the client subscribe: store.subscribe, diff --git a/packages/davinci-client/src/lib/client.store.utils.ts b/packages/davinci-client/src/lib/client.store.utils.ts index d92ba36667..870e7f790b 100644 --- a/packages/davinci-client/src/lib/client.store.utils.ts +++ b/packages/davinci-client/src/lib/client.store.utils.ts @@ -4,7 +4,7 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { configureStore } from '@reduxjs/toolkit'; +import { combineSlices, configureStore, createDynamicMiddleware } from '@reduxjs/toolkit'; import { Match, Either } from 'effect'; import type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; @@ -31,20 +31,48 @@ import { nodeSlice } from './node.slice.js'; import { davinciApi } from './davinci.api.js'; import { wellknownApi } from '@forgerock/sdk-wellknown'; +/** + * Root reducer built with combineSlices to support lazy injection. + * External slices (e.g. oidcApi) can be injected via rootReducer.inject(). + */ +export const rootReducer = combineSlices( + configSlice, + nodeSlice, + davinciApi, + wellknownApi, +).withLazyLoadedSlices(); + +export type RootState = ReturnType; + +export interface RootStateWithNode< + T extends ErrorNode | ContinueNode | StartNode | SuccessNode, +> extends RootState { + node: T; +} + +/** + * Internal store shape that carries the root reducer and dynamic middleware + * so that oidc-client can inject its reducers and middleware at init time. + * + * Consumers only ever see the opaque SdkStore type. + */ +export interface InjectableStore { + readonly store: ReturnType>; + readonly rootReducer: typeof rootReducer; + readonly dynamicMiddleware: ReturnType; +} + export function createClientStore({ requestMiddleware, logger, }: { requestMiddleware?: RequestMiddleware[]; logger?: ReturnType; -}) { - return configureStore({ - reducer: { - config: configSlice.reducer, - node: nodeSlice.reducer, - [davinciApi.reducerPath]: davinciApi.reducer, - [wellknownApi.reducerPath]: wellknownApi.reducer, - }, +}): InjectableStore { + const dynamicMiddleware = createDynamicMiddleware(); + + const store = configureStore({ + reducer: rootReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ thunk: { @@ -59,21 +87,36 @@ export function createClientStore({ }, }) .concat(davinciApi.middleware) - .concat(wellknownApi.middleware), + .concat(wellknownApi.middleware) + .concat(dynamicMiddleware.middleware), }); + + return { store, rootReducer, dynamicMiddleware }; } export type ClientStore = typeof createClientStore; -export type RootState = ReturnType['getState']>; +/** The inner Redux store type — used by effects that need dispatch/getState. */ +export type DavinciStore = InjectableStore['store']; -export interface RootStateWithNode< - T extends ErrorNode | ContinueNode | StartNode | SuccessNode, -> extends RootState { - node: T; -} +export type AppDispatch = ReturnType; -export type AppDispatch = ReturnType['dispatch']>; +export function handleUpdateValidateError( + message: string, + type: 'argument_error' | 'state_error', + cb: (message: string) => void, +): () => InternalErrorResponse { + cb(message); + return function () { + return { + error: { + message: message, + type: type, + }, + type: 'internal_error' as const, + }; + }; +} /** * @function createInternalError @@ -101,32 +144,6 @@ export function isInternalError(value: unknown): value is InternalErrorResponse ); } -/** - * Logs a collector update or validation failure and returns a - * function producing the corresponding `InternalErrorResponse`. - * - * @param message - The error message to log and embed in the response - * @param type - Whether the failure stems from a bad argument or invalid state - * @param cb - Logging callback invoked with `message` (e.g. `log.error`) - * @returns A function that, when called, returns the `InternalErrorResponse` - */ -export function handleUpdateValidateError( - message: string, - type: 'argument_error' | 'state_error', - cb: (message: string) => void, -): () => InternalErrorResponse { - cb(message); - return function () { - return { - error: { - message: message, - type: type, - }, - type: 'internal_error' as const, - }; - }; -} - /** * Type guard: checks whether a collector's `category` is one of the given * `validCategories`, narrowing it to the matching union member on success. @@ -258,3 +275,13 @@ export function resolveCollectorUpdateValue( Match.exhaustive, ); } + +/** Cast InjectableStore to the opaque SdkStore for public API exposure. */ +export function toSdkStore(injectable: InjectableStore): object { + return injectable as unknown as object; +} + +/** Recover the InjectableStore from an opaque SdkStore handle. */ +export function fromSdkStore(sdkStore: object): InjectableStore { + return sdkStore as unknown as InjectableStore; +} diff --git a/packages/journey-client/api-report/journey-client.api.md b/packages/journey-client/api-report/journey-client.api.md index 35a4a51dbe..88ee56f6fb 100644 --- a/packages/journey-client/api-report/journey-client.api.md +++ b/packages/journey-client/api-report/journey-client.api.md @@ -23,6 +23,7 @@ import { PolicyKey } from '@forgerock/sdk-types'; import { PolicyParams } from '@forgerock/sdk-types'; import { PolicyRequirement } from '@forgerock/sdk-types'; import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; +import type { SdkStore } from '@forgerock/sdk-types'; import { Step } from '@forgerock/sdk-types'; import { StepDetail } from '@forgerock/sdk-types'; import { StepType } from '@forgerock/sdk-types'; @@ -197,6 +198,8 @@ export interface JourneyClient { // (undocumented) start: (options?: StartParam) => Promise; // (undocumented) + store: SdkStore; + // (undocumented) subscribe: (listener: () => void) => () => void; // (undocumented) terminate: (options?: { diff --git a/packages/journey-client/api-report/journey-client.types.api.md b/packages/journey-client/api-report/journey-client.types.api.md index d9219a9710..340dadaa91 100644 --- a/packages/journey-client/api-report/journey-client.types.api.md +++ b/packages/journey-client/api-report/journey-client.types.api.md @@ -22,6 +22,7 @@ import { PolicyKey } from '@forgerock/sdk-types'; import { PolicyParams } from '@forgerock/sdk-types'; import { PolicyRequirement } from '@forgerock/sdk-types'; import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; +import type { SdkStore } from '@forgerock/sdk-types'; import { Step } from '@forgerock/sdk-types'; import { StepDetail } from '@forgerock/sdk-types'; import { StepType } from '@forgerock/sdk-types'; @@ -184,6 +185,8 @@ export interface JourneyClient { // (undocumented) start: (options?: StartParam) => Promise; // (undocumented) + store: SdkStore; + // (undocumented) subscribe: (listener: () => void) => () => void; // (undocumented) terminate: (options?: { diff --git a/packages/journey-client/src/lib/client.store.ts b/packages/journey-client/src/lib/client.store.ts index 28acdbc233..dd66152a4d 100644 --- a/packages/journey-client/src/lib/client.store.ts +++ b/packages/journey-client/src/lib/client.store.ts @@ -12,11 +12,11 @@ import { isValidWellknownUrl, createWellknownError, } from '@forgerock/sdk-utilities'; -import type { GenericError } from '@forgerock/sdk-types'; +import type { GenericError, SdkStore } from '@forgerock/sdk-types'; import type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; import type { Step } from '@forgerock/sdk-types'; -import { createJourneyStore } from './client.store.utils.js'; +import { createJourneyStore, toSdkStore } from './client.store.utils.js'; import { configSlice } from './config.slice.js'; import { journeyApi } from './journey.api.js'; import { createStorage } from '@forgerock/storage'; @@ -32,6 +32,7 @@ import type { NextOptions, StartParam, ResumeOptions } from './interfaces.js'; /** The journey client instance returned by the `journey()` function. */ export interface JourneyClient { + store: SdkStore; subscribe: (listener: () => void) => () => void; start: (options?: StartParam) => Promise; next: (step: JourneyStep, options?: NextOptions) => Promise; @@ -113,7 +114,8 @@ export async function journey({ ); } - const store = createJourneyStore({ requestMiddleware, logger: log }); + const injectable = createJourneyStore({ requestMiddleware, logger: log }); + const store = injectable.store; const { wellknown } = config.serverConfig; @@ -154,6 +156,7 @@ export async function journey({ }); const self: JourneyClient = { + store: toSdkStore(injectable) as SdkStore, subscribe: store.subscribe, start: async (options?: StartParam) => { diff --git a/packages/journey-client/src/lib/client.store.utils.ts b/packages/journey-client/src/lib/client.store.utils.ts index 5588c66c42..0298b20ff6 100644 --- a/packages/journey-client/src/lib/client.store.utils.ts +++ b/packages/journey-client/src/lib/client.store.utils.ts @@ -7,17 +7,36 @@ import { logger as loggerFn } from '@forgerock/sdk-logger'; import { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; -import { combineReducers, configureStore } from '@reduxjs/toolkit'; +import { combineSlices, configureStore, createDynamicMiddleware } from '@reduxjs/toolkit'; import { configSlice } from './config.slice.js'; import { journeyApi } from './journey.api.js'; import { wellknownApi } from '@forgerock/sdk-wellknown'; -const rootReducer = combineReducers({ - [journeyApi.reducerPath]: journeyApi.reducer, - [configSlice.name]: configSlice.reducer, - [wellknownApi.reducerPath]: wellknownApi.reducer, -}); +/** + * Root reducer built with combineSlices to support lazy injection. + * External slices (e.g. oidcApi) can be injected via rootReducer.inject(). + */ +export const rootReducer = combineSlices( + journeyApi, + configSlice, + wellknownApi, +).withLazyLoadedSlices(); + +export type RootState = ReturnType; + +/** + * Internal store shape carrying root reducer and dynamic middleware + * so that oidc-client can inject its reducers and middleware at init time. + */ +export interface InjectableStore { + readonly store: ReturnType>; + readonly rootReducer: typeof rootReducer; + readonly dynamicMiddleware: ReturnType; +} + +/** The inner Redux store type — used by effects that need dispatch/getState. */ +export type JourneyStore = InjectableStore['store']; export const createJourneyStore = ({ requestMiddleware, @@ -25,8 +44,10 @@ export const createJourneyStore = ({ }: { requestMiddleware?: RequestMiddleware[]; logger?: ReturnType; -}) => { - return configureStore({ +}): InjectableStore => { + const dynamicMiddleware = createDynamicMiddleware(); + + const store = configureStore({ reducer: rootReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ @@ -39,8 +60,19 @@ export const createJourneyStore = ({ }, }) .concat(journeyApi.middleware) - .concat(wellknownApi.middleware), + .concat(wellknownApi.middleware) + .concat(dynamicMiddleware.middleware), }); + + return { store, rootReducer, dynamicMiddleware }; }; -export type RootState = ReturnType; +/** Cast InjectableStore to the opaque SdkStore for public API exposure. */ +export function toSdkStore(injectable: InjectableStore): object { + return injectable as unknown as object; +} + +/** Recover the InjectableStore from an opaque SdkStore handle. */ +export function fromSdkStore(sdkStore: object): InjectableStore { + return sdkStore as unknown as InjectableStore; +} diff --git a/packages/oidc-client/api-report/oidc-client.api.md b/packages/oidc-client/api-report/oidc-client.api.md index 02a90f352a..d9fe8e87bd 100644 --- a/packages/oidc-client/api-report/oidc-client.api.md +++ b/packages/oidc-client/api-report/oidc-client.api.md @@ -23,6 +23,7 @@ import { OidcConfig } from '@forgerock/sdk-types'; import { QueryDefinition } from '@reduxjs/toolkit/query'; import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; import { ResponseType as ResponseType_2 } from '@forgerock/sdk-types'; +import type { SdkStore } from '@forgerock/sdk-types'; import { StorageConfig } from '@forgerock/storage'; import { StoreEnhancer } from '@reduxjs/toolkit'; import { ThunkDispatch } from '@reduxjs/toolkit'; @@ -283,7 +284,7 @@ export function oidc(input: { custom?: CustomLogger; }; storage?: Partial; -}): Promise<{ +}, sharedStore?: SdkStore): Promise<{ error: string; type: string; subscribe?: undefined; diff --git a/packages/oidc-client/api-report/oidc-client.types.api.md b/packages/oidc-client/api-report/oidc-client.types.api.md index 02a90f352a..d9fe8e87bd 100644 --- a/packages/oidc-client/api-report/oidc-client.types.api.md +++ b/packages/oidc-client/api-report/oidc-client.types.api.md @@ -23,6 +23,7 @@ import { OidcConfig } from '@forgerock/sdk-types'; import { QueryDefinition } from '@reduxjs/toolkit/query'; import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; import { ResponseType as ResponseType_2 } from '@forgerock/sdk-types'; +import type { SdkStore } from '@forgerock/sdk-types'; import { StorageConfig } from '@forgerock/storage'; import { StoreEnhancer } from '@reduxjs/toolkit'; import { ThunkDispatch } from '@reduxjs/toolkit'; @@ -283,7 +284,7 @@ export function oidc(input: { custom?: CustomLogger; }; storage?: Partial; -}): Promise<{ +}, sharedStore?: SdkStore): Promise<{ error: string; type: string; subscribe?: undefined; diff --git a/packages/oidc-client/src/lib/client.store.ts b/packages/oidc-client/src/lib/client.store.ts index c3ebeb15cd..c171f11fe4 100644 --- a/packages/oidc-client/src/lib/client.store.ts +++ b/packages/oidc-client/src/lib/client.store.ts @@ -11,7 +11,7 @@ import { Cause, Effect, Exit, Option } from 'effect'; import { authorizeµ, createParAuthorizeUrlµ } from './authorize.request.js'; import { buildTokenExchangeµ } from './exchange.request.js'; -import { createClientStore, createTokenError } from './client.store.utils.js'; +import { createClientStore, createTokenError, injectIntoStore } from './client.store.utils.js'; import { handleExit } from '@forgerock/sdk-utilities'; import { isExpiryWithinThreshold } from './token.utils.js'; import { logoutµ } from './logout.request.js'; @@ -20,7 +20,7 @@ import { sessionCheckNoneµ, sessionCheckIdTokenµ } from './session.micros.js'; import { wellknownApi, wellknownSelector } from '@forgerock/sdk-wellknown'; import type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; -import type { GenericError, GetAuthorizationUrlOptions } from '@forgerock/sdk-types'; +import type { GenericError, GetAuthorizationUrlOptions, SdkStore } from '@forgerock/sdk-types'; import type { CustomLogger, LogLevel } from '@forgerock/sdk-logger'; import type { StorageConfig } from '@forgerock/storage'; @@ -50,20 +50,23 @@ import type { SessionCheckOptions, SessionCheckSuccess } from './session.types.j * @param {Partial} param.storage - optional storage configuration for persisting OIDC tokens. * @returns {ReturnType} - Returns an object with methods for authorization, token exchange, user info retrieval, and logout. */ -export async function oidc({ - config, - requestMiddleware, - logger, - storage, -}: { - config: OidcConfig; - requestMiddleware?: RequestMiddleware[]; - logger?: { - level: LogLevel; - custom?: CustomLogger; - }; - storage?: Partial; -}) { +export async function oidc( + { + config, + requestMiddleware, + logger, + storage, + }: { + config: OidcConfig; + requestMiddleware?: RequestMiddleware[]; + logger?: { + level: LogLevel; + custom?: CustomLogger; + }; + storage?: Partial; + }, + sharedStore?: SdkStore, +) { const log = loggerFn({ level: logger?.level ?? config.log ?? 'error', custom: logger?.custom, @@ -75,7 +78,9 @@ export async function oidc({ prefix: storage?.prefix || 'pic', ...storage, } as StorageConfig); - const store = createClientStore({ requestMiddleware, logger: log }); + const store = sharedStore + ? injectIntoStore(sharedStore) + : createClientStore({ requestMiddleware, logger: log }); if (!config?.serverConfig?.wellknown) { return { diff --git a/packages/oidc-client/src/lib/client.store.utils.ts b/packages/oidc-client/src/lib/client.store.utils.ts index c58d13b6ab..86be733f02 100644 --- a/packages/oidc-client/src/lib/client.store.utils.ts +++ b/packages/oidc-client/src/lib/client.store.utils.ts @@ -14,6 +14,37 @@ import { wellknownApi } from '@forgerock/sdk-wellknown'; import type { GenericError } from '@forgerock/sdk-types'; import type { FetchBaseQueryError } from '@reduxjs/toolkit/query'; +/** + * Internal InjectableStore shape — mirrored from davinci/journey-client. + * Only used within oidc-client for the shared-store injection path. + */ +interface InjectableStore { + readonly store: ReturnType; + readonly rootReducer: { inject: (api: unknown) => void }; + readonly dynamicMiddleware: { addMiddleware: (...mw: unknown[]) => void }; +} + +/** + * Recovers the InjectableStore from an opaque SdkStore handle so oidc-client + * can inject its own reducer and middleware into a store owned by another client. + */ +function fromSdkStore(sdkStore: object): InjectableStore { + return sdkStore as unknown as InjectableStore; +} + +/** + * Lazily injects oidcApi reducer and middleware into a store that was created + * by davinci() or journey(). Safe to call multiple times — RTK deduplicates injections. + * The cast is safe: after injection, the store's state will contain the oidc and wellknown + * slices, matching the shape produced by createClientStore. + */ +export function injectIntoStore(sdkStore: object): ReturnType { + const { store, rootReducer, dynamicMiddleware } = fromSdkStore(sdkStore); + rootReducer.inject(oidcApi); + dynamicMiddleware.addMiddleware(oidcApi.middleware); + return store as unknown as ReturnType; +} + /** * @function createClientStore * @description Creates a Redux store configured with OIDC and well-known APIs. diff --git a/packages/oidc-client/src/lib/shared-store.test.ts b/packages/oidc-client/src/lib/shared-store.test.ts new file mode 100644 index 0000000000..1f7ed6a7c8 --- /dev/null +++ b/packages/oidc-client/src/lib/shared-store.test.ts @@ -0,0 +1,236 @@ +// @vitest-environment node +/* + * Copyright (c) 2025 - 2026 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { combineSlices, configureStore, createDynamicMiddleware } from '@reduxjs/toolkit'; + +import { wellknownApi } from '@forgerock/sdk-wellknown'; +import { oidc } from './client.store.js'; +import { injectIntoStore } from './client.store.utils.js'; +import { oidcApi } from './oidc.api.js'; + +import type { SdkStore } from '@forgerock/sdk-types'; +import type { OidcConfig } from './config.types.js'; + +// --------------------------------------------------------------------------- +// Fixtures +// --------------------------------------------------------------------------- + +const TEST_WELLKNOWN_URL = + 'https://example.pingone.com/test-env/as/.well-known/openid-configuration'; + +const mockWellknownResponse = { + issuer: 'https://example.pingone.com/test-env/as', + authorization_endpoint: 'https://example.pingone.com/test-env/as/authorize', + token_endpoint: 'https://example.pingone.com/test-env/as/token', + userinfo_endpoint: 'https://example.pingone.com/test-env/as/userinfo', + jwks_uri: 'https://example.pingone.com/test-env/as/jwks', + revocation_endpoint: 'https://example.pingone.com/test-env/as/revoke', + introspection_endpoint: 'https://example.pingone.com/test-env/as/introspect', + pushed_authorization_request_endpoint: 'https://example.pingone.com/test-env/as/par', +}; + +const oidcConfig: OidcConfig = { + clientId: 'test-client-id', + redirectUri: 'http://localhost/callback', + scope: 'openid profile', + serverConfig: { wellknown: TEST_WELLKNOWN_URL }, + responseType: 'code', +}; + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +function makeStorageStub() { + const store = new Map(); + return { + getItem: (key: string) => store.get(key) ?? null, + setItem: (key: string, value: string) => store.set(key, value), + removeItem: (key: string) => store.delete(key), + clear: () => store.clear(), + get length() { + return store.size; + }, + key: (i: number) => [...store.keys()][i] ?? null, + }; +} + +/** + * Constructs a minimal InjectableStore that mirrors what davinci()/journey() creates, + * but without importing those packages. Uses only RTK primitives. + */ +function makeSharedStore(): SdkStore { + const dynamicMiddleware = createDynamicMiddleware(); + const rootReducer = combineSlices(wellknownApi).withLazyLoadedSlices(); + const store = configureStore({ + reducer: rootReducer, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware().concat(wellknownApi.middleware).concat(dynamicMiddleware.middleware), + }); + // Cast to SdkStore the same way toSdkStore() does + return { store, rootReducer, dynamicMiddleware } as unknown as SdkStore; +} + +// --------------------------------------------------------------------------- +// Tests +// --------------------------------------------------------------------------- + +describe('injectIntoStore()', () => { + it('calls rootReducer.inject with oidcApi', () => { + const dynamicMiddleware = createDynamicMiddleware(); + const rootReducer = combineSlices(wellknownApi).withLazyLoadedSlices(); + const store = configureStore({ + reducer: rootReducer, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware().concat(dynamicMiddleware.middleware), + }); + + const injectable = { store, rootReducer, dynamicMiddleware } as unknown as SdkStore; + + const injectSpy = vi.spyOn(rootReducer, 'inject'); + injectIntoStore(injectable); + + expect(injectSpy).toHaveBeenCalledWith(oidcApi); + }); + + it('calls dynamicMiddleware.addMiddleware with oidcApi.middleware', () => { + const dynamicMiddleware = createDynamicMiddleware(); + const rootReducer = combineSlices(wellknownApi).withLazyLoadedSlices(); + const store = configureStore({ + reducer: rootReducer, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware().concat(dynamicMiddleware.middleware), + }); + + const injectable = { store, rootReducer, dynamicMiddleware } as unknown as SdkStore; + + const addMiddlewareSpy = vi.spyOn(dynamicMiddleware, 'addMiddleware'); + injectIntoStore(injectable); + + expect(addMiddlewareSpy).toHaveBeenCalledWith(oidcApi.middleware); + }); +}); + +describe('oidc() standalone — no shared store', () => { + let fetchCallCount = 0; + + beforeEach(() => { + fetchCallCount = 0; + vi.stubGlobal('localStorage', makeStorageStub()); + vi.stubGlobal('sessionStorage', makeStorageStub()); + + vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => { + const url = typeof input === 'string' ? input : (input as Request).url; + fetchCallCount++; + + if (url.includes('.well-known')) { + return new Response(JSON.stringify(mockWellknownResponse), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); + } + + return new Response(JSON.stringify({}), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); + }); + }); + + afterEach(() => { + vi.unstubAllGlobals(); + vi.restoreAllMocks(); + }); + + it('creates its own store and returns a working client', async () => { + const client = await oidc({ config: oidcConfig }); + + expect('error' in client).toBe(false); + if ('error' in client) throw new Error('Expected oidc client, got error'); + + expect(client.subscribe).toBeInstanceOf(Function); + expect(client.token).toBeDefined(); + expect(client.authorize).toBeDefined(); + }); + + it('fetches wellknown during init', async () => { + await oidc({ config: oidcConfig }); + + expect(fetchCallCount).toBeGreaterThan(0); + }); +}); + +describe('oidc() with shared store', () => { + let fetchCallCount = 0; + + beforeEach(() => { + fetchCallCount = 0; + vi.stubGlobal('localStorage', makeStorageStub()); + vi.stubGlobal('sessionStorage', makeStorageStub()); + + vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => { + const url = typeof input === 'string' ? input : (input as Request).url; + fetchCallCount++; + + if (url.includes('.well-known')) { + return new Response(JSON.stringify(mockWellknownResponse), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); + } + + return new Response(JSON.stringify({}), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); + }); + }); + + afterEach(() => { + vi.unstubAllGlobals(); + vi.restoreAllMocks(); + }); + + it('resolves without error when given a shared SdkStore', async () => { + const sharedStore = makeSharedStore(); + const client = await oidc({ config: oidcConfig }, sharedStore); + + expect('error' in client).toBe(false); + if ('error' in client) throw new Error('Expected oidc client, got error'); + + expect(client.subscribe).toBeInstanceOf(Function); + expect(client.token).toBeDefined(); + expect(client.authorize).toBeDefined(); + }); + + it('subscribe() returns an unsubscribe function', async () => { + const sharedStore = makeSharedStore(); + const client = await oidc({ config: oidcConfig }, sharedStore); + + if ('error' in client) throw new Error('Expected oidc client, got error'); + + const listener = vi.fn(); + const unsubscribe = client.subscribe(listener); + + expect(unsubscribe).toBeInstanceOf(Function); + }); + + it('reuses cached wellknown response — no additional fetch when store already has it', async () => { + const sharedStore = makeSharedStore(); + + // Pre-populate the wellknown cache by routing through the typed store from injectIntoStore + const typedStore = injectIntoStore(sharedStore); + await typedStore.dispatch(wellknownApi.endpoints.configuration.initiate(TEST_WELLKNOWN_URL)); + const fetchesAfterPreload = fetchCallCount; + + // oidc() should hit the cache, not make another wellknown request + await oidc({ config: oidcConfig }, sharedStore); + + expect(fetchCallCount).toBe(fetchesAfterPreload); + }); +}); diff --git a/packages/sdk-effects/wellknown/vite.config.ts b/packages/sdk-effects/wellknown/vite.config.ts index dd352b8bbd..cef160f8ba 100644 --- a/packages/sdk-effects/wellknown/vite.config.ts +++ b/packages/sdk-effects/wellknown/vite.config.ts @@ -7,6 +7,7 @@ export default defineConfig(() => ({ test: { watch: false, globals: true, + passWithNoTests: true, environment: 'node', include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], reporters: ['default'], diff --git a/packages/sdk-types/src/index.ts b/packages/sdk-types/src/index.ts index 54036b802a..10b862df1d 100644 --- a/packages/sdk-types/src/index.ts +++ b/packages/sdk-types/src/index.ts @@ -15,3 +15,4 @@ export * from './lib/tokens.types.js'; export * from './lib/config.types.js'; export * from './lib/authorize.types.js'; export * from './lib/policy.types.js'; +export * from './lib/store.types.js'; diff --git a/packages/sdk-types/src/lib/store.types.ts b/packages/sdk-types/src/lib/store.types.ts new file mode 100644 index 0000000000..6653db7c68 --- /dev/null +++ b/packages/sdk-types/src/lib/store.types.ts @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 - 2026 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +/** + * Opaque handle to a shared SDK Redux store. + * + * Consumers can pass this between SDK client factories but cannot access + * Redux internals (dispatch, getState, etc.) through this type — by design. + */ +export interface SdkStore { + readonly __sdkStoreBrand: symbol; +} From aacd4b66e0e6944b03718fb739bc8ca25586282d Mon Sep 17 00:00:00 2001 From: Ryan Bas Date: Mon, 27 Jul 2026 15:38:33 -0600 Subject: [PATCH 06/11] fix(oidc): warn when requestMiddleware is silently dropped with sharedStore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit requestMiddleware has no effect when oidc() uses an injected store — the owning store's thunk.extraArgument is used instead. Emit an explicit warn so callers aren't left debugging silent behavior. Test coverage: adds idempotency, behavioral subscribe, cache-reuse, requestMiddleware-warning, and state-after-injection assertions. --- packages/oidc-client/src/lib/client.store.ts | 6 + .../oidc-client/src/lib/shared-store.test.ts | 137 ++++++++++++------ 2 files changed, 101 insertions(+), 42 deletions(-) diff --git a/packages/oidc-client/src/lib/client.store.ts b/packages/oidc-client/src/lib/client.store.ts index c171f11fe4..e8021936e3 100644 --- a/packages/oidc-client/src/lib/client.store.ts +++ b/packages/oidc-client/src/lib/client.store.ts @@ -78,6 +78,12 @@ export async function oidc( prefix: storage?.prefix || 'pic', ...storage, } as StorageConfig); + if (sharedStore && requestMiddleware?.length) { + log.warn( + '`requestMiddleware` is ignored when a `sharedStore` is provided. ' + + 'Pass request middleware to the davinci() or journey() factory that owns the store.', + ); + } const store = sharedStore ? injectIntoStore(sharedStore) : createClientStore({ requestMiddleware, logger: log }); diff --git a/packages/oidc-client/src/lib/shared-store.test.ts b/packages/oidc-client/src/lib/shared-store.test.ts index 1f7ed6a7c8..7b8b603f74 100644 --- a/packages/oidc-client/src/lib/shared-store.test.ts +++ b/packages/oidc-client/src/lib/shared-store.test.ts @@ -72,10 +72,28 @@ function makeSharedStore(): SdkStore { middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(wellknownApi.middleware).concat(dynamicMiddleware.middleware), }); - // Cast to SdkStore the same way toSdkStore() does return { store, rootReducer, dynamicMiddleware } as unknown as SdkStore; } +function makeFetchMock(onCall?: (url: string) => void) { + return vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => { + const url = typeof input === 'string' ? input : (input as Request).url; + onCall?.(url); + + if (url.includes('.well-known')) { + return new Response(JSON.stringify(mockWellknownResponse), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); + } + + return new Response(JSON.stringify({}), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); + }); +} + // --------------------------------------------------------------------------- // Tests // --------------------------------------------------------------------------- @@ -114,6 +132,32 @@ describe('injectIntoStore()', () => { expect(addMiddlewareSpy).toHaveBeenCalledWith(oidcApi.middleware); }); + + it('oidcApi slice is readable from store state after injection', () => { + const sharedStore = makeSharedStore(); + const typedStore = injectIntoStore(sharedStore); + + // combineSlices registers the reducer on inject(), but state is only recomputed + // on the next dispatch. Trigger a no-op action to force state recalculation. + typedStore.dispatch({ type: '@@test/init' }); + const state = typedStore.getState() as Record; + + expect(state).toHaveProperty(oidcApi.reducerPath); + }); + + it('is idempotent — calling twice does not throw or corrupt state', () => { + const sharedStore = makeSharedStore(); + + expect(() => { + injectIntoStore(sharedStore); + injectIntoStore(sharedStore); + }).not.toThrow(); + + const typedStore = injectIntoStore(sharedStore); + typedStore.dispatch({ type: '@@test/init' }); + const state = typedStore.getState() as Record; + expect(state).toHaveProperty(oidcApi.reducerPath); + }); }); describe('oidc() standalone — no shared store', () => { @@ -123,22 +167,8 @@ describe('oidc() standalone — no shared store', () => { fetchCallCount = 0; vi.stubGlobal('localStorage', makeStorageStub()); vi.stubGlobal('sessionStorage', makeStorageStub()); - - vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => { - const url = typeof input === 'string' ? input : (input as Request).url; - fetchCallCount++; - - if (url.includes('.well-known')) { - return new Response(JSON.stringify(mockWellknownResponse), { - status: 200, - headers: { 'Content-Type': 'application/json' }, - }); - } - - return new Response(JSON.stringify({}), { - status: 200, - headers: { 'Content-Type': 'application/json' }, - }); + makeFetchMock((url) => { + if (url.includes('.well-known')) fetchCallCount++; }); }); @@ -166,28 +196,14 @@ describe('oidc() standalone — no shared store', () => { }); describe('oidc() with shared store', () => { - let fetchCallCount = 0; + let wellknownFetchCount = 0; beforeEach(() => { - fetchCallCount = 0; + wellknownFetchCount = 0; vi.stubGlobal('localStorage', makeStorageStub()); vi.stubGlobal('sessionStorage', makeStorageStub()); - - vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => { - const url = typeof input === 'string' ? input : (input as Request).url; - fetchCallCount++; - - if (url.includes('.well-known')) { - return new Response(JSON.stringify(mockWellknownResponse), { - status: 200, - headers: { 'Content-Type': 'application/json' }, - }); - } - - return new Response(JSON.stringify({}), { - status: 200, - headers: { 'Content-Type': 'application/json' }, - }); + makeFetchMock((url) => { + if (url.includes('.well-known')) wellknownFetchCount++; }); }); @@ -208,29 +224,66 @@ describe('oidc() with shared store', () => { expect(client.authorize).toBeDefined(); }); - it('subscribe() returns an unsubscribe function', async () => { + it('subscribe() fires when oidcApi state changes on the shared store', async () => { const sharedStore = makeSharedStore(); const client = await oidc({ config: oidcConfig }, sharedStore); if ('error' in client) throw new Error('Expected oidc client, got error'); const listener = vi.fn(); - const unsubscribe = client.subscribe(listener); + client.subscribe(listener); - expect(unsubscribe).toBeInstanceOf(Function); + // Dispatch an oidcApi mutation — any action that causes a state change will notify the subscriber + const typedStore = injectIntoStore(sharedStore); + typedStore.dispatch({ type: 'test/action' }); + + expect(listener).toHaveBeenCalled(); }); it('reuses cached wellknown response — no additional fetch when store already has it', async () => { const sharedStore = makeSharedStore(); - // Pre-populate the wellknown cache by routing through the typed store from injectIntoStore + // Simulate the owning store (davinci/journey) having already fetched wellknown const typedStore = injectIntoStore(sharedStore); await typedStore.dispatch(wellknownApi.endpoints.configuration.initiate(TEST_WELLKNOWN_URL)); - const fetchesAfterPreload = fetchCallCount; + const fetchesAfterOwnerInit = wellknownFetchCount; - // oidc() should hit the cache, not make another wellknown request + // oidc() using the same wellknown URL should hit the RTK Query cache await oidc({ config: oidcConfig }, sharedStore); - expect(fetchCallCount).toBe(fetchesAfterPreload); + expect(wellknownFetchCount).toBe(fetchesAfterOwnerInit); + }); + + it('warns when requestMiddleware is passed alongside sharedStore', async () => { + const sharedStore = makeSharedStore(); + const warnSpy = vi.spyOn(console, 'warn').mockImplementation(vi.fn()); + + // Set log level to 'warn' so the logger actually emits the warning to console.warn. + // The default level is 'error', which silently suppresses warn/info/debug messages. + await oidc( + { + config: oidcConfig, + logger: { level: 'warn' }, + requestMiddleware: [() => () => (action: unknown) => action], + }, + sharedStore, + ); + + const warnCalls = warnSpy.mock.calls.map((args) => args.join(' ')); + expect(warnCalls.some((msg) => msg.includes('requestMiddleware'))).toBe(true); + + warnSpy.mockRestore(); + }); + + it('does not warn when no requestMiddleware is passed with sharedStore', async () => { + const sharedStore = makeSharedStore(); + const warnSpy = vi.spyOn(console, 'warn').mockImplementation(vi.fn()); + + await oidc({ config: oidcConfig, logger: { level: 'warn' } }, sharedStore); + + const warnCalls = warnSpy.mock.calls.map((args) => args.join(' ')); + expect(warnCalls.some((msg) => msg.includes('requestMiddleware'))).toBe(false); + + warnSpy.mockRestore(); }); }); From 1ea31e5a418bb875f0f6f797ea4a2775973ba191 Mon Sep 17 00:00:00 2001 From: Ryan Bas Date: Wed, 12 Aug 2026 12:12:07 -0600 Subject: [PATCH 07/11] chore: update-to-rc --- pnpm-lock.yaml | 141 ++++++++++++++++++-------------------------- pnpm-workspace.yaml | 8 +-- 2 files changed, 61 insertions(+), 88 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1bb49164ea..bdd3565bcd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,17 +35,17 @@ catalogs: specifier: 0.87.1 version: 0.87.1 '@effect/opentelemetry': - specifier: 4.0.0-beta.103 - version: 4.0.0-beta.103 + specifier: 4.0.0-rc.108 + version: 4.0.0-rc.108 '@effect/platform-node': - specifier: 4.0.0-beta.103 - version: 4.0.0-beta.103 + specifier: 4.0.0-rc.108 + version: 4.0.0-rc.108 '@effect/vitest': - specifier: 4.0.0-beta.103 - version: 4.0.0-beta.103 + specifier: 4.0.0-rc.108 + version: 4.0.0-rc.108 effect: - specifier: 4.0.0-beta.103 - version: 4.0.0-beta.103 + specifier: 4.0.0-rc.108 + version: 4.0.0-rc.108 vite: vite: specifier: ^7.3.6 @@ -344,7 +344,7 @@ importers: version: 4.9.0 effect: specifier: catalog:effect - version: 4.0.0-beta.103 + version: 4.0.0-rc.108 devDependencies: '@effect/language-service': specifier: catalog:effect @@ -381,10 +381,10 @@ importers: version: 0.87.1 '@effect/opentelemetry': specifier: catalog:effect - version: 4.0.0-beta.103(@opentelemetry/api-logs@0.207.0)(@opentelemetry/api@1.9.0)(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-logs@0.207.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-web@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)(effect@4.0.0-beta.103) + version: 4.0.0-rc.108(@opentelemetry/api-logs@0.207.0)(@opentelemetry/api@1.9.0)(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-logs@0.207.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-web@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)(effect@4.0.0-rc.108) '@effect/platform-node': specifier: catalog:effect - version: 4.0.0-beta.103(effect@4.0.0-beta.103)(ioredis@5.11.1) + version: 4.0.0-rc.108(effect@4.0.0-rc.108)(ioredis@5.11.1) '@opentelemetry/sdk-logs': specifier: 0.207.0 version: 0.207.0(@opentelemetry/api@1.9.0) @@ -402,14 +402,14 @@ importers: version: 2.2.0(@opentelemetry/api@1.9.0) effect: specifier: catalog:effect - version: 4.0.0-beta.103 + version: 4.0.0-rc.108 nanoid: specifier: ^5.1.16 version: 5.1.16 devDependencies: '@effect/vitest': specifier: catalog:effect - version: 4.0.0-beta.103(effect@4.0.0-beta.103)(vitest@4.1.10) + version: 4.0.0-rc.108(effect@4.0.0-rc.108)(vitest@4.1.10) vitest: specifier: catalog:vitest version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) @@ -459,14 +459,14 @@ importers: version: 2.10.1 effect: specifier: catalog:effect - version: 4.0.0-beta.103 + version: 4.0.0-rc.108 immer: specifier: 'catalog:' version: 10.2.0 devDependencies: '@effect/vitest': specifier: catalog:effect - version: 4.0.0-beta.103(effect@4.0.0-beta.103)(vitest@4.1.10) + version: 4.0.0-rc.108(effect@4.0.0-rc.108)(vitest@4.1.10) vitest: specifier: catalog:vitest version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) @@ -512,7 +512,7 @@ importers: version: 2.10.1 effect: specifier: catalog:effect - version: 4.0.0-beta.103 + version: 4.0.0-rc.108 tslib: specifier: 'catalog:' version: 2.8.1 @@ -561,14 +561,14 @@ importers: version: 2.10.1 effect: specifier: catalog:effect - version: 4.0.0-beta.103 + version: 4.0.0-rc.108 jose: specifier: 'catalog:' version: 6.2.3 devDependencies: '@effect/vitest': specifier: catalog:effect - version: 4.0.0-beta.103(effect@4.0.0-beta.103)(vitest@4.1.10) + version: 4.0.0-rc.108(effect@4.0.0-rc.108)(vitest@4.1.10) msw: specifier: 'catalog:' version: 2.12.1(@types/node@24.9.2)(typescript@5.9.3) @@ -635,7 +635,7 @@ importers: version: link:../sdk-types effect: specifier: catalog:effect - version: 4.0.0-beta.103 + version: 4.0.0-rc.108 scratchpad: dependencies: @@ -676,19 +676,19 @@ importers: dependencies: '@effect/platform-node': specifier: catalog:effect - version: 4.0.0-beta.103(effect@4.0.0-beta.103)(ioredis@5.11.1) + version: 4.0.0-rc.108(effect@4.0.0-rc.108)(ioredis@5.11.1) effect: specifier: catalog:effect - version: 4.0.0-beta.103 + version: 4.0.0-rc.108 tools/user-scripts: dependencies: '@effect/platform-node': specifier: catalog:effect - version: 4.0.0-beta.103(effect@4.0.0-beta.103)(ioredis@5.11.1) + version: 4.0.0-rc.108(effect@4.0.0-rc.108)(ioredis@5.11.1) effect: specifier: catalog:effect - version: 4.0.0-beta.103 + version: 4.0.0-rc.108 vitest: specifier: catalog:vitest version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) @@ -698,7 +698,7 @@ importers: version: 0.87.1 '@effect/vitest': specifier: catalog:effect - version: 4.0.0-beta.103(effect@4.0.0-beta.103)(vitest@4.1.10) + version: 4.0.0-rc.108(effect@4.0.0-rc.108)(vitest@4.1.10) packages: @@ -1572,20 +1572,20 @@ packages: resolution: {integrity: sha512-kcljlJmEgqg5mFAM6UShJYJjMqJb3TbHHxrK8Qoubvwugc0aVWpRkbdgQvK5b17puOt3BKXXKOmcV+oQt0oQqQ==} hasBin: true - '@effect/opentelemetry@4.0.0-beta.103': - resolution: {integrity: sha512-nGen5/SeuCkSII+X71YjCUsT/r1AqfS6eWyzCTzXv0NqyLxtnpWJxSYBGy5LtwZFMQsTmQKC7R426IzXbsxOXg==} + '@effect/opentelemetry@4.0.0-rc.108': + resolution: {integrity: sha512-jlJ3XmYhPQv3XV75mIBWUdggkCLIhSNQK2lGM3M89/ifdwkYfKBsPbW1AP36l54ImH79Hi0JrNdL8lOUhctHmg==} engines: {node: '>=18.0.0'} peerDependencies: - '@opentelemetry/api': ^1.9 + '@opentelemetry/api': '>=1.9.0 <2.0.0' '@opentelemetry/api-logs': '>=0.203.0 <0.300.0' - '@opentelemetry/resources': ^2.0.0 + '@opentelemetry/resources': '>=2.0.0 <3.0.0' '@opentelemetry/sdk-logs': '>=0.203.0 <0.300.0' - '@opentelemetry/sdk-metrics': ^2.0.0 - '@opentelemetry/sdk-trace-base': ^2.0.0 - '@opentelemetry/sdk-trace-node': ^2.0.0 - '@opentelemetry/sdk-trace-web': ^2.0.0 - '@opentelemetry/semantic-conventions': ^1.33.0 - effect: ^4.0.0-beta.103 + '@opentelemetry/sdk-metrics': '>=2.0.0 <3.0.0' + '@opentelemetry/sdk-trace-base': '>=2.0.0 <3.0.0' + '@opentelemetry/sdk-trace-node': '>=2.0.0 <3.0.0' + '@opentelemetry/sdk-trace-web': '>=2.0.0 <3.0.0' + '@opentelemetry/semantic-conventions': '>=1.33.0 <2.0.0' + effect: ^4.0.0-rc.108 peerDependenciesMeta: '@opentelemetry/api': optional: true @@ -1604,24 +1604,24 @@ packages: '@opentelemetry/sdk-trace-web': optional: true - '@effect/platform-node-shared@4.0.0-beta.103': - resolution: {integrity: sha512-0aCZMBid5ifqmY55TkfCDLaGTIM8qu3bNFUW7qL9vh/7jFOkaIAMX2MA8muG4deqW17XWxawddWu4v0fK+UW3g==} + '@effect/platform-node-shared@4.0.0-rc.108': + resolution: {integrity: sha512-g5dSRR+tHzFcWav5A6zbug78oV8WPJL5BJqgKlKtow0cQ2IpULcLZaP2xCYR3RJDvz5SETREmPCJ+BNONIsalw==} engines: {node: '>=18.0.0'} peerDependencies: - effect: ^4.0.0-beta.103 + effect: ^4.0.0-rc.108 - '@effect/platform-node@4.0.0-beta.103': - resolution: {integrity: sha512-VD8fbpendwFokMwzC7/MxazjhEVDihPC5NZtomYEyZwGaA1LXMvwP1y8pfXwfshUkG56TN4EMQqzu72c0B9FhA==} + '@effect/platform-node@4.0.0-rc.108': + resolution: {integrity: sha512-Nof78154BaHGdSYr4TPQFZ5+Dg+HkpmbI3SQUdwsby5QNs6yahGJPu2AgdIVqdx7pKZ2w7j/bvdnqoMmkG0PbA==} engines: {node: '>=18.0.0'} peerDependencies: - effect: ^4.0.0-beta.103 - ioredis: ^5.7.0 + effect: ^4.0.0-rc.108 + ioredis: '>=5.7.0 <6.0.0' - '@effect/vitest@4.0.0-beta.103': - resolution: {integrity: sha512-Kz3gemVuJNAZ3e4V6A7BwAP87x2Av8LyHOlCjy9jbZzlncwJXO7Olk1Sje3hdKaet3wEl51A/0/89xJ2IYSgNg==} + '@effect/vitest@4.0.0-rc.108': + resolution: {integrity: sha512-XD2GP1JATN28wnIeFGsBqYMuQDCHIodKKgFulGyG91GvuHqgf2gz+WxR2LPdyNoKMtr7lsbRzVj07niSYtIKzA==} peerDependencies: - effect: ^4.0.0-beta.103 - vitest: ^4.1.0 + effect: ^4.0.0-rc.108 + vitest: '>=4.1.0 <5.0.0' '@emnapi/core@1.4.5': resolution: {integrity: sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==} @@ -4620,8 +4620,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - effect@4.0.0-beta.103: - resolution: {integrity: sha512-pE8TxF4m2tQzVI+77dIlm3s+81TACV1AiX1JEkvY+zVuxgQQ8aGSkqXNJF6b/ST+coCSk5cUdbULpQ7sm4oHyw==} + effect@4.0.0-rc.108: + resolution: {integrity: sha512-KmI3DlKZWPvCL4QQ2FMaPOuxMt/7DrKMENCY/gQ+MkDR5QYw25wgU5Zmh/wVLboNjIci1gNOgNCFe4xqgxli3A==} ejs@5.0.1: resolution: {integrity: sha512-COqBPFMxuPTPspXl2DkVYaDS3HtrD1GpzOGkNTJ1IYkifq/r9h8SVEFrjA3D9/VJGOEoMQcrlhpntcSUrM8k6A==} @@ -5068,9 +5068,6 @@ packages: resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} engines: {node: '>= 18.0.0'} - find-my-way-ts@0.1.6: - resolution: {integrity: sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==} - find-node-modules@2.1.3: resolution: {integrity: sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==} @@ -5543,10 +5540,6 @@ packages: resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ini@7.0.0: - resolution: {integrity: sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w==} - engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} - inquirer@8.2.5: resolution: {integrity: sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==} engines: {node: '>=12.0.0'} @@ -6429,9 +6422,6 @@ packages: typescript: optional: true - multipasta@0.2.8: - resolution: {integrity: sha512-ZPWuMKyv0cSO29f7hozp+k6+crZbQijV8ipMvxNxRf2SwtYGTX1ZX89Kd20VV4H9Znonx+EQn+iy1wGQsJ+b+Q==} - mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} @@ -7791,10 +7781,6 @@ packages: resolution: {integrity: sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==} engines: {node: '>=14.16'} - toml@4.3.0: - resolution: {integrity: sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A==} - engines: {node: '>=20'} - totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -9617,10 +9603,10 @@ snapshots: '@effect/language-service@0.87.1': {} - '@effect/opentelemetry@4.0.0-beta.103(@opentelemetry/api-logs@0.207.0)(@opentelemetry/api@1.9.0)(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-logs@0.207.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-web@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)(effect@4.0.0-beta.103)': + '@effect/opentelemetry@4.0.0-rc.108(@opentelemetry/api-logs@0.207.0)(@opentelemetry/api@1.9.0)(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-logs@0.207.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-web@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)(effect@4.0.0-rc.108)': dependencies: '@opentelemetry/semantic-conventions': 1.38.0 - effect: 4.0.0-beta.103 + effect: 4.0.0-rc.108 optionalDependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/api-logs': 0.207.0 @@ -9631,19 +9617,19 @@ snapshots: '@opentelemetry/sdk-trace-node': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-web': 2.2.0(@opentelemetry/api@1.9.0) - '@effect/platform-node-shared@4.0.0-beta.103(effect@4.0.0-beta.103)': + '@effect/platform-node-shared@4.0.0-rc.108(effect@4.0.0-rc.108)': dependencies: '@types/ws': 8.18.1 - effect: 4.0.0-beta.103 + effect: 4.0.0-rc.108 ws: 8.21.1 transitivePeerDependencies: - bufferutil - utf-8-validate - '@effect/platform-node@4.0.0-beta.103(effect@4.0.0-beta.103)(ioredis@5.11.1)': + '@effect/platform-node@4.0.0-rc.108(effect@4.0.0-rc.108)(ioredis@5.11.1)': dependencies: - '@effect/platform-node-shared': 4.0.0-beta.103(effect@4.0.0-beta.103) - effect: 4.0.0-beta.103 + '@effect/platform-node-shared': 4.0.0-rc.108(effect@4.0.0-rc.108) + effect: 4.0.0-rc.108 ioredis: 5.11.1 mime: 4.1.0 undici: 7.29.0 @@ -9651,9 +9637,9 @@ snapshots: - bufferutil - utf-8-validate - '@effect/vitest@4.0.0-beta.103(effect@4.0.0-beta.103)(vitest@4.1.10)': + '@effect/vitest@4.0.0-rc.108(effect@4.0.0-rc.108)(vitest@4.1.10)': dependencies: - effect: 4.0.0-beta.103 + effect: 4.0.0-rc.108 vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.9.2)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(jsdom@27.4.0(@noble/hashes@1.8.0))(msw@2.12.1(@types/node@24.9.2)(typescript@5.9.3))(vite@7.3.6(@types/node@24.9.2)(jiti@2.6.1)(terser@5.48.0)(tsx@4.21.0)(yaml@2.9.0)) '@emnapi/core@1.4.5': @@ -13010,18 +12996,13 @@ snapshots: ee-first@1.1.1: {} - effect@4.0.0-beta.103: + effect@4.0.0-rc.108: dependencies: '@standard-schema/spec': 1.1.0 fast-check: 4.9.0 - find-my-way-ts: 0.1.6 - ini: 7.0.0 kubernetes-types: 1.30.0 msgpackr: 2.0.5 - multipasta: 0.2.8 - toml: 4.3.0 uuid: 14.0.1 - yaml: 2.9.0 ejs@5.0.1: {} @@ -13657,8 +13638,6 @@ snapshots: transitivePeerDependencies: - supports-color - find-my-way-ts@0.1.6: {} - find-node-modules@2.1.3: dependencies: findup-sync: 4.0.0 @@ -14181,8 +14160,6 @@ snapshots: ini@4.1.3: {} - ini@7.0.0: {} - inquirer@8.2.5: dependencies: ansi-escapes: 4.3.2 @@ -15255,8 +15232,6 @@ snapshots: transitivePeerDependencies: - '@types/node' - multipasta@0.2.8: {} - mute-stream@0.0.8: {} mute-stream@1.0.0: {} @@ -16793,8 +16768,6 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 - toml@4.3.0: {} - totalist@3.0.1: {} tough-cookie@5.1.2: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 1e9c1073e3..0281ac8383 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -17,11 +17,11 @@ catalog: tsx: '4.21.0' catalogs: effect: - effect: '4.0.0-beta.103' + effect: '4.0.0-rc.108' '@effect/language-service': '0.87.1' - '@effect/platform-node': '4.0.0-beta.103' - '@effect/vitest': '4.0.0-beta.103' - '@effect/opentelemetry': '4.0.0-beta.103' + '@effect/platform-node': '4.0.0-rc.108' + '@effect/vitest': '4.0.0-rc.108' + '@effect/opentelemetry': '4.0.0-rc.108' vitest: vitest: '^4.1.0' '@vitest/coverage-v8': '^4.1.0' From f57788e113db150dd7b7a1625c8b61b00633782e Mon Sep 17 00:00:00 2001 From: Ryan Bas Date: Wed, 12 Aug 2026 13:28:39 -0600 Subject: [PATCH 08/11] =?UTF-8?q?fix(davinci-client):=20remove=20trailing?= =?UTF-8?q?=20newline,=20finish=20Either=E2=86=92Result=20migration=20in?= =?UTF-8?q?=20node.reducer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api-report/davinci-client.api.md | 35 +- .../api-report/davinci-client.types.api.md | 35 +- .../davinci-client/src/lib/node.reducer.ts | 6 +- .../api-report/journey-client.api.md | 1007 +++++++++-------- .../api-report/journey-client.types.api.md | 981 ++++++++-------- 5 files changed, 1040 insertions(+), 1024 deletions(-) diff --git a/packages/davinci-client/api-report/davinci-client.api.md b/packages/davinci-client/api-report/davinci-client.api.md index 4c9616c1f5..4bc7e7e411 100644 --- a/packages/davinci-client/api-report/davinci-client.api.md +++ b/packages/davinci-client/api-report/davinci-client.api.md @@ -405,8 +405,12 @@ export function davinci(input: { resume: (input: { continueToken: string }) => Promise; start: ( options?: StartOptions | undefined, - ) => Promise; - update: (collector: T) => Updater; + ) => Promise; + update: < + T extends SingleValueCollectors | MultiSelectCollector | ObjectValueCollectors | AutoCollectors, + >( + collector: T, + ) => Updater; validate: ( collector: | SingleValueCollectors @@ -416,9 +420,6 @@ export function davinci(input: { ) => Validator; pollStatus: (collector: PollingCollector) => Poller; getClient: () => - | { - status: 'start'; - } | { action: string; collectors: Collectors[]; @@ -436,6 +437,12 @@ export function davinci(input: { name?: string; status: 'continue'; } + | { + status: 'failure'; + } + | { + status: 'start'; + } | { authorization?: { code?: string; @@ -447,10 +454,16 @@ export function davinci(input: { getCollectors: () => Collectors[]; getError: () => DaVinciError | null; getErrorCollectors: () => CollectorErrors[]; - getNode: () => StartNode | ErrorNode | FailureNode | ContinueNode | SuccessNode; + getNode: () => ContinueNode | ErrorNode | FailureNode | StartNode | SuccessNode; getServer: () => | { - status: 'start'; + _links?: Links; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + eventName?: string; + status: 'continue'; } | { _links?: Links; @@ -470,13 +483,7 @@ export function davinci(input: { status: 'failure'; } | { - _links?: Links; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - eventName?: string; - status: 'continue'; + status: 'start'; } | { _links?: Links; diff --git a/packages/davinci-client/api-report/davinci-client.types.api.md b/packages/davinci-client/api-report/davinci-client.types.api.md index 79eac2bd49..b509b4aa3d 100644 --- a/packages/davinci-client/api-report/davinci-client.types.api.md +++ b/packages/davinci-client/api-report/davinci-client.types.api.md @@ -405,8 +405,12 @@ export function davinci(input: { resume: (input: { continueToken: string }) => Promise; start: ( options?: StartOptions | undefined, - ) => Promise; - update: (collector: T) => Updater; + ) => Promise; + update: < + T extends SingleValueCollectors | MultiSelectCollector | ObjectValueCollectors | AutoCollectors, + >( + collector: T, + ) => Updater; validate: ( collector: | SingleValueCollectors @@ -416,9 +420,6 @@ export function davinci(input: { ) => Validator; pollStatus: (collector: PollingCollector) => Poller; getClient: () => - | { - status: 'start'; - } | { action: string; collectors: Collectors[]; @@ -436,6 +437,12 @@ export function davinci(input: { name?: string; status: 'continue'; } + | { + status: 'failure'; + } + | { + status: 'start'; + } | { authorization?: { code?: string; @@ -447,10 +454,16 @@ export function davinci(input: { getCollectors: () => Collectors[]; getError: () => DaVinciError | null; getErrorCollectors: () => CollectorErrors[]; - getNode: () => StartNode | ErrorNode | FailureNode | ContinueNode | SuccessNode; + getNode: () => ContinueNode | ErrorNode | FailureNode | StartNode | SuccessNode; getServer: () => | { - status: 'start'; + _links?: Links; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + eventName?: string; + status: 'continue'; } | { _links?: Links; @@ -470,13 +483,7 @@ export function davinci(input: { status: 'failure'; } | { - _links?: Links; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - eventName?: string; - status: 'continue'; + status: 'start'; } | { _links?: Links; diff --git a/packages/davinci-client/src/lib/node.reducer.ts b/packages/davinci-client/src/lib/node.reducer.ts index f7215f85fb..f685c89d38 100644 --- a/packages/davinci-client/src/lib/node.reducer.ts +++ b/packages/davinci-client/src/lib/node.reducer.ts @@ -8,7 +8,7 @@ * Import the required utilities from Redux Toolkit */ import { createAction, createReducer } from '@reduxjs/toolkit'; -import { Either } from 'effect'; +import { Result } from 'effect'; /** * Import the collector utilities @@ -58,8 +58,8 @@ function updateCollector( cb: (resolvedValue: CollectorValueType) => void, ): void { const result = resolveCollectorUpdateValue(collector, value); - if (Either.isRight(result)) { - const resolvedValue = result.right; + if (Result.isSuccess(result)) { + const resolvedValue = result.success; cb(resolvedValue); } } diff --git a/packages/journey-client/api-report/journey-client.api.md b/packages/journey-client/api-report/journey-client.api.md index 88ee56f6fb..173e3a38be 100644 --- a/packages/journey-client/api-report/journey-client.api.md +++ b/packages/journey-client/api-report/journey-client.api.md @@ -1,503 +1,504 @@ -## API Report File for "@forgerock/journey-client" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts - -import { ActionTypes } from '@forgerock/sdk-request-middleware'; -import { AuthResponse } from '@forgerock/sdk-types'; -import { Callback } from '@forgerock/sdk-types'; -import { CallbackType } from '@forgerock/sdk-types'; -import { callbackType } from '@forgerock/sdk-types'; -import { createWellknownError } from '@forgerock/sdk-utilities'; -import { CustomLogger } from '@forgerock/sdk-logger'; -import { FailedPolicyRequirement } from '@forgerock/sdk-types'; -import { FailureDetail } from '@forgerock/sdk-types'; -import { GenericError } from '@forgerock/sdk-types'; -import { isValidWellknownUrl } from '@forgerock/sdk-utilities'; -import { JourneyClientConfig } from '@forgerock/sdk-types'; -import { JourneyServerConfig } from '@forgerock/sdk-types'; -import { LogLevel } from '@forgerock/sdk-logger'; -import { NameValue } from '@forgerock/sdk-types'; -import { PolicyKey } from '@forgerock/sdk-types'; -import { PolicyParams } from '@forgerock/sdk-types'; -import { PolicyRequirement } from '@forgerock/sdk-types'; -import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; -import type { SdkStore } from '@forgerock/sdk-types'; -import { Step } from '@forgerock/sdk-types'; -import { StepDetail } from '@forgerock/sdk-types'; -import { StepType } from '@forgerock/sdk-types'; -import { WellknownResponse } from '@forgerock/sdk-types'; - -export { ActionTypes } - -// @public -export class AttributeInputCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getName(): string; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setValidateOnly(value: boolean): void; - setValue(value: T): void; -} - -export { AuthResponse } - -// @public -export class BaseCallback { - constructor(payload: Callback); - getInputValue(selector?: number | string): unknown; - getOutputByName(name: string, defaultValue: T): T; - getOutputValue(selector?: number | string): unknown; - getType(): CallbackType; - // (undocumented) - payload: Callback; - setInputValue(value: unknown, selector?: number | string | RegExp): void; -} - -export { Callback } - -// @public (undocumented) -export type CallbackFactory = (callback: Callback) => BaseCallback; - -export { CallbackType } - -export { callbackType } - -// @public -export class ChoiceCallback extends BaseCallback { - constructor(payload: Callback); - getChoices(): string[]; - getDefaultChoice(): number; - getPrompt(): string; - // (undocumented) - payload: Callback; - setChoiceIndex(index: number): void; - setChoiceValue(value: string): void; -} - -// @public -export class ConfirmationCallback extends BaseCallback { - constructor(payload: Callback); - getDefaultOption(): number; - getMessageType(): number; - getOptions(): string[]; - getOptionType(): number; - getPrompt(): string; - // (undocumented) - payload: Callback; - setOptionIndex(index: number): void; - setOptionValue(value: string): void; -} - -// @public (undocumented) -export function createCallback(callback: Callback): BaseCallback; - -export { createWellknownError } - -export { CustomLogger } - -// @public -export class DeviceProfileCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - isLocationRequired(): boolean; - isMetadataRequired(): boolean; - // (undocumented) - payload: Callback; - setProfile(profile: DeviceProfileData): void; -} - -// @public (undocumented) -export interface DeviceProfileData { - // (undocumented) - identifier: string; - // (undocumented) - location?: Geolocation_2 | Record; - // (undocumented) - metadata?: { - hardware: { - display: { - [key: string]: string | number | null; - }; - [key: string]: any; - }; - browser: { - [key: string]: string | number | null; - }; - platform: { - [key: string]: string | number | null; - }; - }; -} - -export { FailedPolicyRequirement } - -export { FailureDetail } - -export { GenericError } - -// @public (undocumented) -interface Geolocation_2 { - // (undocumented) - latitude: number; - // (undocumented) - longitude: number; -} -export { Geolocation_2 as Geolocation } - -// @public -export class HiddenValueCallback extends BaseCallback { - constructor(payload: Callback); - // (undocumented) - payload: Callback; -} - -// @public (undocumented) -export interface IdPValue { - // (undocumented) - provider: string; - // (undocumented) - uiConfig: { - [key: string]: string; - }; -} - -// @internal -export interface InternalJourneyClientConfig { - // (undocumented) - error?: GenericError; - // (undocumented) - serverConfig: ResolvedServerConfig; -} - -export { isValidWellknownUrl } - -// @public -export function journey(input: { - config: JourneyClientConfig; - requestMiddleware?: RequestMiddleware[]; - logger?: { - level: LogLevel; - custom?: CustomLogger; - }; -}): Promise; - -// @public -export interface JourneyClient { - // (undocumented) - next: (step: JourneyStep, options?: NextOptions) => Promise; - // (undocumented) - redirect: (step: JourneyStep) => Promise; - // (undocumented) - resume: (url: string, options?: ResumeOptions) => Promise; - // (undocumented) - start: (options?: StartParam) => Promise; - // (undocumented) - store: SdkStore; - // (undocumented) - subscribe: (listener: () => void) => () => void; - // (undocumented) - terminate: (options?: { - query?: Record; - }) => Promise; -} - -export { JourneyClientConfig } - -// @public (undocumented) -export type JourneyLoginFailure = AuthResponse & { - type: StepType.LoginFailure; - payload: Step; - getCode: () => number; - getDetail: () => FailureDetail | undefined; - getMessage: () => string | undefined; - getProcessedMessage: (messageCreator?: MessageCreator) => ProcessedPropertyError[]; - getReason: () => string | undefined; -}; - -// @public (undocumented) -export type JourneyLoginSuccess = AuthResponse & { - type: StepType.LoginSuccess; - payload: Step; - getRealm: () => string | undefined; - getSessionToken: () => string | undefined; - getSuccessUrl: () => string | undefined; -}; - -// @public (undocumented) -export type JourneyResult = JourneyStep | JourneyLoginSuccess | JourneyLoginFailure | GenericError; - -export { JourneyServerConfig } - -// @public (undocumented) -export type JourneyStep = AuthResponse & { - type: StepType.Step; - payload: Step; - callbacks: BaseCallback[]; - getCallbackOfType: (type: CallbackType) => T; - getCallbacksOfType: (type: CallbackType) => T[]; - setCallbackValue: (type: CallbackType, value: unknown) => void; - getDescription: () => string | undefined; - getHeader: () => string | undefined; - getStage: () => string | undefined; -}; - -// @public -export class KbaCreateCallback extends BaseCallback { - constructor(payload: Callback); - getPredefinedQuestions(): string[]; - getPrompt(): string; - isAllowedUserDefinedQuestions(): boolean; - // (undocumented) - payload: Callback; - setAnswer(answer: string): void; - setQuestion(question: string): void; -} - -export { LogLevel } - -// @public (undocumented) -export interface MessageCreator { - // (undocumented) - [key: string]: (propertyName: string, params?: { - [key: string]: unknown; - }) => string; -} - -// @public -export class MetadataCallback extends BaseCallback { - constructor(payload: Callback); - getData(): T; - // (undocumented) - payload: Callback; -} - -// @public -export class NameCallback extends BaseCallback { - constructor(payload: Callback); - getPrompt(): string; - // (undocumented) - payload: Callback; - setName(name: string): void; -} - -export { NameValue } - -// @public (undocumented) -export interface NextOptions { - // (undocumented) - query?: Record; -} - -// @public -export class PasswordCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): string[]; - getPrompt(): string; - // (undocumented) - payload: Callback; - setPassword(password: string): void; -} - -// @public -export class PingOneProtectEvaluationCallback extends BaseCallback { - constructor(payload: Callback); - getPauseBehavioralData(): boolean; - // (undocumented) - payload: Callback; - setClientError(errorMessage: string): void; - setData(data: string): void; -} - -// @public -export class PingOneProtectInitializeCallback extends BaseCallback { - constructor(payload: Callback); - getConfig(): Record | { - envId: string; - consoleLogEnabled: boolean; - deviceAttributesToIgnore: string[]; - customHost: string; - lazyMetadata: boolean; - behavioralDataCollection: boolean; - deviceKeyRsyncIntervals: number; - enableTrust: boolean; - disableTags: boolean; - disableHub: boolean; - }; - // (undocumented) - payload: Callback; - // (undocumented) - setClientError(errorMessage: string): void; -} - -export { PolicyKey } - -export { PolicyParams } - -export { PolicyRequirement } - -// @public -export class PollingWaitCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - getWaitTime(): number; - // (undocumented) - payload: Callback; -} - -// @public (undocumented) -export interface ProcessedPropertyError { - // (undocumented) - detail: FailedPolicyRequirement; - // (undocumented) - messages: string[]; -} - -// @public -export class ReCaptchaCallback extends BaseCallback { - constructor(payload: Callback); - getSiteKey(): string; - // (undocumented) - payload: Callback; - setResult(result: string): void; -} - -// @public -export class ReCaptchaEnterpriseCallback extends BaseCallback { - constructor(payload: Callback); - getApiUrl(): string; - getElementClass(): string; - getSiteKey(): string; - // (undocumented) - payload: Callback; - setAction(action: string): void; - setClientError(error: string): void; - setPayload(payload: unknown): void; - setResult(result: string): void; -} - -// @public -export class RedirectCallback extends BaseCallback { - constructor(payload: Callback); - getRedirectUrl(): string; - // (undocumented) - payload: Callback; -} - -export { RequestMiddleware } - -// @public -export interface ResolvedServerConfig { - // (undocumented) - baseUrl: string; - // (undocumented) - paths: { - authenticate: string; - sessions: string; - }; -} - -// @public (undocumented) -export interface ResumeOptions { - // (undocumented) - journey?: string; - // (undocumented) - query?: Record; -} - -// @public -export class SelectIdPCallback extends BaseCallback { - constructor(payload: Callback); - getProviders(): IdPValue[]; - // (undocumented) - payload: Callback; - setProvider(value: string): void; -} - -// @public (undocumented) -export interface StartParam { - // (undocumented) - journey: string; - // (undocumented) - query?: Record; -} - -export { Step } - -export { StepDetail } - -export { StepType } - -// @public -export class SuspendedTextOutputCallback extends TextOutputCallback { - constructor(payload: Callback); - // (undocumented) - payload: Callback; -} - -// @public -export class TermsAndConditionsCallback extends BaseCallback { - constructor(payload: Callback); - getCreateDate(): Date | null; - getTerms(): string; - getVersion(): string; - // (undocumented) - payload: Callback; - setAccepted(accepted?: boolean): void; -} - -// @public -export class TextInputCallback extends BaseCallback { - constructor(payload: Callback); - getPrompt(): string; - // (undocumented) - payload: Callback; - setInput(input: string): void; -} - -// @public -export class TextOutputCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - getMessageType(): string; - // (undocumented) - payload: Callback; -} - -// @public -export class ValidatedCreatePasswordCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setPassword(password: string): void; - setValidateOnly(value: boolean): void; -} - -// @public -export class ValidatedCreateUsernameCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setName(name: string): void; - setValidateOnly(value: boolean): void; -} - -export { WellknownResponse } - -// (No @packageDocumentation comment for this package) - -``` +## API Report File for "@forgerock/journey-client" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ActionTypes } from '@forgerock/sdk-request-middleware'; +import { AuthResponse } from '@forgerock/sdk-types'; +import { Callback } from '@forgerock/sdk-types'; +import { CallbackType } from '@forgerock/sdk-types'; +import { callbackType } from '@forgerock/sdk-types'; +import { createWellknownError } from '@forgerock/sdk-utilities'; +import { CustomLogger } from '@forgerock/sdk-logger'; +import { FailedPolicyRequirement } from '@forgerock/sdk-types'; +import { FailureDetail } from '@forgerock/sdk-types'; +import { GenericError } from '@forgerock/sdk-types'; +import { isValidWellknownUrl } from '@forgerock/sdk-utilities'; +import { JourneyClientConfig } from '@forgerock/sdk-types'; +import { JourneyServerConfig } from '@forgerock/sdk-types'; +import { LogLevel } from '@forgerock/sdk-logger'; +import { NameValue } from '@forgerock/sdk-types'; +import { PolicyKey } from '@forgerock/sdk-types'; +import { PolicyParams } from '@forgerock/sdk-types'; +import { PolicyRequirement } from '@forgerock/sdk-types'; +import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; +import type { SdkStore } from '@forgerock/sdk-types'; +import { Step } from '@forgerock/sdk-types'; +import { StepDetail } from '@forgerock/sdk-types'; +import { StepType } from '@forgerock/sdk-types'; +import { WellknownResponse } from '@forgerock/sdk-types'; + +export { ActionTypes }; + +// @public +export class AttributeInputCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getName(): string; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setValidateOnly(value: boolean): void; + setValue(value: T): void; +} + +export { AuthResponse }; + +// @public +export class BaseCallback { + constructor(payload: Callback); + getInputValue(selector?: number | string): unknown; + getOutputByName(name: string, defaultValue: T): T; + getOutputValue(selector?: number | string): unknown; + getType(): CallbackType; + // (undocumented) + payload: Callback; + setInputValue(value: unknown, selector?: number | string | RegExp): void; +} + +export { Callback }; + +// @public (undocumented) +export type CallbackFactory = (callback: Callback) => BaseCallback; + +export { CallbackType }; + +export { callbackType }; + +// @public +export class ChoiceCallback extends BaseCallback { + constructor(payload: Callback); + getChoices(): string[]; + getDefaultChoice(): number; + getPrompt(): string; + // (undocumented) + payload: Callback; + setChoiceIndex(index: number): void; + setChoiceValue(value: string): void; +} + +// @public +export class ConfirmationCallback extends BaseCallback { + constructor(payload: Callback); + getDefaultOption(): number; + getMessageType(): number; + getOptions(): string[]; + getOptionType(): number; + getPrompt(): string; + // (undocumented) + payload: Callback; + setOptionIndex(index: number): void; + setOptionValue(value: string): void; +} + +// @public (undocumented) +export function createCallback(callback: Callback): BaseCallback; + +export { createWellknownError }; + +export { CustomLogger }; + +// @public +export class DeviceProfileCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + isLocationRequired(): boolean; + isMetadataRequired(): boolean; + // (undocumented) + payload: Callback; + setProfile(profile: DeviceProfileData): void; +} + +// @public (undocumented) +export interface DeviceProfileData { + // (undocumented) + identifier: string; + // (undocumented) + location?: Geolocation_2 | Record; + // (undocumented) + metadata?: { + hardware: { + display: { + [key: string]: string | number | null; + }; + [key: string]: any; + }; + browser: { + [key: string]: string | number | null; + }; + platform: { + [key: string]: string | number | null; + }; + }; +} + +export { FailedPolicyRequirement }; + +export { FailureDetail }; + +export { GenericError }; + +// @public (undocumented) +interface Geolocation_2 { + // (undocumented) + latitude: number; + // (undocumented) + longitude: number; +} +export { Geolocation_2 as Geolocation }; + +// @public +export class HiddenValueCallback extends BaseCallback { + constructor(payload: Callback); + // (undocumented) + payload: Callback; +} + +// @public (undocumented) +export interface IdPValue { + // (undocumented) + provider: string; + // (undocumented) + uiConfig: { + [key: string]: string; + }; +} + +// @internal +export interface InternalJourneyClientConfig { + // (undocumented) + error?: GenericError; + // (undocumented) + serverConfig: ResolvedServerConfig; +} + +export { isValidWellknownUrl }; + +// @public +export function journey(input: { + config: JourneyClientConfig; + requestMiddleware?: RequestMiddleware[]; + logger?: { + level: LogLevel; + custom?: CustomLogger; + }; +}): Promise; + +// @public +export interface JourneyClient { + // (undocumented) + next: (step: JourneyStep, options?: NextOptions) => Promise; + // (undocumented) + redirect: (step: JourneyStep) => Promise; + // (undocumented) + resume: (url: string, options?: ResumeOptions) => Promise; + // (undocumented) + start: (options?: StartParam) => Promise; + // (undocumented) + store: SdkStore; + // (undocumented) + subscribe: (listener: () => void) => () => void; + // (undocumented) + terminate: (options?: { query?: Record }) => Promise; +} + +export { JourneyClientConfig }; + +// @public (undocumented) +export type JourneyLoginFailure = AuthResponse & { + type: StepType.LoginFailure; + payload: Step; + getCode: () => number; + getDetail: () => FailureDetail | undefined; + getMessage: () => string | undefined; + getProcessedMessage: (messageCreator?: MessageCreator) => ProcessedPropertyError[]; + getReason: () => string | undefined; +}; + +// @public (undocumented) +export type JourneyLoginSuccess = AuthResponse & { + type: StepType.LoginSuccess; + payload: Step; + getRealm: () => string | undefined; + getSessionToken: () => string | undefined; + getSuccessUrl: () => string | undefined; +}; + +// @public (undocumented) +export type JourneyResult = JourneyStep | JourneyLoginSuccess | JourneyLoginFailure | GenericError; + +export { JourneyServerConfig }; + +// @public (undocumented) +export type JourneyStep = AuthResponse & { + type: StepType.Step; + payload: Step; + callbacks: BaseCallback[]; + getCallbackOfType: (type: CallbackType) => T; + getCallbacksOfType: (type: CallbackType) => T[]; + setCallbackValue: (type: CallbackType, value: unknown) => void; + getDescription: () => string | undefined; + getHeader: () => string | undefined; + getStage: () => string | undefined; +}; + +// @public +export class KbaCreateCallback extends BaseCallback { + constructor(payload: Callback); + getPredefinedQuestions(): string[]; + getPrompt(): string; + isAllowedUserDefinedQuestions(): boolean; + // (undocumented) + payload: Callback; + setAnswer(answer: string): void; + setQuestion(question: string): void; +} + +export { LogLevel }; + +// @public (undocumented) +export interface MessageCreator { + // (undocumented) + [key: string]: ( + propertyName: string, + params?: { + [key: string]: unknown; + }, + ) => string; +} + +// @public +export class MetadataCallback extends BaseCallback { + constructor(payload: Callback); + getData(): T; + // (undocumented) + payload: Callback; +} + +// @public +export class NameCallback extends BaseCallback { + constructor(payload: Callback); + getPrompt(): string; + // (undocumented) + payload: Callback; + setName(name: string): void; +} + +export { NameValue }; + +// @public (undocumented) +export interface NextOptions { + // (undocumented) + query?: Record; +} + +// @public +export class PasswordCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): string[]; + getPrompt(): string; + // (undocumented) + payload: Callback; + setPassword(password: string): void; +} + +// @public +export class PingOneProtectEvaluationCallback extends BaseCallback { + constructor(payload: Callback); + getPauseBehavioralData(): boolean; + // (undocumented) + payload: Callback; + setClientError(errorMessage: string): void; + setData(data: string): void; +} + +// @public +export class PingOneProtectInitializeCallback extends BaseCallback { + constructor(payload: Callback); + getConfig(): + | Record + | { + envId: string; + consoleLogEnabled: boolean; + deviceAttributesToIgnore: string[]; + customHost: string; + lazyMetadata: boolean; + behavioralDataCollection: boolean; + deviceKeyRsyncIntervals: number; + enableTrust: boolean; + disableTags: boolean; + disableHub: boolean; + }; + // (undocumented) + payload: Callback; + // (undocumented) + setClientError(errorMessage: string): void; +} + +export { PolicyKey }; + +export { PolicyParams }; + +export { PolicyRequirement }; + +// @public +export class PollingWaitCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + getWaitTime(): number; + // (undocumented) + payload: Callback; +} + +// @public (undocumented) +export interface ProcessedPropertyError { + // (undocumented) + detail: FailedPolicyRequirement; + // (undocumented) + messages: string[]; +} + +// @public +export class ReCaptchaCallback extends BaseCallback { + constructor(payload: Callback); + getSiteKey(): string; + // (undocumented) + payload: Callback; + setResult(result: string): void; +} + +// @public +export class ReCaptchaEnterpriseCallback extends BaseCallback { + constructor(payload: Callback); + getApiUrl(): string; + getElementClass(): string; + getSiteKey(): string; + // (undocumented) + payload: Callback; + setAction(action: string): void; + setClientError(error: string): void; + setPayload(payload: unknown): void; + setResult(result: string): void; +} + +// @public +export class RedirectCallback extends BaseCallback { + constructor(payload: Callback); + getRedirectUrl(): string; + // (undocumented) + payload: Callback; +} + +export { RequestMiddleware }; + +// @public +export interface ResolvedServerConfig { + // (undocumented) + baseUrl: string; + // (undocumented) + paths: { + authenticate: string; + sessions: string; + }; +} + +// @public (undocumented) +export interface ResumeOptions { + // (undocumented) + journey?: string; + // (undocumented) + query?: Record; +} + +// @public +export class SelectIdPCallback extends BaseCallback { + constructor(payload: Callback); + getProviders(): IdPValue[]; + // (undocumented) + payload: Callback; + setProvider(value: string): void; +} + +// @public (undocumented) +export interface StartParam { + // (undocumented) + journey: string; + // (undocumented) + query?: Record; +} + +export { Step }; + +export { StepDetail }; + +export { StepType }; + +// @public +export class SuspendedTextOutputCallback extends TextOutputCallback { + constructor(payload: Callback); + // (undocumented) + payload: Callback; +} + +// @public +export class TermsAndConditionsCallback extends BaseCallback { + constructor(payload: Callback); + getCreateDate(): Date | null; + getTerms(): string; + getVersion(): string; + // (undocumented) + payload: Callback; + setAccepted(accepted?: boolean): void; +} + +// @public +export class TextInputCallback extends BaseCallback { + constructor(payload: Callback); + getPrompt(): string; + // (undocumented) + payload: Callback; + setInput(input: string): void; +} + +// @public +export class TextOutputCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + getMessageType(): string; + // (undocumented) + payload: Callback; +} + +// @public +export class ValidatedCreatePasswordCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setPassword(password: string): void; + setValidateOnly(value: boolean): void; +} + +// @public +export class ValidatedCreateUsernameCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setName(name: string): void; + setValidateOnly(value: boolean): void; +} + +export { WellknownResponse }; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/journey-client/api-report/journey-client.types.api.md b/packages/journey-client/api-report/journey-client.types.api.md index 340dadaa91..d33995d6be 100644 --- a/packages/journey-client/api-report/journey-client.types.api.md +++ b/packages/journey-client/api-report/journey-client.types.api.md @@ -1,490 +1,491 @@ -## API Report File for "@forgerock/journey-client" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts - -import { ActionTypes } from '@forgerock/sdk-request-middleware'; -import { AuthResponse } from '@forgerock/sdk-types'; -import { Callback } from '@forgerock/sdk-types'; -import { CallbackType } from '@forgerock/sdk-types'; -import { createWellknownError } from '@forgerock/sdk-utilities'; -import { CustomLogger } from '@forgerock/sdk-logger'; -import { FailedPolicyRequirement } from '@forgerock/sdk-types'; -import { FailureDetail } from '@forgerock/sdk-types'; -import { GenericError } from '@forgerock/sdk-types'; -import { isValidWellknownUrl } from '@forgerock/sdk-utilities'; -import { JourneyClientConfig } from '@forgerock/sdk-types'; -import { JourneyServerConfig } from '@forgerock/sdk-types'; -import { LogLevel } from '@forgerock/sdk-logger'; -import { NameValue } from '@forgerock/sdk-types'; -import { PolicyKey } from '@forgerock/sdk-types'; -import { PolicyParams } from '@forgerock/sdk-types'; -import { PolicyRequirement } from '@forgerock/sdk-types'; -import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; -import type { SdkStore } from '@forgerock/sdk-types'; -import { Step } from '@forgerock/sdk-types'; -import { StepDetail } from '@forgerock/sdk-types'; -import { StepType } from '@forgerock/sdk-types'; -import { WellknownResponse } from '@forgerock/sdk-types'; - -export { ActionTypes } - -// @public -export class AttributeInputCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getName(): string; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setValidateOnly(value: boolean): void; - setValue(value: T): void; -} - -export { AuthResponse } - -// @public -export class BaseCallback { - constructor(payload: Callback); - getInputValue(selector?: number | string): unknown; - getOutputByName(name: string, defaultValue: T): T; - getOutputValue(selector?: number | string): unknown; - getType(): CallbackType; - // (undocumented) - payload: Callback; - setInputValue(value: unknown, selector?: number | string | RegExp): void; -} - -export { Callback } - -// @public (undocumented) -export type CallbackFactory = (callback: Callback) => BaseCallback; - -export { CallbackType } - -// @public -export class ChoiceCallback extends BaseCallback { - constructor(payload: Callback); - getChoices(): string[]; - getDefaultChoice(): number; - getPrompt(): string; - // (undocumented) - payload: Callback; - setChoiceIndex(index: number): void; - setChoiceValue(value: string): void; -} - -// @public -export class ConfirmationCallback extends BaseCallback { - constructor(payload: Callback); - getDefaultOption(): number; - getMessageType(): number; - getOptions(): string[]; - getOptionType(): number; - getPrompt(): string; - // (undocumented) - payload: Callback; - setOptionIndex(index: number): void; - setOptionValue(value: string): void; -} - -// @public (undocumented) -export function createCallback(callback: Callback): BaseCallback; - -export { createWellknownError } - -export { CustomLogger } - -// @public -export class DeviceProfileCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - isLocationRequired(): boolean; - isMetadataRequired(): boolean; - // (undocumented) - payload: Callback; - setProfile(profile: DeviceProfileData): void; -} - -// @public (undocumented) -export interface DeviceProfileData { - // (undocumented) - identifier: string; - // (undocumented) - location?: Geolocation_2 | Record; - // (undocumented) - metadata?: { - hardware: { - display: { - [key: string]: string | number | null; - }; - [key: string]: any; - }; - browser: { - [key: string]: string | number | null; - }; - platform: { - [key: string]: string | number | null; - }; - }; -} - -export { FailedPolicyRequirement } - -export { FailureDetail } - -export { GenericError } - -// @public (undocumented) -interface Geolocation_2 { - // (undocumented) - latitude: number; - // (undocumented) - longitude: number; -} -export { Geolocation_2 as Geolocation } - -// @public -export class HiddenValueCallback extends BaseCallback { - constructor(payload: Callback); - // (undocumented) - payload: Callback; -} - -// @public (undocumented) -export interface IdPValue { - // (undocumented) - provider: string; - // (undocumented) - uiConfig: { - [key: string]: string; - }; -} - -// @internal -export interface InternalJourneyClientConfig { - // (undocumented) - error?: GenericError; - // (undocumented) - serverConfig: ResolvedServerConfig; -} - -export { isValidWellknownUrl } - -// @public -export interface JourneyClient { - // (undocumented) - next: (step: JourneyStep, options?: NextOptions) => Promise; - // (undocumented) - redirect: (step: JourneyStep) => Promise; - // (undocumented) - resume: (url: string, options?: ResumeOptions) => Promise; - // (undocumented) - start: (options?: StartParam) => Promise; - // (undocumented) - store: SdkStore; - // (undocumented) - subscribe: (listener: () => void) => () => void; - // (undocumented) - terminate: (options?: { - query?: Record; - }) => Promise; -} - -export { JourneyClientConfig } - -// @public (undocumented) -export type JourneyLoginFailure = AuthResponse & { - type: StepType.LoginFailure; - payload: Step; - getCode: () => number; - getDetail: () => FailureDetail | undefined; - getMessage: () => string | undefined; - getProcessedMessage: (messageCreator?: MessageCreator) => ProcessedPropertyError[]; - getReason: () => string | undefined; -}; - -// @public (undocumented) -export type JourneyLoginSuccess = AuthResponse & { - type: StepType.LoginSuccess; - payload: Step; - getRealm: () => string | undefined; - getSessionToken: () => string | undefined; - getSuccessUrl: () => string | undefined; -}; - -// @public (undocumented) -export type JourneyResult = JourneyStep | JourneyLoginSuccess | JourneyLoginFailure | GenericError; - -export { JourneyServerConfig } - -// @public (undocumented) -export type JourneyStep = AuthResponse & { - type: StepType.Step; - payload: Step; - callbacks: BaseCallback[]; - getCallbackOfType: (type: CallbackType) => T; - getCallbacksOfType: (type: CallbackType) => T[]; - setCallbackValue: (type: CallbackType, value: unknown) => void; - getDescription: () => string | undefined; - getHeader: () => string | undefined; - getStage: () => string | undefined; -}; - -// @public -export class KbaCreateCallback extends BaseCallback { - constructor(payload: Callback); - getPredefinedQuestions(): string[]; - getPrompt(): string; - isAllowedUserDefinedQuestions(): boolean; - // (undocumented) - payload: Callback; - setAnswer(answer: string): void; - setQuestion(question: string): void; -} - -export { LogLevel } - -// @public (undocumented) -export interface MessageCreator { - // (undocumented) - [key: string]: (propertyName: string, params?: { - [key: string]: unknown; - }) => string; -} - -// @public -export class MetadataCallback extends BaseCallback { - constructor(payload: Callback); - getData(): T; - // (undocumented) - payload: Callback; -} - -// @public -export class NameCallback extends BaseCallback { - constructor(payload: Callback); - getPrompt(): string; - // (undocumented) - payload: Callback; - setName(name: string): void; -} - -export { NameValue } - -// @public (undocumented) -export interface NextOptions { - // (undocumented) - query?: Record; -} - -// @public -export class PasswordCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): string[]; - getPrompt(): string; - // (undocumented) - payload: Callback; - setPassword(password: string): void; -} - -// @public -export class PingOneProtectEvaluationCallback extends BaseCallback { - constructor(payload: Callback); - getPauseBehavioralData(): boolean; - // (undocumented) - payload: Callback; - setClientError(errorMessage: string): void; - setData(data: string): void; -} - -// @public -export class PingOneProtectInitializeCallback extends BaseCallback { - constructor(payload: Callback); - getConfig(): Record | { - envId: string; - consoleLogEnabled: boolean; - deviceAttributesToIgnore: string[]; - customHost: string; - lazyMetadata: boolean; - behavioralDataCollection: boolean; - deviceKeyRsyncIntervals: number; - enableTrust: boolean; - disableTags: boolean; - disableHub: boolean; - }; - // (undocumented) - payload: Callback; - // (undocumented) - setClientError(errorMessage: string): void; -} - -export { PolicyKey } - -export { PolicyParams } - -export { PolicyRequirement } - -// @public -export class PollingWaitCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - getWaitTime(): number; - // (undocumented) - payload: Callback; -} - -// @public (undocumented) -export interface ProcessedPropertyError { - // (undocumented) - detail: FailedPolicyRequirement; - // (undocumented) - messages: string[]; -} - -// @public -export class ReCaptchaCallback extends BaseCallback { - constructor(payload: Callback); - getSiteKey(): string; - // (undocumented) - payload: Callback; - setResult(result: string): void; -} - -// @public -export class ReCaptchaEnterpriseCallback extends BaseCallback { - constructor(payload: Callback); - getApiUrl(): string; - getElementClass(): string; - getSiteKey(): string; - // (undocumented) - payload: Callback; - setAction(action: string): void; - setClientError(error: string): void; - setPayload(payload: unknown): void; - setResult(result: string): void; -} - -// @public -export class RedirectCallback extends BaseCallback { - constructor(payload: Callback); - getRedirectUrl(): string; - // (undocumented) - payload: Callback; -} - -export { RequestMiddleware } - -// @public -export interface ResolvedServerConfig { - // (undocumented) - baseUrl: string; - // (undocumented) - paths: { - authenticate: string; - sessions: string; - }; -} - -// @public (undocumented) -export interface ResumeOptions { - // (undocumented) - journey?: string; - // (undocumented) - query?: Record; -} - -// @public -export class SelectIdPCallback extends BaseCallback { - constructor(payload: Callback); - getProviders(): IdPValue[]; - // (undocumented) - payload: Callback; - setProvider(value: string): void; -} - -// @public (undocumented) -export interface StartParam { - // (undocumented) - journey: string; - // (undocumented) - query?: Record; -} - -export { Step } - -export { StepDetail } - -export { StepType } - -// @public -export class SuspendedTextOutputCallback extends TextOutputCallback { - constructor(payload: Callback); - // (undocumented) - payload: Callback; -} - -// @public -export class TermsAndConditionsCallback extends BaseCallback { - constructor(payload: Callback); - getCreateDate(): Date | null; - getTerms(): string; - getVersion(): string; - // (undocumented) - payload: Callback; - setAccepted(accepted?: boolean): void; -} - -// @public -export class TextInputCallback extends BaseCallback { - constructor(payload: Callback); - getPrompt(): string; - // (undocumented) - payload: Callback; - setInput(input: string): void; -} - -// @public -export class TextOutputCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - getMessageType(): string; - // (undocumented) - payload: Callback; -} - -// @public -export class ValidatedCreatePasswordCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setPassword(password: string): void; - setValidateOnly(value: boolean): void; -} - -// @public -export class ValidatedCreateUsernameCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setName(name: string): void; - setValidateOnly(value: boolean): void; -} - -export { WellknownResponse } - -// (No @packageDocumentation comment for this package) - -``` +## API Report File for "@forgerock/journey-client" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ActionTypes } from '@forgerock/sdk-request-middleware'; +import { AuthResponse } from '@forgerock/sdk-types'; +import { Callback } from '@forgerock/sdk-types'; +import { CallbackType } from '@forgerock/sdk-types'; +import { createWellknownError } from '@forgerock/sdk-utilities'; +import { CustomLogger } from '@forgerock/sdk-logger'; +import { FailedPolicyRequirement } from '@forgerock/sdk-types'; +import { FailureDetail } from '@forgerock/sdk-types'; +import { GenericError } from '@forgerock/sdk-types'; +import { isValidWellknownUrl } from '@forgerock/sdk-utilities'; +import { JourneyClientConfig } from '@forgerock/sdk-types'; +import { JourneyServerConfig } from '@forgerock/sdk-types'; +import { LogLevel } from '@forgerock/sdk-logger'; +import { NameValue } from '@forgerock/sdk-types'; +import { PolicyKey } from '@forgerock/sdk-types'; +import { PolicyParams } from '@forgerock/sdk-types'; +import { PolicyRequirement } from '@forgerock/sdk-types'; +import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; +import type { SdkStore } from '@forgerock/sdk-types'; +import { Step } from '@forgerock/sdk-types'; +import { StepDetail } from '@forgerock/sdk-types'; +import { StepType } from '@forgerock/sdk-types'; +import { WellknownResponse } from '@forgerock/sdk-types'; + +export { ActionTypes }; + +// @public +export class AttributeInputCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getName(): string; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setValidateOnly(value: boolean): void; + setValue(value: T): void; +} + +export { AuthResponse }; + +// @public +export class BaseCallback { + constructor(payload: Callback); + getInputValue(selector?: number | string): unknown; + getOutputByName(name: string, defaultValue: T): T; + getOutputValue(selector?: number | string): unknown; + getType(): CallbackType; + // (undocumented) + payload: Callback; + setInputValue(value: unknown, selector?: number | string | RegExp): void; +} + +export { Callback }; + +// @public (undocumented) +export type CallbackFactory = (callback: Callback) => BaseCallback; + +export { CallbackType }; + +// @public +export class ChoiceCallback extends BaseCallback { + constructor(payload: Callback); + getChoices(): string[]; + getDefaultChoice(): number; + getPrompt(): string; + // (undocumented) + payload: Callback; + setChoiceIndex(index: number): void; + setChoiceValue(value: string): void; +} + +// @public +export class ConfirmationCallback extends BaseCallback { + constructor(payload: Callback); + getDefaultOption(): number; + getMessageType(): number; + getOptions(): string[]; + getOptionType(): number; + getPrompt(): string; + // (undocumented) + payload: Callback; + setOptionIndex(index: number): void; + setOptionValue(value: string): void; +} + +// @public (undocumented) +export function createCallback(callback: Callback): BaseCallback; + +export { createWellknownError }; + +export { CustomLogger }; + +// @public +export class DeviceProfileCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + isLocationRequired(): boolean; + isMetadataRequired(): boolean; + // (undocumented) + payload: Callback; + setProfile(profile: DeviceProfileData): void; +} + +// @public (undocumented) +export interface DeviceProfileData { + // (undocumented) + identifier: string; + // (undocumented) + location?: Geolocation_2 | Record; + // (undocumented) + metadata?: { + hardware: { + display: { + [key: string]: string | number | null; + }; + [key: string]: any; + }; + browser: { + [key: string]: string | number | null; + }; + platform: { + [key: string]: string | number | null; + }; + }; +} + +export { FailedPolicyRequirement }; + +export { FailureDetail }; + +export { GenericError }; + +// @public (undocumented) +interface Geolocation_2 { + // (undocumented) + latitude: number; + // (undocumented) + longitude: number; +} +export { Geolocation_2 as Geolocation }; + +// @public +export class HiddenValueCallback extends BaseCallback { + constructor(payload: Callback); + // (undocumented) + payload: Callback; +} + +// @public (undocumented) +export interface IdPValue { + // (undocumented) + provider: string; + // (undocumented) + uiConfig: { + [key: string]: string; + }; +} + +// @internal +export interface InternalJourneyClientConfig { + // (undocumented) + error?: GenericError; + // (undocumented) + serverConfig: ResolvedServerConfig; +} + +export { isValidWellknownUrl }; + +// @public +export interface JourneyClient { + // (undocumented) + next: (step: JourneyStep, options?: NextOptions) => Promise; + // (undocumented) + redirect: (step: JourneyStep) => Promise; + // (undocumented) + resume: (url: string, options?: ResumeOptions) => Promise; + // (undocumented) + start: (options?: StartParam) => Promise; + // (undocumented) + store: SdkStore; + // (undocumented) + subscribe: (listener: () => void) => () => void; + // (undocumented) + terminate: (options?: { query?: Record }) => Promise; +} + +export { JourneyClientConfig }; + +// @public (undocumented) +export type JourneyLoginFailure = AuthResponse & { + type: StepType.LoginFailure; + payload: Step; + getCode: () => number; + getDetail: () => FailureDetail | undefined; + getMessage: () => string | undefined; + getProcessedMessage: (messageCreator?: MessageCreator) => ProcessedPropertyError[]; + getReason: () => string | undefined; +}; + +// @public (undocumented) +export type JourneyLoginSuccess = AuthResponse & { + type: StepType.LoginSuccess; + payload: Step; + getRealm: () => string | undefined; + getSessionToken: () => string | undefined; + getSuccessUrl: () => string | undefined; +}; + +// @public (undocumented) +export type JourneyResult = JourneyStep | JourneyLoginSuccess | JourneyLoginFailure | GenericError; + +export { JourneyServerConfig }; + +// @public (undocumented) +export type JourneyStep = AuthResponse & { + type: StepType.Step; + payload: Step; + callbacks: BaseCallback[]; + getCallbackOfType: (type: CallbackType) => T; + getCallbacksOfType: (type: CallbackType) => T[]; + setCallbackValue: (type: CallbackType, value: unknown) => void; + getDescription: () => string | undefined; + getHeader: () => string | undefined; + getStage: () => string | undefined; +}; + +// @public +export class KbaCreateCallback extends BaseCallback { + constructor(payload: Callback); + getPredefinedQuestions(): string[]; + getPrompt(): string; + isAllowedUserDefinedQuestions(): boolean; + // (undocumented) + payload: Callback; + setAnswer(answer: string): void; + setQuestion(question: string): void; +} + +export { LogLevel }; + +// @public (undocumented) +export interface MessageCreator { + // (undocumented) + [key: string]: ( + propertyName: string, + params?: { + [key: string]: unknown; + }, + ) => string; +} + +// @public +export class MetadataCallback extends BaseCallback { + constructor(payload: Callback); + getData(): T; + // (undocumented) + payload: Callback; +} + +// @public +export class NameCallback extends BaseCallback { + constructor(payload: Callback); + getPrompt(): string; + // (undocumented) + payload: Callback; + setName(name: string): void; +} + +export { NameValue }; + +// @public (undocumented) +export interface NextOptions { + // (undocumented) + query?: Record; +} + +// @public +export class PasswordCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): string[]; + getPrompt(): string; + // (undocumented) + payload: Callback; + setPassword(password: string): void; +} + +// @public +export class PingOneProtectEvaluationCallback extends BaseCallback { + constructor(payload: Callback); + getPauseBehavioralData(): boolean; + // (undocumented) + payload: Callback; + setClientError(errorMessage: string): void; + setData(data: string): void; +} + +// @public +export class PingOneProtectInitializeCallback extends BaseCallback { + constructor(payload: Callback); + getConfig(): + | Record + | { + envId: string; + consoleLogEnabled: boolean; + deviceAttributesToIgnore: string[]; + customHost: string; + lazyMetadata: boolean; + behavioralDataCollection: boolean; + deviceKeyRsyncIntervals: number; + enableTrust: boolean; + disableTags: boolean; + disableHub: boolean; + }; + // (undocumented) + payload: Callback; + // (undocumented) + setClientError(errorMessage: string): void; +} + +export { PolicyKey }; + +export { PolicyParams }; + +export { PolicyRequirement }; + +// @public +export class PollingWaitCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + getWaitTime(): number; + // (undocumented) + payload: Callback; +} + +// @public (undocumented) +export interface ProcessedPropertyError { + // (undocumented) + detail: FailedPolicyRequirement; + // (undocumented) + messages: string[]; +} + +// @public +export class ReCaptchaCallback extends BaseCallback { + constructor(payload: Callback); + getSiteKey(): string; + // (undocumented) + payload: Callback; + setResult(result: string): void; +} + +// @public +export class ReCaptchaEnterpriseCallback extends BaseCallback { + constructor(payload: Callback); + getApiUrl(): string; + getElementClass(): string; + getSiteKey(): string; + // (undocumented) + payload: Callback; + setAction(action: string): void; + setClientError(error: string): void; + setPayload(payload: unknown): void; + setResult(result: string): void; +} + +// @public +export class RedirectCallback extends BaseCallback { + constructor(payload: Callback); + getRedirectUrl(): string; + // (undocumented) + payload: Callback; +} + +export { RequestMiddleware }; + +// @public +export interface ResolvedServerConfig { + // (undocumented) + baseUrl: string; + // (undocumented) + paths: { + authenticate: string; + sessions: string; + }; +} + +// @public (undocumented) +export interface ResumeOptions { + // (undocumented) + journey?: string; + // (undocumented) + query?: Record; +} + +// @public +export class SelectIdPCallback extends BaseCallback { + constructor(payload: Callback); + getProviders(): IdPValue[]; + // (undocumented) + payload: Callback; + setProvider(value: string): void; +} + +// @public (undocumented) +export interface StartParam { + // (undocumented) + journey: string; + // (undocumented) + query?: Record; +} + +export { Step }; + +export { StepDetail }; + +export { StepType }; + +// @public +export class SuspendedTextOutputCallback extends TextOutputCallback { + constructor(payload: Callback); + // (undocumented) + payload: Callback; +} + +// @public +export class TermsAndConditionsCallback extends BaseCallback { + constructor(payload: Callback); + getCreateDate(): Date | null; + getTerms(): string; + getVersion(): string; + // (undocumented) + payload: Callback; + setAccepted(accepted?: boolean): void; +} + +// @public +export class TextInputCallback extends BaseCallback { + constructor(payload: Callback); + getPrompt(): string; + // (undocumented) + payload: Callback; + setInput(input: string): void; +} + +// @public +export class TextOutputCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + getMessageType(): string; + // (undocumented) + payload: Callback; +} + +// @public +export class ValidatedCreatePasswordCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setPassword(password: string): void; + setValidateOnly(value: boolean): void; +} + +// @public +export class ValidatedCreateUsernameCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setName(name: string): void; + setValidateOnly(value: boolean): void; +} + +export { WellknownResponse }; + +// (No @packageDocumentation comment for this package) +``` From 960c4c541e4a4fb40be0e029e64fb7f799448488 Mon Sep 17 00:00:00 2001 From: Ryan Bas Date: Wed, 12 Aug 2026 16:07:02 -0600 Subject: [PATCH 09/11] fix(davinci-client): replace remaining Either with Result for Effect v4 --- packages/davinci-client/src/lib/client.store.ts | 8 ++++---- packages/davinci-client/src/lib/client.store.utils.ts | 10 +++++----- packages/davinci-client/src/lib/node.reducer.ts | 3 +-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/davinci-client/src/lib/client.store.ts b/packages/davinci-client/src/lib/client.store.ts index 32f45d9865..676cef92cc 100644 --- a/packages/davinci-client/src/lib/client.store.ts +++ b/packages/davinci-client/src/lib/client.store.ts @@ -4,7 +4,7 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ -import { Effect, Exit, Cause, Option, Either } from 'effect'; +import { Effect, Exit, Cause, Option, Result } from 'effect'; import { type CustomLogger, logger as loggerFn, type LogLevel } from '@forgerock/sdk-logger'; import { createStorage } from '@forgerock/storage'; import { isGenericError, createWellknownError } from '@forgerock/sdk-utilities'; @@ -358,9 +358,9 @@ export async function davinci({ * shape, so the cast is safe. */ const result = resolveCollectorUpdateValue(collectorToUpdate as UpdatableCollectors, value); - if (Either.isLeft(result)) { - log.error(result.left.error.message); - return result.left; + if (Result.isFailure(result)) { + log.error(result.failure.error.message); + return result.failure; } // Update the collector in the store with the value diff --git a/packages/davinci-client/src/lib/client.store.utils.ts b/packages/davinci-client/src/lib/client.store.utils.ts index 870e7f790b..c595834b9a 100644 --- a/packages/davinci-client/src/lib/client.store.utils.ts +++ b/packages/davinci-client/src/lib/client.store.utils.ts @@ -5,7 +5,7 @@ * of the MIT license. See the LICENSE file for details. */ import { combineSlices, configureStore, createDynamicMiddleware } from '@reduxjs/toolkit'; -import { Match, Either } from 'effect'; +import { Match, Result } from 'effect'; import type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; import type { logger as loggerFn } from '@forgerock/sdk-logger'; @@ -170,14 +170,14 @@ export function isValidCollectorCategory( * * @param collector - The collector the value is being validated against * @param value - The candidate value to validate - * @returns `Either.right` with the narrowed value, or `Either.left` with the validation error + * @returns `Result.succeed` with the narrowed value, or `Result.fail` with the validation error */ export function resolveCollectorUpdateValue( collector: T, value: CollectorValueTypes, -): Either.Either, InternalErrorResponse> { - const ok = (v: CollectorValueTypes) => Either.right(v as CollectorValueType); - const err = (message: string) => Either.left(createInternalError(message, 'argument_error')); +): Result.Result, InternalErrorResponse> { + const ok = (v: CollectorValueTypes) => Result.succeed(v as CollectorValueType); + const err = (message: string) => Result.fail(createInternalError(message, 'argument_error')); if (value === undefined) { return err('Value argument cannot be undefined'); diff --git a/packages/davinci-client/src/lib/node.reducer.ts b/packages/davinci-client/src/lib/node.reducer.ts index f685c89d38..73b0e0e75f 100644 --- a/packages/davinci-client/src/lib/node.reducer.ts +++ b/packages/davinci-client/src/lib/node.reducer.ts @@ -59,8 +59,7 @@ function updateCollector( ): void { const result = resolveCollectorUpdateValue(collector, value); if (Result.isSuccess(result)) { - const resolvedValue = result.success; - cb(resolvedValue); + cb(result.success as CollectorValueType); } } From 3b35df210d4581a31d6fa83df11fc0308e9e3734 Mon Sep 17 00:00:00 2001 From: Ryan Bas Date: Wed, 12 Aug 2026 18:33:57 -0600 Subject: [PATCH 10/11] fix(test): alias @forgerock/sdk-wellknown to source in vite configs --- packages/davinci-client/vite.config.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/davinci-client/vite.config.ts b/packages/davinci-client/vite.config.ts index b921b564ce..a08bb40597 100644 --- a/packages/davinci-client/vite.config.ts +++ b/packages/davinci-client/vite.config.ts @@ -4,11 +4,17 @@ * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ +import { resolve } from 'path'; import { defineConfig } from 'vitest/config'; export default defineConfig({ root: __dirname, cacheDir: '../../node_modules/.vite/packages/davinci-client', + resolve: { + alias: { + '@forgerock/sdk-wellknown': resolve(__dirname, '../sdk-effects/wellknown/src/index.ts'), + }, + }, test: { watch: false, typecheck: { From 7908ec26d97675d112547b8705609b168a2234d2 Mon Sep 17 00:00:00 2001 From: Ryan Bas Date: Wed, 12 Aug 2026 18:45:10 -0600 Subject: [PATCH 11/11] fix(davinci-client): break circular import by extracting collector resolver --- .../centralize-redux-store/facts-result.json | 109 - .../centralize-redux-store/facts-review.json | 103 - goals/centralize-redux-store/facts.md | 14 - goals/centralize-redux-store/facts.meta.json | 86 - goals/centralize-redux-store/goal.md | 22 - .../interview-result.json | 53 - goals/centralize-redux-store/interview.json | 113 - goals/centralize-redux-store/plan.md | 187 - .../api-report/davinci-client.api.md | 4467 ++++++++--------- .../api-report/davinci-client.types.api.md | 4461 ++++++++-------- .../src/lib/client.store.utils.ts | 149 +- .../src/lib/collector.resolver.ts | 172 + .../davinci-client/src/lib/node.reducer.ts | 2 +- .../api-report/journey-client.api.md | 1007 ++-- .../api-report/journey-client.types.api.md | 981 ++-- 15 files changed, 5202 insertions(+), 6724 deletions(-) delete mode 100644 goals/centralize-redux-store/facts-result.json delete mode 100644 goals/centralize-redux-store/facts-review.json delete mode 100644 goals/centralize-redux-store/facts.md delete mode 100644 goals/centralize-redux-store/facts.meta.json delete mode 100644 goals/centralize-redux-store/goal.md delete mode 100644 goals/centralize-redux-store/interview-result.json delete mode 100644 goals/centralize-redux-store/interview.json delete mode 100644 goals/centralize-redux-store/plan.md create mode 100644 packages/davinci-client/src/lib/collector.resolver.ts diff --git a/goals/centralize-redux-store/facts-result.json b/goals/centralize-redux-store/facts-result.json deleted file mode 100644 index 1628a1d9d7..0000000000 --- a/goals/centralize-redux-store/facts-result.json +++ /dev/null @@ -1,109 +0,0 @@ -{ - "decision": "submitted", - "stage": "facts", - "result": { - "stage": "facts", - "title": "Centralize Redux Store Across Client Packages", - "goalSlug": "centralize-redux-store", - "facts": [ - { - "id": "fact-1", - "text": "`davinci()` returns an object with a `store` property typed as an opaque `SdkStore` handle (not the raw Redux `Store` type).", - "accepted": true, - "removed": false, - "automatedVerification": true, - "recommendedAutomatedVerification": true - }, - { - "id": "fact-2", - "text": "`journey()` returns an object with a `store` property typed as an opaque `SdkStore` handle.", - "accepted": true, - "removed": false, - "automatedVerification": true, - "recommendedAutomatedVerification": true - }, - { - "id": "fact-3", - "text": "`oidc()` accepts an optional second argument — an `SdkStore` — and uses it instead of creating a new store when provided.", - "accepted": true, - "removed": false, - "automatedVerification": true, - "recommendedAutomatedVerification": true - }, - { - "id": "fact-4", - "text": "When `oidc()` is called without a second argument, it creates its own store exactly as it does today (no behavioral change for standalone usage).", - "accepted": true, - "removed": false, - "automatedVerification": true, - "recommendedAutomatedVerification": true - }, - { - "id": "fact-5", - "text": "The davinci/journey store is pre-provisioned with oidc's reducers (`oidcApi`) so that when `oidc()` receives the shared store, it can dispatch and select from its own slice without any runtime injection.", - "accepted": false, - "removed": false, - "comment": "I don't think we want `oidc` pre-provisioned. We only want `oidc` when it's been used as the oidc client.", - "automatedVerification": true, - "recommendedAutomatedVerification": true - }, - { - "id": "fact-6", - "text": "`wellknownApi` is extracted from `davinci-client`, `journey-client`, and `oidc-client` into `sdk-effects` (or an appropriate shared effects package) so all three import the same instance.", - "accepted": true, - "removed": false, - "automatedVerification": true, - "recommendedAutomatedVerification": true - }, - { - "id": "fact-7", - "text": "When `oidc()` shares a store with `davinci()`, there is only one `wellknown` cache entry — a second call to the same wellknown URL returns from cache without a network request.", - "accepted": true, - "removed": false, - "automatedVerification": true, - "recommendedAutomatedVerification": true - }, - { - "id": "fact-8", - "text": "A single `store.subscribe()` call on the davinci/journey client fires for state changes from both the flow client and oidc client when a shared store is in use.", - "accepted": true, - "removed": false, - "automatedVerification": true, - "recommendedAutomatedVerification": true - }, - { - "id": "fact-9", - "text": "All existing call sites (`davinci({ config })`, `journey({ config })`, `oidc({ config })`) continue to work without modification.", - "accepted": true, - "removed": false, - "automatedVerification": true, - "recommendedAutomatedVerification": true - }, - { - "id": "fact-10", - "text": "TypeScript consumers cannot access internal Redux primitives (dispatch, getState, etc.) through the exposed `SdkStore` type — it is opaque by design.", - "accepted": true, - "removed": false, - "automatedVerification": true, - "recommendedAutomatedVerification": true - }, - { - "id": "fact-11", - "text": "The `requestMiddleware` and `logger` passed to `davinci()`/`journey()` are inherited by oidc when using a shared store — oidc does not need to re-declare them.", - "accepted": true, - "removed": false, - "automatedVerification": false, - "recommendedAutomatedVerification": false - }, - { - "id": "fact-12", - "text": "All affected packages pass `pnpm lint`, `pnpm build`, and `pnpm test` after the changes.", - "accepted": true, - "removed": false, - "automatedVerification": true, - "recommendedAutomatedVerification": true - } - ], - "factsMarkdown": "# Facts\n\n- `davinci()` returns an object with a `store` property typed as an opaque `SdkStore` handle (not the raw Redux `Store` type).\n- `journey()` returns an object with a `store` property typed as an opaque `SdkStore` handle.\n- `oidc()` accepts an optional second argument — an `SdkStore` — and uses it instead of creating a new store when provided.\n- When `oidc()` is called without a second argument, it creates its own store exactly as it does today (no behavioral change for standalone usage).\n- `wellknownApi` is extracted from `davinci-client`, `journey-client`, and `oidc-client` into `sdk-effects` (or an appropriate shared effects package) so all three import the same instance.\n- When `oidc()` shares a store with `davinci()`, there is only one `wellknown` cache entry — a second call to the same wellknown URL returns from cache without a network request.\n- A single `store.subscribe()` call on the davinci/journey client fires for state changes from both the flow client and oidc client when a shared store is in use.\n- All existing call sites (`davinci({ config })`, `journey({ config })`, `oidc({ config })`) continue to work without modification.\n- TypeScript consumers cannot access internal Redux primitives (dispatch, getState, etc.) through the exposed `SdkStore` type — it is opaque by design.\n- The `requestMiddleware` and `logger` passed to `davinci()`/`journey()` are inherited by oidc when using a shared store — oidc does not need to re-declare them.\n- All affected packages pass `pnpm lint`, `pnpm build`, and `pnpm test` after the changes." - } -} diff --git a/goals/centralize-redux-store/facts-review.json b/goals/centralize-redux-store/facts-review.json deleted file mode 100644 index d7653b6042..0000000000 --- a/goals/centralize-redux-store/facts-review.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "stage": "facts", - "title": "Centralize Redux Store Across Client Packages", - "goalSlug": "centralize-redux-store", - "facts": [ - { - "id": "fact-1", - "text": "`davinci()` returns an object with a `store` property typed as an opaque `SdkStore` handle (not the raw Redux `Store` type).", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-2", - "text": "`journey()` returns an object with a `store` property typed as an opaque `SdkStore` handle.", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-3", - "text": "`oidc()` accepts an optional second argument — an `SdkStore` — and uses it instead of creating a new store when provided.", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-4", - "text": "When `oidc()` is called without a second argument, it creates its own store exactly as it does today (no behavioral change for standalone usage).", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-5", - "text": "The davinci/journey store is pre-provisioned with oidc's reducers (`oidcApi`) so that when `oidc()` receives the shared store, it can dispatch and select from its own slice without any runtime injection.", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-6", - "text": "`wellknownApi` is extracted from `davinci-client`, `journey-client`, and `oidc-client` into `sdk-effects` (or an appropriate shared effects package) so all three import the same instance.", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-7", - "text": "When `oidc()` shares a store with `davinci()`, there is only one `wellknown` cache entry — a second call to the same wellknown URL returns from cache without a network request.", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-8", - "text": "A single `store.subscribe()` call on the davinci/journey client fires for state changes from both the flow client and oidc client when a shared store is in use.", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-9", - "text": "All existing call sites (`davinci({ config })`, `journey({ config })`, `oidc({ config })`) continue to work without modification.", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-10", - "text": "TypeScript consumers cannot access internal Redux primitives (dispatch, getState, etc.) through the exposed `SdkStore` type — it is opaque by design.", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-11", - "text": "The `requestMiddleware` and `logger` passed to `davinci()`/`journey()` are inherited by oidc when using a shared store — oidc does not need to re-declare them.", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": false, - "automatedVerification": false - }, - { - "id": "fact-12", - "text": "All affected packages pass `pnpm lint`, `pnpm build`, and `pnpm test` after the changes.", - "accepted": false, - "removed": false, - "recommendedAutomatedVerification": true, - "automatedVerification": true - } - ] -} diff --git a/goals/centralize-redux-store/facts.md b/goals/centralize-redux-store/facts.md deleted file mode 100644 index 49d466e6df..0000000000 --- a/goals/centralize-redux-store/facts.md +++ /dev/null @@ -1,14 +0,0 @@ -# Facts - -- `davinci()` returns an object with a `store` property typed as an opaque `SdkStore` handle (not the raw Redux `Store` type). -- `journey()` returns an object with a `store` property typed as an opaque `SdkStore` handle. -- `oidc()` accepts an optional second argument — an `SdkStore` — and uses it instead of creating a new store when provided. -- When `oidc()` is called without a second argument, it creates its own store exactly as it does today (no behavioral change for standalone usage). -- `oidc` lazily injects its own reducers (`oidcApi`) into the shared store at `oidc()` init time — the owning store (davinci/journey) does NOT pre-provision oidc reducers. -- `wellknownApi` is extracted from `davinci-client`, `journey-client`, and `oidc-client` into `sdk-effects` (or an appropriate shared effects package) so all three import the same instance. -- When `oidc()` shares a store with `davinci()`, there is only one `wellknown` cache entry — a second call to the same wellknown URL returns from cache without a network request. -- A single `store.subscribe()` call on the davinci/journey client fires for state changes from both the flow client and oidc client when a shared store is in use. -- All existing call sites (`davinci({ config })`, `journey({ config })`, `oidc({ config })`) continue to work without modification. -- TypeScript consumers cannot access internal Redux primitives (dispatch, getState, etc.) through the exposed `SdkStore` type — it is opaque by design. -- The `requestMiddleware` and `logger` passed to `davinci()`/`journey()` are inherited by oidc when using a shared store — oidc does not need to re-declare them. -- All affected packages pass `pnpm lint`, `pnpm build`, and `pnpm test` after the changes. diff --git a/goals/centralize-redux-store/facts.meta.json b/goals/centralize-redux-store/facts.meta.json deleted file mode 100644 index 49896c66b7..0000000000 --- a/goals/centralize-redux-store/facts.meta.json +++ /dev/null @@ -1,86 +0,0 @@ -[ - { - "id": "fact-1", - "text": "`davinci()` returns an object with a `store` property typed as an opaque `SdkStore` handle (not the raw Redux `Store` type).", - "comment": "", - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-2", - "text": "`journey()` returns an object with a `store` property typed as an opaque `SdkStore` handle.", - "comment": "", - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-3", - "text": "`oidc()` accepts an optional second argument — an `SdkStore` — and uses it instead of creating a new store when provided.", - "comment": "", - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-4", - "text": "When `oidc()` is called without a second argument, it creates its own store exactly as it does today (no behavioral change for standalone usage).", - "comment": "", - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-5-revised", - "text": "`oidc` lazily injects its own reducers (`oidcApi`) into the shared store at `oidc()` init time — the owning store (davinci/journey) does NOT pre-provision oidc reducers.", - "comment": "User rejected pre-provisioning: 'I don't think we want oidc pre-provisioned. We only want oidc when it's been used as the oidc client.'", - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-6", - "text": "`wellknownApi` is extracted from `davinci-client`, `journey-client`, and `oidc-client` into `sdk-effects` (or an appropriate shared effects package) so all three import the same instance.", - "comment": "", - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-7", - "text": "When `oidc()` shares a store with `davinci()`, there is only one `wellknown` cache entry — a second call to the same wellknown URL returns from cache without a network request.", - "comment": "", - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-8", - "text": "A single `store.subscribe()` call on the davinci/journey client fires for state changes from both the flow client and oidc client when a shared store is in use.", - "comment": "", - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-9", - "text": "All existing call sites (`davinci({ config })`, `journey({ config })`, `oidc({ config })`) continue to work without modification.", - "comment": "", - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-10", - "text": "TypeScript consumers cannot access internal Redux primitives (dispatch, getState, etc.) through the exposed `SdkStore` type — it is opaque by design.", - "comment": "", - "recommendedAutomatedVerification": true, - "automatedVerification": true - }, - { - "id": "fact-11", - "text": "The `requestMiddleware` and `logger` passed to `davinci()`/`journey()` are inherited by oidc when using a shared store — oidc does not need to re-declare them.", - "comment": "", - "recommendedAutomatedVerification": false, - "automatedVerification": false - }, - { - "id": "fact-12", - "text": "All affected packages pass `pnpm lint`, `pnpm build`, and `pnpm test` after the changes.", - "comment": "", - "recommendedAutomatedVerification": true, - "automatedVerification": true - } -] diff --git a/goals/centralize-redux-store/goal.md b/goals/centralize-redux-store/goal.md deleted file mode 100644 index fa4942d99d..0000000000 --- a/goals/centralize-redux-store/goal.md +++ /dev/null @@ -1,22 +0,0 @@ -# Goal: Centralize Redux Store Across Client Packages - -## Articulated Goal - -Expose an opaque `SdkStore` handle from `davinci()` and `journey()`, and allow `oidc()` to accept that handle as an optional second argument. When provided, `oidc` lazily injects its own reducers and middleware into the shared store rather than creating a new one — eliminating the dual-store problem when pairing oidc with a flow client. All existing call sites remain unchanged. - -## Shared Understanding - -See [`facts.md`](./facts.md) for the full list of accepted facts defining correct behavior. - -## Execution Plan - -See [`plan.md`](./plan.md) for the ordered steps, files touched, and verification commands. - -## Done Condition - -- `davinci()` and `journey()` return objects include a `store: SdkStore` property -- `oidc(opts, sharedStore?)` accepts the optional second argument and injects into it when provided -- `wellknownApi` lives in a new `@forgerock/sdk-wellknown` package imported by all three clients -- A shared store results in one wellknown cache entry and a single unified `subscribe` -- All existing call sites work without modification -- `pnpm nx run-many -t build lint test` passes across all affected packages diff --git a/goals/centralize-redux-store/interview-result.json b/goals/centralize-redux-store/interview-result.json deleted file mode 100644 index 63fea5dd15..0000000000 --- a/goals/centralize-redux-store/interview-result.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "decision": "submitted", - "stage": "interview", - "result": { - "stage": "interview", - "title": "Centralize Redux Store Across Client Packages", - "goalSlug": "centralize-redux-store", - "answers": [ - { - "questionId": "store-exposure", - "selectedOptionIds": ["opaque-property"], - "customAnswer": "", - "answer": "store property (opaque SdkStore type)", - "completed": true - }, - { - "questionId": "oidc-injection", - "selectedOptionIds": ["second-arg"], - "customAnswer": "", - "answer": "Second argument to oidc()", - "completed": true - }, - { - "questionId": "wellknown-dedup", - "selectedOptionIds": ["extract-now"], - "customAnswer": "", - "answer": "Extract wellknownApi to sdk-effects in this PR", - "completed": true - }, - { - "questionId": "reducer-injection-strategy", - "selectedOptionIds": ["pre-register"], - "customAnswer": "", - "answer": "Pre-register oidc reducers in davinci/journey store upfront", - "completed": true - }, - { - "questionId": "scope", - "selectedOptionIds": ["davinci", "journey", "oidc", "sdk-effects"], - "customAnswer": "", - "answer": "davinci-client\njourney-client\noidc-client\nsdk-effects (wellknown extraction)", - "completed": true - }, - { - "questionId": "breaking-changes", - "selectedOptionIds": ["minor-ok"], - "customAnswer": "", - "answer": "Minor breaking changes acceptable (semver minor)", - "completed": true - } - ] - } -} diff --git a/goals/centralize-redux-store/interview.json b/goals/centralize-redux-store/interview.json deleted file mode 100644 index 78c7badb5c..0000000000 --- a/goals/centralize-redux-store/interview.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "stage": "interview", - "title": "Centralize Redux Store Across Client Packages", - "goalSlug": "centralize-redux-store", - "questions": [ - { - "id": "store-exposure", - "prompt": "How should `davinci()`/`journey()` expose the store to consumers?", - "description": "The store is currently fully private. The simplest approach is adding a `store` property to the returned client object. An alternative is a dedicated `getStore()` method. A third option is exposing only an opaque handle typed as `SdkStore` (not the full Redux `Store` type) to discourage direct Redux usage.", - "answerMode": "single-custom", - "recommendedAnswer": "Add a `store` property typed as an opaque `SdkStore` handle on the return object — additive, zero breaking changes, consumers can pass it to oidc() but can't easily misuse the raw Redux API.", - "recommendedOptionIds": ["opaque-property"], - "options": [ - { - "id": "opaque-property", - "label": "store property (opaque SdkStore type)" - }, - { - "id": "full-property", - "label": "store property (full Redux Store type)" - }, - { "id": "getter-method", "label": "getStore() method" } - ], - "required": true - }, - { - "id": "oidc-injection", - "prompt": "How should `oidc()` accept the shared store?", - "description": "Option A: add an optional `store` param to the existing config object — `oidc({ config, store: client.store })`. Option B: add it as a second argument — `oidc({ config }, client.store)`. The survey shows oidc() already takes a single destructured options bag.", - "answerMode": "single-custom", - "recommendedAnswer": "Optional `store` field inside the existing options object — consistent with how requestMiddleware and logger are passed today.", - "recommendedOptionIds": ["options-bag"], - "options": [ - { - "id": "options-bag", - "label": "Optional field in existing options object" - }, - { "id": "second-arg", "label": "Second argument to oidc()" } - ], - "required": true - }, - { - "id": "wellknown-dedup", - "prompt": "Should `wellknownApi` be deduplicated as part of this work?", - "description": "All three packages each define their own `wellknownApi` RTK Query slice with the same reducerPath ('wellknown') and endpoint. With a shared store, both registrations would collide on the same reducer key. We could: (A) keep them separate and let RTK Query's cache dedup on-the-fly (they share the same reducerPath so this actually works), (B) extract `wellknownApi` to `sdk-effects` so both packages import the same instance, or (C) defer this to a follow-up.", - "answerMode": "single-custom", - "recommendedAnswer": "Extract wellknownApi to sdk-effects as part of this PR — the same-key collision is a latent bug we'd hit immediately when testing shared store, and extraction is straightforward.", - "recommendedOptionIds": ["extract-now"], - "options": [ - { - "id": "extract-now", - "label": "Extract wellknownApi to sdk-effects in this PR" - }, - { - "id": "rtk-dedup", - "label": "Rely on RTK Query same-key dedup (same reducerPath)" - }, - { "id": "defer", "label": "Defer to a follow-up" } - ], - "required": true - }, - { - "id": "reducer-injection-strategy", - "prompt": "How should oidc inject its reducers into a shared store?", - "description": "RTK 2.0 ships `combineSlices` and lazy reducer injection. Two clean approaches: (A) use `store.dispatch(oidcApi.util.updateSubscriptionOptions(...))` + manually add reducer via `store.injectReducers` if RTK exposes it, or (B) design `createClientStore` / `createJourneyStore` to pre-register all possible reducers with their slices (oidc's included) so the store is fully wired before oidc() receives it. Option B is simpler but slightly over-provisions; Option A is lazy but requires RTK 2.0 `combineSlices`.", - "answerMode": "single-custom", - "recommendedAnswer": "Pre-register all reducers in the owning store (davinci/journey) — avoids runtime injection complexity, reducer keys don't collide (config/node/davinci/journeyReducer/oidc/wellknown are all unique), and the extra state is negligible.", - "recommendedOptionIds": ["pre-register"], - "options": [ - { - "id": "pre-register", - "label": "Pre-register oidc reducers in davinci/journey store upfront" - }, - { - "id": "lazy-inject", - "label": "Lazy inject via RTK combineSlices at oidc() init time" - } - ], - "required": true - }, - { - "id": "scope", - "prompt": "Which packages are in scope for this change?", - "description": "davinci-client and journey-client are the store owners; oidc-client is the joiner. protect and device-client don't use Redux stores currently.", - "answerMode": "multi-custom", - "recommendedAnswer": "davinci-client, journey-client, oidc-client only.", - "recommendedOptionIds": ["davinci", "journey", "oidc"], - "options": [ - { "id": "davinci", "label": "davinci-client" }, - { "id": "journey", "label": "journey-client" }, - { "id": "oidc", "label": "oidc-client" }, - { "id": "sdk-effects", "label": "sdk-effects (wellknown extraction)" } - ], - "required": true - }, - { - "id": "breaking-changes", - "prompt": "Are any breaking changes acceptable?", - "description": "Exposing `store` on the return object is purely additive. Adding `store?` to oidc's options bag is additive. The only potential breaking change is if `wellknownApi` is extracted to sdk-effects and packages previously imported it directly — but that's an internal import path change, not a public API change.", - "answerMode": "single", - "recommendedAnswer": "No breaking changes to public API — internal import path changes are acceptable.", - "recommendedOptionIds": ["no-breaking"], - "options": [ - { "id": "no-breaking", "label": "No breaking public API changes" }, - { - "id": "minor-ok", - "label": "Minor breaking changes acceptable (semver minor)" - } - ], - "required": true - } - ] -} diff --git a/goals/centralize-redux-store/plan.md b/goals/centralize-redux-store/plan.md deleted file mode 100644 index 449aaea4fe..0000000000 --- a/goals/centralize-redux-store/plan.md +++ /dev/null @@ -1,187 +0,0 @@ -# Plan: Centralize Redux Store Across Client Packages - -## Solution Approach - -Migrate all three stores from `configureStore` + `combineReducers` to RTK 2.0 `combineSlices`, which enables lazy reducer injection. `davinci()` and `journey()` expose an opaque `SdkStore` handle on their return object. `oidc()` accepts that handle as an optional second argument and injects its own reducers into it at init time. `wellknownApi` is extracted to a new `sdk-effects/wellknown` package so all three clients share the same RTK Query instance — critical for cache deduplication on a shared store. - -## Ordered Steps - -### Step 1 — Extract `wellknownApi` to `@forgerock/sdk-wellknown` - -**Why first:** The shared store relies on a single `wellknownApi` instance. If each package keeps its own copy, `createApi` creates distinct RTK Query reducers with distinct internal state — sharing the store won't deduplicate the cache. This must land before any store changes. - -**Files to create:** - -- `packages/sdk-effects/wellknown/package.json` — follow `packages/sdk-effects/logger/package.json` as template, name `@forgerock/sdk-wellknown` -- `packages/sdk-effects/wellknown/src/index.ts` — re-exports from `lib/wellknown.api.ts` -- `packages/sdk-effects/wellknown/src/lib/wellknown.api.ts` — canonical implementation (merge `davinci-client`'s version + oidc's `wellknownSelector`/`createWellknownSelector`) -- `packages/sdk-effects/wellknown/vite.config.ts` — copy from `logger/vite.config.ts` -- `packages/sdk-effects/wellknown/project.json` — Nx project config -- `packages/sdk-effects/wellknown/tsconfig.json` / `tsconfig.lib.json` / `tsconfig.spec.json` - -**Files to modify:** - -- `packages/davinci-client/package.json` — add `@forgerock/sdk-wellknown: workspace:*` dep -- `packages/journey-client/package.json` — same -- `packages/oidc-client/package.json` — same -- `packages/davinci-client/src/lib/wellknown.api.ts` — delete file, update all imports to `@forgerock/sdk-wellknown` -- `packages/journey-client/src/lib/wellknown.api.ts` — delete file, update all imports -- `packages/oidc-client/src/lib/wellknown.api.ts` — delete file, update all imports (note: oidc has `wellknownSelector` — move to the shared package) - -**Verification:** - -```bash -pnpm nx build @forgerock/sdk-wellknown -pnpm nx build @forgerock/davinci-client -pnpm nx build @forgerock/journey-client -pnpm nx build @forgerock/oidc-client -pnpm nx test @forgerock/davinci-client -pnpm nx test @forgerock/journey-client -pnpm nx test @forgerock/oidc-client -``` - ---- - -### Step 2 — Introduce `SdkStore` opaque type in a shared location - -**Files to create/modify:** - -- `packages/sdk-types/src/lib/store.types.ts` — define the opaque `SdkStore` interface: - - ```ts - // Opaque handle — consumers can pass it around but cannot access Redux internals - export interface SdkStore { - readonly __brand: unique symbol; - } - ``` - - Internally, the concrete type will extend this. Consumers only ever see `SdkStore`. - -- `packages/sdk-types/src/index.ts` — export `SdkStore` - -**Why here:** `sdk-types` is the shared contracts layer with no runtime code. `SdkStore` is purely a type contract between the packages. Keeping it here avoids a circular dependency (davinci → sdk-types is already valid; oidc → sdk-types is already valid). - -**Verification:** - -```bash -pnpm nx build @forgerock/sdk-types -``` - ---- - -### Step 3 — Migrate `davinci-client` store to `combineSlices` + expose `SdkStore` - -**Files to modify:** - -- `packages/davinci-client/src/lib/client.store.utils.ts`: - - Replace `configureStore` + inline `reducer: {}` with `combineSlices(configSlice, nodeSlice, davinciApi, wellknownApi).withLazyLoadedSlices()` - - Create `const dynamicMiddleware = createDynamicMiddleware()` and add `dynamicMiddleware.middleware` to the `configureStore` middleware chain alongside `davinciApi.middleware` and `wellknownApi.middleware` - - Attach `__dynamicMiddleware: dynamicMiddleware` to the store (or carry it alongside) so `oidc()` can call `addMiddleware` at inject time - - Export the `rootReducer` so the store can be typed - - Export `InjectableStore` type (internal, extends the RTK store type, carries `__dynamicMiddleware` and the `combineSlices` `.inject()` method) -- `packages/davinci-client/src/lib/client.store.ts`: - - Add `store: store as SdkStore` to the return object of `davinci()` - - The local `store` variable remains typed as `InjectableStore` — the cast to `SdkStore` happens only at the return boundary - -- `packages/davinci-client/src/types.ts` — export `DavinciClient` type update picks up `store: SdkStore` automatically via `Awaited>` - -**Verification:** - -```bash -pnpm nx build @forgerock/davinci-client -pnpm nx test @forgerock/davinci-client -# Type check: verify DavinciClient has store: SdkStore -# Type check: verify store.dispatch / store.getState are NOT accessible on SdkStore -``` - ---- - -### Step 4 — Migrate `journey-client` store to `combineSlices` + expose `SdkStore` - -Mirrors Step 3. - -**Files to modify:** - -- `packages/journey-client/src/lib/client.store.utils.ts` — same `combineSlices` migration -- `packages/journey-client/src/lib/client.store.ts` — add `store: store as SdkStore` to return object -- `packages/journey-client/src/types.ts` (or `index.ts`) — `JourneyClient` interface gains `store: SdkStore` - -**Verification:** - -```bash -pnpm nx build @forgerock/journey-client -pnpm nx test @forgerock/journey-client -``` - ---- - -### Step 5 — Migrate `oidc-client` to accept optional `SdkStore` second argument + lazy inject - -**Files to modify:** - -- `packages/oidc-client/src/lib/client.store.utils.ts`: - - Keep `createClientStore` for standalone usage (no change) - - Add `injectIntoStore(store: SdkStore): void` helper — casts back to `InjectableStore`, calls `.inject(oidcApi)` and `.inject(wellknownApi)` - -- `packages/oidc-client/src/lib/client.store.ts` — `oidc()` signature becomes: - - ```ts - export async function oidc(options: OidcOptions, sharedStore?: SdkStore); - ``` - - Inside: - - If `sharedStore` is provided: call `injectIntoStore(sharedStore)`, use `sharedStore` as the internal store (cast to `InjectableStore`) - - If not provided: call `createClientStore(...)` as today - - All methods below are unchanged — they close over `store`, so the injection is transparent - -- `packages/oidc-client/src/types.ts` — `OidcClient` type picks up automatically; export `SdkStore` re-export for consumer convenience - -**Verification:** - -```bash -pnpm nx build @forgerock/oidc-client -pnpm nx test @forgerock/oidc-client -# Integration test: create davinci() → pass client.store to oidc() → assert single wellknown fetch -``` - ---- - -### Step 6 — Write integration tests proving shared-store behavior - -**Files to create/modify:** - -- `packages/oidc-client/src/lib/shared-store.test.ts` (or add to existing integration test file): - - Test: `oidc(opts, davinciClient.store)` — `wellknownApi` cache has exactly one entry, no second network call - - Test: `store.subscribe` on davinci client fires when oidc dispatches - - Test: `oidc(opts)` standalone still creates its own store (existing behavior) - - Test: TypeScript compile-time: `davinciClient.store.dispatch` should be a type error - -**Verification:** - -```bash -pnpm nx test @forgerock/oidc-client -pnpm nx test @forgerock/davinci-client -``` - ---- - -### Step 7 — Verify full suite + type check - -```bash -pnpm nx run-many -t build --no-agents -pnpm nx run-many -t lint -pnpm nx run-many -t test -pnpm tsc --noEmit # or pnpm nx run-many -t typecheck -``` - ---- - -## Risks and Open Questions - -1. **RTK Query middleware — use `createDynamicMiddleware`**: RTK Query API slices need their `.middleware` in the store's middleware chain. For lazy-injected slices like `oidcApi`, we use RTK 2.0's `createDynamicMiddleware`. The owning store (davinci/journey) registers `dynamicMiddleware.middleware` in `configureStore`; the `DynamicMiddlewareInstance` is included in the `InjectableStore` internal type. When `oidc()` injects its reducers via `combineSlices`, it also calls `store.__dynamicMiddleware.addMiddleware(oidcApi.middleware)`. No downside — this is RTK's designed use case for lazy middleware registration. - -2. **`wellknownApi` selector `RootState` coupling**: `oidc-client`'s `wellknownSelector` is typed against oidc's own `RootState`. After extraction to `sdk-wellknown`, it needs a generic state type or the `wellknown` slice state shape directly. Use `wellknownApi.endpoints.configuration.select(url)` directly — it returns a state selector that only requires the `wellknown` key, not a full `RootState`. - -3. **`SdkStore` cast fidelity**: The internal `InjectableStore` → `SdkStore` cast must be verifiably safe. Add a helper that asserts the store has `inject` available at runtime before accepting it in `oidc()`. - -4. **Package creation friction**: Creating a new `sdk-effects/wellknown` sub-package requires Nx project registration. Check `packages/sdk-effects/logger/project.json` and `nx.json` for the exact scaffolding pattern to avoid CI graph errors. diff --git a/packages/davinci-client/api-report/davinci-client.api.md b/packages/davinci-client/api-report/davinci-client.api.md index 4bc7e7e411..76a14485f4 100644 --- a/packages/davinci-client/api-report/davinci-client.api.md +++ b/packages/davinci-client/api-report/davinci-client.api.md @@ -1,2449 +1,2018 @@ -## API Report File for "@forgerock/davinci-client" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { ActionCreatorWithPayload } from '@reduxjs/toolkit'; -import { ActionTypes } from '@forgerock/sdk-request-middleware'; -import { CustomLogger } from '@forgerock/sdk-logger'; -import type { DaVinciConfig } from '@forgerock/sdk-types'; -import { FetchBaseQueryError } from '@reduxjs/toolkit/query'; -import type { FetchBaseQueryMeta } from '@reduxjs/toolkit/query'; -import { GenericError } from '@forgerock/sdk-types'; -import { LogLevel } from '@forgerock/sdk-logger'; -import type { MutationResultSelectorResult } from '@reduxjs/toolkit/query'; -import { QueryStatus } from '@reduxjs/toolkit/query'; -import { Reducer } from '@reduxjs/toolkit'; -import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; -import type { SdkStore } from '@forgerock/sdk-types'; -import { SerializedError } from '@reduxjs/toolkit'; -import { Unsubscribe } from '@reduxjs/toolkit'; - -// @public (undocumented) -export type ActionCollector = - | ActionCollectorNoUrl - | ActionCollectorWithUrl; - -// @public (undocumented) -export interface ActionCollectorNoUrl { - // (undocumented) - category: 'ActionCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ActionCollectors = - | ActionCollectorWithUrl<'IdpCollector'> - | ActionCollectorNoUrl<'ActionCollector'> - | ActionCollectorNoUrl<'FlowCollector'> - | ActionCollectorNoUrl<'SubmitCollector'>; - -// @public -export type ActionCollectorTypes = - | 'FlowCollector' - | 'SubmitCollector' - | 'IdpCollector' - | 'ActionCollector'; - -// @public (undocumented) -export interface ActionCollectorWithUrl { - // (undocumented) - category: 'ActionCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - url?: string | null; - }; - // (undocumented) - type: T; -} - -export { ActionTypes }; - -// @public (undocumented) -export type AgreementField = { - type: 'AGREEMENT'; - key: string; - content: string; - titleEnabled: boolean; - title?: string; - agreement: { - id: string; - useDynamicAgreement: boolean; - }; - enabled: boolean; -}; - -// @public (undocumented) -export interface AssertionValue extends Omit< - PublicKeyCredential, - 'rawId' | 'response' | 'getClientExtensionResults' | 'toJSON' -> { - // (undocumented) - rawId: string; - // (undocumented) - response: { - clientDataJSON: string; - authenticatorData: string; - signature: string; - userHandle: string | null; - }; -} - -// @public (undocumented) -export interface AttestationValue extends Omit< - PublicKeyCredential, - 'rawId' | 'response' | 'getClientExtensionResults' | 'toJSON' -> { - // (undocumented) - rawId: string; - // (undocumented) - response: { - clientDataJSON: string; - attestationObject: string; - }; -} - -// @public (undocumented) -export interface AutoCollector< - C extends AutoCollectorCategories, - T extends AutoCollectorTypes, - IV = string, - OV = Record, -> { - // (undocumented) - category: C; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: IV; - type: string; - validation?: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - type: string; - config: OV; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type AutoCollectorCategories = 'SingleValueAutoCollector' | 'ObjectValueAutoCollector'; - -// @public (undocumented) -export type AutoCollectors = - | ProtectCollector - | FidoRegistrationCollector - | FidoAuthenticationCollector - | MetadataCollector - | PollingCollector - | SingleValueAutoCollector - | ObjectValueAutoCollector; - -// @public (undocumented) -export type AutoCollectorTypes = SingleValueAutoCollectorTypes | ObjectValueAutoCollectorTypes; - -// @public (undocumented) -export interface BooleanCollector extends SingleValueCollectorWithValue< - 'BooleanCollector', - boolean -> { - // (undocumented) - output: SingleValueCollectorWithValue<'BooleanCollector', boolean>['output'] & { - appearance: string; - richContent?: CollectorRichContent; - }; -} - -// @public (undocumented) -export type CollectorCategory = Collectors['category']; - -// @public (undocumented) -export interface CollectorErrors { - // (undocumented) - code: string; - // (undocumented) - message: string; - // (undocumented) - target: string; -} - -// @public -export interface CollectorRichContent { - // (undocumented) - content: string; - // (undocumented) - replacements: RichContentLink[]; -} - -// @public (undocumented) -export type Collectors = - | FlowCollector - | MetadataCollector - | PasswordCollector - | ValidatedPasswordCollector - | TextCollector - | BooleanCollector - | ValidatedBooleanCollector - | SingleSelectCollector - | IdpCollector - | SubmitCollector - | ActionCollector<'ActionCollector'> - | SingleValueCollector<'SingleValueCollector'> - | MultiSelectCollector - | DeviceAuthenticationCollector - | DeviceRegistrationCollector - | PhoneNumberCollector - | PhoneNumberExtensionCollector - | ReadOnlyCollector - | RichTextCollector - | ValidatedTextCollector - | ProtectCollector - | PollingCollector - | FidoRegistrationCollector - | FidoAuthenticationCollector - | QrCodeCollector - | ImageCollector - | UnknownCollector; - -// @public -export type CollectorValueType = T extends - | { - type: 'PasswordCollector'; - } - | { - type: 'ValidatedPasswordCollector'; - } - | { - type: 'SingleSelectCollector'; - } - | { - type: 'DeviceRegistrationCollector'; - } - | { - type: 'DeviceAuthenticationCollector'; - } - | { - type: 'ProtectCollector'; - } - | { - type: 'PollingCollector'; - } - ? string - : T extends { - type: 'TextCollector'; - category: 'SingleValueCollector'; - } - ? string - : T extends { - type: 'TextCollector'; - category: 'ValidatedSingleValueCollector'; - } - ? string - : T extends - | { - type: 'BooleanCollector'; - } - | { - type: 'ValidatedBooleanCollector'; - } - ? boolean - : T extends { - type: 'MultiSelectCollector'; - } - ? string | string[] - : T extends { - type: 'PhoneNumberCollector'; - } - ? PhoneNumberInputValue - : T extends { - type: 'PhoneNumberExtensionCollector'; - } - ? PhoneNumberExtensionInputValue - : T extends { - type: 'FidoRegistrationCollector'; - } - ? FidoRegistrationInputValue | GenericError - : T extends { - type: 'FidoAuthenticationCollector'; - } - ? FidoAuthenticationInputValue | GenericError - : T extends { - type: 'MetadataCollector'; - } - ? Record | MetadataError - : T extends { - category: 'SingleValueCollector'; - } - ? string - : T extends { - category: 'ValidatedSingleValueCollector'; - } - ? string - : T extends { - category: 'SingleValueAutoCollector'; - } - ? string - : T extends { - category: 'MultiValueCollector'; - } - ? string | string[] - : T extends { - category: 'ActionCollector'; - } - ? never - : T extends { - category: 'NoValueCollector'; - } - ? never - : CollectorValueTypes; - -// @public -export type CollectorValueTypes = - | string - | string[] - | boolean - | PhoneNumberInputValue - | PhoneNumberExtensionInputValue - | FidoRegistrationInputValue - | FidoAuthenticationInputValue - | MetadataError - | GenericError; - -// @public (undocumented) -export type ComplexValueFields = - | DeviceAuthenticationField - | DeviceRegistrationField - | PhoneNumberField - | PhoneNumberExtensionField - | FidoRegistrationField - | FidoAuthenticationField - | PollingField - | MetadataField; - -// @public (undocumented) -export interface ContinueNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'continue'; - }; - // (undocumented) - error: null; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - eventName?: string; - status: 'continue'; - }; - // (undocumented) - status: 'continue'; -} - -export { CustomLogger }; - -// @public -export type CustomPollingStatus = string & {}; - -// @public -export function davinci(input: { - config: DaVinciConfig; - requestMiddleware?: RequestMiddleware[]; - logger?: { - level: LogLevel; - custom?: CustomLogger; - }; -}): Promise<{ - store: SdkStore; - subscribe: (listener: () => void) => Unsubscribe; - externalIdp: () => () => Promise; - flow: (action: DaVinciAction) => InitFlow; - next: (args?: DaVinciRequest) => Promise; - resume: (input: { continueToken: string }) => Promise; - start: ( - options?: StartOptions | undefined, - ) => Promise; - update: < - T extends SingleValueCollectors | MultiSelectCollector | ObjectValueCollectors | AutoCollectors, - >( - collector: T, - ) => Updater; - validate: ( - collector: - | SingleValueCollectors - | ObjectValueCollectors - | MultiValueCollectors - | AutoCollectors, - ) => Validator; - pollStatus: (collector: PollingCollector) => Poller; - getClient: () => - | { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'error'; - } - | { - status: 'failure'; - } - | { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'continue'; - } - | { - status: 'failure'; - } - | { - status: 'start'; - } - | { - authorization?: { - code?: string; - state?: string; - }; - status: 'success'; - } - | null; - getCollectors: () => Collectors[]; - getError: () => DaVinciError | null; - getErrorCollectors: () => CollectorErrors[]; - getNode: () => ContinueNode | ErrorNode | FailureNode | StartNode | SuccessNode; - getServer: () => - | { - _links?: Links; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - eventName?: string; - status: 'continue'; - } - | { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'error'; - } - | { - _links?: Links; - eventName?: string; - href?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'failure'; - } - | { - status: 'start'; - } - | { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - session?: string; - status: 'success'; - } - | null; - cache: { - getLatestResponse: () => - | ({ - status: QueryStatus.fulfilled; - } & Omit< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'data' | 'fulfilledTimeStamp' - > & - Required< - Pick< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'data' | 'fulfilledTimeStamp' - > - > & { - error: undefined; - } & { - status: QueryStatus.fulfilled; - isUninitialized: false; - isLoading: false; - isSuccess: true; - isError: false; - }) - | ({ - status: QueryStatus.rejected; - } & Omit< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'error' - > & - Required< - Pick< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'error' - > - > & { - status: QueryStatus.rejected; - isUninitialized: false; - isLoading: false; - isSuccess: false; - isError: true; - }) - | { - error: { - message: string; - type: string; - }; - }; - getResponseWithId: (requestId: string) => - | ({ - status: QueryStatus.fulfilled; - } & Omit< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'data' | 'fulfilledTimeStamp' - > & - Required< - Pick< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'data' | 'fulfilledTimeStamp' - > - > & { - error: undefined; - } & { - status: QueryStatus.fulfilled; - isUninitialized: false; - isLoading: false; - isSuccess: true; - isError: false; - }) - | ({ - status: QueryStatus.rejected; - } & Omit< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'error' - > & - Required< - Pick< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'error' - > - > & { - status: QueryStatus.rejected; - isUninitialized: false; - isLoading: false; - isSuccess: false; - isError: true; - }) - | { - error: { - message: string; - type: string; - }; - }; - }; -}>; - -// @public -export interface DaVinciAction { - // (undocumented) - action: string; -} - -// @public -export interface DaVinciBaseResponse { - // (undocumented) - capabilityName?: string; - // (undocumented) - companyId?: string; - // (undocumented) - connectionId?: string; - // (undocumented) - connectorId?: string; - // (undocumented) - id?: string; - // (undocumented) - interactionId?: string; - // (undocumented) - interactionToken?: string; - // (undocumented) - isResponseCompatibleWithMobileAndWebSdks?: boolean; - // (undocumented) - status?: string; -} - -// @public -export type DaVinciCacheEntry = { - data?: DaVinciBaseResponse; - error?: { - data: DaVinciBaseResponse; - status: number; - }; -} & { - data?: any; - error?: any; -} & MutationResultSelectorResult; - -// @public (undocumented) -export type DavinciClient = Awaited>; - -export { DaVinciConfig }; - -// @public (undocumented) -export interface DaVinciError extends Omit { - // (undocumented) - collectors?: CollectorErrors[]; - // (undocumented) - internalHttpStatus?: number; - // (undocumented) - message: string; - // (undocumented) - status: 'error' | 'failure' | 'unknown'; -} - -// @public (undocumented) -export interface DaVinciErrorCacheEntry { - // (undocumented) - endpointName: 'next' | 'flow' | 'start'; - // (undocumented) - error: { - data: T; - }; - // (undocumented) - fulfilledTimeStamp: number; - // (undocumented) - isError: boolean; - // (undocumented) - isLoading: boolean; - // (undocumented) - isSuccess: boolean; - // (undocumented) - isUninitialized: boolean; - // (undocumented) - requestId: string; - // (undocumented) - startedTimeStamp: number; - // (undocumented) - status: 'fulfilled' | 'pending' | 'rejected'; -} - -// @public (undocumented) -export interface DavinciErrorResponse extends DaVinciBaseResponse { - // (undocumented) - cause?: string | null; - // (undocumented) - code: string | number; - // (undocumented) - details?: ErrorDetail[]; - // (undocumented) - doNotSendToOE?: boolean; - // (undocumented) - error?: { - code?: string; - message?: string; - }; - // (undocumented) - errorCategory?: string; - // (undocumented) - errorMessage?: string; - // (undocumented) - expected?: boolean; - // (undocumented) - httpResponseCode: number; - // (undocumented) - isErrorCustomized?: boolean; - // (undocumented) - message: string; - // (undocumented) - metricAttributes?: { - [key: string]: unknown; - }; -} - -// @public (undocumented) -export interface DaVinciFailureResponse extends DaVinciBaseResponse { - // (undocumented) - error?: { - code?: string; - message?: string; - [key: string]: unknown; - }; -} - -// @public (undocumented) -export type DaVinciField = - | ComplexValueFields - | MultiValueFields - | ReadOnlyFields - | RedirectFields - | SingleValueFields; - -// @public -export interface DaVinciNextResponse extends DaVinciBaseResponse { - // (undocumented) - eventName?: string; - // (undocumented) - form?: { - name?: string; - description?: string; - components?: { - fields?: DaVinciField[]; - }; - }; - // (undocumented) - formData?: { - value?: { - [key: string]: string; - }; - }; - // (undocumented) - _links?: Links; -} - -// @public -export interface DaVinciPollResponse extends DaVinciBaseResponse { - // (undocumented) - eventName?: string; - // (undocumented) - _links?: Links; - // (undocumented) - success?: boolean; -} - -// @public (undocumented) -export interface DaVinciRequest { - // (undocumented) - eventName: string; - // (undocumented) - id: string; - // (undocumented) - interactionId: string; - // (undocumented) - parameters: { - eventType: 'submit' | 'action' | 'polling'; - data: { - actionKey: string; - formData?: Record; - }; - }; -} - -// @public -export type DaVinciRequestValueTypes = - | string - | number - | boolean - | (string | number | boolean)[] - | DeviceValue - | PhoneNumberInputValue - | FidoRegistrationInputValue - | FidoAuthenticationInputValue - | MetadataError - | GenericError; - -// @public (undocumented) -export interface DaVinciSuccessResponse extends DaVinciBaseResponse { - // (undocumented) - authorizeResponse?: OAuthDetails; - // (undocumented) - environment: { - id: string; - [key: string]: unknown; - }; - // (undocumented) - _links?: Links; - // (undocumented) - resetCookie?: boolean; - // (undocumented) - session?: { - id?: string; - [key: string]: unknown; - }; - // (undocumented) - sessionToken?: string; - // (undocumented) - sessionTokenMaxAge?: number; - // (undocumented) - status: string; - // (undocumented) - subFlowSettings?: { - cssLinks?: unknown[]; - cssUrl?: unknown; - jsLinks?: unknown[]; - loadingScreenSettings?: unknown; - reactSkUrl?: unknown; - }; - // (undocumented) - success: true; -} - -// @public (undocumented) -export type DeviceAuthenticationCollector = ObjectOptionsCollectorWithObjectValue< - 'DeviceAuthenticationCollector', - DeviceValue ->; - -// @public (undocumented) -export type DeviceAuthenticationField = { - type: 'DEVICE_AUTHENTICATION'; - key: string; - label: string; - options: { - type: string; - iconSrc: string; - title: string; - id: string; - default: boolean; - description: string; - }[]; - required: boolean; -}; - -// @public (undocumented) -export interface DeviceOptionNoDefault { - // (undocumented) - content: string; - // (undocumented) - key: string; - // (undocumented) - label: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export interface DeviceOptionWithDefault { - // (undocumented) - content: string; - // (undocumented) - default: boolean; - // (undocumented) - key: string; - // (undocumented) - label: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export type DeviceRegistrationCollector = ObjectOptionsCollectorWithStringValue< - 'DeviceRegistrationCollector', - string ->; - -// @public (undocumented) -export type DeviceRegistrationField = { - type: 'DEVICE_REGISTRATION'; - key: string; - label: string; - options: { - type: string; - iconSrc: string; - title: string; - description: string; - }[]; - required: boolean; -}; - -// @public (undocumented) -export interface DeviceValue { - // (undocumented) - id: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export interface ErrorDetail { - // (undocumented) - message?: string; - // (undocumented) - rawResponse?: { - _embedded?: { - users?: Array; - }; - code?: string; - count?: number; - details?: NestedErrorDetails[]; - id?: string; - message?: string; - size?: number; - userFilter?: string; - [key: string]: unknown; - }; - // (undocumented) - statusCode?: number; -} - -// @public (undocumented) -export interface ErrorNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'error'; - }; - // (undocumented) - error: DaVinciError; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'error'; - } | null; - // (undocumented) - status: 'error'; -} - -// @public (undocumented) -export interface FailureNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - status: 'failure'; - }; - // (undocumented) - error: DaVinciError; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - href?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'failure'; - } | null; - // (undocumented) - status: 'failure'; -} - -// @public -export function fido(): FidoClient; - -// @public (undocumented) -export type FidoAuthenticationCollector = AutoCollector< - 'ObjectValueAutoCollector', - 'FidoAuthenticationCollector', - FidoAuthenticationInputValue | GenericError, - FidoAuthenticationOutputValue ->; - -// @public (undocumented) -export type FidoAuthenticationField = { - type: 'FIDO2'; - key: string; - label: string; - publicKeyCredentialRequestOptions: FidoAuthenticationOptions; - action: 'AUTHENTICATE'; - trigger: string; - required: boolean; -}; - -// @public (undocumented) -export interface FidoAuthenticationInputValue { - // (undocumented) - assertionValue?: AssertionValue; -} - -// @public (undocumented) -export interface FidoAuthenticationOptions extends Omit< - PublicKeyCredentialRequestOptions, - 'challenge' | 'allowCredentials' -> { - // (undocumented) - allowCredentials?: { - id: number[]; - transports?: AuthenticatorTransport[]; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - challenge: number[]; -} - -// @public (undocumented) -export interface FidoAuthenticationOutputValue { - // (undocumented) - action: 'AUTHENTICATE'; - // (undocumented) - publicKeyCredentialRequestOptions: FidoAuthenticationOptions; - // (undocumented) - trigger: string; -} - -// @public (undocumented) -export interface FidoClient { - authenticate: ( - options: FidoAuthenticationOptions, - ) => Promise; - register: ( - options: FidoRegistrationOptions, - ) => Promise; -} - -// @public -export type FidoErrorCode = - | 'NotAllowedError' - | 'AbortError' - | 'InvalidStateError' - | 'NotSupportedError' - | 'SecurityError' - | 'TimeoutError' - | 'UnknownError'; - -// @public (undocumented) -export type FidoRegistrationCollector = AutoCollector< - 'ObjectValueAutoCollector', - 'FidoRegistrationCollector', - FidoRegistrationInputValue | GenericError, - FidoRegistrationOutputValue ->; - -// @public (undocumented) -export type FidoRegistrationField = { - type: 'FIDO2'; - key: string; - label: string; - publicKeyCredentialCreationOptions: FidoRegistrationOptions; - action: 'REGISTER'; - trigger: string; - required: boolean; -}; - -// @public (undocumented) -export interface FidoRegistrationInputValue { - // (undocumented) - attestationValue?: AttestationValue; -} - -// @public (undocumented) -export interface FidoRegistrationOptions extends Omit< - PublicKeyCredentialCreationOptions, - 'challenge' | 'user' | 'pubKeyCredParams' | 'excludeCredentials' -> { - // (undocumented) - challenge: number[]; - // (undocumented) - excludeCredentials?: { - id: number[]; - transports?: AuthenticatorTransport[]; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - pubKeyCredParams: { - alg: string | number; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - user: { - id: number[]; - name: string; - displayName: string; - }; -} - -// @public (undocumented) -export interface FidoRegistrationOutputValue { - // (undocumented) - action: 'REGISTER'; - // (undocumented) - publicKeyCredentialCreationOptions: FidoRegistrationOptions; - // (undocumented) - trigger: string; -} - -// @public (undocumented) -export type FlowCollector = ActionCollectorNoUrl<'FlowCollector'>; - -// @public (undocumented) -export type FlowNode = ContinueNode | ErrorNode | StartNode | SuccessNode | FailureNode; - -// @public -export type GetClient = - | StartNode['client'] - | ContinueNode['client'] - | ErrorNode['client'] - | SuccessNode['client'] - | FailureNode['client']; - -// @public (undocumented) -export type IdpCollector = ActionCollectorWithUrl<'IdpCollector'>; - -// @public -export interface ImageCollector extends NoValueCollectorBase<'ImageCollector'> { - // (undocumented) - output: NoValueCollectorBase<'ImageCollector'>['output'] & { - src: string; - alt: string; - href?: string; - }; -} - -// @public (undocumented) -export type ImageField = { - type: 'IMAGE'; - key: string; - description: string; - imageUrl: string; - hyperlinkUrl?: string; -}; - -// @public (undocumented) -export type InferActionCollectorType = T extends 'IdpCollector' - ? IdpCollector - : T extends 'SubmitCollector' - ? SubmitCollector - : T extends 'FlowCollector' - ? FlowCollector - : ActionCollectorWithUrl<'ActionCollector'> | ActionCollectorNoUrl<'ActionCollector'>; - -// @public -export type InferAutoCollectorType = T extends 'ProtectCollector' - ? ProtectCollector - : T extends 'PollingCollector' - ? PollingCollector - : T extends 'FidoRegistrationCollector' - ? FidoRegistrationCollector - : T extends 'FidoAuthenticationCollector' - ? FidoAuthenticationCollector - : T extends 'MetadataCollector' - ? MetadataCollector - : T extends 'ObjectValueAutoCollector' - ? ObjectValueAutoCollector - : SingleValueAutoCollector; - -// @public -export type InferMultiValueCollectorType = - T extends 'MultiSelectCollector' - ? MultiValueCollectorWithValue<'MultiSelectCollector'> - : - | MultiValueCollectorWithValue<'MultiValueCollector'> - | MultiValueCollectorNoValue<'MultiValueCollector'>; - -// @public -export type InferNoValueCollectorType = - T extends 'ReadOnlyCollector' - ? ReadOnlyCollector - : T extends 'RichTextCollector' - ? RichTextCollector - : T extends 'QrCodeCollector' - ? QrCodeCollector - : T extends 'ImageCollector' - ? ImageCollector - : NoValueCollectorBase<'NoValueCollector'>; - -// @public -export type InferSingleValueCollectorType = - T extends 'TextCollector' - ? TextCollector - : T extends 'SingleSelectCollector' - ? SingleSelectCollector - : T extends 'ValidatedTextCollector' - ? ValidatedTextCollector - : T extends 'PasswordCollector' - ? PasswordCollector - : T extends 'ValidatedPasswordCollector' - ? ValidatedPasswordCollector - : T extends 'BooleanCollector' - ? BooleanCollector - : T extends 'ValidatedBooleanCollector' - ? ValidatedBooleanCollector - : - | SingleValueCollectorWithValue<'SingleValueCollector'> - | SingleValueCollectorNoValue<'SingleValueCollector'>; - -// @public (undocumented) -export type InferValueObjectCollectorType = - T extends 'DeviceAuthenticationCollector' - ? DeviceAuthenticationCollector - : T extends 'DeviceRegistrationCollector' - ? DeviceRegistrationCollector - : T extends 'PhoneNumberCollector' - ? PhoneNumberCollector - : T extends 'PhoneNumberExtensionCollector' - ? PhoneNumberExtensionCollector - : - | ObjectOptionsCollectorWithObjectValue<'ObjectValueCollector'> - | ObjectOptionsCollectorWithStringValue<'ObjectValueCollector'>; - -// @public (undocumented) -export type InitFlow = () => Promise; - -// @public (undocumented) -export interface InternalErrorResponse { - // (undocumented) - error: Omit & { - message: string; - }; - // (undocumented) - type: 'internal_error'; -} - -// @public (undocumented) -export interface Links { - // (undocumented) - [key: string]: { - href?: string; - }; -} - -export { LogLevel }; - -// @public (undocumented) -export type MetadataCollector = AutoCollector< - 'ObjectValueAutoCollector', - 'MetadataCollector', - MetadataCollectorInputValue, - Record ->; - -// @public (undocumented) -export type MetadataCollectorInputValue = Record | MetadataError; - -// @public -export interface MetadataError { - // (undocumented) - code: string; - // (undocumented) - message: string; -} - -// @public (undocumented) -export type MetadataField = { - type: 'METADATA'; - key: string; - payload: Record; -}; - -// @public (undocumented) -export type MultiSelectCollector = MultiValueCollectorWithValue<'MultiSelectCollector'>; - -// @public (undocumented) -export type MultiSelectField = { - inputType: 'MULTI_SELECT'; - key: string; - label: string; - options: { - label: string; - value: string; - }[]; - required?: boolean; - type: 'CHECKBOX' | 'COMBOBOX'; -}; - -// @public (undocumented) -export type MultiValueCollector = - | MultiValueCollectorWithValue - | MultiValueCollectorNoValue; - -// @public (undocumented) -export interface MultiValueCollectorNoValue { - // (undocumented) - category: 'MultiValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string[]; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type MultiValueCollectors = - | MultiValueCollectorWithValue<'MultiValueCollector'> - | MultiValueCollectorWithValue<'MultiSelectCollector'>; - -// @public -export type MultiValueCollectorTypes = 'MultiSelectCollector' | 'MultiValueCollector'; - -// @public (undocumented) -export interface MultiValueCollectorWithValue { - // (undocumented) - category: 'MultiValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string[]; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: string[]; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type MultiValueFields = MultiSelectField; - -// @public -export interface NestedErrorDetails { - // (undocumented) - code?: string; - // (undocumented) - innerError?: { - history?: string; - unsatisfiedRequirements?: string[]; - failuresRemaining?: number; - }; - // (undocumented) - message?: string; - // (undocumented) - target?: string; -} - -// @public -export const nextCollectorValues: ActionCreatorWithPayload< - { - fields: DaVinciField[]; - formData: { - value: Record; - }; - }, - string ->; - -// @public -export const nodeCollectorReducer: Reducer & { - getInitialState: () => Collectors[]; -}; - -// @public (undocumented) -export type NodeStates = StartNode | ContinueNode | ErrorNode | SuccessNode | FailureNode; - -// @public (undocumented) -export type NoValueCollector = InferNoValueCollectorType; - -// @public (undocumented) -export interface NoValueCollectorBase { - // (undocumented) - category: 'NoValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type NoValueCollectors = - | NoValueCollectorBase<'NoValueCollector'> - | ReadOnlyCollector - | RichTextCollector - | QrCodeCollector - | ImageCollector; - -// @public -export type NoValueCollectorTypes = - | 'ReadOnlyCollector' - | 'RichTextCollector' - | 'NoValueCollector' - | 'QrCodeCollector' - | 'ImageCollector'; - -// @public -export interface OAuthDetails { - // (undocumented) - [key: string]: unknown; - // (undocumented) - code?: string; - // (undocumented) - state?: string; -} - -// @public (undocumented) -export interface ObjectOptionsCollectorWithObjectValue< - T extends ObjectValueCollectorTypes, - V = Record, - D = Record, -> { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: DeviceOptionWithDefault[]; - value?: D | null; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface ObjectOptionsCollectorWithStringValue< - T extends ObjectValueCollectorTypes, - V = string, -> { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: DeviceOptionNoDefault[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ObjectValueAutoCollector = AutoCollector< - 'ObjectValueAutoCollector', - 'ObjectValueAutoCollector', - Record ->; - -// @public (undocumented) -export type ObjectValueAutoCollectorTypes = - | 'ObjectValueAutoCollector' - | 'FidoRegistrationCollector' - | 'FidoAuthenticationCollector' - | 'MetadataCollector'; - -// @public (undocumented) -export type ObjectValueCollector = - | ObjectOptionsCollectorWithObjectValue - | ObjectOptionsCollectorWithStringValue - | ObjectValueCollectorWithObjectValue; - -// @public (undocumented) -export type ObjectValueCollectors = - | DeviceAuthenticationCollector - | DeviceRegistrationCollector - | PhoneNumberCollector - | PhoneNumberExtensionCollector - | ObjectOptionsCollectorWithObjectValue<'ObjectSelectCollector'> - | ObjectOptionsCollectorWithStringValue<'ObjectSelectCollector'>; - -// @public -export type ObjectValueCollectorTypes = - | 'DeviceAuthenticationCollector' - | 'DeviceRegistrationCollector' - | 'PhoneNumberCollector' - | 'PhoneNumberExtensionCollector' - | 'ObjectOptionsCollector' - | 'ObjectValueCollector' - | 'ObjectSelectCollector'; - -// @public (undocumented) -export interface ObjectValueCollectorWithObjectValue< - T extends ObjectValueCollectorTypes, - IV = Record, - OV = Record, -> { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: IV; - type: string; - validation: (ValidationRequired | ValidationPhoneNumber)[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value?: OV | null; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface OutgoingQueryParams { - // (undocumented) - [key: string]: string | string[]; -} - -// @public (undocumented) -export interface PasswordCollector { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - verify: boolean; - }; - // (undocumented) - type: 'PasswordCollector'; -} - -// @public -export type PasswordField = { - type: 'PASSWORD' | 'PASSWORD_VERIFY'; - key: string; - label: string; - required?: boolean; - verify?: boolean; - passwordPolicy?: PasswordPolicy; -}; - -// @public -export interface PasswordPolicy { - // (undocumented) - createdAt?: string; - // (undocumented) - default?: boolean; - // (undocumented) - description?: string; - // (undocumented) - excludesCommonlyUsed?: boolean; - // (undocumented) - excludesProfileData?: boolean; - // (undocumented) - history?: { - count?: number; - retentionDays?: number; - }; - // (undocumented) - id?: string; - // (undocumented) - length?: { - min?: number; - max?: number; - }; - // (undocumented) - lockout?: { - failureCount?: number; - durationSeconds?: number; - }; - // (undocumented) - maxAgeDays?: number; - // (undocumented) - maxRepeatedCharacters?: number; - // (undocumented) - minAgeDays?: number; - // (undocumented) - minCharacters?: Record; - // (undocumented) - minUniqueCharacters?: number; - // (undocumented) - name?: string; - // (undocumented) - notSimilarToCurrent?: boolean; - // (undocumented) - populationCount?: number; - // (undocumented) - updatedAt?: string; -} - -// @public (undocumented) -export type PhoneNumberCollector = ObjectValueCollectorWithObjectValue< - 'PhoneNumberCollector', - PhoneNumberInputValue, - PhoneNumberOutputValue ->; - -// @public (undocumented) -export interface PhoneNumberExtensionCollector { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: PhoneNumberExtensionInputValue; - type: string; - validation: (ValidationRequired | ValidationPhoneNumber)[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - extensionLabel: string; - value: PhoneNumberExtensionOutputValue; - }; - // (undocumented) - type: 'PhoneNumberExtensionCollector'; -} - -// @public (undocumented) -export type PhoneNumberExtensionField = PhoneNumberField & { - showExtension: boolean; - extensionLabel: string; -}; - -// @public (undocumented) -export interface PhoneNumberExtensionInputValue { - // (undocumented) - countryCode: string; - // (undocumented) - extension: string; - // (undocumented) - phoneNumber: string; -} - -// @public (undocumented) -export interface PhoneNumberExtensionOutputValue { - // (undocumented) - countryCode?: string; - // (undocumented) - extension?: string; - // (undocumented) - phoneNumber?: string; -} - -// @public (undocumented) -export type PhoneNumberField = { - type: 'PHONE_NUMBER'; - key: string; - label: string; - required: boolean; - defaultCountryCode: string | null; - validatePhoneNumber: boolean; -}; - -// @public (undocumented) -export interface PhoneNumberInputValue { - // (undocumented) - countryCode: string; - // (undocumented) - phoneNumber: string; -} - -// @public (undocumented) -export interface PhoneNumberOutputValue { - // (undocumented) - countryCode?: string; - // (undocumented) - phoneNumber?: string; -} - -// @public -export type Poller = () => Promise; - -// @public (undocumented) -export type PollingCollector = AutoCollector< - 'SingleValueAutoCollector', - 'PollingCollector', - string, - PollingOutputValue ->; - -// @public (undocumented) -export type PollingField = { - type: 'POLLING'; - key: string; - pollInterval: number; - pollRetries: number; - pollChallengeStatus?: boolean; - challenge?: string; -}; - -// @public (undocumented) -export interface PollingOutputValue { - // (undocumented) - challenge?: string; - // (undocumented) - pollChallengeStatus?: boolean; - // (undocumented) - pollInterval: number; - // (undocumented) - pollRetries: number; - // (undocumented) - retriesRemaining?: number; -} - -// @public (undocumented) -export type PollingStatus = PollingStatusContinue | PollingStatusChallenge; - -// @public (undocumented) -export type PollingStatusChallenge = - | PollingStatusChallengeComplete - | 'expired' - | 'timedOut' - | 'error'; - -// @public (undocumented) -export type PollingStatusChallengeComplete = - | 'approved' - | 'denied' - | 'continue' - | CustomPollingStatus; - -// @public (undocumented) -export type PollingStatusContinue = 'continue' | 'timedOut'; - -// @public (undocumented) -export type ProtectCollector = AutoCollector< - 'SingleValueAutoCollector', - 'ProtectCollector', - string, - ProtectOutputValue ->; - -// @public (undocumented) -export type ProtectField = { - type: 'PROTECT'; - key: string; - behavioralDataCollection: boolean; - universalDeviceIdentification: boolean; -}; - -// @public -export interface ProtectOutputValue { - // (undocumented) - behavioralDataCollection: boolean; - // (undocumented) - universalDeviceIdentification: boolean; -} - -// @public -export interface QrCodeCollector extends NoValueCollectorBase<'QrCodeCollector'> { - // (undocumented) - output: NoValueCollectorBase<'QrCodeCollector'>['output'] & { - src: string; - }; -} - -// @public (undocumented) -export type QrCodeField = { - type: 'QR_CODE'; - key: string; - content: string; - fallbackText?: string; -}; - -// @public -export interface ReadOnlyCollector extends NoValueCollectorBase<'ReadOnlyCollector'> { - // (undocumented) - output: NoValueCollectorBase<'ReadOnlyCollector'>['output'] & { - content: string; - title?: string; - }; -} - -// @public (undocumented) -export type ReadOnlyField = { - type: 'LABEL'; - content: string; - richContent?: RichContent; - key?: string; -}; - -// @public (undocumented) -export type ReadOnlyFields = ReadOnlyField | QrCodeField | AgreementField | ImageField; - -// @public (undocumented) -export type RedirectField = { - type: 'SOCIAL_LOGIN_BUTTON'; - key: string; - label: string; - links: Links; -}; - -// @public (undocumented) -export type RedirectFields = RedirectField; - -export { RequestMiddleware }; - -// @public -export type RichContent = { - content: string; - replacements?: Record; -}; - -// @public -export interface RichContentLink { - // (undocumented) - href: string; - // (undocumented) - key: string; - // (undocumented) - target?: '_self' | '_blank'; - // (undocumented) - type: 'link'; - // (undocumented) - value: string; -} - -// @public -export type RichContentReplacement = { - type: 'link'; - value: string; - href: string; - target?: '_self' | '_blank'; -}; - -// @public -export interface RichTextCollector extends NoValueCollectorBase<'RichTextCollector'> { - // (undocumented) - output: NoValueCollectorBase<'RichTextCollector'>['output'] & { - content: string; - richContent: CollectorRichContent; - }; -} - -// @public (undocumented) -export interface SelectorOption { - // (undocumented) - label: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export type SingleCheckboxField = { - type: 'SINGLE_CHECKBOX'; - inputType: 'BOOLEAN'; - key: string; - label: string; - required?: boolean; - errorMessage?: string; - appearance: string; - richContent?: RichContent; -}; - -// @public (undocumented) -export type SingleSelectCollector = SingleSelectCollectorWithValue<'SingleSelectCollector'>; - -// @public (undocumented) -export interface SingleSelectCollectorNoValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface SingleSelectCollectorWithValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: string | number | boolean; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleSelectField = { - inputType: 'SINGLE_SELECT'; - key: string; - label: string; - options: { - label: string; - value: string; - }[]; - required?: boolean; - type: 'RADIO' | 'DROPDOWN'; -}; - -// @public (undocumented) -export type SingleValueAutoCollector = AutoCollector< - 'SingleValueAutoCollector', - 'SingleValueAutoCollector', - string ->; - -// @public (undocumented) -export type SingleValueAutoCollectorTypes = - | 'SingleValueAutoCollector' - | 'ProtectCollector' - | 'PollingCollector'; - -// @public -export type SingleValueCollector = - | SingleValueCollectorWithValue - | SingleValueCollectorNoValue; - -// @public (undocumented) -export interface SingleValueCollectorNoValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleValueCollectors = - | PasswordCollector - | ValidatedPasswordCollector - | SingleSelectCollector - | TextCollector - | ValidatedTextCollector - | BooleanCollector - | ValidatedBooleanCollector - | SingleValueCollectorWithValue<'SingleValueCollector'>; - -// @public -export type SingleValueCollectorTypes = - | 'PasswordCollector' - | 'ValidatedPasswordCollector' - | 'BooleanCollector' - | 'ValidatedBooleanCollector' - | 'SingleValueCollector' - | 'SingleSelectCollector' - | 'SingleSelectObjectCollector' - | 'TextCollector' - | 'ValidatedTextCollector'; - -// @public (undocumented) -export interface SingleValueCollectorWithValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: V; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleValueFields = - | StandardField - | PasswordField - | ValidatedField - | SingleCheckboxField - | SingleSelectField - | ProtectField; - -// @public (undocumented) -export type StandardField = { - type: 'TEXT' | 'SUBMIT_BUTTON' | 'FLOW_BUTTON' | 'FLOW_LINK' | 'BUTTON'; - key: string; - label: string; - required?: boolean; -}; - -// @public (undocumented) -export interface StartNode { - // (undocumented) - cache: null; - // (undocumented) - client: { - status: 'start'; - }; - // (undocumented) - error: DaVinciError | null; - // (undocumented) - server: { - status: 'start'; - }; - // (undocumented) - status: 'start'; -} - -// @public (undocumented) -export interface StartOptions { - // (undocumented) - query: Query; -} - -// @public (undocumented) -export type SubmitCollector = ActionCollectorNoUrl<'SubmitCollector'>; - -// @public (undocumented) -export interface SuccessNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - authorization?: { - code?: string; - state?: string; - }; - status: 'success'; - } | null; - // (undocumented) - error: null; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - session?: string; - status: 'success'; - }; - // (undocumented) - status: 'success'; -} - -// @public (undocumented) -export type TextCollector = SingleValueCollectorWithValue<'TextCollector'>; - -// @public (undocumented) -export interface ThrownQueryError { - // (undocumented) - error: FetchBaseQueryError; - // (undocumented) - isHandledError: boolean; - // (undocumented) - meta: FetchBaseQueryMeta; -} - -// @public -export type UnknownCollector = { - category: 'UnknownCollector'; - error: string | null; - type: 'UnknownCollector'; - id: string; - name: string; - output: { - key: string; - label: string; - type: string; - }; -}; - -// @public (undocumented) -export type UnknownField = Record; - -// @public -export type UpdatableCollectors = - | SingleValueCollectors - | MultiSelectCollector - | ObjectValueCollectors - | AutoCollectors; - -// @public (undocumented) -export const updateCollectorValues: ActionCreatorWithPayload< - { - id: string; - value: CollectorValueTypes; - index?: number; - }, - string ->; - -// @public -export type Updater = ( - value: CollectorValueType, - index?: number, -) => InternalErrorResponse | null; - -// @public (undocumented) -export interface ValidatedBooleanCollector extends ValidatedSingleValueCollectorWithValue< - 'ValidatedBooleanCollector', - boolean -> { - // (undocumented) - output: ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean>['output'] & { - appearance: string; - richContent?: CollectorRichContent; - }; -} - -// @public -export type ValidatedCollectors = - | ValidatedTextCollector - | ValidatedBooleanCollector - | ValidatedPasswordCollector - | ObjectValueCollectors - | MultiValueCollectors - | AutoCollectors; - -// @public (undocumented) -export type ValidatedField = { - type: 'TEXT'; - key: string; - label: string; - required: boolean; - validation: { - regex: string; - errorMessage: string; - }; -}; - -// @public (undocumented) -export interface ValidatedPasswordCollector { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - validation: PasswordPolicy; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - verify: boolean; - }; - // (undocumented) - type: 'ValidatedPasswordCollector'; -} - -// @public (undocumented) -export interface ValidatedSingleValueCollectorWithValue< - T extends SingleValueCollectorTypes, - V = string, -> { - // (undocumented) - category: 'ValidatedSingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - type: string; - validation: (ValidationRequired | ValidationRegex)[]; - value: V; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: V; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ValidatedTextCollector = ValidatedSingleValueCollectorWithValue<'TextCollector'>; - -// @public (undocumented) -export interface ValidationPhoneNumber { - // (undocumented) - message: string; - // (undocumented) - rule: boolean; - // (undocumented) - type: 'validatePhoneNumber'; -} - -// @public (undocumented) -export interface ValidationRegex { - // (undocumented) - message: string; - // (undocumented) - rule: string; - // (undocumented) - type: 'regex'; -} - -// @public (undocumented) -export interface ValidationRequired { - // (undocumented) - message: string; - // (undocumented) - rule: boolean; - // (undocumented) - type: 'required'; -} - -// @public -export type Validator = ( - value: CollectorValueType, -) => - | string[] - | { - error: { - message: string; - type: string; - }; - type: string; - }; - -// (No @packageDocumentation comment for this package) -``` +## API Report File for "@forgerock/davinci-client" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { ActionCreatorWithPayload } from '@reduxjs/toolkit'; +import { ActionTypes } from '@forgerock/sdk-request-middleware'; +import { CustomLogger } from '@forgerock/sdk-logger'; +import type { DaVinciConfig } from '@forgerock/sdk-types'; +import { FetchBaseQueryError } from '@reduxjs/toolkit/query'; +import type { FetchBaseQueryMeta } from '@reduxjs/toolkit/query'; +import { GenericError } from '@forgerock/sdk-types'; +import { LogLevel } from '@forgerock/sdk-logger'; +import type { MutationResultSelectorResult } from '@reduxjs/toolkit/query'; +import { QueryStatus } from '@reduxjs/toolkit/query'; +import { Reducer } from '@reduxjs/toolkit'; +import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; +import type { SdkStore } from '@forgerock/sdk-types'; +import { SerializedError } from '@reduxjs/toolkit'; +import { Unsubscribe } from '@reduxjs/toolkit'; + +// @public (undocumented) +export type ActionCollector = ActionCollectorNoUrl | ActionCollectorWithUrl; + +// @public (undocumented) +export interface ActionCollectorNoUrl { + // (undocumented) + category: 'ActionCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ActionCollectors = ActionCollectorWithUrl<'IdpCollector'> | ActionCollectorNoUrl<'ActionCollector'> | ActionCollectorNoUrl<'FlowCollector'> | ActionCollectorNoUrl<'SubmitCollector'>; + +// @public +export type ActionCollectorTypes = 'FlowCollector' | 'SubmitCollector' | 'IdpCollector' | 'ActionCollector'; + +// @public (undocumented) +export interface ActionCollectorWithUrl { + // (undocumented) + category: 'ActionCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + url?: string | null; + }; + // (undocumented) + type: T; +} + +export { ActionTypes } + +// @public (undocumented) +export type AgreementField = { + type: 'AGREEMENT'; + key: string; + content: string; + titleEnabled: boolean; + title?: string; + agreement: { + id: string; + useDynamicAgreement: boolean; + }; + enabled: boolean; +}; + +// @public (undocumented) +export interface AssertionValue extends Omit { + // (undocumented) + rawId: string; + // (undocumented) + response: { + clientDataJSON: string; + authenticatorData: string; + signature: string; + userHandle: string | null; + }; +} + +// @public (undocumented) +export interface AttestationValue extends Omit { + // (undocumented) + rawId: string; + // (undocumented) + response: { + clientDataJSON: string; + attestationObject: string; + }; +} + +// @public (undocumented) +export interface AutoCollector> { + // (undocumented) + category: C; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: IV; + type: string; + validation?: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + type: string; + config: OV; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type AutoCollectorCategories = 'SingleValueAutoCollector' | 'ObjectValueAutoCollector'; + +// @public (undocumented) +export type AutoCollectors = ProtectCollector | FidoRegistrationCollector | FidoAuthenticationCollector | MetadataCollector | PollingCollector | SingleValueAutoCollector | ObjectValueAutoCollector; + +// @public (undocumented) +export type AutoCollectorTypes = SingleValueAutoCollectorTypes | ObjectValueAutoCollectorTypes; + +// @public (undocumented) +export interface BooleanCollector extends SingleValueCollectorWithValue<'BooleanCollector', boolean> { + // (undocumented) + output: SingleValueCollectorWithValue<'BooleanCollector', boolean>['output'] & { + appearance: string; + richContent?: CollectorRichContent; + }; +} + +// @public (undocumented) +export type CollectorCategory = Collectors['category']; + +// @public (undocumented) +export interface CollectorErrors { + // (undocumented) + code: string; + // (undocumented) + message: string; + // (undocumented) + target: string; +} + +// @public +export interface CollectorRichContent { + // (undocumented) + content: string; + // (undocumented) + replacements: RichContentLink[]; +} + +// @public (undocumented) +export type Collectors = FlowCollector | MetadataCollector | PasswordCollector | ValidatedPasswordCollector | TextCollector | BooleanCollector | ValidatedBooleanCollector | SingleSelectCollector | IdpCollector | SubmitCollector | ActionCollector<'ActionCollector'> | SingleValueCollector<'SingleValueCollector'> | MultiSelectCollector | DeviceAuthenticationCollector | DeviceRegistrationCollector | PhoneNumberCollector | PhoneNumberExtensionCollector | ReadOnlyCollector | RichTextCollector | ValidatedTextCollector | ProtectCollector | PollingCollector | FidoRegistrationCollector | FidoAuthenticationCollector | QrCodeCollector | ImageCollector | UnknownCollector; + +// @public +export type CollectorValueType = T extends { + type: 'PasswordCollector'; +} | { + type: 'ValidatedPasswordCollector'; +} | { + type: 'SingleSelectCollector'; +} | { + type: 'DeviceRegistrationCollector'; +} | { + type: 'DeviceAuthenticationCollector'; +} | { + type: 'ProtectCollector'; +} | { + type: 'PollingCollector'; +} ? string : T extends { + type: 'TextCollector'; + category: 'SingleValueCollector'; +} ? string : T extends { + type: 'TextCollector'; + category: 'ValidatedSingleValueCollector'; +} ? string : T extends { + type: 'BooleanCollector'; +} | { + type: 'ValidatedBooleanCollector'; +} ? boolean : T extends { + type: 'MultiSelectCollector'; +} ? string | string[] : T extends { + type: 'PhoneNumberCollector'; +} ? PhoneNumberInputValue : T extends { + type: 'PhoneNumberExtensionCollector'; +} ? PhoneNumberExtensionInputValue : T extends { + type: 'FidoRegistrationCollector'; +} ? FidoRegistrationInputValue | GenericError : T extends { + type: 'FidoAuthenticationCollector'; +} ? FidoAuthenticationInputValue | GenericError : T extends { + type: 'MetadataCollector'; +} ? Record | MetadataError : T extends { + category: 'SingleValueCollector'; +} ? string : T extends { + category: 'ValidatedSingleValueCollector'; +} ? string : T extends { + category: 'SingleValueAutoCollector'; +} ? string : T extends { + category: 'MultiValueCollector'; +} ? string | string[] : T extends { + category: 'ActionCollector'; +} ? never : T extends { + category: 'NoValueCollector'; +} ? never : CollectorValueTypes; + +// @public +export type CollectorValueTypes = string | string[] | boolean | PhoneNumberInputValue | PhoneNumberExtensionInputValue | FidoRegistrationInputValue | FidoAuthenticationInputValue | MetadataError | GenericError; + +// @public (undocumented) +export type ComplexValueFields = DeviceAuthenticationField | DeviceRegistrationField | PhoneNumberField | PhoneNumberExtensionField | FidoRegistrationField | FidoAuthenticationField | PollingField | MetadataField; + +// @public (undocumented) +export interface ContinueNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'continue'; + }; + // (undocumented) + error: null; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + eventName?: string; + status: 'continue'; + }; + // (undocumented) + status: 'continue'; +} + +export { CustomLogger } + +// @public +export type CustomPollingStatus = string & {}; + +// @public +export function davinci(input: { + config: DaVinciConfig; + requestMiddleware?: RequestMiddleware[]; + logger?: { + level: LogLevel; + custom?: CustomLogger; + }; +}): Promise<{ + store: SdkStore; + subscribe: (listener: () => void) => Unsubscribe; + externalIdp: () => (() => Promise); + flow: (action: DaVinciAction) => InitFlow; + next: (args?: DaVinciRequest) => Promise; + resume: (input: { + continueToken: string; + }) => Promise; + start: (options?: StartOptions | undefined) => Promise; + update: (collector: T) => Updater; + validate: (collector: SingleValueCollectors | ObjectValueCollectors | MultiValueCollectors | AutoCollectors) => Validator; + pollStatus: (collector: PollingCollector) => Poller; + getClient: () => { + status: "start"; + } | { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: "error"; + } | { + status: "failure"; + } | { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: "continue"; + } | { + authorization?: { + code?: string; + state?: string; + }; + status: "success"; + } | null; + getCollectors: () => Collectors[]; + getError: () => DaVinciError | null; + getErrorCollectors: () => CollectorErrors[]; + getNode: () => StartNode | ErrorNode | FailureNode | ContinueNode | SuccessNode; + getServer: () => { + status: "start"; + } | { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: "error"; + } | { + _links?: Links; + eventName?: string; + href?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: "failure"; + } | { + _links?: Links; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + eventName?: string; + status: "continue"; + } | { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + session?: string; + status: "success"; + } | null; + cache: { + getLatestResponse: () => ({ + status: QueryStatus.fulfilled; + } & Omit<{ + requestId: string; + data?: unknown; + error?: SerializedError | FetchBaseQueryError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, "data" | "fulfilledTimeStamp"> & Required> & { + error: undefined; + } & { + status: QueryStatus.fulfilled; + isUninitialized: false; + isLoading: false; + isSuccess: true; + isError: false; + }) | ({ + status: QueryStatus.rejected; + } & Omit<{ + requestId: string; + data?: unknown; + error?: SerializedError | FetchBaseQueryError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, "error"> & Required> & { + status: QueryStatus.rejected; + isUninitialized: false; + isLoading: false; + isSuccess: false; + isError: true; + }) | { + error: { + message: string; + type: string; + }; + }; + getResponseWithId: (requestId: string) => ({ + status: QueryStatus.fulfilled; + } & Omit<{ + requestId: string; + data?: unknown; + error?: SerializedError | FetchBaseQueryError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, "data" | "fulfilledTimeStamp"> & Required> & { + error: undefined; + } & { + status: QueryStatus.fulfilled; + isUninitialized: false; + isLoading: false; + isSuccess: true; + isError: false; + }) | ({ + status: QueryStatus.rejected; + } & Omit<{ + requestId: string; + data?: unknown; + error?: SerializedError | FetchBaseQueryError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, "error"> & Required> & { + status: QueryStatus.rejected; + isUninitialized: false; + isLoading: false; + isSuccess: false; + isError: true; + }) | { + error: { + message: string; + type: string; + }; + }; + }; +}>; + +// @public +export interface DaVinciAction { + // (undocumented) + action: string; +} + +// @public +export interface DaVinciBaseResponse { + // (undocumented) + capabilityName?: string; + // (undocumented) + companyId?: string; + // (undocumented) + connectionId?: string; + // (undocumented) + connectorId?: string; + // (undocumented) + id?: string; + // (undocumented) + interactionId?: string; + // (undocumented) + interactionToken?: string; + // (undocumented) + isResponseCompatibleWithMobileAndWebSdks?: boolean; + // (undocumented) + status?: string; +} + +// @public +export type DaVinciCacheEntry = { + data?: DaVinciBaseResponse; + error?: { + data: DaVinciBaseResponse; + status: number; + }; +} & { + data?: any; + error?: any; +} & MutationResultSelectorResult; + +// @public (undocumented) +export type DavinciClient = Awaited>; + +export { DaVinciConfig } + +// @public (undocumented) +export interface DaVinciError extends Omit { + // (undocumented) + collectors?: CollectorErrors[]; + // (undocumented) + internalHttpStatus?: number; + // (undocumented) + message: string; + // (undocumented) + status: 'error' | 'failure' | 'unknown'; +} + +// @public (undocumented) +export interface DaVinciErrorCacheEntry { + // (undocumented) + endpointName: 'next' | 'flow' | 'start'; + // (undocumented) + error: { + data: T; + }; + // (undocumented) + fulfilledTimeStamp: number; + // (undocumented) + isError: boolean; + // (undocumented) + isLoading: boolean; + // (undocumented) + isSuccess: boolean; + // (undocumented) + isUninitialized: boolean; + // (undocumented) + requestId: string; + // (undocumented) + startedTimeStamp: number; + // (undocumented) + status: 'fulfilled' | 'pending' | 'rejected'; +} + +// @public (undocumented) +export interface DavinciErrorResponse extends DaVinciBaseResponse { + // (undocumented) + cause?: string | null; + // (undocumented) + code: string | number; + // (undocumented) + details?: ErrorDetail[]; + // (undocumented) + doNotSendToOE?: boolean; + // (undocumented) + error?: { + code?: string; + message?: string; + }; + // (undocumented) + errorCategory?: string; + // (undocumented) + errorMessage?: string; + // (undocumented) + expected?: boolean; + // (undocumented) + httpResponseCode: number; + // (undocumented) + isErrorCustomized?: boolean; + // (undocumented) + message: string; + // (undocumented) + metricAttributes?: { + [key: string]: unknown; + }; +} + +// @public (undocumented) +export interface DaVinciFailureResponse extends DaVinciBaseResponse { + // (undocumented) + error?: { + code?: string; + message?: string; + [key: string]: unknown; + }; +} + +// @public (undocumented) +export type DaVinciField = ComplexValueFields | MultiValueFields | ReadOnlyFields | RedirectFields | SingleValueFields; + +// @public +export interface DaVinciNextResponse extends DaVinciBaseResponse { + // (undocumented) + eventName?: string; + // (undocumented) + form?: { + name?: string; + description?: string; + components?: { + fields?: DaVinciField[]; + }; + }; + // (undocumented) + formData?: { + value?: { + [key: string]: string; + }; + }; + // (undocumented) + _links?: Links; +} + +// @public +export interface DaVinciPollResponse extends DaVinciBaseResponse { + // (undocumented) + eventName?: string; + // (undocumented) + _links?: Links; + // (undocumented) + success?: boolean; +} + +// @public (undocumented) +export interface DaVinciRequest { + // (undocumented) + eventName: string; + // (undocumented) + id: string; + // (undocumented) + interactionId: string; + // (undocumented) + parameters: { + eventType: 'submit' | 'action' | 'polling'; + data: { + actionKey: string; + formData?: Record; + }; + }; +} + +// @public +export type DaVinciRequestValueTypes = string | number | boolean | (string | number | boolean)[] | DeviceValue | PhoneNumberInputValue | FidoRegistrationInputValue | FidoAuthenticationInputValue | MetadataError | GenericError; + +// @public (undocumented) +export interface DaVinciSuccessResponse extends DaVinciBaseResponse { + // (undocumented) + authorizeResponse?: OAuthDetails; + // (undocumented) + environment: { + id: string; + [key: string]: unknown; + }; + // (undocumented) + _links?: Links; + // (undocumented) + resetCookie?: boolean; + // (undocumented) + session?: { + id?: string; + [key: string]: unknown; + }; + // (undocumented) + sessionToken?: string; + // (undocumented) + sessionTokenMaxAge?: number; + // (undocumented) + status: string; + // (undocumented) + subFlowSettings?: { + cssLinks?: unknown[]; + cssUrl?: unknown; + jsLinks?: unknown[]; + loadingScreenSettings?: unknown; + reactSkUrl?: unknown; + }; + // (undocumented) + success: true; +} + +// @public (undocumented) +export type DeviceAuthenticationCollector = ObjectOptionsCollectorWithObjectValue<'DeviceAuthenticationCollector', DeviceValue>; + +// @public (undocumented) +export type DeviceAuthenticationField = { + type: 'DEVICE_AUTHENTICATION'; + key: string; + label: string; + options: { + type: string; + iconSrc: string; + title: string; + id: string; + default: boolean; + description: string; + }[]; + required: boolean; +}; + +// @public (undocumented) +export interface DeviceOptionNoDefault { + // (undocumented) + content: string; + // (undocumented) + key: string; + // (undocumented) + label: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export interface DeviceOptionWithDefault { + // (undocumented) + content: string; + // (undocumented) + default: boolean; + // (undocumented) + key: string; + // (undocumented) + label: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export type DeviceRegistrationCollector = ObjectOptionsCollectorWithStringValue<'DeviceRegistrationCollector', string>; + +// @public (undocumented) +export type DeviceRegistrationField = { + type: 'DEVICE_REGISTRATION'; + key: string; + label: string; + options: { + type: string; + iconSrc: string; + title: string; + description: string; + }[]; + required: boolean; +}; + +// @public (undocumented) +export interface DeviceValue { + // (undocumented) + id: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export interface ErrorDetail { + // (undocumented) + message?: string; + // (undocumented) + rawResponse?: { + _embedded?: { + users?: Array; + }; + code?: string; + count?: number; + details?: NestedErrorDetails[]; + id?: string; + message?: string; + size?: number; + userFilter?: string; + [key: string]: unknown; + }; + // (undocumented) + statusCode?: number; +} + +// @public (undocumented) +export interface ErrorNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'error'; + }; + // (undocumented) + error: DaVinciError; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'error'; + } | null; + // (undocumented) + status: 'error'; +} + +// @public (undocumented) +export interface FailureNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + status: 'failure'; + }; + // (undocumented) + error: DaVinciError; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + href?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'failure'; + } | null; + // (undocumented) + status: 'failure'; +} + +// @public +export function fido(): FidoClient; + +// @public (undocumented) +export type FidoAuthenticationCollector = AutoCollector<'ObjectValueAutoCollector', 'FidoAuthenticationCollector', FidoAuthenticationInputValue | GenericError, FidoAuthenticationOutputValue>; + +// @public (undocumented) +export type FidoAuthenticationField = { + type: 'FIDO2'; + key: string; + label: string; + publicKeyCredentialRequestOptions: FidoAuthenticationOptions; + action: 'AUTHENTICATE'; + trigger: string; + required: boolean; +}; + +// @public (undocumented) +export interface FidoAuthenticationInputValue { + // (undocumented) + assertionValue?: AssertionValue; +} + +// @public (undocumented) +export interface FidoAuthenticationOptions extends Omit { + // (undocumented) + allowCredentials?: { + id: number[]; + transports?: AuthenticatorTransport[]; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + challenge: number[]; +} + +// @public (undocumented) +export interface FidoAuthenticationOutputValue { + // (undocumented) + action: 'AUTHENTICATE'; + // (undocumented) + publicKeyCredentialRequestOptions: FidoAuthenticationOptions; + // (undocumented) + trigger: string; +} + +// @public (undocumented) +export interface FidoClient { + authenticate: (options: FidoAuthenticationOptions) => Promise; + register: (options: FidoRegistrationOptions) => Promise; +} + +// @public +export type FidoErrorCode = 'NotAllowedError' | 'AbortError' | 'InvalidStateError' | 'NotSupportedError' | 'SecurityError' | 'TimeoutError' | 'UnknownError'; + +// @public (undocumented) +export type FidoRegistrationCollector = AutoCollector<'ObjectValueAutoCollector', 'FidoRegistrationCollector', FidoRegistrationInputValue | GenericError, FidoRegistrationOutputValue>; + +// @public (undocumented) +export type FidoRegistrationField = { + type: 'FIDO2'; + key: string; + label: string; + publicKeyCredentialCreationOptions: FidoRegistrationOptions; + action: 'REGISTER'; + trigger: string; + required: boolean; +}; + +// @public (undocumented) +export interface FidoRegistrationInputValue { + // (undocumented) + attestationValue?: AttestationValue; +} + +// @public (undocumented) +export interface FidoRegistrationOptions extends Omit { + // (undocumented) + challenge: number[]; + // (undocumented) + excludeCredentials?: { + id: number[]; + transports?: AuthenticatorTransport[]; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + pubKeyCredParams: { + alg: string | number; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + user: { + id: number[]; + name: string; + displayName: string; + }; +} + +// @public (undocumented) +export interface FidoRegistrationOutputValue { + // (undocumented) + action: 'REGISTER'; + // (undocumented) + publicKeyCredentialCreationOptions: FidoRegistrationOptions; + // (undocumented) + trigger: string; +} + +// @public (undocumented) +export type FlowCollector = ActionCollectorNoUrl<'FlowCollector'>; + +// @public (undocumented) +export type FlowNode = ContinueNode | ErrorNode | StartNode | SuccessNode | FailureNode; + +// @public +export type GetClient = StartNode['client'] | ContinueNode['client'] | ErrorNode['client'] | SuccessNode['client'] | FailureNode['client']; + +// @public (undocumented) +export type IdpCollector = ActionCollectorWithUrl<'IdpCollector'>; + +// @public +export interface ImageCollector extends NoValueCollectorBase<'ImageCollector'> { + // (undocumented) + output: NoValueCollectorBase<'ImageCollector'>['output'] & { + src: string; + alt: string; + href?: string; + }; +} + +// @public (undocumented) +export type ImageField = { + type: 'IMAGE'; + key: string; + description: string; + imageUrl: string; + hyperlinkUrl?: string; +}; + +// @public (undocumented) +export type InferActionCollectorType = T extends 'IdpCollector' ? IdpCollector : T extends 'SubmitCollector' ? SubmitCollector : T extends 'FlowCollector' ? FlowCollector : ActionCollectorWithUrl<'ActionCollector'> | ActionCollectorNoUrl<'ActionCollector'>; + +// @public +export type InferAutoCollectorType = T extends 'ProtectCollector' ? ProtectCollector : T extends 'PollingCollector' ? PollingCollector : T extends 'FidoRegistrationCollector' ? FidoRegistrationCollector : T extends 'FidoAuthenticationCollector' ? FidoAuthenticationCollector : T extends 'MetadataCollector' ? MetadataCollector : T extends 'ObjectValueAutoCollector' ? ObjectValueAutoCollector : SingleValueAutoCollector; + +// @public +export type InferMultiValueCollectorType = T extends 'MultiSelectCollector' ? MultiValueCollectorWithValue<'MultiSelectCollector'> : MultiValueCollectorWithValue<'MultiValueCollector'> | MultiValueCollectorNoValue<'MultiValueCollector'>; + +// @public +export type InferNoValueCollectorType = T extends 'ReadOnlyCollector' ? ReadOnlyCollector : T extends 'RichTextCollector' ? RichTextCollector : T extends 'QrCodeCollector' ? QrCodeCollector : T extends 'ImageCollector' ? ImageCollector : NoValueCollectorBase<'NoValueCollector'>; + +// @public +export type InferSingleValueCollectorType = T extends 'TextCollector' ? TextCollector : T extends 'SingleSelectCollector' ? SingleSelectCollector : T extends 'ValidatedTextCollector' ? ValidatedTextCollector : T extends 'PasswordCollector' ? PasswordCollector : T extends 'ValidatedPasswordCollector' ? ValidatedPasswordCollector : T extends 'BooleanCollector' ? BooleanCollector : T extends 'ValidatedBooleanCollector' ? ValidatedBooleanCollector : SingleValueCollectorWithValue<'SingleValueCollector'> | SingleValueCollectorNoValue<'SingleValueCollector'>; + +// @public (undocumented) +export type InferValueObjectCollectorType = T extends 'DeviceAuthenticationCollector' ? DeviceAuthenticationCollector : T extends 'DeviceRegistrationCollector' ? DeviceRegistrationCollector : T extends 'PhoneNumberCollector' ? PhoneNumberCollector : T extends 'PhoneNumberExtensionCollector' ? PhoneNumberExtensionCollector : ObjectOptionsCollectorWithObjectValue<'ObjectValueCollector'> | ObjectOptionsCollectorWithStringValue<'ObjectValueCollector'>; + +// @public (undocumented) +export type InitFlow = () => Promise; + +// @public (undocumented) +export interface InternalErrorResponse { + // (undocumented) + error: Omit & { + message: string; + }; + // (undocumented) + type: 'internal_error'; +} + +// @public (undocumented) +export interface Links { + // (undocumented) + [key: string]: { + href?: string; + }; +} + +export { LogLevel } + +// @public (undocumented) +export type MetadataCollector = AutoCollector<'ObjectValueAutoCollector', 'MetadataCollector', MetadataCollectorInputValue, Record>; + +// @public (undocumented) +export type MetadataCollectorInputValue = Record | MetadataError; + +// @public +export interface MetadataError { + // (undocumented) + code: string; + // (undocumented) + message: string; +} + +// @public (undocumented) +export type MetadataField = { + type: 'METADATA'; + key: string; + payload: Record; +}; + +// @public (undocumented) +export type MultiSelectCollector = MultiValueCollectorWithValue<'MultiSelectCollector'>; + +// @public (undocumented) +export type MultiSelectField = { + inputType: 'MULTI_SELECT'; + key: string; + label: string; + options: { + label: string; + value: string; + }[]; + required?: boolean; + type: 'CHECKBOX' | 'COMBOBOX'; +}; + +// @public (undocumented) +export type MultiValueCollector = MultiValueCollectorWithValue | MultiValueCollectorNoValue; + +// @public (undocumented) +export interface MultiValueCollectorNoValue { + // (undocumented) + category: 'MultiValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string[]; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type MultiValueCollectors = MultiValueCollectorWithValue<'MultiValueCollector'> | MultiValueCollectorWithValue<'MultiSelectCollector'>; + +// @public +export type MultiValueCollectorTypes = 'MultiSelectCollector' | 'MultiValueCollector'; + +// @public (undocumented) +export interface MultiValueCollectorWithValue { + // (undocumented) + category: 'MultiValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string[]; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: string[]; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type MultiValueFields = MultiSelectField; + +// @public +export interface NestedErrorDetails { + // (undocumented) + code?: string; + // (undocumented) + innerError?: { + history?: string; + unsatisfiedRequirements?: string[]; + failuresRemaining?: number; + }; + // (undocumented) + message?: string; + // (undocumented) + target?: string; +} + +// @public +export const nextCollectorValues: ActionCreatorWithPayload< { +fields: DaVinciField[]; +formData: { +value: Record; +}; +}, string>; + +// @public +export const nodeCollectorReducer: Reducer & { + getInitialState: () => Collectors[]; +}; + +// @public (undocumented) +export type NodeStates = StartNode | ContinueNode | ErrorNode | SuccessNode | FailureNode; + +// @public (undocumented) +export type NoValueCollector = InferNoValueCollectorType; + +// @public (undocumented) +export interface NoValueCollectorBase { + // (undocumented) + category: 'NoValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type NoValueCollectors = NoValueCollectorBase<'NoValueCollector'> | ReadOnlyCollector | RichTextCollector | QrCodeCollector | ImageCollector; + +// @public +export type NoValueCollectorTypes = 'ReadOnlyCollector' | 'RichTextCollector' | 'NoValueCollector' | 'QrCodeCollector' | 'ImageCollector'; + +// @public +export interface OAuthDetails { + // (undocumented) + [key: string]: unknown; + // (undocumented) + code?: string; + // (undocumented) + state?: string; +} + +// @public (undocumented) +export interface ObjectOptionsCollectorWithObjectValue, D = Record> { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: DeviceOptionWithDefault[]; + value?: D | null; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface ObjectOptionsCollectorWithStringValue { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: DeviceOptionNoDefault[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ObjectValueAutoCollector = AutoCollector<'ObjectValueAutoCollector', 'ObjectValueAutoCollector', Record>; + +// @public (undocumented) +export type ObjectValueAutoCollectorTypes = 'ObjectValueAutoCollector' | 'FidoRegistrationCollector' | 'FidoAuthenticationCollector' | 'MetadataCollector'; + +// @public (undocumented) +export type ObjectValueCollector = ObjectOptionsCollectorWithObjectValue | ObjectOptionsCollectorWithStringValue | ObjectValueCollectorWithObjectValue; + +// @public (undocumented) +export type ObjectValueCollectors = DeviceAuthenticationCollector | DeviceRegistrationCollector | PhoneNumberCollector | PhoneNumberExtensionCollector | ObjectOptionsCollectorWithObjectValue<'ObjectSelectCollector'> | ObjectOptionsCollectorWithStringValue<'ObjectSelectCollector'>; + +// @public +export type ObjectValueCollectorTypes = 'DeviceAuthenticationCollector' | 'DeviceRegistrationCollector' | 'PhoneNumberCollector' | 'PhoneNumberExtensionCollector' | 'ObjectOptionsCollector' | 'ObjectValueCollector' | 'ObjectSelectCollector'; + +// @public (undocumented) +export interface ObjectValueCollectorWithObjectValue, OV = Record> { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: IV; + type: string; + validation: (ValidationRequired | ValidationPhoneNumber)[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value?: OV | null; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface OutgoingQueryParams { + // (undocumented) + [key: string]: string | string[]; +} + +// @public (undocumented) +export interface PasswordCollector { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + verify: boolean; + }; + // (undocumented) + type: 'PasswordCollector'; +} + +// @public +export type PasswordField = { + type: 'PASSWORD' | 'PASSWORD_VERIFY'; + key: string; + label: string; + required?: boolean; + verify?: boolean; + passwordPolicy?: PasswordPolicy; +}; + +// @public +export interface PasswordPolicy { + // (undocumented) + createdAt?: string; + // (undocumented) + default?: boolean; + // (undocumented) + description?: string; + // (undocumented) + excludesCommonlyUsed?: boolean; + // (undocumented) + excludesProfileData?: boolean; + // (undocumented) + history?: { + count?: number; + retentionDays?: number; + }; + // (undocumented) + id?: string; + // (undocumented) + length?: { + min?: number; + max?: number; + }; + // (undocumented) + lockout?: { + failureCount?: number; + durationSeconds?: number; + }; + // (undocumented) + maxAgeDays?: number; + // (undocumented) + maxRepeatedCharacters?: number; + // (undocumented) + minAgeDays?: number; + // (undocumented) + minCharacters?: Record; + // (undocumented) + minUniqueCharacters?: number; + // (undocumented) + name?: string; + // (undocumented) + notSimilarToCurrent?: boolean; + // (undocumented) + populationCount?: number; + // (undocumented) + updatedAt?: string; +} + +// @public (undocumented) +export type PhoneNumberCollector = ObjectValueCollectorWithObjectValue<'PhoneNumberCollector', PhoneNumberInputValue, PhoneNumberOutputValue>; + +// @public (undocumented) +export interface PhoneNumberExtensionCollector { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: PhoneNumberExtensionInputValue; + type: string; + validation: (ValidationRequired | ValidationPhoneNumber)[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + extensionLabel: string; + value: PhoneNumberExtensionOutputValue; + }; + // (undocumented) + type: 'PhoneNumberExtensionCollector'; +} + +// @public (undocumented) +export type PhoneNumberExtensionField = PhoneNumberField & { + showExtension: boolean; + extensionLabel: string; +}; + +// @public (undocumented) +export interface PhoneNumberExtensionInputValue { + // (undocumented) + countryCode: string; + // (undocumented) + extension: string; + // (undocumented) + phoneNumber: string; +} + +// @public (undocumented) +export interface PhoneNumberExtensionOutputValue { + // (undocumented) + countryCode?: string; + // (undocumented) + extension?: string; + // (undocumented) + phoneNumber?: string; +} + +// @public (undocumented) +export type PhoneNumberField = { + type: 'PHONE_NUMBER'; + key: string; + label: string; + required: boolean; + defaultCountryCode: string | null; + validatePhoneNumber: boolean; +}; + +// @public (undocumented) +export interface PhoneNumberInputValue { + // (undocumented) + countryCode: string; + // (undocumented) + phoneNumber: string; +} + +// @public (undocumented) +export interface PhoneNumberOutputValue { + // (undocumented) + countryCode?: string; + // (undocumented) + phoneNumber?: string; +} + +// @public +export type Poller = () => Promise; + +// @public (undocumented) +export type PollingCollector = AutoCollector<'SingleValueAutoCollector', 'PollingCollector', string, PollingOutputValue>; + +// @public (undocumented) +export type PollingField = { + type: 'POLLING'; + key: string; + pollInterval: number; + pollRetries: number; + pollChallengeStatus?: boolean; + challenge?: string; +}; + +// @public (undocumented) +export interface PollingOutputValue { + // (undocumented) + challenge?: string; + // (undocumented) + pollChallengeStatus?: boolean; + // (undocumented) + pollInterval: number; + // (undocumented) + pollRetries: number; + // (undocumented) + retriesRemaining?: number; +} + +// @public (undocumented) +export type PollingStatus = PollingStatusContinue | PollingStatusChallenge; + +// @public (undocumented) +export type PollingStatusChallenge = PollingStatusChallengeComplete | 'expired' | 'timedOut' | 'error'; + +// @public (undocumented) +export type PollingStatusChallengeComplete = 'approved' | 'denied' | 'continue' | CustomPollingStatus; + +// @public (undocumented) +export type PollingStatusContinue = 'continue' | 'timedOut'; + +// @public (undocumented) +export type ProtectCollector = AutoCollector<'SingleValueAutoCollector', 'ProtectCollector', string, ProtectOutputValue>; + +// @public (undocumented) +export type ProtectField = { + type: 'PROTECT'; + key: string; + behavioralDataCollection: boolean; + universalDeviceIdentification: boolean; +}; + +// @public +export interface ProtectOutputValue { + // (undocumented) + behavioralDataCollection: boolean; + // (undocumented) + universalDeviceIdentification: boolean; +} + +// @public +export interface QrCodeCollector extends NoValueCollectorBase<'QrCodeCollector'> { + // (undocumented) + output: NoValueCollectorBase<'QrCodeCollector'>['output'] & { + src: string; + }; +} + +// @public (undocumented) +export type QrCodeField = { + type: 'QR_CODE'; + key: string; + content: string; + fallbackText?: string; +}; + +// @public +export interface ReadOnlyCollector extends NoValueCollectorBase<'ReadOnlyCollector'> { + // (undocumented) + output: NoValueCollectorBase<'ReadOnlyCollector'>['output'] & { + content: string; + title?: string; + }; +} + +// @public (undocumented) +export type ReadOnlyField = { + type: 'LABEL'; + content: string; + richContent?: RichContent; + key?: string; +}; + +// @public (undocumented) +export type ReadOnlyFields = ReadOnlyField | QrCodeField | AgreementField | ImageField; + +// @public (undocumented) +export type RedirectField = { + type: 'SOCIAL_LOGIN_BUTTON'; + key: string; + label: string; + links: Links; +}; + +// @public (undocumented) +export type RedirectFields = RedirectField; + +export { RequestMiddleware } + +// @public +export type RichContent = { + content: string; + replacements?: Record; +}; + +// @public +export interface RichContentLink { + // (undocumented) + href: string; + // (undocumented) + key: string; + // (undocumented) + target?: '_self' | '_blank'; + // (undocumented) + type: 'link'; + // (undocumented) + value: string; +} + +// @public +export type RichContentReplacement = { + type: 'link'; + value: string; + href: string; + target?: '_self' | '_blank'; +}; + +// @public +export interface RichTextCollector extends NoValueCollectorBase<'RichTextCollector'> { + // (undocumented) + output: NoValueCollectorBase<'RichTextCollector'>['output'] & { + content: string; + richContent: CollectorRichContent; + }; +} + +// @public (undocumented) +export interface SelectorOption { + // (undocumented) + label: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export type SingleCheckboxField = { + type: 'SINGLE_CHECKBOX'; + inputType: 'BOOLEAN'; + key: string; + label: string; + required?: boolean; + errorMessage?: string; + appearance: string; + richContent?: RichContent; +}; + +// @public (undocumented) +export type SingleSelectCollector = SingleSelectCollectorWithValue<'SingleSelectCollector'>; + +// @public (undocumented) +export interface SingleSelectCollectorNoValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface SingleSelectCollectorWithValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: string | number | boolean; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleSelectField = { + inputType: 'SINGLE_SELECT'; + key: string; + label: string; + options: { + label: string; + value: string; + }[]; + required?: boolean; + type: 'RADIO' | 'DROPDOWN'; +}; + +// @public (undocumented) +export type SingleValueAutoCollector = AutoCollector<'SingleValueAutoCollector', 'SingleValueAutoCollector', string>; + +// @public (undocumented) +export type SingleValueAutoCollectorTypes = 'SingleValueAutoCollector' | 'ProtectCollector' | 'PollingCollector'; + +// @public +export type SingleValueCollector = SingleValueCollectorWithValue | SingleValueCollectorNoValue; + +// @public (undocumented) +export interface SingleValueCollectorNoValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleValueCollectors = PasswordCollector | ValidatedPasswordCollector | SingleSelectCollector | TextCollector | ValidatedTextCollector | BooleanCollector | ValidatedBooleanCollector | SingleValueCollectorWithValue<'SingleValueCollector'>; + +// @public +export type SingleValueCollectorTypes = 'PasswordCollector' | 'ValidatedPasswordCollector' | 'BooleanCollector' | 'ValidatedBooleanCollector' | 'SingleValueCollector' | 'SingleSelectCollector' | 'SingleSelectObjectCollector' | 'TextCollector' | 'ValidatedTextCollector'; + +// @public (undocumented) +export interface SingleValueCollectorWithValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: V; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleValueFields = StandardField | PasswordField | ValidatedField | SingleCheckboxField | SingleSelectField | ProtectField; + +// @public (undocumented) +export type StandardField = { + type: 'TEXT' | 'SUBMIT_BUTTON' | 'FLOW_BUTTON' | 'FLOW_LINK' | 'BUTTON'; + key: string; + label: string; + required?: boolean; +}; + +// @public (undocumented) +export interface StartNode { + // (undocumented) + cache: null; + // (undocumented) + client: { + status: 'start'; + }; + // (undocumented) + error: DaVinciError | null; + // (undocumented) + server: { + status: 'start'; + }; + // (undocumented) + status: 'start'; +} + +// @public (undocumented) +export interface StartOptions { + // (undocumented) + query: Query; +} + +// @public (undocumented) +export type SubmitCollector = ActionCollectorNoUrl<'SubmitCollector'>; + +// @public (undocumented) +export interface SuccessNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + authorization?: { + code?: string; + state?: string; + }; + status: 'success'; + } | null; + // (undocumented) + error: null; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + session?: string; + status: 'success'; + }; + // (undocumented) + status: 'success'; +} + +// @public (undocumented) +export type TextCollector = SingleValueCollectorWithValue<'TextCollector'>; + +// @public (undocumented) +export interface ThrownQueryError { + // (undocumented) + error: FetchBaseQueryError; + // (undocumented) + isHandledError: boolean; + // (undocumented) + meta: FetchBaseQueryMeta; +} + +// @public +export type UnknownCollector = { + category: 'UnknownCollector'; + error: string | null; + type: 'UnknownCollector'; + id: string; + name: string; + output: { + key: string; + label: string; + type: string; + }; +}; + +// @public (undocumented) +export type UnknownField = Record; + +// @public +export type UpdatableCollectors = SingleValueCollectors | MultiSelectCollector | ObjectValueCollectors | AutoCollectors; + +// @public (undocumented) +export const updateCollectorValues: ActionCreatorWithPayload< { +id: string; +value: CollectorValueTypes; +index?: number; +}, string>; + +// @public +export type Updater = (value: CollectorValueType, index?: number) => InternalErrorResponse | null; + +// @public (undocumented) +export interface ValidatedBooleanCollector extends ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean> { + // (undocumented) + output: ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean>['output'] & { + appearance: string; + richContent?: CollectorRichContent; + }; +} + +// @public +export type ValidatedCollectors = ValidatedTextCollector | ValidatedBooleanCollector | ValidatedPasswordCollector | ObjectValueCollectors | MultiValueCollectors | AutoCollectors; + +// @public (undocumented) +export type ValidatedField = { + type: 'TEXT'; + key: string; + label: string; + required: boolean; + validation: { + regex: string; + errorMessage: string; + }; +}; + +// @public (undocumented) +export interface ValidatedPasswordCollector { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + validation: PasswordPolicy; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + verify: boolean; + }; + // (undocumented) + type: 'ValidatedPasswordCollector'; +} + +// @public (undocumented) +export interface ValidatedSingleValueCollectorWithValue { + // (undocumented) + category: 'ValidatedSingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + type: string; + validation: (ValidationRequired | ValidationRegex)[]; + value: V; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: V; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ValidatedTextCollector = ValidatedSingleValueCollectorWithValue<'TextCollector'>; + +// @public (undocumented) +export interface ValidationPhoneNumber { + // (undocumented) + message: string; + // (undocumented) + rule: boolean; + // (undocumented) + type: 'validatePhoneNumber'; +} + +// @public (undocumented) +export interface ValidationRegex { + // (undocumented) + message: string; + // (undocumented) + rule: string; + // (undocumented) + type: 'regex'; +} + +// @public (undocumented) +export interface ValidationRequired { + // (undocumented) + message: string; + // (undocumented) + rule: boolean; + // (undocumented) + type: 'required'; +} + +// @public +export type Validator = (value: CollectorValueType) => string[] | { + error: { + message: string; + type: string; + }; + type: string; +}; + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/davinci-client/api-report/davinci-client.types.api.md b/packages/davinci-client/api-report/davinci-client.types.api.md index b509b4aa3d..538e1c101c 100644 --- a/packages/davinci-client/api-report/davinci-client.types.api.md +++ b/packages/davinci-client/api-report/davinci-client.types.api.md @@ -1,2446 +1,2015 @@ -## API Report File for "@forgerock/davinci-client" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { ActionCreatorWithPayload } from '@reduxjs/toolkit'; -import { ActionTypes } from '@forgerock/sdk-request-middleware'; -import { CustomLogger } from '@forgerock/sdk-logger'; -import type { DaVinciConfig } from '@forgerock/sdk-types'; -import { FetchBaseQueryError } from '@reduxjs/toolkit/query'; -import type { FetchBaseQueryMeta } from '@reduxjs/toolkit/query'; -import { GenericError } from '@forgerock/sdk-types'; -import { LogLevel } from '@forgerock/sdk-logger'; -import type { MutationResultSelectorResult } from '@reduxjs/toolkit/query'; -import { QueryStatus } from '@reduxjs/toolkit/query'; -import { Reducer } from '@reduxjs/toolkit'; -import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; -import type { SdkStore } from '@forgerock/sdk-types'; -import { SerializedError } from '@reduxjs/toolkit'; -import { Unsubscribe } from '@reduxjs/toolkit'; - -// @public (undocumented) -export type ActionCollector = - | ActionCollectorNoUrl - | ActionCollectorWithUrl; - -// @public (undocumented) -export interface ActionCollectorNoUrl { - // (undocumented) - category: 'ActionCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ActionCollectors = - | ActionCollectorWithUrl<'IdpCollector'> - | ActionCollectorNoUrl<'ActionCollector'> - | ActionCollectorNoUrl<'FlowCollector'> - | ActionCollectorNoUrl<'SubmitCollector'>; - -// @public -export type ActionCollectorTypes = - | 'FlowCollector' - | 'SubmitCollector' - | 'IdpCollector' - | 'ActionCollector'; - -// @public (undocumented) -export interface ActionCollectorWithUrl { - // (undocumented) - category: 'ActionCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - url?: string | null; - }; - // (undocumented) - type: T; -} - -export { ActionTypes }; - -// @public (undocumented) -export type AgreementField = { - type: 'AGREEMENT'; - key: string; - content: string; - titleEnabled: boolean; - title?: string; - agreement: { - id: string; - useDynamicAgreement: boolean; - }; - enabled: boolean; -}; - -// @public (undocumented) -export interface AssertionValue extends Omit< - PublicKeyCredential, - 'rawId' | 'response' | 'getClientExtensionResults' | 'toJSON' -> { - // (undocumented) - rawId: string; - // (undocumented) - response: { - clientDataJSON: string; - authenticatorData: string; - signature: string; - userHandle: string | null; - }; -} - -// @public (undocumented) -export interface AttestationValue extends Omit< - PublicKeyCredential, - 'rawId' | 'response' | 'getClientExtensionResults' | 'toJSON' -> { - // (undocumented) - rawId: string; - // (undocumented) - response: { - clientDataJSON: string; - attestationObject: string; - }; -} - -// @public (undocumented) -export interface AutoCollector< - C extends AutoCollectorCategories, - T extends AutoCollectorTypes, - IV = string, - OV = Record, -> { - // (undocumented) - category: C; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: IV; - type: string; - validation?: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - type: string; - config: OV; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type AutoCollectorCategories = 'SingleValueAutoCollector' | 'ObjectValueAutoCollector'; - -// @public (undocumented) -export type AutoCollectors = - | ProtectCollector - | FidoRegistrationCollector - | FidoAuthenticationCollector - | MetadataCollector - | PollingCollector - | SingleValueAutoCollector - | ObjectValueAutoCollector; - -// @public (undocumented) -export type AutoCollectorTypes = SingleValueAutoCollectorTypes | ObjectValueAutoCollectorTypes; - -// @public (undocumented) -export interface BooleanCollector extends SingleValueCollectorWithValue< - 'BooleanCollector', - boolean -> { - // (undocumented) - output: SingleValueCollectorWithValue<'BooleanCollector', boolean>['output'] & { - appearance: string; - richContent?: CollectorRichContent; - }; -} - -// @public (undocumented) -export type CollectorCategory = Collectors['category']; - -// @public (undocumented) -export interface CollectorErrors { - // (undocumented) - code: string; - // (undocumented) - message: string; - // (undocumented) - target: string; -} - -// @public -export interface CollectorRichContent { - // (undocumented) - content: string; - // (undocumented) - replacements: RichContentLink[]; -} - -// @public (undocumented) -export type Collectors = - | FlowCollector - | MetadataCollector - | PasswordCollector - | ValidatedPasswordCollector - | TextCollector - | BooleanCollector - | ValidatedBooleanCollector - | SingleSelectCollector - | IdpCollector - | SubmitCollector - | ActionCollector<'ActionCollector'> - | SingleValueCollector<'SingleValueCollector'> - | MultiSelectCollector - | DeviceAuthenticationCollector - | DeviceRegistrationCollector - | PhoneNumberCollector - | PhoneNumberExtensionCollector - | ReadOnlyCollector - | RichTextCollector - | ValidatedTextCollector - | ProtectCollector - | PollingCollector - | FidoRegistrationCollector - | FidoAuthenticationCollector - | QrCodeCollector - | ImageCollector - | UnknownCollector; - -// @public -export type CollectorValueType = T extends - | { - type: 'PasswordCollector'; - } - | { - type: 'ValidatedPasswordCollector'; - } - | { - type: 'SingleSelectCollector'; - } - | { - type: 'DeviceRegistrationCollector'; - } - | { - type: 'DeviceAuthenticationCollector'; - } - | { - type: 'ProtectCollector'; - } - | { - type: 'PollingCollector'; - } - ? string - : T extends { - type: 'TextCollector'; - category: 'SingleValueCollector'; - } - ? string - : T extends { - type: 'TextCollector'; - category: 'ValidatedSingleValueCollector'; - } - ? string - : T extends - | { - type: 'BooleanCollector'; - } - | { - type: 'ValidatedBooleanCollector'; - } - ? boolean - : T extends { - type: 'MultiSelectCollector'; - } - ? string | string[] - : T extends { - type: 'PhoneNumberCollector'; - } - ? PhoneNumberInputValue - : T extends { - type: 'PhoneNumberExtensionCollector'; - } - ? PhoneNumberExtensionInputValue - : T extends { - type: 'FidoRegistrationCollector'; - } - ? FidoRegistrationInputValue | GenericError - : T extends { - type: 'FidoAuthenticationCollector'; - } - ? FidoAuthenticationInputValue | GenericError - : T extends { - type: 'MetadataCollector'; - } - ? Record | MetadataError - : T extends { - category: 'SingleValueCollector'; - } - ? string - : T extends { - category: 'ValidatedSingleValueCollector'; - } - ? string - : T extends { - category: 'SingleValueAutoCollector'; - } - ? string - : T extends { - category: 'MultiValueCollector'; - } - ? string | string[] - : T extends { - category: 'ActionCollector'; - } - ? never - : T extends { - category: 'NoValueCollector'; - } - ? never - : CollectorValueTypes; - -// @public -export type CollectorValueTypes = - | string - | string[] - | boolean - | PhoneNumberInputValue - | PhoneNumberExtensionInputValue - | FidoRegistrationInputValue - | FidoAuthenticationInputValue - | MetadataError - | GenericError; - -// @public (undocumented) -export type ComplexValueFields = - | DeviceAuthenticationField - | DeviceRegistrationField - | PhoneNumberField - | PhoneNumberExtensionField - | FidoRegistrationField - | FidoAuthenticationField - | PollingField - | MetadataField; - -// @public (undocumented) -export interface ContinueNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'continue'; - }; - // (undocumented) - error: null; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - eventName?: string; - status: 'continue'; - }; - // (undocumented) - status: 'continue'; -} - -export { CustomLogger }; - -// @public -export type CustomPollingStatus = string & {}; - -// @public -export function davinci(input: { - config: DaVinciConfig; - requestMiddleware?: RequestMiddleware[]; - logger?: { - level: LogLevel; - custom?: CustomLogger; - }; -}): Promise<{ - store: SdkStore; - subscribe: (listener: () => void) => Unsubscribe; - externalIdp: () => () => Promise; - flow: (action: DaVinciAction) => InitFlow; - next: (args?: DaVinciRequest) => Promise; - resume: (input: { continueToken: string }) => Promise; - start: ( - options?: StartOptions | undefined, - ) => Promise; - update: < - T extends SingleValueCollectors | MultiSelectCollector | ObjectValueCollectors | AutoCollectors, - >( - collector: T, - ) => Updater; - validate: ( - collector: - | SingleValueCollectors - | ObjectValueCollectors - | MultiValueCollectors - | AutoCollectors, - ) => Validator; - pollStatus: (collector: PollingCollector) => Poller; - getClient: () => - | { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'error'; - } - | { - status: 'failure'; - } - | { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'continue'; - } - | { - status: 'failure'; - } - | { - status: 'start'; - } - | { - authorization?: { - code?: string; - state?: string; - }; - status: 'success'; - } - | null; - getCollectors: () => Collectors[]; - getError: () => DaVinciError | null; - getErrorCollectors: () => CollectorErrors[]; - getNode: () => ContinueNode | ErrorNode | FailureNode | StartNode | SuccessNode; - getServer: () => - | { - _links?: Links; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - eventName?: string; - status: 'continue'; - } - | { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'error'; - } - | { - _links?: Links; - eventName?: string; - href?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'failure'; - } - | { - status: 'start'; - } - | { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - session?: string; - status: 'success'; - } - | null; - cache: { - getLatestResponse: () => - | ({ - status: QueryStatus.fulfilled; - } & Omit< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'data' | 'fulfilledTimeStamp' - > & - Required< - Pick< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'data' | 'fulfilledTimeStamp' - > - > & { - error: undefined; - } & { - status: QueryStatus.fulfilled; - isUninitialized: false; - isLoading: false; - isSuccess: true; - isError: false; - }) - | ({ - status: QueryStatus.rejected; - } & Omit< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'error' - > & - Required< - Pick< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'error' - > - > & { - status: QueryStatus.rejected; - isUninitialized: false; - isLoading: false; - isSuccess: false; - isError: true; - }) - | { - error: { - message: string; - type: string; - }; - }; - getResponseWithId: (requestId: string) => - | ({ - status: QueryStatus.fulfilled; - } & Omit< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'data' | 'fulfilledTimeStamp' - > & - Required< - Pick< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'data' | 'fulfilledTimeStamp' - > - > & { - error: undefined; - } & { - status: QueryStatus.fulfilled; - isUninitialized: false; - isLoading: false; - isSuccess: true; - isError: false; - }) - | ({ - status: QueryStatus.rejected; - } & Omit< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'error' - > & - Required< - Pick< - { - requestId: string; - data?: unknown; - error?: FetchBaseQueryError | SerializedError | undefined; - endpointName: string; - startedTimeStamp: number; - fulfilledTimeStamp?: number; - }, - 'error' - > - > & { - status: QueryStatus.rejected; - isUninitialized: false; - isLoading: false; - isSuccess: false; - isError: true; - }) - | { - error: { - message: string; - type: string; - }; - }; - }; -}>; - -// @public -export interface DaVinciAction { - // (undocumented) - action: string; -} - -// @public -export interface DaVinciBaseResponse { - // (undocumented) - capabilityName?: string; - // (undocumented) - companyId?: string; - // (undocumented) - connectionId?: string; - // (undocumented) - connectorId?: string; - // (undocumented) - id?: string; - // (undocumented) - interactionId?: string; - // (undocumented) - interactionToken?: string; - // (undocumented) - isResponseCompatibleWithMobileAndWebSdks?: boolean; - // (undocumented) - status?: string; -} - -// @public -export type DaVinciCacheEntry = { - data?: DaVinciBaseResponse; - error?: { - data: DaVinciBaseResponse; - status: number; - }; -} & { - data?: any; - error?: any; -} & MutationResultSelectorResult; - -// @public (undocumented) -export type DavinciClient = Awaited>; - -export { DaVinciConfig }; - -// @public (undocumented) -export interface DaVinciError extends Omit { - // (undocumented) - collectors?: CollectorErrors[]; - // (undocumented) - internalHttpStatus?: number; - // (undocumented) - message: string; - // (undocumented) - status: 'error' | 'failure' | 'unknown'; -} - -// @public (undocumented) -export interface DaVinciErrorCacheEntry { - // (undocumented) - endpointName: 'next' | 'flow' | 'start'; - // (undocumented) - error: { - data: T; - }; - // (undocumented) - fulfilledTimeStamp: number; - // (undocumented) - isError: boolean; - // (undocumented) - isLoading: boolean; - // (undocumented) - isSuccess: boolean; - // (undocumented) - isUninitialized: boolean; - // (undocumented) - requestId: string; - // (undocumented) - startedTimeStamp: number; - // (undocumented) - status: 'fulfilled' | 'pending' | 'rejected'; -} - -// @public (undocumented) -export interface DavinciErrorResponse extends DaVinciBaseResponse { - // (undocumented) - cause?: string | null; - // (undocumented) - code: string | number; - // (undocumented) - details?: ErrorDetail[]; - // (undocumented) - doNotSendToOE?: boolean; - // (undocumented) - error?: { - code?: string; - message?: string; - }; - // (undocumented) - errorCategory?: string; - // (undocumented) - errorMessage?: string; - // (undocumented) - expected?: boolean; - // (undocumented) - httpResponseCode: number; - // (undocumented) - isErrorCustomized?: boolean; - // (undocumented) - message: string; - // (undocumented) - metricAttributes?: { - [key: string]: unknown; - }; -} - -// @public (undocumented) -export interface DaVinciFailureResponse extends DaVinciBaseResponse { - // (undocumented) - error?: { - code?: string; - message?: string; - [key: string]: unknown; - }; -} - -// @public (undocumented) -export type DaVinciField = - | ComplexValueFields - | MultiValueFields - | ReadOnlyFields - | RedirectFields - | SingleValueFields; - -// @public -export interface DaVinciNextResponse extends DaVinciBaseResponse { - // (undocumented) - eventName?: string; - // (undocumented) - form?: { - name?: string; - description?: string; - components?: { - fields?: DaVinciField[]; - }; - }; - // (undocumented) - formData?: { - value?: { - [key: string]: string; - }; - }; - // (undocumented) - _links?: Links; -} - -// @public -export interface DaVinciPollResponse extends DaVinciBaseResponse { - // (undocumented) - eventName?: string; - // (undocumented) - _links?: Links; - // (undocumented) - success?: boolean; -} - -// @public (undocumented) -export interface DaVinciRequest { - // (undocumented) - eventName: string; - // (undocumented) - id: string; - // (undocumented) - interactionId: string; - // (undocumented) - parameters: { - eventType: 'submit' | 'action' | 'polling'; - data: { - actionKey: string; - formData?: Record; - }; - }; -} - -// @public -export type DaVinciRequestValueTypes = - | string - | number - | boolean - | (string | number | boolean)[] - | DeviceValue - | PhoneNumberInputValue - | FidoRegistrationInputValue - | FidoAuthenticationInputValue - | MetadataError - | GenericError; - -// @public (undocumented) -export interface DaVinciSuccessResponse extends DaVinciBaseResponse { - // (undocumented) - authorizeResponse?: OAuthDetails; - // (undocumented) - environment: { - id: string; - [key: string]: unknown; - }; - // (undocumented) - _links?: Links; - // (undocumented) - resetCookie?: boolean; - // (undocumented) - session?: { - id?: string; - [key: string]: unknown; - }; - // (undocumented) - sessionToken?: string; - // (undocumented) - sessionTokenMaxAge?: number; - // (undocumented) - status: string; - // (undocumented) - subFlowSettings?: { - cssLinks?: unknown[]; - cssUrl?: unknown; - jsLinks?: unknown[]; - loadingScreenSettings?: unknown; - reactSkUrl?: unknown; - }; - // (undocumented) - success: true; -} - -// @public (undocumented) -export type DeviceAuthenticationCollector = ObjectOptionsCollectorWithObjectValue< - 'DeviceAuthenticationCollector', - DeviceValue ->; - -// @public (undocumented) -export type DeviceAuthenticationField = { - type: 'DEVICE_AUTHENTICATION'; - key: string; - label: string; - options: { - type: string; - iconSrc: string; - title: string; - id: string; - default: boolean; - description: string; - }[]; - required: boolean; -}; - -// @public (undocumented) -export interface DeviceOptionNoDefault { - // (undocumented) - content: string; - // (undocumented) - key: string; - // (undocumented) - label: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export interface DeviceOptionWithDefault { - // (undocumented) - content: string; - // (undocumented) - default: boolean; - // (undocumented) - key: string; - // (undocumented) - label: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export type DeviceRegistrationCollector = ObjectOptionsCollectorWithStringValue< - 'DeviceRegistrationCollector', - string ->; - -// @public (undocumented) -export type DeviceRegistrationField = { - type: 'DEVICE_REGISTRATION'; - key: string; - label: string; - options: { - type: string; - iconSrc: string; - title: string; - description: string; - }[]; - required: boolean; -}; - -// @public (undocumented) -export interface DeviceValue { - // (undocumented) - id: string; - // (undocumented) - type: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export interface ErrorDetail { - // (undocumented) - message?: string; - // (undocumented) - rawResponse?: { - _embedded?: { - users?: Array; - }; - code?: string; - count?: number; - details?: NestedErrorDetails[]; - id?: string; - message?: string; - size?: number; - userFilter?: string; - [key: string]: unknown; - }; - // (undocumented) - statusCode?: number; -} - -// @public (undocumented) -export interface ErrorNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - action: string; - collectors: Collectors[]; - description?: string; - name?: string; - status: 'error'; - }; - // (undocumented) - error: DaVinciError; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'error'; - } | null; - // (undocumented) - status: 'error'; -} - -// @public (undocumented) -export interface FailureNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - status: 'failure'; - }; - // (undocumented) - error: DaVinciError; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - href?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - status: 'failure'; - } | null; - // (undocumented) - status: 'failure'; -} - -// @public (undocumented) -export type FidoAuthenticationCollector = AutoCollector< - 'ObjectValueAutoCollector', - 'FidoAuthenticationCollector', - FidoAuthenticationInputValue | GenericError, - FidoAuthenticationOutputValue ->; - -// @public (undocumented) -export type FidoAuthenticationField = { - type: 'FIDO2'; - key: string; - label: string; - publicKeyCredentialRequestOptions: FidoAuthenticationOptions; - action: 'AUTHENTICATE'; - trigger: string; - required: boolean; -}; - -// @public (undocumented) -export interface FidoAuthenticationInputValue { - // (undocumented) - assertionValue?: AssertionValue; -} - -// @public (undocumented) -export interface FidoAuthenticationOptions extends Omit< - PublicKeyCredentialRequestOptions, - 'challenge' | 'allowCredentials' -> { - // (undocumented) - allowCredentials?: { - id: number[]; - transports?: AuthenticatorTransport[]; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - challenge: number[]; -} - -// @public (undocumented) -export interface FidoAuthenticationOutputValue { - // (undocumented) - action: 'AUTHENTICATE'; - // (undocumented) - publicKeyCredentialRequestOptions: FidoAuthenticationOptions; - // (undocumented) - trigger: string; -} - -// @public (undocumented) -export interface FidoClient { - authenticate: ( - options: FidoAuthenticationOptions, - ) => Promise; - register: ( - options: FidoRegistrationOptions, - ) => Promise; -} - -// @public -export type FidoErrorCode = - | 'NotAllowedError' - | 'AbortError' - | 'InvalidStateError' - | 'NotSupportedError' - | 'SecurityError' - | 'TimeoutError' - | 'UnknownError'; - -// @public (undocumented) -export type FidoRegistrationCollector = AutoCollector< - 'ObjectValueAutoCollector', - 'FidoRegistrationCollector', - FidoRegistrationInputValue | GenericError, - FidoRegistrationOutputValue ->; - -// @public (undocumented) -export type FidoRegistrationField = { - type: 'FIDO2'; - key: string; - label: string; - publicKeyCredentialCreationOptions: FidoRegistrationOptions; - action: 'REGISTER'; - trigger: string; - required: boolean; -}; - -// @public (undocumented) -export interface FidoRegistrationInputValue { - // (undocumented) - attestationValue?: AttestationValue; -} - -// @public (undocumented) -export interface FidoRegistrationOptions extends Omit< - PublicKeyCredentialCreationOptions, - 'challenge' | 'user' | 'pubKeyCredParams' | 'excludeCredentials' -> { - // (undocumented) - challenge: number[]; - // (undocumented) - excludeCredentials?: { - id: number[]; - transports?: AuthenticatorTransport[]; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - pubKeyCredParams: { - alg: string | number; - type: PublicKeyCredentialType; - }[]; - // (undocumented) - user: { - id: number[]; - name: string; - displayName: string; - }; -} - -// @public (undocumented) -export interface FidoRegistrationOutputValue { - // (undocumented) - action: 'REGISTER'; - // (undocumented) - publicKeyCredentialCreationOptions: FidoRegistrationOptions; - // (undocumented) - trigger: string; -} - -// @public (undocumented) -export type FlowCollector = ActionCollectorNoUrl<'FlowCollector'>; - -// @public (undocumented) -export type FlowNode = ContinueNode | ErrorNode | StartNode | SuccessNode | FailureNode; - -// @public -export type GetClient = - | StartNode['client'] - | ContinueNode['client'] - | ErrorNode['client'] - | SuccessNode['client'] - | FailureNode['client']; - -// @public (undocumented) -export type IdpCollector = ActionCollectorWithUrl<'IdpCollector'>; - -// @public -export interface ImageCollector extends NoValueCollectorBase<'ImageCollector'> { - // (undocumented) - output: NoValueCollectorBase<'ImageCollector'>['output'] & { - src: string; - alt: string; - href?: string; - }; -} - -// @public (undocumented) -export type ImageField = { - type: 'IMAGE'; - key: string; - description: string; - imageUrl: string; - hyperlinkUrl?: string; -}; - -// @public (undocumented) -export type InferActionCollectorType = T extends 'IdpCollector' - ? IdpCollector - : T extends 'SubmitCollector' - ? SubmitCollector - : T extends 'FlowCollector' - ? FlowCollector - : ActionCollectorWithUrl<'ActionCollector'> | ActionCollectorNoUrl<'ActionCollector'>; - -// @public -export type InferAutoCollectorType = T extends 'ProtectCollector' - ? ProtectCollector - : T extends 'PollingCollector' - ? PollingCollector - : T extends 'FidoRegistrationCollector' - ? FidoRegistrationCollector - : T extends 'FidoAuthenticationCollector' - ? FidoAuthenticationCollector - : T extends 'MetadataCollector' - ? MetadataCollector - : T extends 'ObjectValueAutoCollector' - ? ObjectValueAutoCollector - : SingleValueAutoCollector; - -// @public -export type InferMultiValueCollectorType = - T extends 'MultiSelectCollector' - ? MultiValueCollectorWithValue<'MultiSelectCollector'> - : - | MultiValueCollectorWithValue<'MultiValueCollector'> - | MultiValueCollectorNoValue<'MultiValueCollector'>; - -// @public -export type InferNoValueCollectorType = - T extends 'ReadOnlyCollector' - ? ReadOnlyCollector - : T extends 'RichTextCollector' - ? RichTextCollector - : T extends 'QrCodeCollector' - ? QrCodeCollector - : T extends 'ImageCollector' - ? ImageCollector - : NoValueCollectorBase<'NoValueCollector'>; - -// @public -export type InferSingleValueCollectorType = - T extends 'TextCollector' - ? TextCollector - : T extends 'SingleSelectCollector' - ? SingleSelectCollector - : T extends 'ValidatedTextCollector' - ? ValidatedTextCollector - : T extends 'PasswordCollector' - ? PasswordCollector - : T extends 'ValidatedPasswordCollector' - ? ValidatedPasswordCollector - : T extends 'BooleanCollector' - ? BooleanCollector - : T extends 'ValidatedBooleanCollector' - ? ValidatedBooleanCollector - : - | SingleValueCollectorWithValue<'SingleValueCollector'> - | SingleValueCollectorNoValue<'SingleValueCollector'>; - -// @public (undocumented) -export type InferValueObjectCollectorType = - T extends 'DeviceAuthenticationCollector' - ? DeviceAuthenticationCollector - : T extends 'DeviceRegistrationCollector' - ? DeviceRegistrationCollector - : T extends 'PhoneNumberCollector' - ? PhoneNumberCollector - : T extends 'PhoneNumberExtensionCollector' - ? PhoneNumberExtensionCollector - : - | ObjectOptionsCollectorWithObjectValue<'ObjectValueCollector'> - | ObjectOptionsCollectorWithStringValue<'ObjectValueCollector'>; - -// @public (undocumented) -export type InitFlow = () => Promise; - -// @public (undocumented) -export interface InternalErrorResponse { - // (undocumented) - error: Omit & { - message: string; - }; - // (undocumented) - type: 'internal_error'; -} - -// @public (undocumented) -export interface Links { - // (undocumented) - [key: string]: { - href?: string; - }; -} - -export { LogLevel }; - -// @public (undocumented) -export type MetadataCollector = AutoCollector< - 'ObjectValueAutoCollector', - 'MetadataCollector', - MetadataCollectorInputValue, - Record ->; - -// @public (undocumented) -export type MetadataCollectorInputValue = Record | MetadataError; - -// @public -export interface MetadataError { - // (undocumented) - code: string; - // (undocumented) - message: string; -} - -// @public (undocumented) -export type MetadataField = { - type: 'METADATA'; - key: string; - payload: Record; -}; - -// @public (undocumented) -export type MultiSelectCollector = MultiValueCollectorWithValue<'MultiSelectCollector'>; - -// @public (undocumented) -export type MultiSelectField = { - inputType: 'MULTI_SELECT'; - key: string; - label: string; - options: { - label: string; - value: string; - }[]; - required?: boolean; - type: 'CHECKBOX' | 'COMBOBOX'; -}; - -// @public (undocumented) -export type MultiValueCollector = - | MultiValueCollectorWithValue - | MultiValueCollectorNoValue; - -// @public (undocumented) -export interface MultiValueCollectorNoValue { - // (undocumented) - category: 'MultiValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string[]; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type MultiValueCollectors = - | MultiValueCollectorWithValue<'MultiValueCollector'> - | MultiValueCollectorWithValue<'MultiSelectCollector'>; - -// @public -export type MultiValueCollectorTypes = 'MultiSelectCollector' | 'MultiValueCollector'; - -// @public (undocumented) -export interface MultiValueCollectorWithValue { - // (undocumented) - category: 'MultiValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string[]; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: string[]; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type MultiValueFields = MultiSelectField; - -// @public -export interface NestedErrorDetails { - // (undocumented) - code?: string; - // (undocumented) - innerError?: { - history?: string; - unsatisfiedRequirements?: string[]; - failuresRemaining?: number; - }; - // (undocumented) - message?: string; - // (undocumented) - target?: string; -} - -// @public -export const nextCollectorValues: ActionCreatorWithPayload< - { - fields: DaVinciField[]; - formData: { - value: Record; - }; - }, - string ->; - -// @public -export const nodeCollectorReducer: Reducer & { - getInitialState: () => Collectors[]; -}; - -// @public (undocumented) -export type NodeStates = StartNode | ContinueNode | ErrorNode | SuccessNode | FailureNode; - -// @public (undocumented) -export type NoValueCollector = InferNoValueCollectorType; - -// @public (undocumented) -export interface NoValueCollectorBase { - // (undocumented) - category: 'NoValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type NoValueCollectors = - | NoValueCollectorBase<'NoValueCollector'> - | ReadOnlyCollector - | RichTextCollector - | QrCodeCollector - | ImageCollector; - -// @public -export type NoValueCollectorTypes = - | 'ReadOnlyCollector' - | 'RichTextCollector' - | 'NoValueCollector' - | 'QrCodeCollector' - | 'ImageCollector'; - -// @public -export interface OAuthDetails { - // (undocumented) - [key: string]: unknown; - // (undocumented) - code?: string; - // (undocumented) - state?: string; -} - -// @public (undocumented) -export interface ObjectOptionsCollectorWithObjectValue< - T extends ObjectValueCollectorTypes, - V = Record, - D = Record, -> { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: DeviceOptionWithDefault[]; - value?: D | null; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface ObjectOptionsCollectorWithStringValue< - T extends ObjectValueCollectorTypes, - V = string, -> { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - validation: ValidationRequired[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: DeviceOptionNoDefault[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ObjectValueAutoCollector = AutoCollector< - 'ObjectValueAutoCollector', - 'ObjectValueAutoCollector', - Record ->; - -// @public (undocumented) -export type ObjectValueAutoCollectorTypes = - | 'ObjectValueAutoCollector' - | 'FidoRegistrationCollector' - | 'FidoAuthenticationCollector' - | 'MetadataCollector'; - -// @public (undocumented) -export type ObjectValueCollector = - | ObjectOptionsCollectorWithObjectValue - | ObjectOptionsCollectorWithStringValue - | ObjectValueCollectorWithObjectValue; - -// @public (undocumented) -export type ObjectValueCollectors = - | DeviceAuthenticationCollector - | DeviceRegistrationCollector - | PhoneNumberCollector - | PhoneNumberExtensionCollector - | ObjectOptionsCollectorWithObjectValue<'ObjectSelectCollector'> - | ObjectOptionsCollectorWithStringValue<'ObjectSelectCollector'>; - -// @public -export type ObjectValueCollectorTypes = - | 'DeviceAuthenticationCollector' - | 'DeviceRegistrationCollector' - | 'PhoneNumberCollector' - | 'PhoneNumberExtensionCollector' - | 'ObjectOptionsCollector' - | 'ObjectValueCollector' - | 'ObjectSelectCollector'; - -// @public (undocumented) -export interface ObjectValueCollectorWithObjectValue< - T extends ObjectValueCollectorTypes, - IV = Record, - OV = Record, -> { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: IV; - type: string; - validation: (ValidationRequired | ValidationPhoneNumber)[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value?: OV | null; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface OutgoingQueryParams { - // (undocumented) - [key: string]: string | string[]; -} - -// @public (undocumented) -export interface PasswordCollector { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - verify: boolean; - }; - // (undocumented) - type: 'PasswordCollector'; -} - -// @public -export type PasswordField = { - type: 'PASSWORD' | 'PASSWORD_VERIFY'; - key: string; - label: string; - required?: boolean; - verify?: boolean; - passwordPolicy?: PasswordPolicy; -}; - -// @public -export interface PasswordPolicy { - // (undocumented) - createdAt?: string; - // (undocumented) - default?: boolean; - // (undocumented) - description?: string; - // (undocumented) - excludesCommonlyUsed?: boolean; - // (undocumented) - excludesProfileData?: boolean; - // (undocumented) - history?: { - count?: number; - retentionDays?: number; - }; - // (undocumented) - id?: string; - // (undocumented) - length?: { - min?: number; - max?: number; - }; - // (undocumented) - lockout?: { - failureCount?: number; - durationSeconds?: number; - }; - // (undocumented) - maxAgeDays?: number; - // (undocumented) - maxRepeatedCharacters?: number; - // (undocumented) - minAgeDays?: number; - // (undocumented) - minCharacters?: Record; - // (undocumented) - minUniqueCharacters?: number; - // (undocumented) - name?: string; - // (undocumented) - notSimilarToCurrent?: boolean; - // (undocumented) - populationCount?: number; - // (undocumented) - updatedAt?: string; -} - -// @public (undocumented) -export type PhoneNumberCollector = ObjectValueCollectorWithObjectValue< - 'PhoneNumberCollector', - PhoneNumberInputValue, - PhoneNumberOutputValue ->; - -// @public (undocumented) -export interface PhoneNumberExtensionCollector { - // (undocumented) - category: 'ObjectValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: PhoneNumberExtensionInputValue; - type: string; - validation: (ValidationRequired | ValidationPhoneNumber)[] | null; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - extensionLabel: string; - value: PhoneNumberExtensionOutputValue; - }; - // (undocumented) - type: 'PhoneNumberExtensionCollector'; -} - -// @public (undocumented) -export type PhoneNumberExtensionField = PhoneNumberField & { - showExtension: boolean; - extensionLabel: string; -}; - -// @public (undocumented) -export interface PhoneNumberExtensionInputValue { - // (undocumented) - countryCode: string; - // (undocumented) - extension: string; - // (undocumented) - phoneNumber: string; -} - -// @public (undocumented) -export interface PhoneNumberExtensionOutputValue { - // (undocumented) - countryCode?: string; - // (undocumented) - extension?: string; - // (undocumented) - phoneNumber?: string; -} - -// @public (undocumented) -export type PhoneNumberField = { - type: 'PHONE_NUMBER'; - key: string; - label: string; - required: boolean; - defaultCountryCode: string | null; - validatePhoneNumber: boolean; -}; - -// @public (undocumented) -export interface PhoneNumberInputValue { - // (undocumented) - countryCode: string; - // (undocumented) - phoneNumber: string; -} - -// @public (undocumented) -export interface PhoneNumberOutputValue { - // (undocumented) - countryCode?: string; - // (undocumented) - phoneNumber?: string; -} - -// @public -export type Poller = () => Promise; - -// @public (undocumented) -export type PollingCollector = AutoCollector< - 'SingleValueAutoCollector', - 'PollingCollector', - string, - PollingOutputValue ->; - -// @public (undocumented) -export type PollingField = { - type: 'POLLING'; - key: string; - pollInterval: number; - pollRetries: number; - pollChallengeStatus?: boolean; - challenge?: string; -}; - -// @public (undocumented) -export interface PollingOutputValue { - // (undocumented) - challenge?: string; - // (undocumented) - pollChallengeStatus?: boolean; - // (undocumented) - pollInterval: number; - // (undocumented) - pollRetries: number; - // (undocumented) - retriesRemaining?: number; -} - -// @public (undocumented) -export type PollingStatus = PollingStatusContinue | PollingStatusChallenge; - -// @public (undocumented) -export type PollingStatusChallenge = - | PollingStatusChallengeComplete - | 'expired' - | 'timedOut' - | 'error'; - -// @public (undocumented) -export type PollingStatusChallengeComplete = - | 'approved' - | 'denied' - | 'continue' - | CustomPollingStatus; - -// @public (undocumented) -export type PollingStatusContinue = 'continue' | 'timedOut'; - -// @public (undocumented) -export type ProtectCollector = AutoCollector< - 'SingleValueAutoCollector', - 'ProtectCollector', - string, - ProtectOutputValue ->; - -// @public (undocumented) -export type ProtectField = { - type: 'PROTECT'; - key: string; - behavioralDataCollection: boolean; - universalDeviceIdentification: boolean; -}; - -// @public -export interface ProtectOutputValue { - // (undocumented) - behavioralDataCollection: boolean; - // (undocumented) - universalDeviceIdentification: boolean; -} - -// @public -export interface QrCodeCollector extends NoValueCollectorBase<'QrCodeCollector'> { - // (undocumented) - output: NoValueCollectorBase<'QrCodeCollector'>['output'] & { - src: string; - }; -} - -// @public (undocumented) -export type QrCodeField = { - type: 'QR_CODE'; - key: string; - content: string; - fallbackText?: string; -}; - -// @public -export interface ReadOnlyCollector extends NoValueCollectorBase<'ReadOnlyCollector'> { - // (undocumented) - output: NoValueCollectorBase<'ReadOnlyCollector'>['output'] & { - content: string; - title?: string; - }; -} - -// @public (undocumented) -export type ReadOnlyField = { - type: 'LABEL'; - content: string; - richContent?: RichContent; - key?: string; -}; - -// @public (undocumented) -export type ReadOnlyFields = ReadOnlyField | QrCodeField | AgreementField | ImageField; - -// @public (undocumented) -export type RedirectField = { - type: 'SOCIAL_LOGIN_BUTTON'; - key: string; - label: string; - links: Links; -}; - -// @public (undocumented) -export type RedirectFields = RedirectField; - -export { RequestMiddleware }; - -// @public -export type RichContent = { - content: string; - replacements?: Record; -}; - -// @public -export interface RichContentLink { - // (undocumented) - href: string; - // (undocumented) - key: string; - // (undocumented) - target?: '_self' | '_blank'; - // (undocumented) - type: 'link'; - // (undocumented) - value: string; -} - -// @public -export type RichContentReplacement = { - type: 'link'; - value: string; - href: string; - target?: '_self' | '_blank'; -}; - -// @public -export interface RichTextCollector extends NoValueCollectorBase<'RichTextCollector'> { - // (undocumented) - output: NoValueCollectorBase<'RichTextCollector'>['output'] & { - content: string; - richContent: CollectorRichContent; - }; -} - -// @public (undocumented) -export interface SelectorOption { - // (undocumented) - label: string; - // (undocumented) - value: string; -} - -// @public (undocumented) -export type SingleCheckboxField = { - type: 'SINGLE_CHECKBOX'; - inputType: 'BOOLEAN'; - key: string; - label: string; - required?: boolean; - errorMessage?: string; - appearance: string; - richContent?: RichContent; -}; - -// @public (undocumented) -export type SingleSelectCollector = SingleSelectCollectorWithValue<'SingleSelectCollector'>; - -// @public (undocumented) -export interface SingleSelectCollectorNoValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export interface SingleSelectCollectorWithValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: string | number | boolean; - options: SelectorOption[]; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleSelectField = { - inputType: 'SINGLE_SELECT'; - key: string; - label: string; - options: { - label: string; - value: string; - }[]; - required?: boolean; - type: 'RADIO' | 'DROPDOWN'; -}; - -// @public (undocumented) -export type SingleValueAutoCollector = AutoCollector< - 'SingleValueAutoCollector', - 'SingleValueAutoCollector', - string ->; - -// @public (undocumented) -export type SingleValueAutoCollectorTypes = - | 'SingleValueAutoCollector' - | 'ProtectCollector' - | 'PollingCollector'; - -// @public -export type SingleValueCollector = - | SingleValueCollectorWithValue - | SingleValueCollectorNoValue; - -// @public (undocumented) -export interface SingleValueCollectorNoValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleValueCollectors = - | PasswordCollector - | ValidatedPasswordCollector - | SingleSelectCollector - | TextCollector - | ValidatedTextCollector - | BooleanCollector - | ValidatedBooleanCollector - | SingleValueCollectorWithValue<'SingleValueCollector'>; - -// @public -export type SingleValueCollectorTypes = - | 'PasswordCollector' - | 'ValidatedPasswordCollector' - | 'BooleanCollector' - | 'ValidatedBooleanCollector' - | 'SingleValueCollector' - | 'SingleSelectCollector' - | 'SingleSelectObjectCollector' - | 'TextCollector' - | 'ValidatedTextCollector'; - -// @public (undocumented) -export interface SingleValueCollectorWithValue { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: V; - type: string; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: V; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type SingleValueFields = - | StandardField - | PasswordField - | ValidatedField - | SingleCheckboxField - | SingleSelectField - | ProtectField; - -// @public (undocumented) -export type StandardField = { - type: 'TEXT' | 'SUBMIT_BUTTON' | 'FLOW_BUTTON' | 'FLOW_LINK' | 'BUTTON'; - key: string; - label: string; - required?: boolean; -}; - -// @public (undocumented) -export interface StartNode { - // (undocumented) - cache: null; - // (undocumented) - client: { - status: 'start'; - }; - // (undocumented) - error: DaVinciError | null; - // (undocumented) - server: { - status: 'start'; - }; - // (undocumented) - status: 'start'; -} - -// @public (undocumented) -export interface StartOptions { - // (undocumented) - query: Query; -} - -// @public (undocumented) -export type SubmitCollector = ActionCollectorNoUrl<'SubmitCollector'>; - -// @public (undocumented) -export interface SuccessNode { - // (undocumented) - cache: { - key: string; - }; - // (undocumented) - client: { - authorization?: { - code?: string; - state?: string; - }; - status: 'success'; - } | null; - // (undocumented) - error: null; - // (undocumented) - httpStatus: number; - // (undocumented) - server: { - _links?: Links; - eventName?: string; - id?: string; - interactionId?: string; - interactionToken?: string; - href?: string; - session?: string; - status: 'success'; - }; - // (undocumented) - status: 'success'; -} - -// @public (undocumented) -export type TextCollector = SingleValueCollectorWithValue<'TextCollector'>; - -// @public (undocumented) -export interface ThrownQueryError { - // (undocumented) - error: FetchBaseQueryError; - // (undocumented) - isHandledError: boolean; - // (undocumented) - meta: FetchBaseQueryMeta; -} - -// @public -export type UnknownCollector = { - category: 'UnknownCollector'; - error: string | null; - type: 'UnknownCollector'; - id: string; - name: string; - output: { - key: string; - label: string; - type: string; - }; -}; - -// @public (undocumented) -export type UnknownField = Record; - -// @public -export type UpdatableCollectors = - | SingleValueCollectors - | MultiSelectCollector - | ObjectValueCollectors - | AutoCollectors; - -// @public (undocumented) -export const updateCollectorValues: ActionCreatorWithPayload< - { - id: string; - value: CollectorValueTypes; - index?: number; - }, - string ->; - -// @public -export type Updater = ( - value: CollectorValueType, - index?: number, -) => InternalErrorResponse | null; - -// @public (undocumented) -export interface ValidatedBooleanCollector extends ValidatedSingleValueCollectorWithValue< - 'ValidatedBooleanCollector', - boolean -> { - // (undocumented) - output: ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean>['output'] & { - appearance: string; - richContent?: CollectorRichContent; - }; -} - -// @public -export type ValidatedCollectors = - | ValidatedTextCollector - | ValidatedBooleanCollector - | ValidatedPasswordCollector - | ObjectValueCollectors - | MultiValueCollectors - | AutoCollectors; - -// @public (undocumented) -export type ValidatedField = { - type: 'TEXT'; - key: string; - label: string; - required: boolean; - validation: { - regex: string; - errorMessage: string; - }; -}; - -// @public (undocumented) -export interface ValidatedPasswordCollector { - // (undocumented) - category: 'SingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - value: string | number | boolean; - type: string; - validation: PasswordPolicy; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - verify: boolean; - }; - // (undocumented) - type: 'ValidatedPasswordCollector'; -} - -// @public (undocumented) -export interface ValidatedSingleValueCollectorWithValue< - T extends SingleValueCollectorTypes, - V = string, -> { - // (undocumented) - category: 'ValidatedSingleValueCollector'; - // (undocumented) - error: string | null; - // (undocumented) - id: string; - // (undocumented) - input: { - key: string; - type: string; - validation: (ValidationRequired | ValidationRegex)[]; - value: V; - }; - // (undocumented) - name: string; - // (undocumented) - output: { - key: string; - label: string; - type: string; - value: V; - }; - // (undocumented) - type: T; -} - -// @public (undocumented) -export type ValidatedTextCollector = ValidatedSingleValueCollectorWithValue<'TextCollector'>; - -// @public (undocumented) -export interface ValidationPhoneNumber { - // (undocumented) - message: string; - // (undocumented) - rule: boolean; - // (undocumented) - type: 'validatePhoneNumber'; -} - -// @public (undocumented) -export interface ValidationRegex { - // (undocumented) - message: string; - // (undocumented) - rule: string; - // (undocumented) - type: 'regex'; -} - -// @public (undocumented) -export interface ValidationRequired { - // (undocumented) - message: string; - // (undocumented) - rule: boolean; - // (undocumented) - type: 'required'; -} - -// @public -export type Validator = ( - value: CollectorValueType, -) => - | string[] - | { - error: { - message: string; - type: string; - }; - type: string; - }; - -// (No @packageDocumentation comment for this package) -``` +## API Report File for "@forgerock/davinci-client" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { ActionCreatorWithPayload } from '@reduxjs/toolkit'; +import { ActionTypes } from '@forgerock/sdk-request-middleware'; +import { CustomLogger } from '@forgerock/sdk-logger'; +import type { DaVinciConfig } from '@forgerock/sdk-types'; +import { FetchBaseQueryError } from '@reduxjs/toolkit/query'; +import type { FetchBaseQueryMeta } from '@reduxjs/toolkit/query'; +import { GenericError } from '@forgerock/sdk-types'; +import { LogLevel } from '@forgerock/sdk-logger'; +import type { MutationResultSelectorResult } from '@reduxjs/toolkit/query'; +import { QueryStatus } from '@reduxjs/toolkit/query'; +import { Reducer } from '@reduxjs/toolkit'; +import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; +import type { SdkStore } from '@forgerock/sdk-types'; +import { SerializedError } from '@reduxjs/toolkit'; +import { Unsubscribe } from '@reduxjs/toolkit'; + +// @public (undocumented) +export type ActionCollector = ActionCollectorNoUrl | ActionCollectorWithUrl; + +// @public (undocumented) +export interface ActionCollectorNoUrl { + // (undocumented) + category: 'ActionCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ActionCollectors = ActionCollectorWithUrl<'IdpCollector'> | ActionCollectorNoUrl<'ActionCollector'> | ActionCollectorNoUrl<'FlowCollector'> | ActionCollectorNoUrl<'SubmitCollector'>; + +// @public +export type ActionCollectorTypes = 'FlowCollector' | 'SubmitCollector' | 'IdpCollector' | 'ActionCollector'; + +// @public (undocumented) +export interface ActionCollectorWithUrl { + // (undocumented) + category: 'ActionCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + url?: string | null; + }; + // (undocumented) + type: T; +} + +export { ActionTypes } + +// @public (undocumented) +export type AgreementField = { + type: 'AGREEMENT'; + key: string; + content: string; + titleEnabled: boolean; + title?: string; + agreement: { + id: string; + useDynamicAgreement: boolean; + }; + enabled: boolean; +}; + +// @public (undocumented) +export interface AssertionValue extends Omit { + // (undocumented) + rawId: string; + // (undocumented) + response: { + clientDataJSON: string; + authenticatorData: string; + signature: string; + userHandle: string | null; + }; +} + +// @public (undocumented) +export interface AttestationValue extends Omit { + // (undocumented) + rawId: string; + // (undocumented) + response: { + clientDataJSON: string; + attestationObject: string; + }; +} + +// @public (undocumented) +export interface AutoCollector> { + // (undocumented) + category: C; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: IV; + type: string; + validation?: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + type: string; + config: OV; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type AutoCollectorCategories = 'SingleValueAutoCollector' | 'ObjectValueAutoCollector'; + +// @public (undocumented) +export type AutoCollectors = ProtectCollector | FidoRegistrationCollector | FidoAuthenticationCollector | MetadataCollector | PollingCollector | SingleValueAutoCollector | ObjectValueAutoCollector; + +// @public (undocumented) +export type AutoCollectorTypes = SingleValueAutoCollectorTypes | ObjectValueAutoCollectorTypes; + +// @public (undocumented) +export interface BooleanCollector extends SingleValueCollectorWithValue<'BooleanCollector', boolean> { + // (undocumented) + output: SingleValueCollectorWithValue<'BooleanCollector', boolean>['output'] & { + appearance: string; + richContent?: CollectorRichContent; + }; +} + +// @public (undocumented) +export type CollectorCategory = Collectors['category']; + +// @public (undocumented) +export interface CollectorErrors { + // (undocumented) + code: string; + // (undocumented) + message: string; + // (undocumented) + target: string; +} + +// @public +export interface CollectorRichContent { + // (undocumented) + content: string; + // (undocumented) + replacements: RichContentLink[]; +} + +// @public (undocumented) +export type Collectors = FlowCollector | MetadataCollector | PasswordCollector | ValidatedPasswordCollector | TextCollector | BooleanCollector | ValidatedBooleanCollector | SingleSelectCollector | IdpCollector | SubmitCollector | ActionCollector<'ActionCollector'> | SingleValueCollector<'SingleValueCollector'> | MultiSelectCollector | DeviceAuthenticationCollector | DeviceRegistrationCollector | PhoneNumberCollector | PhoneNumberExtensionCollector | ReadOnlyCollector | RichTextCollector | ValidatedTextCollector | ProtectCollector | PollingCollector | FidoRegistrationCollector | FidoAuthenticationCollector | QrCodeCollector | ImageCollector | UnknownCollector; + +// @public +export type CollectorValueType = T extends { + type: 'PasswordCollector'; +} | { + type: 'ValidatedPasswordCollector'; +} | { + type: 'SingleSelectCollector'; +} | { + type: 'DeviceRegistrationCollector'; +} | { + type: 'DeviceAuthenticationCollector'; +} | { + type: 'ProtectCollector'; +} | { + type: 'PollingCollector'; +} ? string : T extends { + type: 'TextCollector'; + category: 'SingleValueCollector'; +} ? string : T extends { + type: 'TextCollector'; + category: 'ValidatedSingleValueCollector'; +} ? string : T extends { + type: 'BooleanCollector'; +} | { + type: 'ValidatedBooleanCollector'; +} ? boolean : T extends { + type: 'MultiSelectCollector'; +} ? string | string[] : T extends { + type: 'PhoneNumberCollector'; +} ? PhoneNumberInputValue : T extends { + type: 'PhoneNumberExtensionCollector'; +} ? PhoneNumberExtensionInputValue : T extends { + type: 'FidoRegistrationCollector'; +} ? FidoRegistrationInputValue | GenericError : T extends { + type: 'FidoAuthenticationCollector'; +} ? FidoAuthenticationInputValue | GenericError : T extends { + type: 'MetadataCollector'; +} ? Record | MetadataError : T extends { + category: 'SingleValueCollector'; +} ? string : T extends { + category: 'ValidatedSingleValueCollector'; +} ? string : T extends { + category: 'SingleValueAutoCollector'; +} ? string : T extends { + category: 'MultiValueCollector'; +} ? string | string[] : T extends { + category: 'ActionCollector'; +} ? never : T extends { + category: 'NoValueCollector'; +} ? never : CollectorValueTypes; + +// @public +export type CollectorValueTypes = string | string[] | boolean | PhoneNumberInputValue | PhoneNumberExtensionInputValue | FidoRegistrationInputValue | FidoAuthenticationInputValue | MetadataError | GenericError; + +// @public (undocumented) +export type ComplexValueFields = DeviceAuthenticationField | DeviceRegistrationField | PhoneNumberField | PhoneNumberExtensionField | FidoRegistrationField | FidoAuthenticationField | PollingField | MetadataField; + +// @public (undocumented) +export interface ContinueNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'continue'; + }; + // (undocumented) + error: null; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + eventName?: string; + status: 'continue'; + }; + // (undocumented) + status: 'continue'; +} + +export { CustomLogger } + +// @public +export type CustomPollingStatus = string & {}; + +// @public +export function davinci(input: { + config: DaVinciConfig; + requestMiddleware?: RequestMiddleware[]; + logger?: { + level: LogLevel; + custom?: CustomLogger; + }; +}): Promise<{ + store: SdkStore; + subscribe: (listener: () => void) => Unsubscribe; + externalIdp: () => (() => Promise); + flow: (action: DaVinciAction) => InitFlow; + next: (args?: DaVinciRequest) => Promise; + resume: (input: { + continueToken: string; + }) => Promise; + start: (options?: StartOptions | undefined) => Promise; + update: (collector: T) => Updater; + validate: (collector: SingleValueCollectors | ObjectValueCollectors | MultiValueCollectors | AutoCollectors) => Validator; + pollStatus: (collector: PollingCollector) => Poller; + getClient: () => { + status: "start"; + } | { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: "error"; + } | { + status: "failure"; + } | { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: "continue"; + } | { + authorization?: { + code?: string; + state?: string; + }; + status: "success"; + } | null; + getCollectors: () => Collectors[]; + getError: () => DaVinciError | null; + getErrorCollectors: () => CollectorErrors[]; + getNode: () => StartNode | ErrorNode | FailureNode | ContinueNode | SuccessNode; + getServer: () => { + status: "start"; + } | { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: "error"; + } | { + _links?: Links; + eventName?: string; + href?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: "failure"; + } | { + _links?: Links; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + eventName?: string; + status: "continue"; + } | { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + session?: string; + status: "success"; + } | null; + cache: { + getLatestResponse: () => ({ + status: QueryStatus.fulfilled; + } & Omit<{ + requestId: string; + data?: unknown; + error?: SerializedError | FetchBaseQueryError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, "data" | "fulfilledTimeStamp"> & Required> & { + error: undefined; + } & { + status: QueryStatus.fulfilled; + isUninitialized: false; + isLoading: false; + isSuccess: true; + isError: false; + }) | ({ + status: QueryStatus.rejected; + } & Omit<{ + requestId: string; + data?: unknown; + error?: SerializedError | FetchBaseQueryError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, "error"> & Required> & { + status: QueryStatus.rejected; + isUninitialized: false; + isLoading: false; + isSuccess: false; + isError: true; + }) | { + error: { + message: string; + type: string; + }; + }; + getResponseWithId: (requestId: string) => ({ + status: QueryStatus.fulfilled; + } & Omit<{ + requestId: string; + data?: unknown; + error?: SerializedError | FetchBaseQueryError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, "data" | "fulfilledTimeStamp"> & Required> & { + error: undefined; + } & { + status: QueryStatus.fulfilled; + isUninitialized: false; + isLoading: false; + isSuccess: true; + isError: false; + }) | ({ + status: QueryStatus.rejected; + } & Omit<{ + requestId: string; + data?: unknown; + error?: SerializedError | FetchBaseQueryError | undefined; + endpointName: string; + startedTimeStamp: number; + fulfilledTimeStamp?: number; + }, "error"> & Required> & { + status: QueryStatus.rejected; + isUninitialized: false; + isLoading: false; + isSuccess: false; + isError: true; + }) | { + error: { + message: string; + type: string; + }; + }; + }; +}>; + +// @public +export interface DaVinciAction { + // (undocumented) + action: string; +} + +// @public +export interface DaVinciBaseResponse { + // (undocumented) + capabilityName?: string; + // (undocumented) + companyId?: string; + // (undocumented) + connectionId?: string; + // (undocumented) + connectorId?: string; + // (undocumented) + id?: string; + // (undocumented) + interactionId?: string; + // (undocumented) + interactionToken?: string; + // (undocumented) + isResponseCompatibleWithMobileAndWebSdks?: boolean; + // (undocumented) + status?: string; +} + +// @public +export type DaVinciCacheEntry = { + data?: DaVinciBaseResponse; + error?: { + data: DaVinciBaseResponse; + status: number; + }; +} & { + data?: any; + error?: any; +} & MutationResultSelectorResult; + +// @public (undocumented) +export type DavinciClient = Awaited>; + +export { DaVinciConfig } + +// @public (undocumented) +export interface DaVinciError extends Omit { + // (undocumented) + collectors?: CollectorErrors[]; + // (undocumented) + internalHttpStatus?: number; + // (undocumented) + message: string; + // (undocumented) + status: 'error' | 'failure' | 'unknown'; +} + +// @public (undocumented) +export interface DaVinciErrorCacheEntry { + // (undocumented) + endpointName: 'next' | 'flow' | 'start'; + // (undocumented) + error: { + data: T; + }; + // (undocumented) + fulfilledTimeStamp: number; + // (undocumented) + isError: boolean; + // (undocumented) + isLoading: boolean; + // (undocumented) + isSuccess: boolean; + // (undocumented) + isUninitialized: boolean; + // (undocumented) + requestId: string; + // (undocumented) + startedTimeStamp: number; + // (undocumented) + status: 'fulfilled' | 'pending' | 'rejected'; +} + +// @public (undocumented) +export interface DavinciErrorResponse extends DaVinciBaseResponse { + // (undocumented) + cause?: string | null; + // (undocumented) + code: string | number; + // (undocumented) + details?: ErrorDetail[]; + // (undocumented) + doNotSendToOE?: boolean; + // (undocumented) + error?: { + code?: string; + message?: string; + }; + // (undocumented) + errorCategory?: string; + // (undocumented) + errorMessage?: string; + // (undocumented) + expected?: boolean; + // (undocumented) + httpResponseCode: number; + // (undocumented) + isErrorCustomized?: boolean; + // (undocumented) + message: string; + // (undocumented) + metricAttributes?: { + [key: string]: unknown; + }; +} + +// @public (undocumented) +export interface DaVinciFailureResponse extends DaVinciBaseResponse { + // (undocumented) + error?: { + code?: string; + message?: string; + [key: string]: unknown; + }; +} + +// @public (undocumented) +export type DaVinciField = ComplexValueFields | MultiValueFields | ReadOnlyFields | RedirectFields | SingleValueFields; + +// @public +export interface DaVinciNextResponse extends DaVinciBaseResponse { + // (undocumented) + eventName?: string; + // (undocumented) + form?: { + name?: string; + description?: string; + components?: { + fields?: DaVinciField[]; + }; + }; + // (undocumented) + formData?: { + value?: { + [key: string]: string; + }; + }; + // (undocumented) + _links?: Links; +} + +// @public +export interface DaVinciPollResponse extends DaVinciBaseResponse { + // (undocumented) + eventName?: string; + // (undocumented) + _links?: Links; + // (undocumented) + success?: boolean; +} + +// @public (undocumented) +export interface DaVinciRequest { + // (undocumented) + eventName: string; + // (undocumented) + id: string; + // (undocumented) + interactionId: string; + // (undocumented) + parameters: { + eventType: 'submit' | 'action' | 'polling'; + data: { + actionKey: string; + formData?: Record; + }; + }; +} + +// @public +export type DaVinciRequestValueTypes = string | number | boolean | (string | number | boolean)[] | DeviceValue | PhoneNumberInputValue | FidoRegistrationInputValue | FidoAuthenticationInputValue | MetadataError | GenericError; + +// @public (undocumented) +export interface DaVinciSuccessResponse extends DaVinciBaseResponse { + // (undocumented) + authorizeResponse?: OAuthDetails; + // (undocumented) + environment: { + id: string; + [key: string]: unknown; + }; + // (undocumented) + _links?: Links; + // (undocumented) + resetCookie?: boolean; + // (undocumented) + session?: { + id?: string; + [key: string]: unknown; + }; + // (undocumented) + sessionToken?: string; + // (undocumented) + sessionTokenMaxAge?: number; + // (undocumented) + status: string; + // (undocumented) + subFlowSettings?: { + cssLinks?: unknown[]; + cssUrl?: unknown; + jsLinks?: unknown[]; + loadingScreenSettings?: unknown; + reactSkUrl?: unknown; + }; + // (undocumented) + success: true; +} + +// @public (undocumented) +export type DeviceAuthenticationCollector = ObjectOptionsCollectorWithObjectValue<'DeviceAuthenticationCollector', DeviceValue>; + +// @public (undocumented) +export type DeviceAuthenticationField = { + type: 'DEVICE_AUTHENTICATION'; + key: string; + label: string; + options: { + type: string; + iconSrc: string; + title: string; + id: string; + default: boolean; + description: string; + }[]; + required: boolean; +}; + +// @public (undocumented) +export interface DeviceOptionNoDefault { + // (undocumented) + content: string; + // (undocumented) + key: string; + // (undocumented) + label: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export interface DeviceOptionWithDefault { + // (undocumented) + content: string; + // (undocumented) + default: boolean; + // (undocumented) + key: string; + // (undocumented) + label: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export type DeviceRegistrationCollector = ObjectOptionsCollectorWithStringValue<'DeviceRegistrationCollector', string>; + +// @public (undocumented) +export type DeviceRegistrationField = { + type: 'DEVICE_REGISTRATION'; + key: string; + label: string; + options: { + type: string; + iconSrc: string; + title: string; + description: string; + }[]; + required: boolean; +}; + +// @public (undocumented) +export interface DeviceValue { + // (undocumented) + id: string; + // (undocumented) + type: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export interface ErrorDetail { + // (undocumented) + message?: string; + // (undocumented) + rawResponse?: { + _embedded?: { + users?: Array; + }; + code?: string; + count?: number; + details?: NestedErrorDetails[]; + id?: string; + message?: string; + size?: number; + userFilter?: string; + [key: string]: unknown; + }; + // (undocumented) + statusCode?: number; +} + +// @public (undocumented) +export interface ErrorNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + action: string; + collectors: Collectors[]; + description?: string; + name?: string; + status: 'error'; + }; + // (undocumented) + error: DaVinciError; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'error'; + } | null; + // (undocumented) + status: 'error'; +} + +// @public (undocumented) +export interface FailureNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + status: 'failure'; + }; + // (undocumented) + error: DaVinciError; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + href?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + status: 'failure'; + } | null; + // (undocumented) + status: 'failure'; +} + +// @public (undocumented) +export type FidoAuthenticationCollector = AutoCollector<'ObjectValueAutoCollector', 'FidoAuthenticationCollector', FidoAuthenticationInputValue | GenericError, FidoAuthenticationOutputValue>; + +// @public (undocumented) +export type FidoAuthenticationField = { + type: 'FIDO2'; + key: string; + label: string; + publicKeyCredentialRequestOptions: FidoAuthenticationOptions; + action: 'AUTHENTICATE'; + trigger: string; + required: boolean; +}; + +// @public (undocumented) +export interface FidoAuthenticationInputValue { + // (undocumented) + assertionValue?: AssertionValue; +} + +// @public (undocumented) +export interface FidoAuthenticationOptions extends Omit { + // (undocumented) + allowCredentials?: { + id: number[]; + transports?: AuthenticatorTransport[]; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + challenge: number[]; +} + +// @public (undocumented) +export interface FidoAuthenticationOutputValue { + // (undocumented) + action: 'AUTHENTICATE'; + // (undocumented) + publicKeyCredentialRequestOptions: FidoAuthenticationOptions; + // (undocumented) + trigger: string; +} + +// @public (undocumented) +export interface FidoClient { + authenticate: (options: FidoAuthenticationOptions) => Promise; + register: (options: FidoRegistrationOptions) => Promise; +} + +// @public +export type FidoErrorCode = 'NotAllowedError' | 'AbortError' | 'InvalidStateError' | 'NotSupportedError' | 'SecurityError' | 'TimeoutError' | 'UnknownError'; + +// @public (undocumented) +export type FidoRegistrationCollector = AutoCollector<'ObjectValueAutoCollector', 'FidoRegistrationCollector', FidoRegistrationInputValue | GenericError, FidoRegistrationOutputValue>; + +// @public (undocumented) +export type FidoRegistrationField = { + type: 'FIDO2'; + key: string; + label: string; + publicKeyCredentialCreationOptions: FidoRegistrationOptions; + action: 'REGISTER'; + trigger: string; + required: boolean; +}; + +// @public (undocumented) +export interface FidoRegistrationInputValue { + // (undocumented) + attestationValue?: AttestationValue; +} + +// @public (undocumented) +export interface FidoRegistrationOptions extends Omit { + // (undocumented) + challenge: number[]; + // (undocumented) + excludeCredentials?: { + id: number[]; + transports?: AuthenticatorTransport[]; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + pubKeyCredParams: { + alg: string | number; + type: PublicKeyCredentialType; + }[]; + // (undocumented) + user: { + id: number[]; + name: string; + displayName: string; + }; +} + +// @public (undocumented) +export interface FidoRegistrationOutputValue { + // (undocumented) + action: 'REGISTER'; + // (undocumented) + publicKeyCredentialCreationOptions: FidoRegistrationOptions; + // (undocumented) + trigger: string; +} + +// @public (undocumented) +export type FlowCollector = ActionCollectorNoUrl<'FlowCollector'>; + +// @public (undocumented) +export type FlowNode = ContinueNode | ErrorNode | StartNode | SuccessNode | FailureNode; + +// @public +export type GetClient = StartNode['client'] | ContinueNode['client'] | ErrorNode['client'] | SuccessNode['client'] | FailureNode['client']; + +// @public (undocumented) +export type IdpCollector = ActionCollectorWithUrl<'IdpCollector'>; + +// @public +export interface ImageCollector extends NoValueCollectorBase<'ImageCollector'> { + // (undocumented) + output: NoValueCollectorBase<'ImageCollector'>['output'] & { + src: string; + alt: string; + href?: string; + }; +} + +// @public (undocumented) +export type ImageField = { + type: 'IMAGE'; + key: string; + description: string; + imageUrl: string; + hyperlinkUrl?: string; +}; + +// @public (undocumented) +export type InferActionCollectorType = T extends 'IdpCollector' ? IdpCollector : T extends 'SubmitCollector' ? SubmitCollector : T extends 'FlowCollector' ? FlowCollector : ActionCollectorWithUrl<'ActionCollector'> | ActionCollectorNoUrl<'ActionCollector'>; + +// @public +export type InferAutoCollectorType = T extends 'ProtectCollector' ? ProtectCollector : T extends 'PollingCollector' ? PollingCollector : T extends 'FidoRegistrationCollector' ? FidoRegistrationCollector : T extends 'FidoAuthenticationCollector' ? FidoAuthenticationCollector : T extends 'MetadataCollector' ? MetadataCollector : T extends 'ObjectValueAutoCollector' ? ObjectValueAutoCollector : SingleValueAutoCollector; + +// @public +export type InferMultiValueCollectorType = T extends 'MultiSelectCollector' ? MultiValueCollectorWithValue<'MultiSelectCollector'> : MultiValueCollectorWithValue<'MultiValueCollector'> | MultiValueCollectorNoValue<'MultiValueCollector'>; + +// @public +export type InferNoValueCollectorType = T extends 'ReadOnlyCollector' ? ReadOnlyCollector : T extends 'RichTextCollector' ? RichTextCollector : T extends 'QrCodeCollector' ? QrCodeCollector : T extends 'ImageCollector' ? ImageCollector : NoValueCollectorBase<'NoValueCollector'>; + +// @public +export type InferSingleValueCollectorType = T extends 'TextCollector' ? TextCollector : T extends 'SingleSelectCollector' ? SingleSelectCollector : T extends 'ValidatedTextCollector' ? ValidatedTextCollector : T extends 'PasswordCollector' ? PasswordCollector : T extends 'ValidatedPasswordCollector' ? ValidatedPasswordCollector : T extends 'BooleanCollector' ? BooleanCollector : T extends 'ValidatedBooleanCollector' ? ValidatedBooleanCollector : SingleValueCollectorWithValue<'SingleValueCollector'> | SingleValueCollectorNoValue<'SingleValueCollector'>; + +// @public (undocumented) +export type InferValueObjectCollectorType = T extends 'DeviceAuthenticationCollector' ? DeviceAuthenticationCollector : T extends 'DeviceRegistrationCollector' ? DeviceRegistrationCollector : T extends 'PhoneNumberCollector' ? PhoneNumberCollector : T extends 'PhoneNumberExtensionCollector' ? PhoneNumberExtensionCollector : ObjectOptionsCollectorWithObjectValue<'ObjectValueCollector'> | ObjectOptionsCollectorWithStringValue<'ObjectValueCollector'>; + +// @public (undocumented) +export type InitFlow = () => Promise; + +// @public (undocumented) +export interface InternalErrorResponse { + // (undocumented) + error: Omit & { + message: string; + }; + // (undocumented) + type: 'internal_error'; +} + +// @public (undocumented) +export interface Links { + // (undocumented) + [key: string]: { + href?: string; + }; +} + +export { LogLevel } + +// @public (undocumented) +export type MetadataCollector = AutoCollector<'ObjectValueAutoCollector', 'MetadataCollector', MetadataCollectorInputValue, Record>; + +// @public (undocumented) +export type MetadataCollectorInputValue = Record | MetadataError; + +// @public +export interface MetadataError { + // (undocumented) + code: string; + // (undocumented) + message: string; +} + +// @public (undocumented) +export type MetadataField = { + type: 'METADATA'; + key: string; + payload: Record; +}; + +// @public (undocumented) +export type MultiSelectCollector = MultiValueCollectorWithValue<'MultiSelectCollector'>; + +// @public (undocumented) +export type MultiSelectField = { + inputType: 'MULTI_SELECT'; + key: string; + label: string; + options: { + label: string; + value: string; + }[]; + required?: boolean; + type: 'CHECKBOX' | 'COMBOBOX'; +}; + +// @public (undocumented) +export type MultiValueCollector = MultiValueCollectorWithValue | MultiValueCollectorNoValue; + +// @public (undocumented) +export interface MultiValueCollectorNoValue { + // (undocumented) + category: 'MultiValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string[]; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type MultiValueCollectors = MultiValueCollectorWithValue<'MultiValueCollector'> | MultiValueCollectorWithValue<'MultiSelectCollector'>; + +// @public +export type MultiValueCollectorTypes = 'MultiSelectCollector' | 'MultiValueCollector'; + +// @public (undocumented) +export interface MultiValueCollectorWithValue { + // (undocumented) + category: 'MultiValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string[]; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: string[]; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type MultiValueFields = MultiSelectField; + +// @public +export interface NestedErrorDetails { + // (undocumented) + code?: string; + // (undocumented) + innerError?: { + history?: string; + unsatisfiedRequirements?: string[]; + failuresRemaining?: number; + }; + // (undocumented) + message?: string; + // (undocumented) + target?: string; +} + +// @public +export const nextCollectorValues: ActionCreatorWithPayload< { +fields: DaVinciField[]; +formData: { +value: Record; +}; +}, string>; + +// @public +export const nodeCollectorReducer: Reducer & { + getInitialState: () => Collectors[]; +}; + +// @public (undocumented) +export type NodeStates = StartNode | ContinueNode | ErrorNode | SuccessNode | FailureNode; + +// @public (undocumented) +export type NoValueCollector = InferNoValueCollectorType; + +// @public (undocumented) +export interface NoValueCollectorBase { + // (undocumented) + category: 'NoValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type NoValueCollectors = NoValueCollectorBase<'NoValueCollector'> | ReadOnlyCollector | RichTextCollector | QrCodeCollector | ImageCollector; + +// @public +export type NoValueCollectorTypes = 'ReadOnlyCollector' | 'RichTextCollector' | 'NoValueCollector' | 'QrCodeCollector' | 'ImageCollector'; + +// @public +export interface OAuthDetails { + // (undocumented) + [key: string]: unknown; + // (undocumented) + code?: string; + // (undocumented) + state?: string; +} + +// @public (undocumented) +export interface ObjectOptionsCollectorWithObjectValue, D = Record> { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: DeviceOptionWithDefault[]; + value?: D | null; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface ObjectOptionsCollectorWithStringValue { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + validation: ValidationRequired[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: DeviceOptionNoDefault[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ObjectValueAutoCollector = AutoCollector<'ObjectValueAutoCollector', 'ObjectValueAutoCollector', Record>; + +// @public (undocumented) +export type ObjectValueAutoCollectorTypes = 'ObjectValueAutoCollector' | 'FidoRegistrationCollector' | 'FidoAuthenticationCollector' | 'MetadataCollector'; + +// @public (undocumented) +export type ObjectValueCollector = ObjectOptionsCollectorWithObjectValue | ObjectOptionsCollectorWithStringValue | ObjectValueCollectorWithObjectValue; + +// @public (undocumented) +export type ObjectValueCollectors = DeviceAuthenticationCollector | DeviceRegistrationCollector | PhoneNumberCollector | PhoneNumberExtensionCollector | ObjectOptionsCollectorWithObjectValue<'ObjectSelectCollector'> | ObjectOptionsCollectorWithStringValue<'ObjectSelectCollector'>; + +// @public +export type ObjectValueCollectorTypes = 'DeviceAuthenticationCollector' | 'DeviceRegistrationCollector' | 'PhoneNumberCollector' | 'PhoneNumberExtensionCollector' | 'ObjectOptionsCollector' | 'ObjectValueCollector' | 'ObjectSelectCollector'; + +// @public (undocumented) +export interface ObjectValueCollectorWithObjectValue, OV = Record> { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: IV; + type: string; + validation: (ValidationRequired | ValidationPhoneNumber)[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value?: OV | null; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface OutgoingQueryParams { + // (undocumented) + [key: string]: string | string[]; +} + +// @public (undocumented) +export interface PasswordCollector { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + verify: boolean; + }; + // (undocumented) + type: 'PasswordCollector'; +} + +// @public +export type PasswordField = { + type: 'PASSWORD' | 'PASSWORD_VERIFY'; + key: string; + label: string; + required?: boolean; + verify?: boolean; + passwordPolicy?: PasswordPolicy; +}; + +// @public +export interface PasswordPolicy { + // (undocumented) + createdAt?: string; + // (undocumented) + default?: boolean; + // (undocumented) + description?: string; + // (undocumented) + excludesCommonlyUsed?: boolean; + // (undocumented) + excludesProfileData?: boolean; + // (undocumented) + history?: { + count?: number; + retentionDays?: number; + }; + // (undocumented) + id?: string; + // (undocumented) + length?: { + min?: number; + max?: number; + }; + // (undocumented) + lockout?: { + failureCount?: number; + durationSeconds?: number; + }; + // (undocumented) + maxAgeDays?: number; + // (undocumented) + maxRepeatedCharacters?: number; + // (undocumented) + minAgeDays?: number; + // (undocumented) + minCharacters?: Record; + // (undocumented) + minUniqueCharacters?: number; + // (undocumented) + name?: string; + // (undocumented) + notSimilarToCurrent?: boolean; + // (undocumented) + populationCount?: number; + // (undocumented) + updatedAt?: string; +} + +// @public (undocumented) +export type PhoneNumberCollector = ObjectValueCollectorWithObjectValue<'PhoneNumberCollector', PhoneNumberInputValue, PhoneNumberOutputValue>; + +// @public (undocumented) +export interface PhoneNumberExtensionCollector { + // (undocumented) + category: 'ObjectValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: PhoneNumberExtensionInputValue; + type: string; + validation: (ValidationRequired | ValidationPhoneNumber)[] | null; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + extensionLabel: string; + value: PhoneNumberExtensionOutputValue; + }; + // (undocumented) + type: 'PhoneNumberExtensionCollector'; +} + +// @public (undocumented) +export type PhoneNumberExtensionField = PhoneNumberField & { + showExtension: boolean; + extensionLabel: string; +}; + +// @public (undocumented) +export interface PhoneNumberExtensionInputValue { + // (undocumented) + countryCode: string; + // (undocumented) + extension: string; + // (undocumented) + phoneNumber: string; +} + +// @public (undocumented) +export interface PhoneNumberExtensionOutputValue { + // (undocumented) + countryCode?: string; + // (undocumented) + extension?: string; + // (undocumented) + phoneNumber?: string; +} + +// @public (undocumented) +export type PhoneNumberField = { + type: 'PHONE_NUMBER'; + key: string; + label: string; + required: boolean; + defaultCountryCode: string | null; + validatePhoneNumber: boolean; +}; + +// @public (undocumented) +export interface PhoneNumberInputValue { + // (undocumented) + countryCode: string; + // (undocumented) + phoneNumber: string; +} + +// @public (undocumented) +export interface PhoneNumberOutputValue { + // (undocumented) + countryCode?: string; + // (undocumented) + phoneNumber?: string; +} + +// @public +export type Poller = () => Promise; + +// @public (undocumented) +export type PollingCollector = AutoCollector<'SingleValueAutoCollector', 'PollingCollector', string, PollingOutputValue>; + +// @public (undocumented) +export type PollingField = { + type: 'POLLING'; + key: string; + pollInterval: number; + pollRetries: number; + pollChallengeStatus?: boolean; + challenge?: string; +}; + +// @public (undocumented) +export interface PollingOutputValue { + // (undocumented) + challenge?: string; + // (undocumented) + pollChallengeStatus?: boolean; + // (undocumented) + pollInterval: number; + // (undocumented) + pollRetries: number; + // (undocumented) + retriesRemaining?: number; +} + +// @public (undocumented) +export type PollingStatus = PollingStatusContinue | PollingStatusChallenge; + +// @public (undocumented) +export type PollingStatusChallenge = PollingStatusChallengeComplete | 'expired' | 'timedOut' | 'error'; + +// @public (undocumented) +export type PollingStatusChallengeComplete = 'approved' | 'denied' | 'continue' | CustomPollingStatus; + +// @public (undocumented) +export type PollingStatusContinue = 'continue' | 'timedOut'; + +// @public (undocumented) +export type ProtectCollector = AutoCollector<'SingleValueAutoCollector', 'ProtectCollector', string, ProtectOutputValue>; + +// @public (undocumented) +export type ProtectField = { + type: 'PROTECT'; + key: string; + behavioralDataCollection: boolean; + universalDeviceIdentification: boolean; +}; + +// @public +export interface ProtectOutputValue { + // (undocumented) + behavioralDataCollection: boolean; + // (undocumented) + universalDeviceIdentification: boolean; +} + +// @public +export interface QrCodeCollector extends NoValueCollectorBase<'QrCodeCollector'> { + // (undocumented) + output: NoValueCollectorBase<'QrCodeCollector'>['output'] & { + src: string; + }; +} + +// @public (undocumented) +export type QrCodeField = { + type: 'QR_CODE'; + key: string; + content: string; + fallbackText?: string; +}; + +// @public +export interface ReadOnlyCollector extends NoValueCollectorBase<'ReadOnlyCollector'> { + // (undocumented) + output: NoValueCollectorBase<'ReadOnlyCollector'>['output'] & { + content: string; + title?: string; + }; +} + +// @public (undocumented) +export type ReadOnlyField = { + type: 'LABEL'; + content: string; + richContent?: RichContent; + key?: string; +}; + +// @public (undocumented) +export type ReadOnlyFields = ReadOnlyField | QrCodeField | AgreementField | ImageField; + +// @public (undocumented) +export type RedirectField = { + type: 'SOCIAL_LOGIN_BUTTON'; + key: string; + label: string; + links: Links; +}; + +// @public (undocumented) +export type RedirectFields = RedirectField; + +export { RequestMiddleware } + +// @public +export type RichContent = { + content: string; + replacements?: Record; +}; + +// @public +export interface RichContentLink { + // (undocumented) + href: string; + // (undocumented) + key: string; + // (undocumented) + target?: '_self' | '_blank'; + // (undocumented) + type: 'link'; + // (undocumented) + value: string; +} + +// @public +export type RichContentReplacement = { + type: 'link'; + value: string; + href: string; + target?: '_self' | '_blank'; +}; + +// @public +export interface RichTextCollector extends NoValueCollectorBase<'RichTextCollector'> { + // (undocumented) + output: NoValueCollectorBase<'RichTextCollector'>['output'] & { + content: string; + richContent: CollectorRichContent; + }; +} + +// @public (undocumented) +export interface SelectorOption { + // (undocumented) + label: string; + // (undocumented) + value: string; +} + +// @public (undocumented) +export type SingleCheckboxField = { + type: 'SINGLE_CHECKBOX'; + inputType: 'BOOLEAN'; + key: string; + label: string; + required?: boolean; + errorMessage?: string; + appearance: string; + richContent?: RichContent; +}; + +// @public (undocumented) +export type SingleSelectCollector = SingleSelectCollectorWithValue<'SingleSelectCollector'>; + +// @public (undocumented) +export interface SingleSelectCollectorNoValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface SingleSelectCollectorWithValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: string | number | boolean; + options: SelectorOption[]; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleSelectField = { + inputType: 'SINGLE_SELECT'; + key: string; + label: string; + options: { + label: string; + value: string; + }[]; + required?: boolean; + type: 'RADIO' | 'DROPDOWN'; +}; + +// @public (undocumented) +export type SingleValueAutoCollector = AutoCollector<'SingleValueAutoCollector', 'SingleValueAutoCollector', string>; + +// @public (undocumented) +export type SingleValueAutoCollectorTypes = 'SingleValueAutoCollector' | 'ProtectCollector' | 'PollingCollector'; + +// @public +export type SingleValueCollector = SingleValueCollectorWithValue | SingleValueCollectorNoValue; + +// @public (undocumented) +export interface SingleValueCollectorNoValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleValueCollectors = PasswordCollector | ValidatedPasswordCollector | SingleSelectCollector | TextCollector | ValidatedTextCollector | BooleanCollector | ValidatedBooleanCollector | SingleValueCollectorWithValue<'SingleValueCollector'>; + +// @public +export type SingleValueCollectorTypes = 'PasswordCollector' | 'ValidatedPasswordCollector' | 'BooleanCollector' | 'ValidatedBooleanCollector' | 'SingleValueCollector' | 'SingleSelectCollector' | 'SingleSelectObjectCollector' | 'TextCollector' | 'ValidatedTextCollector'; + +// @public (undocumented) +export interface SingleValueCollectorWithValue { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: V; + type: string; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: V; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type SingleValueFields = StandardField | PasswordField | ValidatedField | SingleCheckboxField | SingleSelectField | ProtectField; + +// @public (undocumented) +export type StandardField = { + type: 'TEXT' | 'SUBMIT_BUTTON' | 'FLOW_BUTTON' | 'FLOW_LINK' | 'BUTTON'; + key: string; + label: string; + required?: boolean; +}; + +// @public (undocumented) +export interface StartNode { + // (undocumented) + cache: null; + // (undocumented) + client: { + status: 'start'; + }; + // (undocumented) + error: DaVinciError | null; + // (undocumented) + server: { + status: 'start'; + }; + // (undocumented) + status: 'start'; +} + +// @public (undocumented) +export interface StartOptions { + // (undocumented) + query: Query; +} + +// @public (undocumented) +export type SubmitCollector = ActionCollectorNoUrl<'SubmitCollector'>; + +// @public (undocumented) +export interface SuccessNode { + // (undocumented) + cache: { + key: string; + }; + // (undocumented) + client: { + authorization?: { + code?: string; + state?: string; + }; + status: 'success'; + } | null; + // (undocumented) + error: null; + // (undocumented) + httpStatus: number; + // (undocumented) + server: { + _links?: Links; + eventName?: string; + id?: string; + interactionId?: string; + interactionToken?: string; + href?: string; + session?: string; + status: 'success'; + }; + // (undocumented) + status: 'success'; +} + +// @public (undocumented) +export type TextCollector = SingleValueCollectorWithValue<'TextCollector'>; + +// @public (undocumented) +export interface ThrownQueryError { + // (undocumented) + error: FetchBaseQueryError; + // (undocumented) + isHandledError: boolean; + // (undocumented) + meta: FetchBaseQueryMeta; +} + +// @public +export type UnknownCollector = { + category: 'UnknownCollector'; + error: string | null; + type: 'UnknownCollector'; + id: string; + name: string; + output: { + key: string; + label: string; + type: string; + }; +}; + +// @public (undocumented) +export type UnknownField = Record; + +// @public +export type UpdatableCollectors = SingleValueCollectors | MultiSelectCollector | ObjectValueCollectors | AutoCollectors; + +// @public (undocumented) +export const updateCollectorValues: ActionCreatorWithPayload< { +id: string; +value: CollectorValueTypes; +index?: number; +}, string>; + +// @public +export type Updater = (value: CollectorValueType, index?: number) => InternalErrorResponse | null; + +// @public (undocumented) +export interface ValidatedBooleanCollector extends ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean> { + // (undocumented) + output: ValidatedSingleValueCollectorWithValue<'ValidatedBooleanCollector', boolean>['output'] & { + appearance: string; + richContent?: CollectorRichContent; + }; +} + +// @public +export type ValidatedCollectors = ValidatedTextCollector | ValidatedBooleanCollector | ValidatedPasswordCollector | ObjectValueCollectors | MultiValueCollectors | AutoCollectors; + +// @public (undocumented) +export type ValidatedField = { + type: 'TEXT'; + key: string; + label: string; + required: boolean; + validation: { + regex: string; + errorMessage: string; + }; +}; + +// @public (undocumented) +export interface ValidatedPasswordCollector { + // (undocumented) + category: 'SingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + value: string | number | boolean; + type: string; + validation: PasswordPolicy; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + verify: boolean; + }; + // (undocumented) + type: 'ValidatedPasswordCollector'; +} + +// @public (undocumented) +export interface ValidatedSingleValueCollectorWithValue { + // (undocumented) + category: 'ValidatedSingleValueCollector'; + // (undocumented) + error: string | null; + // (undocumented) + id: string; + // (undocumented) + input: { + key: string; + type: string; + validation: (ValidationRequired | ValidationRegex)[]; + value: V; + }; + // (undocumented) + name: string; + // (undocumented) + output: { + key: string; + label: string; + type: string; + value: V; + }; + // (undocumented) + type: T; +} + +// @public (undocumented) +export type ValidatedTextCollector = ValidatedSingleValueCollectorWithValue<'TextCollector'>; + +// @public (undocumented) +export interface ValidationPhoneNumber { + // (undocumented) + message: string; + // (undocumented) + rule: boolean; + // (undocumented) + type: 'validatePhoneNumber'; +} + +// @public (undocumented) +export interface ValidationRegex { + // (undocumented) + message: string; + // (undocumented) + rule: string; + // (undocumented) + type: 'regex'; +} + +// @public (undocumented) +export interface ValidationRequired { + // (undocumented) + message: string; + // (undocumented) + rule: boolean; + // (undocumented) + type: 'required'; +} + +// @public +export type Validator = (value: CollectorValueType) => string[] | { + error: { + message: string; + type: string; + }; + type: string; +}; + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/davinci-client/src/lib/client.store.utils.ts b/packages/davinci-client/src/lib/client.store.utils.ts index c595834b9a..5d30fe7f04 100644 --- a/packages/davinci-client/src/lib/client.store.utils.ts +++ b/packages/davinci-client/src/lib/client.store.utils.ts @@ -5,26 +5,13 @@ * of the MIT license. See the LICENSE file for details. */ import { combineSlices, configureStore, createDynamicMiddleware } from '@reduxjs/toolkit'; -import { Match, Result } from 'effect'; import type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; import type { logger as loggerFn } from '@forgerock/sdk-logger'; import type { GenericError } from '@forgerock/sdk-types'; -import type { - ErrorNode, - ContinueNode, - StartNode, - SuccessNode, - Collectors, - CollectorCategory, -} from './node.types.js'; -import type { - CollectorValueType, - CollectorValueTypes, - InternalErrorResponse, - UpdatableCollectors, -} from './client.types.js'; +import type { ErrorNode, ContinueNode, StartNode, SuccessNode } from './node.types.js'; +import type { InternalErrorResponse } from './client.types.js'; import { configSlice } from './config.slice.js'; import { nodeSlice } from './node.slice.js'; @@ -144,137 +131,7 @@ export function isInternalError(value: unknown): value is InternalErrorResponse ); } -/** - * Type guard: checks whether a collector's `category` is one of the given - * `validCategories`, narrowing it to the matching union member on success. - * - * @param collector - The collector to check - * @param validCategories - The set of categories considered valid - * @returns `true` if `collector.category` is included in `validCategories` - */ -export function isValidCollectorCategory( - collector: Collectors, - validCategories: C[], -): collector is Extract { - return validCategories.some((validCategory) => collector.category === validCategory); -} - -/** - * Validates a value against the shape a given collector accepts, returning the - * value narrowed to `CollectorValueType` on success. - * - * This is the single source of truth for the collector→value-type correlation: - * both `update()` (pre-dispatch, to fail fast) and the `node/update` reducer - * (post-dispatch, to type the assignment) call this same function so the - * mapping can't drift between the two call sites. - * - * @param collector - The collector the value is being validated against - * @param value - The candidate value to validate - * @returns `Result.succeed` with the narrowed value, or `Result.fail` with the validation error - */ -export function resolveCollectorUpdateValue( - collector: T, - value: CollectorValueTypes, -): Result.Result, InternalErrorResponse> { - const ok = (v: CollectorValueTypes) => Result.succeed(v as CollectorValueType); - const err = (message: string) => Result.fail(createInternalError(message, 'argument_error')); - - if (value === undefined) { - return err('Value argument cannot be undefined'); - } - - return Match.value(collector).pipe( - Match.when({ type: 'BooleanCollector' }, () => - typeof value === 'boolean' ? ok(value) : err('Value argument must be a boolean'), - ), - Match.when({ type: 'ValidatedBooleanCollector' }, () => - typeof value === 'boolean' ? ok(value) : err('Value argument must be a boolean'), - ), - Match.when({ type: 'DeviceAuthenticationCollector' }, (c) => { - if (typeof value !== 'string') return err('Value argument must be a string'); - const option = c.output.options.find((option) => option.value === value); - return option ? ok(value) : err('No option found matching value to update'); - }), - Match.when({ type: 'DeviceRegistrationCollector' }, (c) => { - if (typeof value !== 'string') return err('Value argument must be a string'); - const option = c.output.options.find((option) => option.value === value); - return option ? ok(value) : err('No option found matching value to update'); - }), - Match.when({ type: 'PhoneNumberCollector' }, () => { - if (typeof value !== 'object' || value === null || Array.isArray(value)) { - return err('Value argument must be an object'); - } - if (!('phoneNumber' in value) || !('countryCode' in value)) { - return err('Value argument must contain a phoneNumber and countryCode property'); - } - return ok(value); - }), - Match.when({ type: 'PhoneNumberExtensionCollector' }, () => { - if (typeof value !== 'object' || value === null || Array.isArray(value)) { - return err('Value argument must be an object'); - } - if (!('phoneNumber' in value) || !('countryCode' in value) || !('extension' in value)) { - return err( - 'Value argument must contain a phoneNumber, countryCode, and extension property', - ); - } - return ok(value); - }), - Match.when({ type: 'FidoRegistrationCollector' }, () => { - if (typeof value !== 'object' || value === null || Array.isArray(value)) { - return err('Value argument must be an object'); - } - const isFidoError = 'type' in value && value.type === 'fido_error'; - if (!isFidoError && !('attestationValue' in value)) { - return err('Value argument must contain an attestationValue property'); - } - return ok(value); - }), - Match.when({ type: 'FidoAuthenticationCollector' }, () => { - if (typeof value !== 'object' || value === null || Array.isArray(value)) { - return err('Value argument must be an object'); - } - const isFidoError = 'type' in value && value.type === 'fido_error'; - if (!isFidoError && !('assertionValue' in value)) { - return err('Value argument must contain an assertionValue property'); - } - return ok(value); - }), - Match.when({ type: 'MetadataCollector' }, () => { - if (typeof value !== 'object' || value === null || Array.isArray(value)) { - return err('Value argument must be an object'); - } - return ok(value); - }), - Match.when({ category: 'SingleValueCollector' }, () => - typeof value === 'string' ? ok(value) : err('Value argument must be a string'), - ), - Match.when({ category: 'ValidatedSingleValueCollector' }, () => - typeof value === 'string' ? ok(value) : err('Value argument must be a string'), - ), - Match.when({ category: 'SingleValueAutoCollector' }, () => - typeof value === 'string' ? ok(value) : err('Value argument must be a string'), - ), - Match.when({ category: 'MultiValueCollector' }, () => - typeof value === 'string' || Array.isArray(value) - ? ok(value) - : err('MultiValueCollector does not accept an object'), - ), - Match.when({ category: 'ObjectValueCollector' }, () => { - if (typeof value !== 'object' || value === null || Array.isArray(value)) { - return err('Value argument must be an object'); - } - return ok(value); - }), - Match.when({ category: 'ObjectValueAutoCollector' }, () => { - if (typeof value !== 'object' || value === null || Array.isArray(value)) { - return err('Value argument must be an object'); - } - return ok(value); - }), - Match.exhaustive, - ); -} +export { isValidCollectorCategory, resolveCollectorUpdateValue } from './collector.resolver.js'; /** Cast InjectableStore to the opaque SdkStore for public API exposure. */ export function toSdkStore(injectable: InjectableStore): object { diff --git a/packages/davinci-client/src/lib/collector.resolver.ts b/packages/davinci-client/src/lib/collector.resolver.ts new file mode 100644 index 0000000000..10e5c8252e --- /dev/null +++ b/packages/davinci-client/src/lib/collector.resolver.ts @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2025 - 2026 Ping Identity Corporation. All rights reserved. + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +/** + * Pure resolver functions for collector value validation. + * + * Extracted from client.store.utils.ts into its own module to break the + * circular import chain: + * + * node.slice.ts → node.reducer.ts → client.store.utils.ts → nodeSlice (node.slice.ts) + * + * By living here, node.reducer.ts can import these functions without touching + * client.store.utils.ts (which imports nodeSlice). client.store.utils.ts + * re-exports from this file to preserve its public API. + */ +import { Match, Result } from 'effect'; + +import type { CollectorCategory, Collectors } from './node.types.js'; +import type { + CollectorValueType, + CollectorValueTypes, + InternalErrorResponse, + UpdatableCollectors, +} from './client.types.js'; + +import type { GenericError } from '@forgerock/sdk-types'; + +/** Locally-inlined copy of createInternalError to avoid importing from client.store.utils.ts, + * which imports nodeSlice (node.slice.ts) and would recreate the circular dependency. + */ +function createInternalError( + message: string, + type: GenericError['type'] = 'internal_error', +): InternalErrorResponse { + return { error: { message, type }, type: 'internal_error' }; +} + +/** + * Type guard: checks whether a collector's `category` is one of the given + * `validCategories`, narrowing it to the matching union member on success. + * + * @param collector - The collector to check + * @param validCategories - The set of categories considered valid + * @returns `true` if `collector.category` is included in `validCategories` + */ +export function isValidCollectorCategory( + collector: Collectors, + validCategories: C[], +): collector is Extract { + return validCategories.some((validCategory) => collector.category === validCategory); +} + +/** + * Validates a value against the shape a given collector accepts, returning the + * value narrowed to `CollectorValueType` on success. + * + * This is the single source of truth for the collector→value-type correlation: + * both `update()` (pre-dispatch, to fail fast) and the `node/update` reducer + * (post-dispatch, to type the assignment) call this same function so the + * mapping can't drift between the two call sites. + * + * @param collector - The collector the value is being validated against + * @param value - The candidate value to validate + * @returns `Result.succeed` with the narrowed value, or `Result.fail` with the validation error + */ +export function resolveCollectorUpdateValue( + collector: T, + value: CollectorValueTypes, +): Result.Result, InternalErrorResponse> { + const ok = (v: CollectorValueTypes) => Result.succeed(v as CollectorValueType); + const err = (message: string) => Result.fail(createInternalError(message, 'argument_error')); + + if (value === undefined) { + return err('Value argument cannot be undefined'); + } + + return Match.value(collector).pipe( + Match.when({ type: 'BooleanCollector' }, () => + typeof value === 'boolean' ? ok(value) : err('Value argument must be a boolean'), + ), + Match.when({ type: 'ValidatedBooleanCollector' }, () => + typeof value === 'boolean' ? ok(value) : err('Value argument must be a boolean'), + ), + Match.when({ type: 'DeviceAuthenticationCollector' }, (c) => { + if (typeof value !== 'string') return err('Value argument must be a string'); + const option = c.output.options.find((option) => option.value === value); + return option ? ok(value) : err('No option found matching value to update'); + }), + Match.when({ type: 'DeviceRegistrationCollector' }, (c) => { + if (typeof value !== 'string') return err('Value argument must be a string'); + const option = c.output.options.find((option) => option.value === value); + return option ? ok(value) : err('No option found matching value to update'); + }), + Match.when({ type: 'PhoneNumberCollector' }, () => { + if (typeof value !== 'object' || value === null || Array.isArray(value)) { + return err('Value argument must be an object'); + } + if (!('phoneNumber' in value) || !('countryCode' in value)) { + return err('Value argument must contain a phoneNumber and countryCode property'); + } + return ok(value); + }), + Match.when({ type: 'PhoneNumberExtensionCollector' }, () => { + if (typeof value !== 'object' || value === null || Array.isArray(value)) { + return err('Value argument must be an object'); + } + if (!('phoneNumber' in value) || !('countryCode' in value) || !('extension' in value)) { + return err( + 'Value argument must contain a phoneNumber, countryCode, and extension property', + ); + } + return ok(value); + }), + Match.when({ type: 'FidoRegistrationCollector' }, () => { + if (typeof value !== 'object' || value === null || Array.isArray(value)) { + return err('Value argument must be an object'); + } + const isFidoError = 'type' in value && value.type === 'fido_error'; + if (!isFidoError && !('attestationValue' in value)) { + return err('Value argument must contain an attestationValue property'); + } + return ok(value); + }), + Match.when({ type: 'FidoAuthenticationCollector' }, () => { + if (typeof value !== 'object' || value === null || Array.isArray(value)) { + return err('Value argument must be an object'); + } + const isFidoError = 'type' in value && value.type === 'fido_error'; + if (!isFidoError && !('assertionValue' in value)) { + return err('Value argument must contain an assertionValue property'); + } + return ok(value); + }), + Match.when({ type: 'MetadataCollector' }, () => { + if (typeof value !== 'object' || value === null || Array.isArray(value)) { + return err('Value argument must be an object'); + } + return ok(value); + }), + Match.when({ category: 'SingleValueCollector' }, () => + typeof value === 'string' ? ok(value) : err('Value argument must be a string'), + ), + Match.when({ category: 'ValidatedSingleValueCollector' }, () => + typeof value === 'string' ? ok(value) : err('Value argument must be a string'), + ), + Match.when({ category: 'SingleValueAutoCollector' }, () => + typeof value === 'string' ? ok(value) : err('Value argument must be a string'), + ), + Match.when({ category: 'MultiValueCollector' }, () => + typeof value === 'string' || Array.isArray(value) + ? ok(value) + : err('MultiValueCollector does not accept an object'), + ), + Match.when({ category: 'ObjectValueCollector' }, () => { + if (typeof value !== 'object' || value === null || Array.isArray(value)) { + return err('Value argument must be an object'); + } + return ok(value); + }), + Match.when({ category: 'ObjectValueAutoCollector' }, () => { + if (typeof value !== 'object' || value === null || Array.isArray(value)) { + return err('Value argument must be an object'); + } + return ok(value); + }), + Match.exhaustive, + ); +} diff --git a/packages/davinci-client/src/lib/node.reducer.ts b/packages/davinci-client/src/lib/node.reducer.ts index 73b0e0e75f..e2822b89c7 100644 --- a/packages/davinci-client/src/lib/node.reducer.ts +++ b/packages/davinci-client/src/lib/node.reducer.ts @@ -37,7 +37,7 @@ import { returnQrCodeCollector, returnImageCollector, } from './collector.utils.js'; -import { resolveCollectorUpdateValue } from './client.store.utils.js'; +import { resolveCollectorUpdateValue } from './collector.resolver.js'; import type { DaVinciField, UnknownField } from './davinci.types.js'; import type { PhoneNumberOutputValue, PhoneNumberExtensionOutputValue } from './collector.types.js'; import type { diff --git a/packages/journey-client/api-report/journey-client.api.md b/packages/journey-client/api-report/journey-client.api.md index 173e3a38be..88ee56f6fb 100644 --- a/packages/journey-client/api-report/journey-client.api.md +++ b/packages/journey-client/api-report/journey-client.api.md @@ -1,504 +1,503 @@ -## API Report File for "@forgerock/journey-client" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { ActionTypes } from '@forgerock/sdk-request-middleware'; -import { AuthResponse } from '@forgerock/sdk-types'; -import { Callback } from '@forgerock/sdk-types'; -import { CallbackType } from '@forgerock/sdk-types'; -import { callbackType } from '@forgerock/sdk-types'; -import { createWellknownError } from '@forgerock/sdk-utilities'; -import { CustomLogger } from '@forgerock/sdk-logger'; -import { FailedPolicyRequirement } from '@forgerock/sdk-types'; -import { FailureDetail } from '@forgerock/sdk-types'; -import { GenericError } from '@forgerock/sdk-types'; -import { isValidWellknownUrl } from '@forgerock/sdk-utilities'; -import { JourneyClientConfig } from '@forgerock/sdk-types'; -import { JourneyServerConfig } from '@forgerock/sdk-types'; -import { LogLevel } from '@forgerock/sdk-logger'; -import { NameValue } from '@forgerock/sdk-types'; -import { PolicyKey } from '@forgerock/sdk-types'; -import { PolicyParams } from '@forgerock/sdk-types'; -import { PolicyRequirement } from '@forgerock/sdk-types'; -import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; -import type { SdkStore } from '@forgerock/sdk-types'; -import { Step } from '@forgerock/sdk-types'; -import { StepDetail } from '@forgerock/sdk-types'; -import { StepType } from '@forgerock/sdk-types'; -import { WellknownResponse } from '@forgerock/sdk-types'; - -export { ActionTypes }; - -// @public -export class AttributeInputCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getName(): string; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setValidateOnly(value: boolean): void; - setValue(value: T): void; -} - -export { AuthResponse }; - -// @public -export class BaseCallback { - constructor(payload: Callback); - getInputValue(selector?: number | string): unknown; - getOutputByName(name: string, defaultValue: T): T; - getOutputValue(selector?: number | string): unknown; - getType(): CallbackType; - // (undocumented) - payload: Callback; - setInputValue(value: unknown, selector?: number | string | RegExp): void; -} - -export { Callback }; - -// @public (undocumented) -export type CallbackFactory = (callback: Callback) => BaseCallback; - -export { CallbackType }; - -export { callbackType }; - -// @public -export class ChoiceCallback extends BaseCallback { - constructor(payload: Callback); - getChoices(): string[]; - getDefaultChoice(): number; - getPrompt(): string; - // (undocumented) - payload: Callback; - setChoiceIndex(index: number): void; - setChoiceValue(value: string): void; -} - -// @public -export class ConfirmationCallback extends BaseCallback { - constructor(payload: Callback); - getDefaultOption(): number; - getMessageType(): number; - getOptions(): string[]; - getOptionType(): number; - getPrompt(): string; - // (undocumented) - payload: Callback; - setOptionIndex(index: number): void; - setOptionValue(value: string): void; -} - -// @public (undocumented) -export function createCallback(callback: Callback): BaseCallback; - -export { createWellknownError }; - -export { CustomLogger }; - -// @public -export class DeviceProfileCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - isLocationRequired(): boolean; - isMetadataRequired(): boolean; - // (undocumented) - payload: Callback; - setProfile(profile: DeviceProfileData): void; -} - -// @public (undocumented) -export interface DeviceProfileData { - // (undocumented) - identifier: string; - // (undocumented) - location?: Geolocation_2 | Record; - // (undocumented) - metadata?: { - hardware: { - display: { - [key: string]: string | number | null; - }; - [key: string]: any; - }; - browser: { - [key: string]: string | number | null; - }; - platform: { - [key: string]: string | number | null; - }; - }; -} - -export { FailedPolicyRequirement }; - -export { FailureDetail }; - -export { GenericError }; - -// @public (undocumented) -interface Geolocation_2 { - // (undocumented) - latitude: number; - // (undocumented) - longitude: number; -} -export { Geolocation_2 as Geolocation }; - -// @public -export class HiddenValueCallback extends BaseCallback { - constructor(payload: Callback); - // (undocumented) - payload: Callback; -} - -// @public (undocumented) -export interface IdPValue { - // (undocumented) - provider: string; - // (undocumented) - uiConfig: { - [key: string]: string; - }; -} - -// @internal -export interface InternalJourneyClientConfig { - // (undocumented) - error?: GenericError; - // (undocumented) - serverConfig: ResolvedServerConfig; -} - -export { isValidWellknownUrl }; - -// @public -export function journey(input: { - config: JourneyClientConfig; - requestMiddleware?: RequestMiddleware[]; - logger?: { - level: LogLevel; - custom?: CustomLogger; - }; -}): Promise; - -// @public -export interface JourneyClient { - // (undocumented) - next: (step: JourneyStep, options?: NextOptions) => Promise; - // (undocumented) - redirect: (step: JourneyStep) => Promise; - // (undocumented) - resume: (url: string, options?: ResumeOptions) => Promise; - // (undocumented) - start: (options?: StartParam) => Promise; - // (undocumented) - store: SdkStore; - // (undocumented) - subscribe: (listener: () => void) => () => void; - // (undocumented) - terminate: (options?: { query?: Record }) => Promise; -} - -export { JourneyClientConfig }; - -// @public (undocumented) -export type JourneyLoginFailure = AuthResponse & { - type: StepType.LoginFailure; - payload: Step; - getCode: () => number; - getDetail: () => FailureDetail | undefined; - getMessage: () => string | undefined; - getProcessedMessage: (messageCreator?: MessageCreator) => ProcessedPropertyError[]; - getReason: () => string | undefined; -}; - -// @public (undocumented) -export type JourneyLoginSuccess = AuthResponse & { - type: StepType.LoginSuccess; - payload: Step; - getRealm: () => string | undefined; - getSessionToken: () => string | undefined; - getSuccessUrl: () => string | undefined; -}; - -// @public (undocumented) -export type JourneyResult = JourneyStep | JourneyLoginSuccess | JourneyLoginFailure | GenericError; - -export { JourneyServerConfig }; - -// @public (undocumented) -export type JourneyStep = AuthResponse & { - type: StepType.Step; - payload: Step; - callbacks: BaseCallback[]; - getCallbackOfType: (type: CallbackType) => T; - getCallbacksOfType: (type: CallbackType) => T[]; - setCallbackValue: (type: CallbackType, value: unknown) => void; - getDescription: () => string | undefined; - getHeader: () => string | undefined; - getStage: () => string | undefined; -}; - -// @public -export class KbaCreateCallback extends BaseCallback { - constructor(payload: Callback); - getPredefinedQuestions(): string[]; - getPrompt(): string; - isAllowedUserDefinedQuestions(): boolean; - // (undocumented) - payload: Callback; - setAnswer(answer: string): void; - setQuestion(question: string): void; -} - -export { LogLevel }; - -// @public (undocumented) -export interface MessageCreator { - // (undocumented) - [key: string]: ( - propertyName: string, - params?: { - [key: string]: unknown; - }, - ) => string; -} - -// @public -export class MetadataCallback extends BaseCallback { - constructor(payload: Callback); - getData(): T; - // (undocumented) - payload: Callback; -} - -// @public -export class NameCallback extends BaseCallback { - constructor(payload: Callback); - getPrompt(): string; - // (undocumented) - payload: Callback; - setName(name: string): void; -} - -export { NameValue }; - -// @public (undocumented) -export interface NextOptions { - // (undocumented) - query?: Record; -} - -// @public -export class PasswordCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): string[]; - getPrompt(): string; - // (undocumented) - payload: Callback; - setPassword(password: string): void; -} - -// @public -export class PingOneProtectEvaluationCallback extends BaseCallback { - constructor(payload: Callback); - getPauseBehavioralData(): boolean; - // (undocumented) - payload: Callback; - setClientError(errorMessage: string): void; - setData(data: string): void; -} - -// @public -export class PingOneProtectInitializeCallback extends BaseCallback { - constructor(payload: Callback); - getConfig(): - | Record - | { - envId: string; - consoleLogEnabled: boolean; - deviceAttributesToIgnore: string[]; - customHost: string; - lazyMetadata: boolean; - behavioralDataCollection: boolean; - deviceKeyRsyncIntervals: number; - enableTrust: boolean; - disableTags: boolean; - disableHub: boolean; - }; - // (undocumented) - payload: Callback; - // (undocumented) - setClientError(errorMessage: string): void; -} - -export { PolicyKey }; - -export { PolicyParams }; - -export { PolicyRequirement }; - -// @public -export class PollingWaitCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - getWaitTime(): number; - // (undocumented) - payload: Callback; -} - -// @public (undocumented) -export interface ProcessedPropertyError { - // (undocumented) - detail: FailedPolicyRequirement; - // (undocumented) - messages: string[]; -} - -// @public -export class ReCaptchaCallback extends BaseCallback { - constructor(payload: Callback); - getSiteKey(): string; - // (undocumented) - payload: Callback; - setResult(result: string): void; -} - -// @public -export class ReCaptchaEnterpriseCallback extends BaseCallback { - constructor(payload: Callback); - getApiUrl(): string; - getElementClass(): string; - getSiteKey(): string; - // (undocumented) - payload: Callback; - setAction(action: string): void; - setClientError(error: string): void; - setPayload(payload: unknown): void; - setResult(result: string): void; -} - -// @public -export class RedirectCallback extends BaseCallback { - constructor(payload: Callback); - getRedirectUrl(): string; - // (undocumented) - payload: Callback; -} - -export { RequestMiddleware }; - -// @public -export interface ResolvedServerConfig { - // (undocumented) - baseUrl: string; - // (undocumented) - paths: { - authenticate: string; - sessions: string; - }; -} - -// @public (undocumented) -export interface ResumeOptions { - // (undocumented) - journey?: string; - // (undocumented) - query?: Record; -} - -// @public -export class SelectIdPCallback extends BaseCallback { - constructor(payload: Callback); - getProviders(): IdPValue[]; - // (undocumented) - payload: Callback; - setProvider(value: string): void; -} - -// @public (undocumented) -export interface StartParam { - // (undocumented) - journey: string; - // (undocumented) - query?: Record; -} - -export { Step }; - -export { StepDetail }; - -export { StepType }; - -// @public -export class SuspendedTextOutputCallback extends TextOutputCallback { - constructor(payload: Callback); - // (undocumented) - payload: Callback; -} - -// @public -export class TermsAndConditionsCallback extends BaseCallback { - constructor(payload: Callback); - getCreateDate(): Date | null; - getTerms(): string; - getVersion(): string; - // (undocumented) - payload: Callback; - setAccepted(accepted?: boolean): void; -} - -// @public -export class TextInputCallback extends BaseCallback { - constructor(payload: Callback); - getPrompt(): string; - // (undocumented) - payload: Callback; - setInput(input: string): void; -} - -// @public -export class TextOutputCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - getMessageType(): string; - // (undocumented) - payload: Callback; -} - -// @public -export class ValidatedCreatePasswordCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setPassword(password: string): void; - setValidateOnly(value: boolean): void; -} - -// @public -export class ValidatedCreateUsernameCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setName(name: string): void; - setValidateOnly(value: boolean): void; -} - -export { WellknownResponse }; - -// (No @packageDocumentation comment for this package) -``` +## API Report File for "@forgerock/journey-client" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { ActionTypes } from '@forgerock/sdk-request-middleware'; +import { AuthResponse } from '@forgerock/sdk-types'; +import { Callback } from '@forgerock/sdk-types'; +import { CallbackType } from '@forgerock/sdk-types'; +import { callbackType } from '@forgerock/sdk-types'; +import { createWellknownError } from '@forgerock/sdk-utilities'; +import { CustomLogger } from '@forgerock/sdk-logger'; +import { FailedPolicyRequirement } from '@forgerock/sdk-types'; +import { FailureDetail } from '@forgerock/sdk-types'; +import { GenericError } from '@forgerock/sdk-types'; +import { isValidWellknownUrl } from '@forgerock/sdk-utilities'; +import { JourneyClientConfig } from '@forgerock/sdk-types'; +import { JourneyServerConfig } from '@forgerock/sdk-types'; +import { LogLevel } from '@forgerock/sdk-logger'; +import { NameValue } from '@forgerock/sdk-types'; +import { PolicyKey } from '@forgerock/sdk-types'; +import { PolicyParams } from '@forgerock/sdk-types'; +import { PolicyRequirement } from '@forgerock/sdk-types'; +import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; +import type { SdkStore } from '@forgerock/sdk-types'; +import { Step } from '@forgerock/sdk-types'; +import { StepDetail } from '@forgerock/sdk-types'; +import { StepType } from '@forgerock/sdk-types'; +import { WellknownResponse } from '@forgerock/sdk-types'; + +export { ActionTypes } + +// @public +export class AttributeInputCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getName(): string; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setValidateOnly(value: boolean): void; + setValue(value: T): void; +} + +export { AuthResponse } + +// @public +export class BaseCallback { + constructor(payload: Callback); + getInputValue(selector?: number | string): unknown; + getOutputByName(name: string, defaultValue: T): T; + getOutputValue(selector?: number | string): unknown; + getType(): CallbackType; + // (undocumented) + payload: Callback; + setInputValue(value: unknown, selector?: number | string | RegExp): void; +} + +export { Callback } + +// @public (undocumented) +export type CallbackFactory = (callback: Callback) => BaseCallback; + +export { CallbackType } + +export { callbackType } + +// @public +export class ChoiceCallback extends BaseCallback { + constructor(payload: Callback); + getChoices(): string[]; + getDefaultChoice(): number; + getPrompt(): string; + // (undocumented) + payload: Callback; + setChoiceIndex(index: number): void; + setChoiceValue(value: string): void; +} + +// @public +export class ConfirmationCallback extends BaseCallback { + constructor(payload: Callback); + getDefaultOption(): number; + getMessageType(): number; + getOptions(): string[]; + getOptionType(): number; + getPrompt(): string; + // (undocumented) + payload: Callback; + setOptionIndex(index: number): void; + setOptionValue(value: string): void; +} + +// @public (undocumented) +export function createCallback(callback: Callback): BaseCallback; + +export { createWellknownError } + +export { CustomLogger } + +// @public +export class DeviceProfileCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + isLocationRequired(): boolean; + isMetadataRequired(): boolean; + // (undocumented) + payload: Callback; + setProfile(profile: DeviceProfileData): void; +} + +// @public (undocumented) +export interface DeviceProfileData { + // (undocumented) + identifier: string; + // (undocumented) + location?: Geolocation_2 | Record; + // (undocumented) + metadata?: { + hardware: { + display: { + [key: string]: string | number | null; + }; + [key: string]: any; + }; + browser: { + [key: string]: string | number | null; + }; + platform: { + [key: string]: string | number | null; + }; + }; +} + +export { FailedPolicyRequirement } + +export { FailureDetail } + +export { GenericError } + +// @public (undocumented) +interface Geolocation_2 { + // (undocumented) + latitude: number; + // (undocumented) + longitude: number; +} +export { Geolocation_2 as Geolocation } + +// @public +export class HiddenValueCallback extends BaseCallback { + constructor(payload: Callback); + // (undocumented) + payload: Callback; +} + +// @public (undocumented) +export interface IdPValue { + // (undocumented) + provider: string; + // (undocumented) + uiConfig: { + [key: string]: string; + }; +} + +// @internal +export interface InternalJourneyClientConfig { + // (undocumented) + error?: GenericError; + // (undocumented) + serverConfig: ResolvedServerConfig; +} + +export { isValidWellknownUrl } + +// @public +export function journey(input: { + config: JourneyClientConfig; + requestMiddleware?: RequestMiddleware[]; + logger?: { + level: LogLevel; + custom?: CustomLogger; + }; +}): Promise; + +// @public +export interface JourneyClient { + // (undocumented) + next: (step: JourneyStep, options?: NextOptions) => Promise; + // (undocumented) + redirect: (step: JourneyStep) => Promise; + // (undocumented) + resume: (url: string, options?: ResumeOptions) => Promise; + // (undocumented) + start: (options?: StartParam) => Promise; + // (undocumented) + store: SdkStore; + // (undocumented) + subscribe: (listener: () => void) => () => void; + // (undocumented) + terminate: (options?: { + query?: Record; + }) => Promise; +} + +export { JourneyClientConfig } + +// @public (undocumented) +export type JourneyLoginFailure = AuthResponse & { + type: StepType.LoginFailure; + payload: Step; + getCode: () => number; + getDetail: () => FailureDetail | undefined; + getMessage: () => string | undefined; + getProcessedMessage: (messageCreator?: MessageCreator) => ProcessedPropertyError[]; + getReason: () => string | undefined; +}; + +// @public (undocumented) +export type JourneyLoginSuccess = AuthResponse & { + type: StepType.LoginSuccess; + payload: Step; + getRealm: () => string | undefined; + getSessionToken: () => string | undefined; + getSuccessUrl: () => string | undefined; +}; + +// @public (undocumented) +export type JourneyResult = JourneyStep | JourneyLoginSuccess | JourneyLoginFailure | GenericError; + +export { JourneyServerConfig } + +// @public (undocumented) +export type JourneyStep = AuthResponse & { + type: StepType.Step; + payload: Step; + callbacks: BaseCallback[]; + getCallbackOfType: (type: CallbackType) => T; + getCallbacksOfType: (type: CallbackType) => T[]; + setCallbackValue: (type: CallbackType, value: unknown) => void; + getDescription: () => string | undefined; + getHeader: () => string | undefined; + getStage: () => string | undefined; +}; + +// @public +export class KbaCreateCallback extends BaseCallback { + constructor(payload: Callback); + getPredefinedQuestions(): string[]; + getPrompt(): string; + isAllowedUserDefinedQuestions(): boolean; + // (undocumented) + payload: Callback; + setAnswer(answer: string): void; + setQuestion(question: string): void; +} + +export { LogLevel } + +// @public (undocumented) +export interface MessageCreator { + // (undocumented) + [key: string]: (propertyName: string, params?: { + [key: string]: unknown; + }) => string; +} + +// @public +export class MetadataCallback extends BaseCallback { + constructor(payload: Callback); + getData(): T; + // (undocumented) + payload: Callback; +} + +// @public +export class NameCallback extends BaseCallback { + constructor(payload: Callback); + getPrompt(): string; + // (undocumented) + payload: Callback; + setName(name: string): void; +} + +export { NameValue } + +// @public (undocumented) +export interface NextOptions { + // (undocumented) + query?: Record; +} + +// @public +export class PasswordCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): string[]; + getPrompt(): string; + // (undocumented) + payload: Callback; + setPassword(password: string): void; +} + +// @public +export class PingOneProtectEvaluationCallback extends BaseCallback { + constructor(payload: Callback); + getPauseBehavioralData(): boolean; + // (undocumented) + payload: Callback; + setClientError(errorMessage: string): void; + setData(data: string): void; +} + +// @public +export class PingOneProtectInitializeCallback extends BaseCallback { + constructor(payload: Callback); + getConfig(): Record | { + envId: string; + consoleLogEnabled: boolean; + deviceAttributesToIgnore: string[]; + customHost: string; + lazyMetadata: boolean; + behavioralDataCollection: boolean; + deviceKeyRsyncIntervals: number; + enableTrust: boolean; + disableTags: boolean; + disableHub: boolean; + }; + // (undocumented) + payload: Callback; + // (undocumented) + setClientError(errorMessage: string): void; +} + +export { PolicyKey } + +export { PolicyParams } + +export { PolicyRequirement } + +// @public +export class PollingWaitCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + getWaitTime(): number; + // (undocumented) + payload: Callback; +} + +// @public (undocumented) +export interface ProcessedPropertyError { + // (undocumented) + detail: FailedPolicyRequirement; + // (undocumented) + messages: string[]; +} + +// @public +export class ReCaptchaCallback extends BaseCallback { + constructor(payload: Callback); + getSiteKey(): string; + // (undocumented) + payload: Callback; + setResult(result: string): void; +} + +// @public +export class ReCaptchaEnterpriseCallback extends BaseCallback { + constructor(payload: Callback); + getApiUrl(): string; + getElementClass(): string; + getSiteKey(): string; + // (undocumented) + payload: Callback; + setAction(action: string): void; + setClientError(error: string): void; + setPayload(payload: unknown): void; + setResult(result: string): void; +} + +// @public +export class RedirectCallback extends BaseCallback { + constructor(payload: Callback); + getRedirectUrl(): string; + // (undocumented) + payload: Callback; +} + +export { RequestMiddleware } + +// @public +export interface ResolvedServerConfig { + // (undocumented) + baseUrl: string; + // (undocumented) + paths: { + authenticate: string; + sessions: string; + }; +} + +// @public (undocumented) +export interface ResumeOptions { + // (undocumented) + journey?: string; + // (undocumented) + query?: Record; +} + +// @public +export class SelectIdPCallback extends BaseCallback { + constructor(payload: Callback); + getProviders(): IdPValue[]; + // (undocumented) + payload: Callback; + setProvider(value: string): void; +} + +// @public (undocumented) +export interface StartParam { + // (undocumented) + journey: string; + // (undocumented) + query?: Record; +} + +export { Step } + +export { StepDetail } + +export { StepType } + +// @public +export class SuspendedTextOutputCallback extends TextOutputCallback { + constructor(payload: Callback); + // (undocumented) + payload: Callback; +} + +// @public +export class TermsAndConditionsCallback extends BaseCallback { + constructor(payload: Callback); + getCreateDate(): Date | null; + getTerms(): string; + getVersion(): string; + // (undocumented) + payload: Callback; + setAccepted(accepted?: boolean): void; +} + +// @public +export class TextInputCallback extends BaseCallback { + constructor(payload: Callback); + getPrompt(): string; + // (undocumented) + payload: Callback; + setInput(input: string): void; +} + +// @public +export class TextOutputCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + getMessageType(): string; + // (undocumented) + payload: Callback; +} + +// @public +export class ValidatedCreatePasswordCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setPassword(password: string): void; + setValidateOnly(value: boolean): void; +} + +// @public +export class ValidatedCreateUsernameCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setName(name: string): void; + setValidateOnly(value: boolean): void; +} + +export { WellknownResponse } + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/journey-client/api-report/journey-client.types.api.md b/packages/journey-client/api-report/journey-client.types.api.md index d33995d6be..340dadaa91 100644 --- a/packages/journey-client/api-report/journey-client.types.api.md +++ b/packages/journey-client/api-report/journey-client.types.api.md @@ -1,491 +1,490 @@ -## API Report File for "@forgerock/journey-client" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { ActionTypes } from '@forgerock/sdk-request-middleware'; -import { AuthResponse } from '@forgerock/sdk-types'; -import { Callback } from '@forgerock/sdk-types'; -import { CallbackType } from '@forgerock/sdk-types'; -import { createWellknownError } from '@forgerock/sdk-utilities'; -import { CustomLogger } from '@forgerock/sdk-logger'; -import { FailedPolicyRequirement } from '@forgerock/sdk-types'; -import { FailureDetail } from '@forgerock/sdk-types'; -import { GenericError } from '@forgerock/sdk-types'; -import { isValidWellknownUrl } from '@forgerock/sdk-utilities'; -import { JourneyClientConfig } from '@forgerock/sdk-types'; -import { JourneyServerConfig } from '@forgerock/sdk-types'; -import { LogLevel } from '@forgerock/sdk-logger'; -import { NameValue } from '@forgerock/sdk-types'; -import { PolicyKey } from '@forgerock/sdk-types'; -import { PolicyParams } from '@forgerock/sdk-types'; -import { PolicyRequirement } from '@forgerock/sdk-types'; -import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; -import type { SdkStore } from '@forgerock/sdk-types'; -import { Step } from '@forgerock/sdk-types'; -import { StepDetail } from '@forgerock/sdk-types'; -import { StepType } from '@forgerock/sdk-types'; -import { WellknownResponse } from '@forgerock/sdk-types'; - -export { ActionTypes }; - -// @public -export class AttributeInputCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getName(): string; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setValidateOnly(value: boolean): void; - setValue(value: T): void; -} - -export { AuthResponse }; - -// @public -export class BaseCallback { - constructor(payload: Callback); - getInputValue(selector?: number | string): unknown; - getOutputByName(name: string, defaultValue: T): T; - getOutputValue(selector?: number | string): unknown; - getType(): CallbackType; - // (undocumented) - payload: Callback; - setInputValue(value: unknown, selector?: number | string | RegExp): void; -} - -export { Callback }; - -// @public (undocumented) -export type CallbackFactory = (callback: Callback) => BaseCallback; - -export { CallbackType }; - -// @public -export class ChoiceCallback extends BaseCallback { - constructor(payload: Callback); - getChoices(): string[]; - getDefaultChoice(): number; - getPrompt(): string; - // (undocumented) - payload: Callback; - setChoiceIndex(index: number): void; - setChoiceValue(value: string): void; -} - -// @public -export class ConfirmationCallback extends BaseCallback { - constructor(payload: Callback); - getDefaultOption(): number; - getMessageType(): number; - getOptions(): string[]; - getOptionType(): number; - getPrompt(): string; - // (undocumented) - payload: Callback; - setOptionIndex(index: number): void; - setOptionValue(value: string): void; -} - -// @public (undocumented) -export function createCallback(callback: Callback): BaseCallback; - -export { createWellknownError }; - -export { CustomLogger }; - -// @public -export class DeviceProfileCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - isLocationRequired(): boolean; - isMetadataRequired(): boolean; - // (undocumented) - payload: Callback; - setProfile(profile: DeviceProfileData): void; -} - -// @public (undocumented) -export interface DeviceProfileData { - // (undocumented) - identifier: string; - // (undocumented) - location?: Geolocation_2 | Record; - // (undocumented) - metadata?: { - hardware: { - display: { - [key: string]: string | number | null; - }; - [key: string]: any; - }; - browser: { - [key: string]: string | number | null; - }; - platform: { - [key: string]: string | number | null; - }; - }; -} - -export { FailedPolicyRequirement }; - -export { FailureDetail }; - -export { GenericError }; - -// @public (undocumented) -interface Geolocation_2 { - // (undocumented) - latitude: number; - // (undocumented) - longitude: number; -} -export { Geolocation_2 as Geolocation }; - -// @public -export class HiddenValueCallback extends BaseCallback { - constructor(payload: Callback); - // (undocumented) - payload: Callback; -} - -// @public (undocumented) -export interface IdPValue { - // (undocumented) - provider: string; - // (undocumented) - uiConfig: { - [key: string]: string; - }; -} - -// @internal -export interface InternalJourneyClientConfig { - // (undocumented) - error?: GenericError; - // (undocumented) - serverConfig: ResolvedServerConfig; -} - -export { isValidWellknownUrl }; - -// @public -export interface JourneyClient { - // (undocumented) - next: (step: JourneyStep, options?: NextOptions) => Promise; - // (undocumented) - redirect: (step: JourneyStep) => Promise; - // (undocumented) - resume: (url: string, options?: ResumeOptions) => Promise; - // (undocumented) - start: (options?: StartParam) => Promise; - // (undocumented) - store: SdkStore; - // (undocumented) - subscribe: (listener: () => void) => () => void; - // (undocumented) - terminate: (options?: { query?: Record }) => Promise; -} - -export { JourneyClientConfig }; - -// @public (undocumented) -export type JourneyLoginFailure = AuthResponse & { - type: StepType.LoginFailure; - payload: Step; - getCode: () => number; - getDetail: () => FailureDetail | undefined; - getMessage: () => string | undefined; - getProcessedMessage: (messageCreator?: MessageCreator) => ProcessedPropertyError[]; - getReason: () => string | undefined; -}; - -// @public (undocumented) -export type JourneyLoginSuccess = AuthResponse & { - type: StepType.LoginSuccess; - payload: Step; - getRealm: () => string | undefined; - getSessionToken: () => string | undefined; - getSuccessUrl: () => string | undefined; -}; - -// @public (undocumented) -export type JourneyResult = JourneyStep | JourneyLoginSuccess | JourneyLoginFailure | GenericError; - -export { JourneyServerConfig }; - -// @public (undocumented) -export type JourneyStep = AuthResponse & { - type: StepType.Step; - payload: Step; - callbacks: BaseCallback[]; - getCallbackOfType: (type: CallbackType) => T; - getCallbacksOfType: (type: CallbackType) => T[]; - setCallbackValue: (type: CallbackType, value: unknown) => void; - getDescription: () => string | undefined; - getHeader: () => string | undefined; - getStage: () => string | undefined; -}; - -// @public -export class KbaCreateCallback extends BaseCallback { - constructor(payload: Callback); - getPredefinedQuestions(): string[]; - getPrompt(): string; - isAllowedUserDefinedQuestions(): boolean; - // (undocumented) - payload: Callback; - setAnswer(answer: string): void; - setQuestion(question: string): void; -} - -export { LogLevel }; - -// @public (undocumented) -export interface MessageCreator { - // (undocumented) - [key: string]: ( - propertyName: string, - params?: { - [key: string]: unknown; - }, - ) => string; -} - -// @public -export class MetadataCallback extends BaseCallback { - constructor(payload: Callback); - getData(): T; - // (undocumented) - payload: Callback; -} - -// @public -export class NameCallback extends BaseCallback { - constructor(payload: Callback); - getPrompt(): string; - // (undocumented) - payload: Callback; - setName(name: string): void; -} - -export { NameValue }; - -// @public (undocumented) -export interface NextOptions { - // (undocumented) - query?: Record; -} - -// @public -export class PasswordCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): string[]; - getPrompt(): string; - // (undocumented) - payload: Callback; - setPassword(password: string): void; -} - -// @public -export class PingOneProtectEvaluationCallback extends BaseCallback { - constructor(payload: Callback); - getPauseBehavioralData(): boolean; - // (undocumented) - payload: Callback; - setClientError(errorMessage: string): void; - setData(data: string): void; -} - -// @public -export class PingOneProtectInitializeCallback extends BaseCallback { - constructor(payload: Callback); - getConfig(): - | Record - | { - envId: string; - consoleLogEnabled: boolean; - deviceAttributesToIgnore: string[]; - customHost: string; - lazyMetadata: boolean; - behavioralDataCollection: boolean; - deviceKeyRsyncIntervals: number; - enableTrust: boolean; - disableTags: boolean; - disableHub: boolean; - }; - // (undocumented) - payload: Callback; - // (undocumented) - setClientError(errorMessage: string): void; -} - -export { PolicyKey }; - -export { PolicyParams }; - -export { PolicyRequirement }; - -// @public -export class PollingWaitCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - getWaitTime(): number; - // (undocumented) - payload: Callback; -} - -// @public (undocumented) -export interface ProcessedPropertyError { - // (undocumented) - detail: FailedPolicyRequirement; - // (undocumented) - messages: string[]; -} - -// @public -export class ReCaptchaCallback extends BaseCallback { - constructor(payload: Callback); - getSiteKey(): string; - // (undocumented) - payload: Callback; - setResult(result: string): void; -} - -// @public -export class ReCaptchaEnterpriseCallback extends BaseCallback { - constructor(payload: Callback); - getApiUrl(): string; - getElementClass(): string; - getSiteKey(): string; - // (undocumented) - payload: Callback; - setAction(action: string): void; - setClientError(error: string): void; - setPayload(payload: unknown): void; - setResult(result: string): void; -} - -// @public -export class RedirectCallback extends BaseCallback { - constructor(payload: Callback); - getRedirectUrl(): string; - // (undocumented) - payload: Callback; -} - -export { RequestMiddleware }; - -// @public -export interface ResolvedServerConfig { - // (undocumented) - baseUrl: string; - // (undocumented) - paths: { - authenticate: string; - sessions: string; - }; -} - -// @public (undocumented) -export interface ResumeOptions { - // (undocumented) - journey?: string; - // (undocumented) - query?: Record; -} - -// @public -export class SelectIdPCallback extends BaseCallback { - constructor(payload: Callback); - getProviders(): IdPValue[]; - // (undocumented) - payload: Callback; - setProvider(value: string): void; -} - -// @public (undocumented) -export interface StartParam { - // (undocumented) - journey: string; - // (undocumented) - query?: Record; -} - -export { Step }; - -export { StepDetail }; - -export { StepType }; - -// @public -export class SuspendedTextOutputCallback extends TextOutputCallback { - constructor(payload: Callback); - // (undocumented) - payload: Callback; -} - -// @public -export class TermsAndConditionsCallback extends BaseCallback { - constructor(payload: Callback); - getCreateDate(): Date | null; - getTerms(): string; - getVersion(): string; - // (undocumented) - payload: Callback; - setAccepted(accepted?: boolean): void; -} - -// @public -export class TextInputCallback extends BaseCallback { - constructor(payload: Callback); - getPrompt(): string; - // (undocumented) - payload: Callback; - setInput(input: string): void; -} - -// @public -export class TextOutputCallback extends BaseCallback { - constructor(payload: Callback); - getMessage(): string; - getMessageType(): string; - // (undocumented) - payload: Callback; -} - -// @public -export class ValidatedCreatePasswordCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setPassword(password: string): void; - setValidateOnly(value: boolean): void; -} - -// @public -export class ValidatedCreateUsernameCallback extends BaseCallback { - constructor(payload: Callback); - getFailedPolicies(): PolicyRequirement[]; - getPolicies(): Record; - getPrompt(): string; - isRequired(): boolean; - // (undocumented) - payload: Callback; - setName(name: string): void; - setValidateOnly(value: boolean): void; -} - -export { WellknownResponse }; - -// (No @packageDocumentation comment for this package) -``` +## API Report File for "@forgerock/journey-client" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { ActionTypes } from '@forgerock/sdk-request-middleware'; +import { AuthResponse } from '@forgerock/sdk-types'; +import { Callback } from '@forgerock/sdk-types'; +import { CallbackType } from '@forgerock/sdk-types'; +import { createWellknownError } from '@forgerock/sdk-utilities'; +import { CustomLogger } from '@forgerock/sdk-logger'; +import { FailedPolicyRequirement } from '@forgerock/sdk-types'; +import { FailureDetail } from '@forgerock/sdk-types'; +import { GenericError } from '@forgerock/sdk-types'; +import { isValidWellknownUrl } from '@forgerock/sdk-utilities'; +import { JourneyClientConfig } from '@forgerock/sdk-types'; +import { JourneyServerConfig } from '@forgerock/sdk-types'; +import { LogLevel } from '@forgerock/sdk-logger'; +import { NameValue } from '@forgerock/sdk-types'; +import { PolicyKey } from '@forgerock/sdk-types'; +import { PolicyParams } from '@forgerock/sdk-types'; +import { PolicyRequirement } from '@forgerock/sdk-types'; +import { RequestMiddleware } from '@forgerock/sdk-request-middleware'; +import type { SdkStore } from '@forgerock/sdk-types'; +import { Step } from '@forgerock/sdk-types'; +import { StepDetail } from '@forgerock/sdk-types'; +import { StepType } from '@forgerock/sdk-types'; +import { WellknownResponse } from '@forgerock/sdk-types'; + +export { ActionTypes } + +// @public +export class AttributeInputCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getName(): string; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setValidateOnly(value: boolean): void; + setValue(value: T): void; +} + +export { AuthResponse } + +// @public +export class BaseCallback { + constructor(payload: Callback); + getInputValue(selector?: number | string): unknown; + getOutputByName(name: string, defaultValue: T): T; + getOutputValue(selector?: number | string): unknown; + getType(): CallbackType; + // (undocumented) + payload: Callback; + setInputValue(value: unknown, selector?: number | string | RegExp): void; +} + +export { Callback } + +// @public (undocumented) +export type CallbackFactory = (callback: Callback) => BaseCallback; + +export { CallbackType } + +// @public +export class ChoiceCallback extends BaseCallback { + constructor(payload: Callback); + getChoices(): string[]; + getDefaultChoice(): number; + getPrompt(): string; + // (undocumented) + payload: Callback; + setChoiceIndex(index: number): void; + setChoiceValue(value: string): void; +} + +// @public +export class ConfirmationCallback extends BaseCallback { + constructor(payload: Callback); + getDefaultOption(): number; + getMessageType(): number; + getOptions(): string[]; + getOptionType(): number; + getPrompt(): string; + // (undocumented) + payload: Callback; + setOptionIndex(index: number): void; + setOptionValue(value: string): void; +} + +// @public (undocumented) +export function createCallback(callback: Callback): BaseCallback; + +export { createWellknownError } + +export { CustomLogger } + +// @public +export class DeviceProfileCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + isLocationRequired(): boolean; + isMetadataRequired(): boolean; + // (undocumented) + payload: Callback; + setProfile(profile: DeviceProfileData): void; +} + +// @public (undocumented) +export interface DeviceProfileData { + // (undocumented) + identifier: string; + // (undocumented) + location?: Geolocation_2 | Record; + // (undocumented) + metadata?: { + hardware: { + display: { + [key: string]: string | number | null; + }; + [key: string]: any; + }; + browser: { + [key: string]: string | number | null; + }; + platform: { + [key: string]: string | number | null; + }; + }; +} + +export { FailedPolicyRequirement } + +export { FailureDetail } + +export { GenericError } + +// @public (undocumented) +interface Geolocation_2 { + // (undocumented) + latitude: number; + // (undocumented) + longitude: number; +} +export { Geolocation_2 as Geolocation } + +// @public +export class HiddenValueCallback extends BaseCallback { + constructor(payload: Callback); + // (undocumented) + payload: Callback; +} + +// @public (undocumented) +export interface IdPValue { + // (undocumented) + provider: string; + // (undocumented) + uiConfig: { + [key: string]: string; + }; +} + +// @internal +export interface InternalJourneyClientConfig { + // (undocumented) + error?: GenericError; + // (undocumented) + serverConfig: ResolvedServerConfig; +} + +export { isValidWellknownUrl } + +// @public +export interface JourneyClient { + // (undocumented) + next: (step: JourneyStep, options?: NextOptions) => Promise; + // (undocumented) + redirect: (step: JourneyStep) => Promise; + // (undocumented) + resume: (url: string, options?: ResumeOptions) => Promise; + // (undocumented) + start: (options?: StartParam) => Promise; + // (undocumented) + store: SdkStore; + // (undocumented) + subscribe: (listener: () => void) => () => void; + // (undocumented) + terminate: (options?: { + query?: Record; + }) => Promise; +} + +export { JourneyClientConfig } + +// @public (undocumented) +export type JourneyLoginFailure = AuthResponse & { + type: StepType.LoginFailure; + payload: Step; + getCode: () => number; + getDetail: () => FailureDetail | undefined; + getMessage: () => string | undefined; + getProcessedMessage: (messageCreator?: MessageCreator) => ProcessedPropertyError[]; + getReason: () => string | undefined; +}; + +// @public (undocumented) +export type JourneyLoginSuccess = AuthResponse & { + type: StepType.LoginSuccess; + payload: Step; + getRealm: () => string | undefined; + getSessionToken: () => string | undefined; + getSuccessUrl: () => string | undefined; +}; + +// @public (undocumented) +export type JourneyResult = JourneyStep | JourneyLoginSuccess | JourneyLoginFailure | GenericError; + +export { JourneyServerConfig } + +// @public (undocumented) +export type JourneyStep = AuthResponse & { + type: StepType.Step; + payload: Step; + callbacks: BaseCallback[]; + getCallbackOfType: (type: CallbackType) => T; + getCallbacksOfType: (type: CallbackType) => T[]; + setCallbackValue: (type: CallbackType, value: unknown) => void; + getDescription: () => string | undefined; + getHeader: () => string | undefined; + getStage: () => string | undefined; +}; + +// @public +export class KbaCreateCallback extends BaseCallback { + constructor(payload: Callback); + getPredefinedQuestions(): string[]; + getPrompt(): string; + isAllowedUserDefinedQuestions(): boolean; + // (undocumented) + payload: Callback; + setAnswer(answer: string): void; + setQuestion(question: string): void; +} + +export { LogLevel } + +// @public (undocumented) +export interface MessageCreator { + // (undocumented) + [key: string]: (propertyName: string, params?: { + [key: string]: unknown; + }) => string; +} + +// @public +export class MetadataCallback extends BaseCallback { + constructor(payload: Callback); + getData(): T; + // (undocumented) + payload: Callback; +} + +// @public +export class NameCallback extends BaseCallback { + constructor(payload: Callback); + getPrompt(): string; + // (undocumented) + payload: Callback; + setName(name: string): void; +} + +export { NameValue } + +// @public (undocumented) +export interface NextOptions { + // (undocumented) + query?: Record; +} + +// @public +export class PasswordCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): string[]; + getPrompt(): string; + // (undocumented) + payload: Callback; + setPassword(password: string): void; +} + +// @public +export class PingOneProtectEvaluationCallback extends BaseCallback { + constructor(payload: Callback); + getPauseBehavioralData(): boolean; + // (undocumented) + payload: Callback; + setClientError(errorMessage: string): void; + setData(data: string): void; +} + +// @public +export class PingOneProtectInitializeCallback extends BaseCallback { + constructor(payload: Callback); + getConfig(): Record | { + envId: string; + consoleLogEnabled: boolean; + deviceAttributesToIgnore: string[]; + customHost: string; + lazyMetadata: boolean; + behavioralDataCollection: boolean; + deviceKeyRsyncIntervals: number; + enableTrust: boolean; + disableTags: boolean; + disableHub: boolean; + }; + // (undocumented) + payload: Callback; + // (undocumented) + setClientError(errorMessage: string): void; +} + +export { PolicyKey } + +export { PolicyParams } + +export { PolicyRequirement } + +// @public +export class PollingWaitCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + getWaitTime(): number; + // (undocumented) + payload: Callback; +} + +// @public (undocumented) +export interface ProcessedPropertyError { + // (undocumented) + detail: FailedPolicyRequirement; + // (undocumented) + messages: string[]; +} + +// @public +export class ReCaptchaCallback extends BaseCallback { + constructor(payload: Callback); + getSiteKey(): string; + // (undocumented) + payload: Callback; + setResult(result: string): void; +} + +// @public +export class ReCaptchaEnterpriseCallback extends BaseCallback { + constructor(payload: Callback); + getApiUrl(): string; + getElementClass(): string; + getSiteKey(): string; + // (undocumented) + payload: Callback; + setAction(action: string): void; + setClientError(error: string): void; + setPayload(payload: unknown): void; + setResult(result: string): void; +} + +// @public +export class RedirectCallback extends BaseCallback { + constructor(payload: Callback); + getRedirectUrl(): string; + // (undocumented) + payload: Callback; +} + +export { RequestMiddleware } + +// @public +export interface ResolvedServerConfig { + // (undocumented) + baseUrl: string; + // (undocumented) + paths: { + authenticate: string; + sessions: string; + }; +} + +// @public (undocumented) +export interface ResumeOptions { + // (undocumented) + journey?: string; + // (undocumented) + query?: Record; +} + +// @public +export class SelectIdPCallback extends BaseCallback { + constructor(payload: Callback); + getProviders(): IdPValue[]; + // (undocumented) + payload: Callback; + setProvider(value: string): void; +} + +// @public (undocumented) +export interface StartParam { + // (undocumented) + journey: string; + // (undocumented) + query?: Record; +} + +export { Step } + +export { StepDetail } + +export { StepType } + +// @public +export class SuspendedTextOutputCallback extends TextOutputCallback { + constructor(payload: Callback); + // (undocumented) + payload: Callback; +} + +// @public +export class TermsAndConditionsCallback extends BaseCallback { + constructor(payload: Callback); + getCreateDate(): Date | null; + getTerms(): string; + getVersion(): string; + // (undocumented) + payload: Callback; + setAccepted(accepted?: boolean): void; +} + +// @public +export class TextInputCallback extends BaseCallback { + constructor(payload: Callback); + getPrompt(): string; + // (undocumented) + payload: Callback; + setInput(input: string): void; +} + +// @public +export class TextOutputCallback extends BaseCallback { + constructor(payload: Callback); + getMessage(): string; + getMessageType(): string; + // (undocumented) + payload: Callback; +} + +// @public +export class ValidatedCreatePasswordCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setPassword(password: string): void; + setValidateOnly(value: boolean): void; +} + +// @public +export class ValidatedCreateUsernameCallback extends BaseCallback { + constructor(payload: Callback); + getFailedPolicies(): PolicyRequirement[]; + getPolicies(): Record; + getPrompt(): string; + isRequired(): boolean; + // (undocumented) + payload: Callback; + setName(name: string): void; + setValidateOnly(value: boolean): void; +} + +export { WellknownResponse } + +// (No @packageDocumentation comment for this package) + +```