Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .changeset/rich-cows-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
'@forgerock/journey-client': minor
'@forgerock/sdk-oidc': minor
'@forgerock/sdk-utilities': minor
'@forgerock/davinci-client': patch
'@forgerock/oidc-client': patch
---

### @forgerock/journey-client

Add well-known OIDC endpoint discovery support. The journey client can now fetch configuration from the `.well-known/openid-configuration` endpoint:

```typescript
const client = await journey({
serverConfig: {
baseUrl: 'https://am.example.com/am/',
wellknown:
'https://am.example.com/am/oauth2/realms/root/realms/alpha/.well-known/openid-configuration',
},
});
```

The realm path can be automatically inferred from the well-known issuer URL.

### @forgerock/sdk-oidc

Add shared well-known module with RTK Query API for OIDC endpoint discovery:

- `wellknownApi` - RTK Query API for fetching well-known configuration
- `createWellknownSelector` - Selector factory for cached well-known data
- `createWellknownError` - Typed error creation from fetch failures
- Re-exports pure utilities from `@forgerock/sdk-utilities`

### @forgerock/sdk-utilities

Add pure well-known utilities:

- `inferRealmFromIssuer` - Extract realm path from AM issuer URLs
- `isValidWellknownUrl` - Validate well-known URLs (HTTPS required, HTTP allowed for localhost)

### @forgerock/davinci-client

Refactored to use shared well-known module from `@forgerock/sdk-oidc`.

### @forgerock/oidc-client

Refactored to use shared well-known module from `@forgerock/sdk-oidc`.
8 changes: 5 additions & 3 deletions e2e/am-mock-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
"author": "",
"main": "./index.js",
"dependencies": {
"@types/express": "^4.17.17",
"body-parser": "^2.2.0",
"body-parser": "^2.2.2",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"express": "^4.21.2",
"express": "^5.2.1",
"superagent": "^10.2.3",
"uuid": "^13.0.0"
},
"devDependencies": {
"@types/express": "^5.0.0"
}
}
4 changes: 2 additions & 2 deletions e2e/am-mock-api/src/app/routes.resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ async function authorization(req, res, next) {

export default function (app) {
// Passthrough route that enforces authentication
app.all('/resource/*', async (req, res, next) => {
app.all('/resource/{*splat}', async (req, res, next) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed when i rebased open-deps (part of this express upgrade)

if (env.NODE_ENV === 'LIVE' && req.hostname === FORGEOPS) {
// Only enforce authentication if IG is not used
// In other words, the call comes directly from app
Expand Down Expand Up @@ -156,7 +156,7 @@ export default function (app) {
}
});

app.get('/resource/rest/*', wait, authorization, async (req, res) => {
app.get('/resource/rest/{*splat}', wait, authorization, async (req, res) => {
if (env.NODE_ENV === 'live') {
if (req.access.actions && req.access.actions.GET) {
res.json({ message: 'Successfully retrieved resource!' });
Expand Down
14 changes: 7 additions & 7 deletions e2e/davinci-app/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
{
"name": "@forgerock/davinci-app",
"version": "0.0.0",
"private": true,
"description": "Ping DaVinci Client Test App",
"type": "module",
"private": true,
"nx": {
"tags": ["scope:e2e"]
},
"scripts": {
"build": "pnpm nx nxBuild",
"lint": "pnpm nx nxLint",
Expand All @@ -16,8 +13,11 @@
"dependencies": {
"@forgerock/davinci-client": "workspace:*",
"@forgerock/javascript-sdk": "4.7.0",
"@forgerock/sdk-logger": "workspace:*",
"@forgerock/protect": "workspace:*"
"@forgerock/protect": "workspace:*",
"@forgerock/sdk-logger": "workspace:*"
},
"devDependencies": {}
"devDependencies": {},
"nx": {
"tags": ["scope:e2e"]
}
}
9 changes: 0 additions & 9 deletions e2e/davinci-app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,6 @@
"skipLibCheck": true
},
"references": [
{
"path": "../../packages/sdk-effects/logger"
},
{
"path": "../../packages/protect"
},
{
"path": "../../packages/davinci-client"
},
{
"path": "./tsconfig.app.json"
},
Expand Down
6 changes: 3 additions & 3 deletions e2e/device-client-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
"@forgerock/javascript-sdk": "4.7.0",
"effect": "^3.12.7"
},
"nx": {
"tags": ["scope:e2e"]
},
"devDependencies": {
"@effect/language-service": "^0.20.0"
},
"nx": {
"tags": ["scope:e2e"]
}
}
3 changes: 0 additions & 3 deletions e2e/device-client-app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
"files": [],
"include": [],
"references": [
{
"path": "../../packages/device-client"
},
{
"path": "./tsconfig.app.json"
}
Expand Down
8 changes: 4 additions & 4 deletions e2e/journey-app/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
{
"name": "@forgerock/journey-app",
"version": "1.3.0",
"private": true,
"description": "Ping Journey Client Test App",
"type": "module",
"private": true,
"nx": {
"tags": ["scope:e2e"]
},
"scripts": {
"build": "pnpm nx nxBuild",
"lint": "pnpm nx nxLint",
Expand All @@ -18,5 +15,8 @@
"@forgerock/oidc-client": "workspace:*",
"@forgerock/protect": "workspace:*",
"@forgerock/sdk-logger": "workspace:*"
},
"nx": {
"tags": ["scope:e2e"]
}
}
12 changes: 0 additions & 12 deletions e2e/journey-app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,6 @@
"skipLibCheck": true
},
"references": [
{
"path": "../../packages/sdk-effects/logger"
},
{
"path": "../../packages/oidc-client"
},
{
"path": "../../packages/protect"
},
{
"path": "../../packages/journey-client"
},
{
"path": "./tsconfig.app.json"
},
Expand Down
3 changes: 0 additions & 3 deletions e2e/oidc-app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
"files": [],
"include": [],
"references": [
{
"path": "../../packages/oidc-client"
},
{
"path": "./tsconfig.app.json"
}
Expand Down
2 changes: 1 addition & 1 deletion e2e/protect-app/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "@forgerock/protect-app",
"version": "0.0.0",
"description": "Ping Protect Test Apps",
"private": true,
"description": "Ping Protect Test Apps",
"type": "module",
"scripts": {
"build": "pnpm nx nxBuild",
Expand Down
3 changes: 0 additions & 3 deletions e2e/protect-app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
"skipLibCheck": true
},
"references": [
{
"path": "../../packages/protect"
},
{
"path": "./tsconfig.app.json"
},
Expand Down
8 changes: 7 additions & 1 deletion nx.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@
"buildTargetName": "nxBuild",
"serveTargetName": "nxServe",
"previewTargetName": "nxPreview",
"testTargetName": "nxTest",
"serveStaticTargetName": "serve-static",
"typecheckTargetName": "typecheck",
"buildDepsTargetName": "vite:build-deps",
Expand All @@ -146,6 +145,13 @@
"configName": "tsconfig.lib.json"
}
}
},
{
"plugin": "@nx/vitest",
"options": {
"testTargetName": "nxTest"
},
"include": ["packages/**/**/*", "e2e/**/**/*", "tools/**/**/*"]
}
],
"parallel": 1,
Expand Down
34 changes: 18 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"path": "./node_modules/cz-conventional-changelog"
}
},
"dependencies": {},
"devDependencies": {
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.9",
Expand All @@ -58,17 +59,18 @@
"@effect/cli": "catalog:effect",
"@eslint/eslintrc": "^3.0.0",
"@eslint/js": "~9.39.0",
"@nx/devkit": "21.2.3",
"@nx/eslint": "21.2.3",
"@nx/eslint-plugin": "21.2.3",
"@nx/express": "21.2.3",
"@nx/jest": "21.2.3",
"@nx/js": "21.2.3",
"@nx/playwright": "21.2.3",
"@nx/plugin": "21.2.3",
"@nx/vite": "21.2.3",
"@nx/web": "21.2.3",
"@nx/workspace": "21.2.3",
"@nx/devkit": "22.3.3",
"@nx/eslint": "22.3.3",
"@nx/eslint-plugin": "22.3.3",
"@nx/express": "22.3.3",
"@nx/jest": "22.3.3",
"@nx/js": "22.3.3",
"@nx/playwright": "22.3.3",
"@nx/plugin": "22.3.3",
"@nx/vite": "22.3.3",
"@nx/vitest": "22.3.3",
"@nx/web": "22.3.3",
"@nx/workspace": "22.3.3",
"@playwright/test": "^1.47.2",
"@swc-node/register": "1.10.10",
"@swc/cli": "0.6.0",
Expand All @@ -82,8 +84,8 @@
"@typescript-eslint/parser": "^8.45.0",
"@typescript-eslint/typescript-estree": "8.23.0",
"@typescript-eslint/utils": "^8.13.0",
"@vitest/coverage-v8": "^3.0.5",
"@vitest/ui": "3.0.4",
"@vitest/coverage-v8": "4.0.9",
"@vitest/ui": "4.0.9",
"conventional-changelog-conventionalcommits": "^8.0.0",
"cz-conventional-changelog": "^3.3.0",
"cz-git": "^1.6.1",
Expand All @@ -100,7 +102,7 @@
"jsonc-eslint-parser": "^2.1.0",
"lint-staged": "^15.0.0",
"madge": "8.0.0",
"nx": "21.2.3",
"nx": "22.3.3",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of this is because of dependency upgrades

"pkg-pr-new": "^0.0.60",
"playwright": "^1.47.2",
"prettier": "^3.2.5",
Expand All @@ -115,9 +117,9 @@
"typescript": "5.8.3",
"typescript-eslint": "^8.19.0",
"verdaccio": "6.2.1",
"vite": "6.4.1",
"vite": "catalog:vite",
"vitest": "catalog:vitest",
"vitest-canvas-mock": "^0.3.3"
"vitest-canvas-mock": "catalog:vitest"
},
"packageManager": "pnpm@10.21.0+sha512.da3337267e400fdd3d479a6c68079ac6db01d8ca4f67572083e722775a796788a7a9956613749e000fac20d424b594f7a791a5f4e2e13581c5ef947f26968a40",
"engines": {
Expand Down
24 changes: 12 additions & 12 deletions packages/davinci-client/src/lib/client.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { createClientStore, handleUpdateValidateError, RootState } from './clien
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, createWellknownError } from '@forgerock/sdk-oidc';

import type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware';
/**
Expand Down Expand Up @@ -88,14 +88,14 @@ export async function davinci<ActionType extends ActionTypes = ActionTypes>({
throw error;
}

const { data: openIdResponse } = await store.dispatch(
wellknownApi.endpoints.wellknown.initiate(config.serverConfig.wellknown),
const { data: openIdResponse, error: fetchError } = await store.dispatch(
wellknownApi.endpoints.configuration.initiate(config.serverConfig.wellknown),
);

if (!openIdResponse) {
const error = new Error('error fetching `wellknown` response for OpenId Configuration');
log.error(error.message);
throw error;
if (fetchError || !openIdResponse) {
const genericError = createWellknownError(fetchError);
log.error(`${genericError.error}: ${genericError.message}`);
throw new Error(genericError.message);
}

store.dispatch(configSlice.actions.set({ ...config, wellknownResponse: openIdResponse }));
Expand Down Expand Up @@ -249,11 +249,11 @@ export async function davinci<ActionType extends ActionTypes = ActionTypes>({

return node;
} catch (err) {
const error = err as Error;
log.error(error.message);
const errorMessage = err instanceof Error ? err.message : String(err);
log.error(errorMessage);
return {
error: {
message: error.message ?? 'An unexpected error occurred during resume operation',
message: errorMessage || 'An unexpected error occurred during resume operation',
type: 'internal_error',
Comment on lines +252 to 257
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid "undefined" / "null" messages when non-Error values are thrown.

String(err) can produce unhelpful messages and skip the fallback. Consider guarding nullish values; apply the same guard in the update catch at Line 339.

🔧 Suggested tweak
-        const errorMessage = err instanceof Error ? err.message : String(err);
-        log.error(errorMessage);
+        const errorMessage =
+          err instanceof Error ? err.message : err ? String(err) : '';
+        log.error(errorMessage || 'An unexpected error occurred during resume operation');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const errorMessage = err instanceof Error ? err.message : String(err);
log.error(errorMessage);
return {
error: {
message: error.message ?? 'An unexpected error occurred during resume operation',
message: errorMessage || 'An unexpected error occurred during resume operation',
type: 'internal_error',
const errorMessage =
err instanceof Error ? err.message : err ? String(err) : '';
log.error(errorMessage || 'An unexpected error occurred during resume operation');
return {
error: {
message: errorMessage || 'An unexpected error occurred during resume operation',
type: 'internal_error',
🤖 Prompt for AI Agents
In `@packages/davinci-client/src/lib/client.store.ts` around lines 252 - 257, The
catch blocks produce unhelpful "undefined"/"null" strings by using String(err);
change the error extraction in the resume and update catch handlers to guard
nullish thrown values: compute errorMessage with something like err instanceof
Error ? err.message : (err == null ? '' : String(err)), use
log.error(errorMessage) and keep the existing fallback when building the
returned error object so the fallback 'An unexpected error occurred...' is used;
apply the same fix to the update catch at the block that constructs errorMessage
around Line 339 (update/resume catch handlers and the errorMessage
variable/log.error usage).

},
type: 'internal_error',
Expand Down Expand Up @@ -336,10 +336,10 @@ export async function davinci<ActionType extends ActionTypes = ActionTypes>({
store.dispatch(nodeSlice.actions.update({ id, value, index }));
return null;
} catch (err) {
const error = err as Error;
const errorMessage = err instanceof Error ? err.message : String(err);
return {
type: 'internal_error',
error: { message: error.message, type: 'internal_error' },
error: { message: errorMessage, type: 'internal_error' },
};
}
};
Expand Down
2 changes: 1 addition & 1 deletion packages/davinci-client/src/lib/client.store.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { configSlice } from './config.slice.js';
import { nodeSlice } from './node.slice.js';
import { davinciApi } from './davinci.api.js';
import { ErrorNode, ContinueNode, StartNode, SuccessNode } from '../types.js';
import { wellknownApi } from './wellknown.api.js';
import { wellknownApi } from '@forgerock/sdk-oidc';
import { InternalErrorResponse } from './client.types.js';

export function createClientStore<ActionType extends ActionTypes>({
Expand Down
Loading
Loading