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
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ jobs:
with:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

- name: Lint dependency versions
run: pnpm syncpack:lint

- run: pnpm nx fix-ci
if: always()

Expand Down
12 changes: 12 additions & 0 deletions .syncpackrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "./node_modules/syncpack/schema.json",
"source": [
"package.json",
"packages/*/package.json",
"packages/sdk-effects/*/package.json",
"packages/utils/*/package.json",
"e2e/*/package.json",
"tools/*/package.json",
"scratchpad/package.json"
]
}
2 changes: 1 addition & 1 deletion e2e/am-mock-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"uuid": "^14.0.0"
},
"devDependencies": {
"@types/express": "^5.0.0"
"@types/express": "catalog:"
}
}
21 changes: 12 additions & 9 deletions e2e/davinci-app/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
*/
import './style.css';

import { Config, FRUser, TokenManager } from '@forgerock/javascript-sdk';
import { davinci } from '@forgerock/davinci-client';
import { oidc } from '@forgerock/oidc-client';
import type { OidcConfig } from '@forgerock/oidc-client/types';
import type {
CustomLogger,
DaVinciConfig,
Expand Down Expand Up @@ -85,6 +86,11 @@ const urlParams = new URLSearchParams(window.location.search);

(async () => {
const davinciClient: DavinciClient = await davinci({ config, logger, requestMiddleware });
const oidcResult = await oidc({ config: config as OidcConfig });
if ('error' in oidcResult) {
throw new Error(`Failed to initialize oidc client: ${oidcResult.error}`);
}
const oidcClient = oidcResult;
Comment on lines +89 to +93
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect OidcConfig and the oidc() return type / error shape
fd -t f 'tsconfig.lib.json' packages/oidc-client 2>/dev/null
fd -t f -e ts . packages/oidc-client/src 2>/dev/null | head -50

# OidcConfig definition
ast-grep --pattern 'export type OidcConfig = $$$'
ast-grep --pattern 'export interface OidcConfig { $$$ }'

# DaVinciConfig definition
ast-grep --pattern 'export type DaVinciConfig = $$$'
ast-grep --pattern 'export interface DaVinciConfig { $$$ }'

# oidc() factory return type / error shape
ast-grep --pattern 'export function oidc($$$) { $$$ }'
ast-grep --pattern 'export const oidc = $$$'
rg -nP --type=ts -C3 "\berror\s*:" packages/oidc-client/src 2>/dev/null | head -60

Repository: ForgeRock/ping-javascript-sdk

Length of output: 5411


🏁 Script executed:

# Get OidcConfig definition
rg -n "export type OidcConfig|export interface OidcConfig" packages/oidc-client/src --type=ts -A 10

# Get DaVinciConfig definition
rg -n "export type DaVinciConfig|export interface DaVinciConfig" --type=ts -A 10

Repository: ForgeRock/ping-javascript-sdk

Length of output: 1443


🏁 Script executed:

# Check the oidc function export and its return type
rg -n "export.*function oidc|export.*const oidc" packages/oidc-client/src --type=ts -A 5

# Look for the complete oidc API return type (likely has data + error union)
rg -n "type.*OidcFactoryResult|interface.*OidcFactoryResult|export.*Result.*oidc|return.*error.*data" packages/oidc-client/src --type=ts -B 2 -A 5

Repository: ForgeRock/ping-javascript-sdk

Length of output: 1015


🏁 Script executed:

# Verify the error field type in the main oidc API
cat packages/oidc-client/src/lib/oidc.api.ts | head -200

Repository: ForgeRock/ping-javascript-sdk

Length of output: 6924


🏁 Script executed:

# Get full oidc function signature including return type
cat packages/oidc-client/src/lib/client.store.ts | sed -n '51,100p'

Repository: ForgeRock/ping-javascript-sdk

Length of output: 1549


🏁 Script executed:

# Search for the return type definition
rg -n "OidcClientResult|OidcFactoryResult|type.*oidc.*Result" packages/oidc-client/src --type=ts -A 3

Repository: ForgeRock/ping-javascript-sdk

Length of output: 55


🏁 Script executed:

# Look for where oidc function returns error
rg -n "return.*error|error.*:" packages/oidc-client/src/lib/client.store.ts --type=ts -B 2 -A 2 | head -80

Repository: ForgeRock/ping-javascript-sdk

Length of output: 3274


The type cast config as OidcConfig masks a structural incompatibility.

OidcConfig (extends AsyncLegacyConfigOptions with required clientId, redirectUri, scope, serverConfig.wellknown) is incompatible with DaVinciConfig (extends AsyncLegacyConfigOptions with only optional responseType). Casting bypasses type checking and will only surface missing required fields at runtime. Build an OidcConfig explicitly or export a validation/conversion helper instead of asserting the type.

The error message handling on line 91 is fine—oidcResult.error is always a string from the oidc factory.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/davinci-app/main.ts` around lines 89 - 93, Don't cast DaVinciConfig to
OidcConfig; instead construct/validate a proper OidcConfig before calling oidc.
Replace the `oidc({ config: config as OidcConfig })` call by building an
explicit OidcConfig object (containing required fields clientId, redirectUri,
scope, and serverConfig.wellknown) from the existing config or by calling a
conversion/validation helper (e.g., buildOidcConfig(config) /
validateOidcConfig(config)) so structural incompatibilities are caught at
compile time; then pass that validated OidcConfig into the oidc(...) call and
assign the result to oidcClient as before.

const protectApi = protect({ envId: '02fb4743-189a-4bc7-9d6c-a919edfe6447' });
const continueToken = urlParams.get('continueToken');
const formEl = document.getElementById('form') as HTMLFormElement;
Expand All @@ -98,10 +104,6 @@ const urlParams = new URLSearchParams(window.location.search);

if (continueToken) {
resumed = await davinciClient.resume({ continueToken });
} else {
// the current davinci-config has a slightly
// different middleware type than the old legacy config
await Config.setAsync(config as any);
}

function renderComplete() {
Expand Down Expand Up @@ -140,25 +142,26 @@ const urlParams = new URLSearchParams(window.location.search);

const tokenBtn = document.getElementById('tokensButton') as HTMLButtonElement;
tokenBtn.addEventListener('click', async () => {
tokens = await TokenManager.getTokens({ query: { code, state } });
tokens = await oidcClient.token.exchange(code, state);

console.log(tokens);

const accessTokenValue = tokens && 'accessToken' in tokens ? tokens.accessToken : '';
const tokenPreEl = document.getElementById('accessTokenContainer') as HTMLPreElement;
tokenPreEl.innerHTML = `
<pre
data-testid="access-token"
id="accessTokenValue"
style="display: block; max-width: 400px; text-wrap: wrap; overflow-wrap: anywhere;"
>${tokens?.accessToken}</pre>
>${accessTokenValue}</pre>
`;
});

const loginBtn = document.getElementById('logoutButton') as HTMLButtonElement;
loginBtn.addEventListener('click', async () => {
await FRUser.logout({ logoutRedirectUri: `${window.location.origin}/` });
await oidcClient.user.logout();

//window.location.reload();
window.location.reload();
});
}

Expand Down
2 changes: 1 addition & 1 deletion e2e/davinci-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"dependencies": {
"@forgerock/davinci-client": "workspace:*",
"@forgerock/javascript-sdk": "4.7.0",
"@forgerock/oidc-client": "workspace:*",
"@forgerock/protect": "workspace:*",
"@forgerock/sdk-logger": "workspace:*"
},
Expand Down
3 changes: 3 additions & 0 deletions e2e/davinci-app/tsconfig.app.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
{
"path": "../../packages/protect/tsconfig.lib.json"
},
{
"path": "../../packages/oidc-client/tsconfig.lib.json"
},
{
"path": "../../packages/davinci-client/tsconfig.lib.json"
}
Expand Down
6 changes: 0 additions & 6 deletions e2e/davinci-suites/src/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,8 @@ test('Test happy paths on test page', async ({ page }) => {
return true;
}
});
const signoff = page.waitForResponse((response) => {
if (response.url().includes('/signoff') && response.status() === 302) {
return true;
}
});
await logoutButton.click();
await revokeCall;
await signoff;
await expect(page.getByText('Username/Password Form')).toBeVisible();
});
test('ensure query params passed to start are sent off in authorize call', async ({ page }) => {
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 @@ -10,11 +10,11 @@
},
"dependencies": {
"@forgerock/device-client": "workspace:*",
"@forgerock/javascript-sdk": "4.7.0",
"effect": "^3.12.7"
"@forgerock/javascript-sdk": "catalog:",
"effect": "catalog:effect"
},
"devDependencies": {
"@effect/language-service": "^0.20.0"
"@effect/language-service": "catalog:effect"
},
"nx": {
"tags": ["scope:e2e"]
Expand Down
2 changes: 1 addition & 1 deletion e2e/protect-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"serve": "pnpm nx nxServe"
},
"dependencies": {
"@forgerock/javascript-sdk": "4.7.0",
"@forgerock/javascript-sdk": "catalog:",
"@forgerock/protect": "workspace:*"
},
"nx": {
Expand Down
11 changes: 11 additions & 0 deletions lefthook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ pre-commit:
format:
run: pnpm nx format:write
stage_fixed: true
syncpack:
glob: >-
{package.json,
pnpm-workspace.yaml,
packages/*/package.json,
packages/sdk-effects/*/package.json,
packages/utils/*/package.json,
e2e/*/package.json,
tools/*/package.json,
scratchpad/package.json}
run: pnpm syncpack:lint
interface-mapping:
glob: >-
{tools/interface-mapping-validator/**/*.ts,
Expand Down
14 changes: 8 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
"preinstall": "npx only-allow pnpm",
"prepare": "lefthook install",
"serve": "nx serve",
"syncpack:lint": "syncpack lint --source 'package.json' --source 'packages/*/package.json' --source 'packages/sdk-effects/*/package.json' --source 'packages/utils/*/package.json' --source 'e2e/*/package.json' --source 'tools/*/package.json' --source 'scratchpad/package.json'",
"syncpack:fix": "syncpack fix --source 'package.json' --source 'packages/*/package.json' --source 'packages/sdk-effects/*/package.json' --source 'packages/utils/*/package.json' --source 'e2e/*/package.json' --source 'tools/*/package.json' --source 'scratchpad/package.json'",
"test": "CI=true nx affected:test",
"test:e2e": "CI=true nx affected:e2e",
"verdaccio": "nx local-registry",
Expand All @@ -45,7 +47,6 @@
"path": "./node_modules/cz-conventional-changelog"
}
},
"dependencies": {},
"devDependencies": {
"@changesets/changelog-github": "^0.6.0",
"@changesets/cli": "^2.27.9",
Expand All @@ -55,6 +56,7 @@
"@effect/cli": "catalog:effect",
"@eslint/eslintrc": "^3.0.0",
"@eslint/js": "~9.39.0",
"@evilmartians/lefthook": "^2.1.4",
"@nx/devkit": "22.6.5",
"@nx/eslint": "22.6.5",
"@nx/eslint-plugin": "22.6.5",
Expand All @@ -74,13 +76,13 @@
"@swc/helpers": "0.5.21",
"@types/eslint": "9.6.1",
"@types/estree": "^1.0.1",
"@types/express": "5.0.6",
"@types/express": "catalog:",
"@types/node": "24.9.2",
"@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/parser": "^8.45.0",
"@typescript-eslint/typescript-estree": "8.23.0",
"@typescript-eslint/utils": "^8.13.0",
"@vitest/coverage-v8": "3.2.4",
"@vitest/coverage-v8": "catalog:vitest",
"@vitest/ui": "3.2.4",
"conventional-changelog-conventionalcommits": "^8.0.0",
"cz-conventional-changelog": "^3.3.0",
Expand All @@ -92,7 +94,6 @@
"eslint-plugin-playwright": "^2.0.0",
"eslint-plugin-prettier": "^5.2.3",
"fast-check": "^4.0.0",
"@evilmartians/lefthook": "^2.1.4",
"jiti": "2.6.1",
"jsdom": "27.4.0",
"jsonc-eslint-parser": "^2.1.0",
Expand All @@ -103,10 +104,11 @@
"prettier": "^3.2.5",
"shx": "^0.4.0",
"swc-loader": "0.2.7",
"syncpack": "^15.0.0",
"ts-node": "10.9.2",
"tsx": "^4.20.0",
"ts-patch": "3.3.0",
"tslib": "^2.5.0",
"tslib": "catalog:",
"tsx": "catalog:",
"typedoc": "^0.27.4",
"typedoc-github-theme": "0.2.1",
"typedoc-plugin-rename-defaults": "^0.7.2",
Expand Down
Loading
Loading