-
Notifications
You must be signed in to change notification settings - Fork 3
SDKS-5067: Standardize SDK Configuration #684
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| --- | ||
| '@forgerock/sdk-utilities': minor | ||
| '@forgerock/sdk-types': minor | ||
| '@forgerock/sdk-oidc': minor | ||
| '@forgerock/oidc-client': minor | ||
| '@forgerock/journey-client': minor | ||
| '@forgerock/davinci-client': minor | ||
| --- | ||
|
|
||
| Add unified cross-platform SDK configuration support | ||
|
|
||
| All three client factories (`oidc`, `journey`, `davinci`) now accept the cross-platform unified JSON config schema alongside the existing internal config shape. Pass a unified config object and the factory maps, validates, and rejects on invalid input. | ||
|
|
||
| **New in `@forgerock/sdk-utilities`:** | ||
|
|
||
| - `UnifiedSdkConfig`, `UnifiedOidcConfig`, `UnifiedJourneyConfig` types | ||
| - `validateUnifiedSdkConfig` / `validateUnifiedOidcConfig` — pure validation returning `ConfigValidationResult<T>` (no throws) | ||
| - `unifiedToOidcConfig`, `unifiedToJourneyConfig`, `unifiedToDavinciConfig` — pure mapping functions | ||
| - `isUnifiedSdkConfig` discriminator (`'oidc' in input || 'journey' in input`) | ||
|
|
||
| **New in `@forgerock/sdk-types`:** | ||
|
|
||
| - `GetAuthorizationUrlOptions` extended with `loginHint`, `nonce`, `display`, `uiLocales`, `acrValues`; `prompt` widened to include `'select_account'` | ||
|
|
||
| **New in `@forgerock/sdk-oidc`:** | ||
|
|
||
| - `buildAuthorizeParams` forwards all new OIDC authorize params into the URL | ||
|
|
||
| **New in `@forgerock/oidc-client`:** | ||
|
|
||
| - `oidc()` factory accepts unified JSON config; rejects Promise on validation failure | ||
| - `endSession` appends `post_logout_redirect_uri` when `signOutRedirectUri` is set | ||
| - Authorize URL construction forwards `loginHint`, `state`, `nonce`, `display`, `prompt`, `uiLocales`, `acrValues`, `additionalParameters` | ||
|
|
||
| **New in `@forgerock/journey-client`:** | ||
|
|
||
| - `journey()` factory accepts unified JSON config; throws on validation failure | ||
|
|
||
| **New in `@forgerock/davinci-client`:** | ||
|
|
||
| - `davinci()` factory accepts unified JSON config; throws on validation failure |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,13 @@ import { Micro } from 'effect'; | |
| import { exitIsFail, exitIsSuccess } from 'effect/Micro'; | ||
| import { type CustomLogger, logger as loggerFn, type LogLevel } from '@forgerock/sdk-logger'; | ||
| import { createStorage } from '@forgerock/storage'; | ||
| import { isGenericError, createWellknownError } from '@forgerock/sdk-utilities'; | ||
| import { | ||
| isGenericError, | ||
| isUnifiedSdkConfig, | ||
| unifiedToDavinciConfig, | ||
| validateUnifiedSdkConfig, | ||
| createWellknownError, | ||
| } from '@forgerock/sdk-utilities'; | ||
|
|
||
| /** | ||
| * Import RTK slices and api | ||
|
|
@@ -66,18 +72,38 @@ import type { ContinueNode, StartNode } from './node.types.js'; | |
| * @returns {Observable} - an observable client for DaVinci flows | ||
| */ | ||
| export async function davinci<ActionType extends ActionTypes = ActionTypes>({ | ||
| config, | ||
| config: rawConfig, | ||
| requestMiddleware, | ||
| logger, | ||
| }: { | ||
| config: DaVinciConfig; | ||
| config: DaVinciConfig | Record<string, unknown>; | ||
| requestMiddleware?: RequestMiddleware<ActionType>[]; | ||
| logger?: { | ||
| level: LogLevel; | ||
| custom?: CustomLogger; | ||
| }; | ||
| }) { | ||
| const log = loggerFn({ level: logger?.level || 'error', custom: logger?.custom }); | ||
| let config: DaVinciConfig; | ||
|
|
||
| if (isUnifiedSdkConfig(rawConfig)) { | ||
| const validation = validateUnifiedSdkConfig(rawConfig, true); | ||
| if (!validation.success) { | ||
| const messages = validation.errors.map((e) => `${e.field}: ${e.message}`).join(', '); | ||
| throw new Error(`Invalid unified SDK config: ${messages}`); | ||
| } | ||
| const mapped = unifiedToDavinciConfig(validation.data); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if "unified" is referring the "Unified SDK" here or the "Unified JSON Config". Can we rename it jsonToDavinciConfig or something? I believe we are trying to move away from calling it the "Unified SDK" and this may even change in the future. |
||
| if (!mapped.success) { | ||
| throw new Error(`Invalid unified SDK config: ${mapped.error.field}: ${mapped.error.message}`); | ||
| } | ||
| config = mapped.data as DaVinciConfig; | ||
| } else { | ||
| config = rawConfig as DaVinciConfig; | ||
| } | ||
|
|
||
| const log = loggerFn({ | ||
| level: logger?.level ?? config.log ?? 'error', | ||
| custom: logger?.custom, | ||
| }); | ||
|
Comment on lines
+86
to
+106
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i'm not a huge fan of this here. I think we should maybe write a separate validation function if we need to do some validation but i'm concerned about the type of |
||
| const store = createClientStore({ requestMiddleware, logger: log }); | ||
| const serverInfo = createStorage<ContinueNode['server']>({ | ||
| type: 'localStorage', | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Andy's design doc, he suggests initializing the client through a new property called
jsonwhich contains the json config. Is there a reason why you deviated from this? I think it may be a good idea to distinguish between the standard config and json config. The typing could also be a little more strict than Record<string, unknown>. If we have agreed on a standard JSON config as a team then we should be able to create an interface for it. This also removes the need for a isUnifiedSdkConfig utility.