Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
39ee8bf
feat: add-recognize-proxy
ryanbas21 Apr 23, 2026
b60f46c
feat: implement recognize client and error handling in SDK
eugeniobet-ping Jun 5, 2026
e9817c8
feat: refactor recognize SDK error handling and improve type definitions
eugeniobet-ping Jun 11, 2026
0d673aa
feat: update error handling in recognize SDK to throw descriptive err…
eugeniobet-ping Jun 12, 2026
b66ab2b
feat: update RecognizeWcCompleteDetail to use interface instead of ty…
eugeniobet-ping Jun 12, 2026
7bd16ba
feat: enhance recognize tests and update vitest configuration for jsd…
eugeniobet-ping Jun 12, 2026
43da855
feat: update createRecognizeError to use Error type for cause and imp…
eugeniobet-ping Jun 12, 2026
01690ab
feat: optimize error and event handling
dariosechi-ping Jun 12, 2026
79e5c7e
fix: export RecognizeError from recognize.types so index.ts can re-ex…
eugeniobet-ping Jun 15, 2026
af2a930
chore: replace empty interfaces with type aliases and reorder Recogni…
eugeniobet-ping Jun 15, 2026
1ce8a57
feat(recognize): rename Wc types, refactor error model, update bundle…
dariosechi-ping Jun 18, 2026
6f3cc8d
chore: update ESLint config to ignore recognize-sdk directory
eugeniobet-ping Jun 26, 2026
ca4d39b
feat: updated to use sdk 3.0
eugeniobet-ping Jul 6, 2026
821537f
feat: update Keyless SDK bundle and WASM binaries to v3.0
eugeniobet-ping Jul 6, 2026
f56144a
chore(recognize): remove stale WebSocket error codes dropped in v3.0
eugeniobet-ping Jul 6, 2026
f1b5aa8
feat(recognize): update Keyless SDK bundle and WASM binaries to v3.0.1
eugeniobet-ping Jul 7, 2026
0d316df
feat(recognize): update Keyless SDK type definitions to v3.0.1
eugeniobet-ping Jul 7, 2026
3929c3d
feat(recognize): handle recoverable-error, recognition-failure, and n…
eugeniobet-ping Jul 8, 2026
84922f6
feat(recognize): update Keyless SDK bundle, add new error codes and w…
dariosechi-ping Jul 8, 2026
f510de4
test(recognize): distinguish KeylessRecoverableErrorEvent from ErrorE…
dariosechi-ping Jul 8, 2026
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
24 changes: 24 additions & 0 deletions e2e/recognize-app/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import baseConfig from '../../eslint.config.mjs';

export default [
{
ignores: [
'node_modules',
'*.md',
'LICENSE',
'.swcrc',
'.babelrc',
'.env*',
'.bin',
'dist',
'.eslintignore',
'*.html',
'*.svg',
'*.css',
'public',
'*.json',
'*.d.ts',
],
},
...baseConfig,
];
18 changes: 18 additions & 0 deletions e2e/recognize-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@forgerock/recognize-app",
"version": "0.0.1",
"private": true,
"scripts": {
"build": "pnpm nx nxBuild",
"lint": "pnpm nx nxLint",
"preview": "pnpm nx nxPreview",
"serve": "pnpm nx nxServe"
},
"dependencies": {
"@forgerock/journey-client": "workspace:*",
"@forgerock/recognize": "workspace:*"
},
"nx": {
"tags": ["scope:e2e"]
}
}
14 changes: 14 additions & 0 deletions e2e/recognize-app/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Recognize E2E Test Index | Ping Identity JavaScript SDK</title>
</head>
<body>
<div id="app">
<h2>Recognize E2E Test Index | Ping Identity JavaScript SDK</h2>
</div>
<script type="module" src="index.ts"></script>
</body>
</html>
35 changes: 35 additions & 0 deletions e2e/recognize-app/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { recognize } from '@forgerock/recognize';
import './styles.css';

const client = recognize({
authorizationToken: 'USER_AUTHORIZATION_FROM_CUSTOMER',
customer: 'CUSTOMER_NAME',
serviceURL: 'KEYLESS_SERVICE_URL',
transactionData: 'DATA_FROM_CUSTOMER_SERVER_TO_BE_SIGNED',
});

client.subscribe({
next: (event) => {
console.log('[recognize]', event.type, event.detail);
},
error: (err) => {
console.error('[recognize] error', {
code: err.code,
message: err.message,
name: err.name,
cause: err.cause,
});
},
complete: (detail) => {
console.log('[recognize] complete', detail);
},
});

const appEl = document.getElementById('app');
if (appEl) {
client
.init({ mode: 'mount', container: appEl, type: 'auth', username: 'USERNAME' })
.then((err) => {
if (err) console.error('[recognize] init error', err);
});
Comment on lines +30 to +34

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

Handle the rejected init() promise path.

Only the fulfilled path is handled. If init() rejects, this can become an unhandled rejection and destabilize/flaky-fail E2E runs.

Proposed fix
 if (appEl) {
   client
     .init({ mode: 'mount', container: appEl, type: 'auth', username: 'USERNAME' })
     .then((err) => {
       if (err) console.error('[recognize] init error', err);
-    });
+    })
+    .catch((err) => {
+      console.error('[recognize] init rejected', err);
+    });
 }
📝 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
client
.init({ mode: 'mount', container: appEl, type: 'auth', username: 'USERNAME' })
.then((err) => {
if (err) console.error('[recognize] init error', err);
});
client
.init({ mode: 'mount', container: appEl, type: 'auth', username: 'USERNAME' })
.then((err) => {
if (err) console.error('[recognize] init error', err);
})
.catch((err) => {
console.error('[recognize] init rejected', err);
});
🤖 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/recognize-app/src/index.ts` around lines 32 - 36, The client.init()
promise chain in the mount initialization section only handles the fulfilled
path with .then(), leaving promise rejections unhandled which can cause flaky
E2E test failures. Add a .catch() handler after the .then() block to properly
handle any rejections that occur during the init() call, ensuring errors from
rejected promises are logged and don't destabilize the test execution.

}
11 changes: 11 additions & 0 deletions e2e/recognize-app/src/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
body {
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
margin: 0;
padding: 2rem;
}

#app {
max-width: 960px;
margin: 0 auto;
}
29 changes: 29 additions & 0 deletions e2e/recognize-app/tsconfig.app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"types": ["node"],
"rootDir": "src",
"module": "esnext",
"moduleResolution": "bundler",
"tsBuildInfoFile": "dist/tsconfig.app.tsbuildinfo"
},
"exclude": [
"out-tsc",
"dist",
"src/**/*.spec.ts",
"src/**/*.test.ts",
"eslint.config.js",
"eslint.config.cjs",
"eslint.config.mjs"
],
"include": ["src/**/*.ts"],
"references": [
{
"path": "../../packages/recognize/tsconfig.lib.json"
},
{
"path": "../../packages/journey-client/tsconfig.lib.json"
}
]
}
10 changes: 10 additions & 0 deletions e2e/recognize-app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
}
]
}
33 changes: 33 additions & 0 deletions e2e/recognize-app/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { defineConfig } from 'vite';
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));

export default defineConfig(() => ({
root: __dirname + '/src',
cacheDir: '../../node_modules/.vite/e2e/recognize-app',
publicDir: __dirname + '/public',
server: {
port: 8443,
host: 'localhost',
},
preview: {
port: 8443,
host: 'localhost',
},
plugins: [],
build: {
outDir: __dirname + '/dist',
emptyOutDir: true,
reportCompressedSize: true,
rollupOptions: {
input: {
main: resolve(__dirname + '/src', 'index.html'),
},
output: {
entryFileNames: '[name]/main.js',
},
},
},
}));
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
"path": "./node_modules/cz-conventional-changelog"
}
},
"dependencies": {},
"devDependencies": {
"@changesets/changelog-github": "^0.6.0",
"@changesets/cli": "^2.27.9",
Expand Down Expand Up @@ -131,6 +130,7 @@
"undici@^7": "^7.24.0",
"picomatch@>=4": "^4.0.4",
"picomatch@<3": "^2.3.2"
}
},
"onlyBuiltDependencies": ["@evilmartians/lefthook", "@swc/core", "nx"]
}
}
11 changes: 11 additions & 0 deletions packages/recognize/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# recognize

This library was generated with [Nx](https://nx.dev).

## Building

Run `nx build recognize` to build the library.

## Running unit tests

Run `nx test recognize` to execute the unit tests via [Vitest](https://vitest.dev/).
26 changes: 26 additions & 0 deletions packages/recognize/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import baseConfig from '../../eslint.config.mjs';

export default [
...baseConfig,
{
files: ['**/*.json'],
rules: {
'@nx/dependency-checks': [
'error',
{
ignoredFiles: [
'{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}',
'{projectRoot}/vite.config.{js,ts,mjs,mts}',
'{projectRoot}/src/lib/recognize-sdk/**/*',
],
},
],
},
languageOptions: {
parser: await import('jsonc-eslint-parser'),
},
},
{
ignores: ['**/out-tsc', '**/recognize-sdk/**'],
},
];
45 changes: 45 additions & 0 deletions packages/recognize/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "@forgerock/recognize",
"version": "0.0.1",
"private": true,
"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",
"dependencies": {
"tslib": "^2.3.0"
},
"devDependencies": {
"@aracna/web-components": "^1.1.18"
},
"nx": {
"tags": ["scope:package"],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "packages/recognize/dist",
"main": "packages/recognize/src/index.ts",
"tsConfig": "packages/recognize/tsconfig.lib.json",
"generatePackageJson": false,
"assets": [
{
"input": "packages/recognize/src/lib/recognize-sdk",
"glob": "**/*",
"output": "./src/lib/recognize-sdk"
}
]
}
}
}
}
}
15 changes: 15 additions & 0 deletions packages/recognize/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export { recognize, RecognizeError } from './lib/recognize.js';
export { RecognizeErrorCode } from './lib/defs/recognize-error-code.js';
export type {
RecognizeSessionType,
RecognizeWebComponent,
RecognizeWebComponentClient,
RecognizeWebComponentCompleteData,
RecognizeWebComponentConfiguration,
RecognizeWebComponentEvent,
RecognizeWebComponentInitOptions,
RecognizeWebComponentObserver,
RecognizeWebComponentStepChangeEventDetail,
RecognizeWebComponentUnsubscribe,
RecognizeWebComponentVideoFrameQualityEventDetail,
} from './lib/recognize.types.js';
13 changes: 13 additions & 0 deletions packages/recognize/src/lib/classes/recognize-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { RecognizeErrorCode } from '../defs/recognize-error-code.js';

/** @public */
export class RecognizeError extends Error {
code: RecognizeErrorCode;

constructor(code: RecognizeErrorCode, options?: ErrorOptions) {
super(RecognizeErrorCode[code], options);

this.code = code;
this.name = 'RecognizeError';
}
}
11 changes: 11 additions & 0 deletions packages/recognize/src/lib/defs/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/** @internal */
export const CAMERA_ONLY_DISABLE_STEPS: string[] = [
'bootstrap',
'camera-instructions',
'done',
'error',
'microphone-permission',
'server-computation',
'stm-choice',
'stm-qrcode',
];
51 changes: 51 additions & 0 deletions packages/recognize/src/lib/defs/recognize-error-code.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
*
* Copyright © 2026 Ping Identity Corporation. All right reserved.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*
*/

/** @public */
export enum RecognizeErrorCode {
SDK_ERROR = 1000,
SDK_NOT_CONFIGURED = 1001,
SDK_INVALID_CONFIGURATION = 1002,
SDK_LOGGING_CONFIGURATION_FAILED = 1003,
SDK_STORAGE_FAILED = 1004,
SDK_USER_CANCELLED = 1005,
SDK_TIMEOUT = 1006,
SDK_NO_NETWORK_CONNECTION = 1007,
SDK_DYNAMIC_LINKING_PAYLOAD_MALFORMED = 1008,
SDK_ARTIFACT_RETRIEVE_FAILED = 1009,
SDK_INVALID_CLIENT_STATE = 1010,
SDK_OUTDATED_APP = 1012,
SDK_WEB_ASSEMBLY_IMPORT_FAILED = 1013,
SDK_WEB_ASSEMBLY_IMPORT_NOT_FULFILLED = 1014,
SDK_WEB_ASSEMBLY_ERROR = 1015,
SDK_INVALID_CUSTOMER_PROPERTIES = 1016,
CAMERA_ERROR = 2000,
CAMERA_NOT_FOUND = 2001,
CAMERA_PERMISSION_DENIED = 2002,
CAMERA_NOT_SUPPORTED = 2003,
CORE_ERROR = 3000,
CORE_NOT_ENOUGH_API_KEY_SEATS = 3001,
CORE_USER_ALREADY_ENROLLED = 3002,
CORE_USER_NOT_ENROLLED = 3003,
CORE_FACE_NOT_MATCHING = 3004,
CORE_NOT_ENOUGH_CIRCUITS = 3005,
CORE_SECRET_NOT_FOUND = 3006,
CORE_USER_LOCKED_OUT = 3007,
CORE_CUSTOMER_NOT_FOUND = 3008,
BIOM_ERROR = 4000,
BIOM_REJECTED = 4001,
BIOM_GENUINE_PRESENCE_NOT_ESTABLISHED = 4002,
BIOM_LIVENESS_ENVIRONMENT_AWARE_NOT_SUPPORTED = 4003,
BIOM_DEVICE_ENVIRONMENT_AWARE_NOT_SUPPORTED = 4004,
SERVER_ERROR = 5000,
SERVER_RECOGNITION_FAILED = 5002,
SERVER_AUTHORIZATION_FAILED = 5003,
SECURITY_ERROR = 6000,
SECURITY_DEVICE_NOT_GENUINE = 6001,
}
Loading
Loading