diff --git a/README.md b/README.md index 740072d..95ee340 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ Monorepo for the **Aziface Web SDK** (`@azify/aziface-web`) and reference demo a ## Packages & apps -| Path | Description | -| --- | --- | +| Path | Description | +| ---------------------------------------- | ------------------------------------------------------------------------------------------- | | [`packages/aziface`](./packages/aziface) | Publishable SDK — biometric flows for React (enroll, authenticate, liveness, document scan) | -| [`apps/nextapp`](./apps/nextapp) | Next.js demo app | -| [`apps/viteapp`](./apps/viteapp) | Vite + React demo app | +| [`apps/nextapp`](./apps/nextapp) | Next.js demo app | +| [`apps/viteapp`](./apps/viteapp) | Vite + React demo app | **SDK documentation (installation, API, types):** [packages/aziface/README.md](./packages/aziface/README.md) @@ -28,15 +28,15 @@ npm ci ### Development -| Command | Description | -| --- | --- | -| `npm run dev` | Start all workspaces that expose a `dev` script | -| `npm run next:dev` | Next.js demo at `http://localhost:3000` | -| `npm run vite:dev` | Vite demo at `http://localhost:5173` | -| `npm run build` | Build all workspaces | -| `npm run next:build` | Build Next.js demo only | -| `npm run vite:build` | Build Vite demo only | -| `npm run clean` | Remove build artifacts | +| Command | Description | +| -------------------- | ----------------------------------------------- | +| `npm run dev` | Start all workspaces that expose a `dev` script | +| `npm run next:dev` | Next.js demo at `http://localhost:3000` | +| `npm run vite:dev` | Vite demo at `http://localhost:5173` | +| `npm run build` | Build all workspaces | +| `npm run next:build` | Build Next.js demo only | +| `npm run vite:build` | Build Vite demo only | +| `npm run clean` | Remove build artifacts | ### SDK package only @@ -69,10 +69,10 @@ aziface-web/ **Commit → release mapping** (configured in `.releaserc.js`): -| Commit type | Version bump | -| --- | --- | -| `feat`, `chore` | minor | -| `fix`, `perf`, `style` | patch | +| Commit type | Version bump | +| ------------------------- | --------------------------------- | +| `feat`, `chore` | minor | +| `fix`, `perf`, `style` | patch | | `BREAKING CHANGE` in body | major (default analyzer behavior) | ### CI @@ -104,11 +104,11 @@ Requires `GH_TOKEN` and `NPM_TOKEN` with publish access to the `@azify` scope. ### GitHub Actions secrets -| Secret | Purpose | -| --- | --- | -| `GH_TOKEN_V2` | Push release commits, create GitHub releases | -| `NPM_TOKEN_V2` | Publish `@azify/aziface-web` to npm (Automation token with **Read and Write** on `@azify`) | -| `AZIFACE_ASSETS_URL` | FaceTec assets (CI/internal use) | +| Secret | Purpose | +| -------------------- | ------------------------------------------------------------------------------------------ | +| `GH_TOKEN_V2` | Push release commits, create GitHub releases | +| `NPM_TOKEN_V2` | Publish `@azify/aziface-web` to npm (Automation token with **Read and Write** on `@azify`) | +| `AZIFACE_ASSETS_URL` | FaceTec assets (CI/internal use) | ## License diff --git a/apps/nextapp/app/home.tsx b/apps/nextapp/app/home.tsx index 9291cbd..94e5580 100644 --- a/apps/nextapp/app/home.tsx +++ b/apps/nextapp/app/home.tsx @@ -1,22 +1,17 @@ 'use client'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import toast, { Toaster } from 'react-hot-toast'; import { useBiometricConfigs } from '@/services'; import { useUser } from '@/hooks'; import { - authenticate, dispose, - enroll, initialize, - liveness, - photoMatch, - photoScan, setLocale, - SessionError, InitializeParams, InitializeHeaders, Locale, + useAziface, } from '@azify/aziface-web'; import { FaceType } from '@/types/services.types'; import { LOCALES } from '@/constants'; @@ -28,6 +23,8 @@ export function Home() { const { data: configs } = useBiometricConfigs(); const { tokenBiometric, logout } = useUser(); + const { error, authenticate, enroll, liveness, photoMatch, photoScan } = + useAziface(); const onInitialize = (): void => { const params: InitializeParams = { @@ -72,33 +69,32 @@ export function Home() { }; const onFaceScan = async (type: FaceType): Promise => { - try { - switch (type) { - case 'enroll': - await enroll(); - break; - case 'authenticate': - await authenticate(); - break; - case 'liveness': - await liveness(); - break; - case 'photoMatch': - await photoMatch(); - break; - case 'photoScan': - await photoScan(); - break; - default: - toast.error(`Invalid face scan type: ${type}`); - break; - } - } catch (error) { - const sessionError = error as SessionError; - toast.error(sessionError.message); + switch (type) { + case 'enroll': + await enroll(); + break; + case 'authenticate': + await authenticate(); + break; + case 'liveness': + await liveness(); + break; + case 'photoMatch': + await photoMatch(); + break; + case 'photoScan': + await photoScan(); + break; + default: + toast.error(`Invalid face scan type: ${type}`); + break; } }; + useEffect(() => { + if (error) toast.error(error.message); + }, [error]); + return (
diff --git a/apps/nextapp/package.json b/apps/nextapp/package.json index b8b8142..1bdab96 100644 --- a/apps/nextapp/package.json +++ b/apps/nextapp/package.json @@ -16,7 +16,7 @@ "react-dom": "19.2.3", "react-hot-toast": "^2.6.0", "react-if": "^4.1.6", - "zustand": "^5.0.12" + "zustand": "^5.0.14" }, "devDependencies": { "@tailwindcss/postcss": "^4", diff --git a/apps/viteapp/README.md b/apps/viteapp/README.md index 14e2439..f5af884 100644 --- a/apps/viteapp/README.md +++ b/apps/viteapp/README.md @@ -8,13 +8,14 @@ Use this app to validate SDK changes in a Vite environment before publishing. - Node.js 22+ - FaceTec assets under `public/core/` (see [SDK static assets](../../packages/aziface/README.md#static-assets)) + ## Environment variables -| Variable | App | Description | -| --- | --- | --- | +| Variable | App | Description | +| ---------------------------- | ------- | -------------------- | | `VITE_PUBLIC_API_URL_AZTECH` | ViteApp | Aziface API base URL | -| `VITE_PUBLIC_API_CLIENT_API` | ViteApp | Client API base URL | -| `VITE_PUBLIC_X_API_KEY` | ViteApp | API key header | +| `VITE_PUBLIC_API_CLIENT_API` | ViteApp | Client API base URL | +| `VITE_PUBLIC_X_API_KEY` | ViteApp | API key header | Create a `.env` file in this directory with the values above (ask the team for staging credentials). @@ -38,12 +39,12 @@ npm run lint ## Project layout -| Path | Description | -| --- | --- | -| `src/screens/` | App screens (`login`, `home`) | -| `src/services/` | API client and biometric config | +| Path | Description | +| ---------------------- | -------------------------------- | +| `src/screens/` | App screens (`login`, `home`) | +| `src/services/` | API client and biometric config | | `public/core/facetec/` | FaceTec SDK script and resources | -| `public/core/images/` | Theme images for `withTheme` | +| `public/core/images/` | Theme images for `withTheme` | ## SDK integration diff --git a/apps/viteapp/eslint.config.js b/apps/viteapp/eslint.config.js index 5e6b472..ef614d2 100644 --- a/apps/viteapp/eslint.config.js +++ b/apps/viteapp/eslint.config.js @@ -16,7 +16,6 @@ export default defineConfig([ reactRefresh.configs.vite, ], languageOptions: { - ecmaVersion: 2020, globals: globals.browser, }, }, diff --git a/apps/viteapp/package.json b/apps/viteapp/package.json index 631b083..0a1bc39 100644 --- a/apps/viteapp/package.json +++ b/apps/viteapp/package.json @@ -10,29 +10,33 @@ "preview": "vite preview" }, "dependencies": { - "@azify/aziface-web": "1.0.6", - "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-query": "5.74.9", + "@azify/aziface-web": "1.1.0", + "@tailwindcss/vite": "^4.3.3", + "@tanstack/react-query": "5.91.0", "axios": "1.13.6", - "react": "^19.2.4", - "react-dom": "^19.2.4", + "react": "^19.2.7", + "react-dom": "^19.2.7", "react-hot-toast": "^2.6.0", "react-if": "^4.1.6", - "tailwindcss": "^4.2.2", - "zustand": "5.0.3" + "tailwindcss": "^4.3.3", + "zustand": "5.0.14" }, "devDependencies": { - "@eslint/js": "^9.39.4", - "@types/node": "^24.12.2", - "@types/react": "^19.2.14", + "@babel/core": "^7.29.7", + "@eslint/js": "^10.0.1", + "@rolldown/plugin-babel": "^0.2.3", + "@types/babel__core": "^7.20.5", + "@types/node": "^24.13.2", + "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.1", - "eslint": "^9.39.4", - "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-react-refresh": "^0.5.2", - "globals": "^17.4.0", + "@vitejs/plugin-react": "^6.0.3", + "babel-plugin-react-compiler": "^1.0.0", + "eslint": "^10.6.0", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.3", + "globals": "^17.7.0", "typescript": "~6.0.2", - "typescript-eslint": "^8.58.0", - "vite": "^8.0.4" + "typescript-eslint": "^8.62.0", + "vite": "^8.1.1" } } diff --git a/apps/viteapp/src/main.tsx b/apps/viteapp/src/main.tsx index e17d50b..dcf08c3 100644 --- a/apps/viteapp/src/main.tsx +++ b/apps/viteapp/src/main.tsx @@ -1,6 +1,7 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import App from './App.tsx'; +import './index.css'; createRoot(document.getElementById('root')!).render( diff --git a/apps/viteapp/src/screens/home.tsx b/apps/viteapp/src/screens/home.tsx index 33c6b9b..8d6fd96 100644 --- a/apps/viteapp/src/screens/home.tsx +++ b/apps/viteapp/src/screens/home.tsx @@ -1,17 +1,12 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import toast, { Toaster } from 'react-hot-toast'; import { useBiometricConfigs } from '../services'; import { useUser } from '../hooks'; import { - authenticate, dispose, - enroll, initialize, - liveness, - photoMatch, - photoScan, setLocale, - SessionError, + useAziface, type InitializeParams, type InitializeHeaders, type Locale, @@ -26,6 +21,8 @@ export function Home() { const { data: configs } = useBiometricConfigs(); const { tokenBiometric, logout } = useUser(); + const { error, authenticate, enroll, liveness, photoMatch, photoScan } = + useAziface(); const onInitialize = (): void => { const params: InitializeParams = { @@ -70,33 +67,32 @@ export function Home() { }; const onFaceScan = async (type: FaceType): Promise => { - try { - switch (type) { - case 'enroll': - await enroll(); - break; - case 'authenticate': - await authenticate(); - break; - case 'liveness': - await liveness(); - break; - case 'photoMatch': - await photoMatch(); - break; - case 'photoScan': - await photoScan(); - break; - default: - toast.error(`Invalid face scan type: ${type}`); - break; - } - } catch (error) { - const sessionError = error as SessionError; - toast.error(sessionError.message); + switch (type) { + case 'enroll': + await enroll(); + break; + case 'authenticate': + await authenticate(); + break; + case 'liveness': + await liveness(); + break; + case 'photoMatch': + await photoMatch(); + break; + case 'photoScan': + await photoScan(); + break; + default: + toast.error(`Invalid face scan type: ${type}`); + break; } }; + useEffect(() => { + if (error) toast.error(error.message); + }, [error]); + return (
diff --git a/apps/viteapp/tsconfig.app.json b/apps/viteapp/tsconfig.app.json index 1d29c88..6830b6f 100644 --- a/apps/viteapp/tsconfig.app.json +++ b/apps/viteapp/tsconfig.app.json @@ -2,9 +2,10 @@ "compilerOptions": { "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "target": "es2023", - "lib": ["ES2023", "DOM", "DOM.Iterable"], + "lib": ["ES2023", "DOM"], "module": "esnext", "types": ["vite/client"], + "allowArbitraryExtensions": true, "skipLibCheck": true, /* Bundler mode */ diff --git a/apps/viteapp/tsconfig.node.json b/apps/viteapp/tsconfig.node.json index d3c52ea..8455dcb 100644 --- a/apps/viteapp/tsconfig.node.json +++ b/apps/viteapp/tsconfig.node.json @@ -3,12 +3,11 @@ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "target": "es2023", "lib": ["ES2023"], - "module": "esnext", "types": ["node"], "skipLibCheck": true, /* Bundler mode */ - "moduleResolution": "bundler", + "module": "nodenext", "allowImportingTsExtensions": true, "verbatimModuleSyntax": true, "moduleDetection": "force", diff --git a/apps/viteapp/vite.config.ts b/apps/viteapp/vite.config.ts index da17daf..b31e9a1 100644 --- a/apps/viteapp/vite.config.ts +++ b/apps/viteapp/vite.config.ts @@ -1,7 +1,13 @@ import { defineConfig } from 'vite'; -import react from '@vitejs/plugin-react'; +import react, { reactCompilerPreset } from '@vitejs/plugin-react'; +import babel from '@rolldown/plugin-babel'; import tailwindcss from '@tailwindcss/vite'; +// https://vite.dev/config/ export default defineConfig({ - plugins: [react(), tailwindcss()], + plugins: [ + react(), + tailwindcss(), + babel({ presets: [reactCompilerPreset()] }), + ], }); diff --git a/packages/aziface/README.md b/packages/aziface/README.md index 0bc92f0..3ff087c 100644 --- a/packages/aziface/README.md +++ b/packages/aziface/README.md @@ -18,11 +18,6 @@ Web SDK adapter for React — face enrollment, authentication, liveness, and doc - [`Properties`](#properties) - [`dispose`](#dispose) - [`Properties`](#properties-1) - - [`enroll`](#enroll) - - [`authenticate`](#authenticate) - - [`liveness`](#liveness) - - [`photoScan`](#photoscan) - - [`photoMatch`](#photomatch) - [`withTheme`](#withtheme) - [`Properties`](#properties-2) - [`Custom images`](#custom-images) @@ -30,6 +25,14 @@ Web SDK adapter for React — face enrollment, authentication, liveness, and doc - [`resetTheme`](#resettheme) - [`setLocale`](#setlocale) - [`Properties`](#properties-3) +- [Hooks] + - [`useAziface`](#useaziface) + - [`Properties`](#properties-4) + - [`enroll`](#enroll) + - [`authenticate`](#authenticate) + - [`liveness`](#liveness) + - [`photoScan`](#photoscan) + - [`photoMatch`](#photomatch) - [Styles](#styles) - [Types](#types) - [`Initialize`](#initialize-1) @@ -57,21 +60,25 @@ Web SDK adapter for React — face enrollment, authentication, liveness, and doc - **FaceTec static assets** hosted by your application (not bundled in the npm package) - Valid Aziface credentials: `deviceKeyIdentifier`, `baseUrl`, and `x-token-bearer` +
+ ## Installation ```bash npm i @azify/aziface-web ``` +
+ ## Static assets The SDK expects FaceTec resources to be available at runtime. Host the following paths in your app's public directory: -| Path | Purpose | -| --- | --- | -| `/core/facetec/FaceTecSDK.js` | FaceTec browser SDK (loaded via `