-
Notifications
You must be signed in to change notification settings - Fork 3
Recognize setup #691
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?
Recognize setup #691
Changes from all commits
39ee8bf
b60f46c
e9817c8
0d673aa
b66ab2b
7bd16ba
43da855
01690ab
79e5c7e
af2a930
1ce8a57
6f3cc8d
ca4d39b
821537f
f56144a
f1b5aa8
0d316df
3929c3d
84922f6
f510de4
9c87943
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,5 @@ | ||
| --- | ||
| '@forgerock/recognize': minor | ||
| --- | ||
|
|
||
| Initial release of the Ping Recognize SDK |
| 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, | ||
| ]; |
| 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"] | ||
| } | ||
| } |
| 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> |
| 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); | ||
| }); | ||
| } | ||
| 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; | ||
| } |
| 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" | ||
| } | ||
| ] | ||
| } |
| 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" | ||
| } | ||
| ] | ||
| } |
| 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', | ||
| }, | ||
| }, | ||
| }, | ||
| })); |
|
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. We should probably update this.
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. Before we officially publish this, we will need to add a summary, instructions, example code, and how to find more documentation and such to this README. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,56 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # @forgerock/recognize | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| Facial recognition client for the Ping JavaScript SDK. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Installation | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||||||||||||
| npm install @forgerock/recognize | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Usage | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { recognize } from '@forgerock/recognize'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| 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', err), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| complete: (detail) => console.log('[recognize] complete', detail), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| await client.init({ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| mode: 'mount', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| container: document.getElementById('app'), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type: 'auth', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| username: 'USERNAME', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+23
to
+34
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. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Fix TypeScript compilation errors in the usage example. In strict mode, TypeScript users copying this example will encounter compilation errors:
📝 Proposed fix to make the example strictly typed client.subscribe({
- next: (event) => console.log('[recognize]', event.type, event.detail),
+ next: (event) => console.log('[recognize]', event.type, 'detail' in event ? event.detail : undefined),
error: (err) => console.error('[recognize] error', err),
complete: (detail) => console.log('[recognize] complete', detail),
});
await client.init({
mode: 'mount',
- container: document.getElementById('app'),
+ container: document.getElementById('app') as HTMLElement,
type: 'auth',
username: 'USERNAME',
});📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| // When done | ||||||||||||||||||||||||||||||||||||||||||||||||||
| client.dispose(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Configuration | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| | Option | Type | Required | Description | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| |--------|------|----------|-------------| | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `customer` | `string` | Yes | Customer identifier | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `serviceURL` | `string` | Yes | URL of the recognition service | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `authorizationToken` | `string` | No | Authorization token | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `lang` | `string` | No | Language code for the UI | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `theme` | `unknown` | No | Theme object | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `disableSteps` | `string[]` | No | Steps to skip in the flow | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `enableCameraFlash` | `boolean` | No | Enable camera flash | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `enableCameraInstructions` | `boolean` | No | Show camera instructions | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `disableLogger` | `boolean` | No | Disable internal logging | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `disablePoweredBy` | `boolean` | No | Hide the "Powered by" badge | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `enableWasmPthreads` | `boolean` | No | Enable WASM pthreads | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `operationID` | `string` | No | Custom operation ID | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| | `transactionData` | `string` | No | Transaction data string | | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| 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}/vitest.config.{js,ts,mjs,mts}', | ||
| '{projectRoot}/src/lib/recognize-sdk/**/*', | ||
| ], | ||
| ignoredDependencies: ['tslib'], | ||
| }, | ||
| ], | ||
| }, | ||
| languageOptions: { | ||
| parser: await import('jsonc-eslint-parser'), | ||
| }, | ||
| }, | ||
| { | ||
| ignores: ['**/out-tsc', '**/recognize-sdk/**'], | ||
| }, | ||
| ]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| { | ||
| "name": "@forgerock/recognize", | ||
| "version": "0.0.1", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/ForgeRock/ping-javascript-sdk.git", | ||
| "directory": "packages/recognize" | ||
| }, | ||
| "description": "Facial recognition client for the Ping JavaScript SDK", | ||
| "license": "MIT", | ||
| "author": "ForgeRock", | ||
| "sideEffects": ["dist/src/lib/recognize-sdk/index.js"], | ||
| "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": { | ||
| "lint": "pnpm nx nxLint", | ||
| "test": "pnpm nx nxTest", | ||
| "test:watch": "pnpm nx nxTest --watch" | ||
| }, | ||
| "dependencies": {}, | ||
| "devDependencies": { | ||
| "@aracna/web-components": "^1.1.18" | ||
| }, | ||
|
Comment on lines
+31
to
+34
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. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Description: Check if `@aracna/web-components` is imported in exported types.
# Test: Search for `@aracna/web-components` imports in the lib directory
rg '`@aracna`' packages/recognize/src/lib/Repository: ForgeRock/ping-javascript-sdk Length of output: 3242 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '--- packages/recognize/package.json ---'
cat -n packages/recognize/package.json
echo
echo '--- related package manifests mentioning `@aracna/web-components` ---'
rg -n '"`@aracna/web-components`"|peerDependencies|dependencies|devDependencies' packages/recognize package.json -g 'package.json'Repository: ForgeRock/ping-javascript-sdk Length of output: 2533 🏁 Script executed: #!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p = Path('packages/recognize/package.json')
print(p.read_text())
PYRepository: ForgeRock/ping-javascript-sdk Length of output: 1776 Move
🤖 Prompt for AI Agents |
||
| "publishConfig": { | ||
| "access": "public" | ||
| }, | ||
| "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" | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
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. We like to use the convention of separating runtime code and type definitions. We try to only export the runtime code in the root |
| 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'; |
|
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. We like to treat errors within the SDK as plain objects, rather than extensions of the |
| 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 { | ||
|
Contributor
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. Should we enforce functional patterns here? |
||
| code: RecognizeErrorCode; | ||
|
|
||
| constructor(code: RecognizeErrorCode, options?: ErrorOptions) { | ||
| super(RecognizeErrorCode[code], options); | ||
|
|
||
| this.code = code; | ||
| this.name = 'RecognizeError'; | ||
| } | ||
| } | ||
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.
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
🤖 Prompt for AI Agents