@41devs/naya-id-angular 0.1.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,221 +1,111 @@
1
+ import { StartVerificationParams, NayaResult, NayaEvent, NayaSupport, NayaCountryCode, NayaDocumentType } from '@41devs/naya-id-js';
2
+ export { NayaAuth, NayaCaptureOptions, NayaConfig, NayaConsentOptions, NayaCountryCode, NayaDocumentType, NayaDocumentTypeMismatchPolicy, NayaErrorCode, NayaEvent, NayaEventName, NayaHandoffOptions, NayaLivenessAssets, NayaLivenessOptions, NayaLocale, NayaOcrData, NayaResult, NayaStatus, NayaSupport, NayaThemeOverrides, ResolvedNayaConfig, StartVerificationParams } from '@41devs/naya-id-js';
1
3
  import * as i0 from '@angular/core';
2
4
 
3
5
  /**
4
- * Configuration du parcours de vérification Naya ID.
5
- *
6
- * Reprend, à l'identique, le modèle du SDK Flutter : tous les champs sont
7
- * optionnels et le SDK fonctionne avec des valeurs par défaut raisonnables
8
- * (tous pays, tous documents, français).
9
- */
10
- /** Pays supportés par Naya ID (zone CEDEAO). Code = ISO 3166-1 alpha-2. */
11
- declare const NAYA_COUNTRIES: readonly [{
12
- readonly code: "BJ";
13
- readonly label: "Bénin";
14
- }, {
15
- readonly code: "CI";
16
- readonly label: "Côte d'Ivoire";
17
- }, {
18
- readonly code: "SN";
19
- readonly label: "Sénégal";
20
- }, {
21
- readonly code: "ML";
22
- readonly label: "Mali";
23
- }, {
24
- readonly code: "BF";
25
- readonly label: "Burkina Faso";
26
- }, {
27
- readonly code: "TG";
28
- readonly label: "Togo";
29
- }];
30
- type NayaCountryCode = (typeof NAYA_COUNTRIES)[number]['code'];
31
- /** Types de documents acceptés. La valeur est envoyée telle quelle à l'API. */
32
- type NayaDocumentType = 'cni' | 'passeport' | 'permis';
33
- declare const NAYA_DOCUMENT_TYPES: readonly NayaDocumentType[];
34
- /** Langues de l'interface du SDK. */
35
- type NayaLocale = 'fr' | 'en';
36
- /**
37
- * Fournisseur d'authentification.
38
- *
39
- * Deux modes, un seul à renseigner :
40
- * • `apiKey` — la clé d'application est transmise depuis le navigateur.
41
- * Simple, mais la clé est lisible côté client : à réserver
42
- * aux démos et aux intégrations où le front est maîtrisé.
43
- * • `sessionToken` — jeton éphémère obtenu par le backend du client, limité à
44
- * une vérification. À privilégier en production. Le SDK est
45
- * prêt à le consommer dès que l'API l'expose.
46
- *
47
- * L'abstraction est volontaire : passer de l'un à l'autre ne touche pas au reste
48
- * du SDK.
6
+ * Parcours réutilisable : une instance qu'on ouvre, ferme et écoute.
7
+ * Miroir de `create()` du SDK Naya, avec les rappels ramenés dans la zone
8
+ * Angular.
49
9
  */
50
- interface NayaAuth {
51
- apiKey?: string;
52
- sessionToken?: string;
53
- }
54
- /** Palette optionnelle : surcharge des couleurs de marque. */
55
- interface NayaThemeOverrides {
56
- /** Couleur principale (défaut : navy Naya #1A3A5C). */
57
- primaryColor?: string;
58
- /** Couleur d'accent des CTA (défaut : ambre Naya #F5A623). */
59
- accentColor?: string;
10
+ interface NayaVerification {
11
+ /** Monte l'interface et résout à la fermeture. Un seul `open` à la fois. */
12
+ open(): Promise<NayaResult>;
13
+ /** Ferme le parcours (résultat `cancelled`). */
14
+ close(): void;
15
+ /** Abonne un écouteur ; rend la fonction de désabonnement. */
16
+ on(event: NayaEvent['type'] | 'result', cb: (payload: NayaEvent | NayaResult) => void): () => void;
17
+ /** Ferme et libère les écouteurs. */
18
+ destroy(): void;
19
+ readonly isOpen: boolean;
60
20
  }
61
- interface NayaConfig {
62
- /** Pré-sélectionne le pays : l'utilisateur ne le choisit plus. */
63
- country?: NayaCountryCode;
64
- /**
65
- * Types de documents proposés. S'il n'y en a qu'un et que `country` est
66
- * défini, l'écran de sélection est sauté.
67
- */
68
- documentTypes?: readonly NayaDocumentType[];
69
- /** Pays proposés quand `country` n'est pas défini. */
70
- countries?: readonly NayaCountryCode[];
71
- /** Langue de l'interface. */
72
- locale?: NayaLocale;
73
- /**
74
- * URL (HTTPS) notifiée par le serveur Naya à chaque décision sur cette
75
- * session — décision automatique puis, le cas échéant, revue manuelle.
76
- */
77
- callbackUrl?: string;
78
- /** Nombre de parcours autorisés après un rejet (bouton « Réessayer »). */
79
- maxAttempts?: number;
80
- /** Surcharge des couleurs de marque. */
81
- theme?: NayaThemeOverrides;
82
- /** URL d'un logo client, affiché à côté de « Propulsé par Naya ID ». */
83
- clientLogoUrl?: string;
84
- /** Base URL de l'API — ne changer que pour un environnement de test. */
85
- baseUrl?: string;
86
- /**
87
- * Emplacement des ressources de détection de vivacité (MediaPipe). Par
88
- * défaut, elles sont chargées depuis un CDN public. Les applications à CSP
89
- * stricte (qui bloquent les hôtes externes) doivent auto-héberger ces
90
- * fichiers et renseigner ici leurs URL.
91
- */
92
- livenessAssets?: {
93
- /** Base des fichiers WASM `@mediapipe/tasks-vision`. */
94
- wasmBaseUrl?: string;
95
- /** URL du modèle `.task` de Face Landmarker. */
96
- modelUrl?: string;
97
- };
98
- }
99
- /** Libellé lisible d'un code pays. */
100
- declare function countryLabel(code: NayaCountryCode): string;
101
-
102
- /**
103
- * Résultat du parcours, rendu à l'application cliente à la fermeture du SDK.
104
- * Miroir fidèle du modèle Flutter (`naya_result.dart`).
105
- */
106
- /** Issue du parcours de vérification. */
107
- type NayaStatus =
108
- /** Identité vérifiée et approuvée automatiquement. */
109
- 'approved'
110
- /** Dossier envoyé en revue manuelle — décision finale ultérieure. */
111
- | 'review'
112
- /** Vérification rejetée (document expiré, visage non concordant…). */
113
- | 'rejected'
114
- /** L'utilisateur a quitté le parcours avant la fin. */
115
- | 'cancelled'
116
- /** Erreur technique (réseau, serveur…) ayant interrompu le parcours. */
117
- | 'error';
118
- /**
119
- * Données d'identité extraites du document par l'OCR Naya, éventuellement
120
- * corrigées par l'utilisateur.
121
- */
122
- interface NayaOcrData {
123
- lastName?: string;
124
- firstName?: string;
125
- /** Format YYYY-MM-DD. */
126
- dateOfBirth?: string;
127
- placeOfBirth?: string;
128
- nationality?: string;
129
- /** Format YYYY-MM-DD. */
130
- expirationDate?: string;
131
- documentNumber?: string;
132
- /** Numéro Personnel d'Identification (Bénin) — 10 chiffres. */
133
- npi?: string;
134
- issuingCountry?: string;
135
- issuingAuthority?: string;
136
- /** 'M' ou 'F'. */
137
- gender?: string;
138
- }
139
- /** Résultat retourné à l'application cliente. */
140
- interface NayaResult {
141
- status: NayaStatus;
142
- /**
143
- * Identifiant de la session Naya — à conserver côté client pour rapprocher
144
- * les notifications `callbackUrl` et le dashboard.
145
- */
146
- verificationId?: string;
147
- /** Score de risque agrégé 0-100 (plus haut = plus sûr). */
148
- riskScore?: number;
149
- /** Concordance faciale document ↔ selfie, 0-100. */
150
- matchScore?: number;
151
- /** Intégrité du document, 0-100. */
152
- authenticityScore?: number;
153
- /** Score de vivacité, 0-100. */
154
- livenessScore?: number;
155
- /** Confiance de l'extraction OCR, 0-100. */
156
- ocrConfidence?: number;
157
- /** Données d'identité finales (OCR fusionné avec les corrections). */
158
- ocrData?: NayaOcrData;
159
- /** Note d'analyse produite par le pipeline Naya. */
160
- note?: string;
161
- /** Détail de l'erreur quand `status` vaut `'error'`. */
162
- errorMessage?: string;
163
- }
164
-
165
21
  /**
166
22
  * Point d'entrée du SDK Naya ID pour Angular.
167
23
  *
168
- * Injecter le service, puis lancer le parcours :
169
- *
170
24
  * ```ts
171
25
  * const result = await this.naya.startVerification({
172
- * auth: { apiKey: 'naya_live_xxx' },
173
- * config: { country: 'BJ' },
26
+ * auth: { verificationId, sessionToken },
27
+ * config: { locale: 'fr' },
174
28
  * });
175
29
  * ```
176
30
  *
177
- * `startVerification` monte l'interface Naya en plein écran au-dessus de
178
- * l'application, gère la capture et la vivacité, puis résout un `NayaResult` :
179
- * `approved`, `review`, `rejected`, `cancelled` (l'utilisateur a quitté) ou
180
- * `error`. Elle ne rejette jamais.
31
+ * Le parcours (consentement, capture, vivacité, décision) est celui du SDK
32
+ * navigateur `@41devs/naya-id-js` : une seule implémentation, partagée avec
33
+ * les intégrations sans framework. Cette bibliothèque y ajoute ce qu'attend
34
+ * une application Angular :
35
+ *
36
+ * • **injection** — un service `providedIn: 'root'`, testable et
37
+ * remplaçable ;
38
+ * • **chargement différé** — le SDK n'entre pas dans le bundle initial ;
39
+ * il est importé au premier lancement ;
40
+ * • **zone** — le parcours tourne hors de la zone Angular (le flux caméra
41
+ * déclencherait sinon une détection de changements par trame), et les
42
+ * rappels de l'hôte y sont ramenés pour que signaux et vues se mettent
43
+ * à jour normalement ;
44
+ * • **rendu serveur** — sans `document`, le service rend une erreur typée
45
+ * au lieu de lever.
181
46
  */
182
47
  declare class NayaIdService {
183
- private readonly appRef;
184
- private readonly environmentInjector;
48
+ private readonly zone;
49
+ private readonly platformId;
50
+ /** Chargé une seule fois, au premier usage. */
51
+ private sdk?;
52
+ private load;
53
+ private get isBrowser();
54
+ private serverSideResult;
55
+ /**
56
+ * Enveloppe la configuration de l'hôte pour ramener ses rappels dans la
57
+ * zone Angular. Sans cela, un `onEvent` qui écrit dans un signal ne
58
+ * déclencherait aucun rafraîchissement : le parcours tourne hors zone.
59
+ */
60
+ private withZone;
185
61
  /**
186
62
  * Lance le parcours de vérification d'identité.
187
63
  *
188
- * @param params.auth Clé d'application (`apiKey`) ou jeton de session
189
- * éphémère (`sessionToken`). En production, privilégier
190
- * le jeton : la clé embarquée dans le front est lisible
191
- * côté navigateur.
192
- * @param params.config Configuration optionnelle (pays, documents, langue,
193
- * callbackUrl, thème…).
64
+ * Authentification, au choix :
65
+ * • `auth.verificationId` + `auth.sessionToken`, rendus à votre backend
66
+ * par `POST /verifications/start` — à privilégier en production, la
67
+ * clé ne quitte pas le serveur ;
68
+ * • `auth.apiKey` — démos et fronts maîtrisés. Une clé live doit
69
+ * déclarer ses origines dans le dashboard.
70
+ *
71
+ * **Ne rejette jamais** : une erreur ou une annulation revient sous forme
72
+ * de `NayaResult` (`status: 'error'` avec `errorCode`, ou `'cancelled'`).
73
+ */
74
+ startVerification(params: StartVerificationParams): Promise<NayaResult>;
75
+ /**
76
+ * Instance réutilisable, pour piloter l'ouverture et la fermeture depuis
77
+ * un composant et suivre les événements du parcours.
78
+ */
79
+ create(params: StartVerificationParams): Promise<NayaVerification>;
80
+ /**
81
+ * Vérifie que le navigateur peut exécuter le parcours (caméra, contexte
82
+ * sécurisé, navigateur intégré) avant de l'ouvrir.
83
+ */
84
+ isSupported(): Promise<NayaSupport>;
85
+ /** Version du SDK navigateur effectivement chargé. */
86
+ version(): Promise<string>;
87
+ /**
88
+ * Pays couverts, avec leur libellé — pour un sélecteur affiché par l'hôte
89
+ * avant d'ouvrir le parcours.
90
+ *
91
+ * Accesseur asynchrone, et non constante réexportée : une valeur importée
92
+ * statiquement depuis cette bibliothèque entraînerait tout le SDK
93
+ * navigateur dans le bundle initial de votre application. Vous n'en avez
94
+ * besoin que si vous construisez votre propre sélection ; sinon `config`
95
+ * accepte directement les codes (`country: 'BJ'`), typés par
96
+ * `NayaCountryCode`.
194
97
  */
195
- startVerification(params: {
196
- auth: NayaAuth;
197
- config?: NayaConfig;
198
- }): Promise<NayaResult>;
98
+ countries(): Promise<readonly {
99
+ code: NayaCountryCode;
100
+ label: string;
101
+ }[]>;
102
+ /** Types de pièces acceptés. Même remarque que [countries]. */
103
+ documentTypes(): Promise<readonly NayaDocumentType[]>;
104
+ /** Libellé lisible d'un code pays. */
105
+ countryLabel(code: NayaCountryCode): Promise<string>;
199
106
  static ɵfac: i0.ɵɵFactoryDeclaration<NayaIdService, never>;
200
107
  static ɵprov: i0.ɵɵInjectableDeclaration<NayaIdService>;
201
108
  }
202
109
 
203
- /**
204
- * Client HTTP du pipeline de vérification Naya.
205
- *
206
- * Bâti sur `fetch` natif — la librairie reste ainsi utilisable sans
207
- * `provideHttpClient` ni dépendance au module HTTP d'Angular. Les délais sont
208
- * dimensionnés pour les étapes longues (OCR et décision côté serveur).
209
- *
210
- * Authentification via `NayaAuth` : `apiKey` (en-tête `X-API-Key`) ou
211
- * `sessionToken` (en-tête `Authorization: Bearer`). Le choix est transparent
212
- * pour le reste du SDK.
213
- */
214
- /** Erreur renvoyée par l'API Naya ou par le transport réseau. */
215
- declare class NayaApiError extends Error {
216
- readonly statusCode?: number | undefined;
217
- constructor(message: string, statusCode?: number | undefined);
218
- }
219
-
220
- export { NAYA_COUNTRIES, NAYA_DOCUMENT_TYPES, NayaApiError, NayaIdService, countryLabel };
221
- export type { NayaAuth, NayaConfig, NayaCountryCode, NayaDocumentType, NayaLocale, NayaOcrData, NayaResult, NayaStatus, NayaThemeOverrides };
110
+ export { NayaIdService };
111
+ export type { NayaVerification };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@41devs/naya-id-angular",
3
- "version": "0.1.1",
4
- "description": "SDK Angular officiel de Naya ID — vérification d'identité (eKYC) clé en main pour l'Afrique de l'Ouest.",
3
+ "version": "0.4.0",
4
+ "description": "SDK Angular officiel de Naya ID — vérification d'identité (eKYC) clé en main pour l'Afrique de l'Ouest : consentement, capture guidée, défi de vivacité imposé par le serveur, confirmation des données, résultat expliqué.",
5
5
  "keywords": [
6
6
  "kyc",
7
7
  "ekyc",
@@ -14,12 +14,12 @@
14
14
  "license": "SEE LICENSE IN LICENSE",
15
15
  "author": "41Devs",
16
16
  "peerDependencies": {
17
- "@angular/common": "^20.3.0",
18
- "@angular/core": "^20.3.0"
17
+ "@angular/common": "^19.0.0 || ^20.0.0",
18
+ "@angular/core": "^19.0.0 || ^20.0.0"
19
19
  },
20
20
  "dependencies": {
21
21
  "tslib": "^2.3.0",
22
- "@mediapipe/tasks-vision": "^1.0.1"
22
+ "@41devs/naya-id-js": "^0.4.0"
23
23
  },
24
24
  "sideEffects": false,
25
25
  "module": "fesm2022/41devs-naya-id-angular.mjs",
@@ -1,292 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { inject, ApplicationRef, EnvironmentInjector, Injectable } from '@angular/core';
3
-
4
- /**
5
- * Configuration du parcours de vérification Naya ID.
6
- *
7
- * Reprend, à l'identique, le modèle du SDK Flutter : tous les champs sont
8
- * optionnels et le SDK fonctionne avec des valeurs par défaut raisonnables
9
- * (tous pays, tous documents, français).
10
- */
11
- /** Pays supportés par Naya ID (zone CEDEAO). Code = ISO 3166-1 alpha-2. */
12
- const NAYA_COUNTRIES = [
13
- { code: 'BJ', label: 'Bénin' },
14
- { code: 'CI', label: "Côte d'Ivoire" },
15
- { code: 'SN', label: 'Sénégal' },
16
- { code: 'ML', label: 'Mali' },
17
- { code: 'BF', label: 'Burkina Faso' },
18
- { code: 'TG', label: 'Togo' },
19
- ];
20
- const NAYA_DOCUMENT_TYPES = [
21
- 'cni',
22
- 'passeport',
23
- 'permis',
24
- ];
25
- const NAYA_DEFAULT_PRIMARY = '#1A3A5C';
26
- const NAYA_DEFAULT_ACCENT = '#F5A623';
27
- const NAYA_DEFAULT_BASE_URL = 'https://api.naya.41devs.com/v1';
28
- /** Applique les valeurs par défaut à une configuration partielle. */
29
- function resolveConfig(config = {}) {
30
- return {
31
- country: config.country,
32
- documentTypes: config.documentTypes ?? NAYA_DOCUMENT_TYPES,
33
- countries: config.countries ?? NAYA_COUNTRIES.map((c) => c.code),
34
- locale: config.locale ?? 'fr',
35
- callbackUrl: config.callbackUrl,
36
- maxAttempts: config.maxAttempts ?? 2,
37
- theme: {
38
- primaryColor: config.theme?.primaryColor ?? NAYA_DEFAULT_PRIMARY,
39
- accentColor: config.theme?.accentColor ?? NAYA_DEFAULT_ACCENT,
40
- },
41
- clientLogoUrl: config.clientLogoUrl,
42
- baseUrl: config.baseUrl ?? NAYA_DEFAULT_BASE_URL,
43
- livenessAssets: {
44
- wasmBaseUrl: config.livenessAssets?.wasmBaseUrl,
45
- modelUrl: config.livenessAssets?.modelUrl,
46
- },
47
- };
48
- }
49
- /** Libellé lisible d'un code pays. */
50
- function countryLabel(code) {
51
- return NAYA_COUNTRIES.find((c) => c.code === code)?.label ?? code;
52
- }
53
- /** La CNI CEDEAO porte sa MRZ au verso ; passeport et permis n'en ont pas besoin. */
54
- function documentNeedsVerso(doc) {
55
- return doc === 'cni';
56
- }
57
-
58
- /**
59
- * Point d'entrée du SDK Naya ID pour Angular.
60
- *
61
- * Injecter le service, puis lancer le parcours :
62
- *
63
- * ```ts
64
- * const result = await this.naya.startVerification({
65
- * auth: { apiKey: 'naya_live_xxx' },
66
- * config: { country: 'BJ' },
67
- * });
68
- * ```
69
- *
70
- * `startVerification` monte l'interface Naya en plein écran au-dessus de
71
- * l'application, gère la capture et la vivacité, puis résout un `NayaResult` :
72
- * `approved`, `review`, `rejected`, `cancelled` (l'utilisateur a quitté) ou
73
- * `error`. Elle ne rejette jamais.
74
- */
75
- class NayaIdService {
76
- appRef = inject(ApplicationRef);
77
- environmentInjector = inject(EnvironmentInjector);
78
- /**
79
- * Lance le parcours de vérification d'identité.
80
- *
81
- * @param params.auth Clé d'application (`apiKey`) ou jeton de session
82
- * éphémère (`sessionToken`). En production, privilégier
83
- * le jeton : la clé embarquée dans le front est lisible
84
- * côté navigateur.
85
- * @param params.config Configuration optionnelle (pays, documents, langue,
86
- * callbackUrl, thème…).
87
- */
88
- async startVerification(params) {
89
- const auth = params.auth;
90
- const config = resolveConfig(params.config);
91
- if (!auth.apiKey && !auth.sessionToken) {
92
- return {
93
- status: 'error',
94
- errorMessage: 'Authentification manquante : fournissez auth.apiKey ou auth.sessionToken.',
95
- };
96
- }
97
- // L'interface (overlay + écrans) est importée à la demande : elle reste
98
- // hors du bundle initial de l'application tant que la vérification n'est
99
- // pas lancée.
100
- const { mountNayaFlow } = await import('./41devs-naya-id-angular-naya-flow.launcher-xIwcsV6g.mjs');
101
- return mountNayaFlow({ appRef: this.appRef, environmentInjector: this.environmentInjector }, auth, config);
102
- }
103
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.28", ngImport: i0, type: NayaIdService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
104
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.28", ngImport: i0, type: NayaIdService, providedIn: 'root' });
105
- }
106
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.28", ngImport: i0, type: NayaIdService, decorators: [{
107
- type: Injectable,
108
- args: [{ providedIn: 'root' }]
109
- }] });
110
-
111
- /**
112
- * Résultat du parcours, rendu à l'application cliente à la fermeture du SDK.
113
- * Miroir fidèle du modèle Flutter (`naya_result.dart`).
114
- */
115
- const OCR_FIELDS = [
116
- 'lastName', 'firstName', 'dateOfBirth', 'placeOfBirth', 'nationality',
117
- 'expirationDate', 'documentNumber', 'npi', 'issuingCountry',
118
- 'issuingAuthority', 'gender',
119
- ];
120
- /** Lit un objet OCR brut de l'API en ne retenant que les champs connus. */
121
- function parseOcrData(raw) {
122
- if (!raw || typeof raw !== 'object')
123
- return undefined;
124
- const src = raw;
125
- const out = {};
126
- for (const field of OCR_FIELDS) {
127
- const value = src[field];
128
- if (typeof value === 'string' && value.length > 0)
129
- out[field] = value;
130
- }
131
- return Object.keys(out).length ? out : undefined;
132
- }
133
- /** Réduit un objet OCR à ses seuls champs renseignés, en chaînes. */
134
- function ocrToDeclaredData(ocr) {
135
- const out = {};
136
- for (const field of OCR_FIELDS) {
137
- const value = ocr[field];
138
- if (value)
139
- out[field] = value;
140
- }
141
- return out;
142
- }
143
- function cancelledResult(verificationId) {
144
- return { status: 'cancelled', verificationId };
145
- }
146
- function errorResult(errorMessage, verificationId) {
147
- return { status: 'error', errorMessage, verificationId };
148
- }
149
-
150
- /**
151
- * Client HTTP du pipeline de vérification Naya.
152
- *
153
- * Bâti sur `fetch` natif — la librairie reste ainsi utilisable sans
154
- * `provideHttpClient` ni dépendance au module HTTP d'Angular. Les délais sont
155
- * dimensionnés pour les étapes longues (OCR et décision côté serveur).
156
- *
157
- * Authentification via `NayaAuth` : `apiKey` (en-tête `X-API-Key`) ou
158
- * `sessionToken` (en-tête `Authorization: Bearer`). Le choix est transparent
159
- * pour le reste du SDK.
160
- */
161
- /** Erreur renvoyée par l'API Naya ou par le transport réseau. */
162
- class NayaApiError extends Error {
163
- statusCode;
164
- constructor(message, statusCode) {
165
- super(message);
166
- this.statusCode = statusCode;
167
- this.name = 'NayaApiError';
168
- }
169
- }
170
- const SECONDS = 1000;
171
- class NayaApiClient {
172
- auth;
173
- baseUrl;
174
- constructor(auth, baseUrl) {
175
- this.auth = auth;
176
- this.baseUrl = baseUrl;
177
- }
178
- headers() {
179
- const h = { 'Content-Type': 'application/json' };
180
- if (this.auth.sessionToken) {
181
- h['Authorization'] = `Bearer ${this.auth.sessionToken}`;
182
- }
183
- else if (this.auth.apiKey) {
184
- h['X-API-Key'] = this.auth.apiKey;
185
- }
186
- return h;
187
- }
188
- async post(path, body, timeoutMs = 30 * SECONDS) {
189
- const controller = new AbortController();
190
- const timer = setTimeout(() => controller.abort(), timeoutMs);
191
- let res;
192
- try {
193
- res = await fetch(`${this.baseUrl}${path}`, {
194
- method: 'POST',
195
- headers: this.headers(),
196
- body: JSON.stringify(body),
197
- signal: controller.signal,
198
- });
199
- }
200
- catch (err) {
201
- const aborted = err instanceof DOMException && err.name === 'AbortError';
202
- throw new NayaApiError(aborted ? 'Délai dépassé — réessayez.' : 'Réseau indisponible.');
203
- }
204
- finally {
205
- clearTimeout(timer);
206
- }
207
- let json;
208
- try {
209
- json = await res.json();
210
- }
211
- catch {
212
- throw new NayaApiError('Réponse illisible du serveur.', res.status);
213
- }
214
- if (res.status >= 400 || json?.success !== true) {
215
- const message = (json?.error && typeof json.error === 'object'
216
- ? json.error.message
217
- : undefined) ?? 'Erreur inconnue.';
218
- throw new NayaApiError(message, res.status);
219
- }
220
- return (json.data ?? {});
221
- }
222
- /** Ouvre une session de vérification. */
223
- async start(params) {
224
- const data = await this.post('/verifications/start', {
225
- documentType: params.documentType,
226
- country: params.country,
227
- ...(params.callbackUrl ? { callbackUrl: params.callbackUrl } : {}),
228
- device: 'Web',
229
- });
230
- return {
231
- verificationId: String(data['verificationId'] ?? ''),
232
- sessionToken: String(data['sessionToken'] ?? ''),
233
- };
234
- }
235
- /**
236
- * Envoie le document capturé. L'OCR serveur est synchrone : la réponse
237
- * contient les champs extraits, utilisés pour pré-remplir l'étape suivante.
238
- * Le verso, quand il est fourni, porte la MRZ des CNI CEDEAO.
239
- */
240
- async uploadDocument(verificationId, params) {
241
- const data = await this.post(`/verifications/${verificationId}/document`, {
242
- imageBase64Recto: params.rectoBase64,
243
- ...(params.versoBase64 ? { imageBase64Verso: params.versoBase64 } : {}),
244
- }, 120 * SECONDS);
245
- return parseOcrData(data['ocrData']);
246
- }
247
- /**
248
- * Envoie le selfie et le score de vivacité mesuré sur l'appareil.
249
- * `matchScore` est requis par l'endpoint mais recalculé côté serveur : on
250
- * transmet 0, comme le SDK Flutter.
251
- */
252
- async submitLiveness(verificationId, params) {
253
- await this.post(`/verifications/${verificationId}/liveness`, {
254
- livenessScore: params.livenessScore,
255
- matchScore: 0,
256
- selfieBase64: params.selfieBase64,
257
- }, 60 * SECONDS);
258
- }
259
- /** Déclenche l'analyse finale (OCR différé, biométrie, AML, décision). */
260
- async submit(verificationId, userDeclaredData) {
261
- const data = await this.post(`/verifications/${verificationId}/submit`, userDeclaredData && Object.keys(userDeclaredData).length
262
- ? { userDeclaredData }
263
- : {}, 180 * SECONDS);
264
- return {
265
- status: String(data['status'] ?? 'review'),
266
- riskScore: numOrUndef(data['riskScore']),
267
- matchScore: numOrUndef(data['matchScore']),
268
- authenticityScore: numOrUndef(data['authenticityScore']),
269
- livenessScore: numOrUndef(data['livenessScore']),
270
- ocrConfidence: numOrUndef(data['ocrConfidence']),
271
- ocrData: parseOcrData(data['ocrData']),
272
- note: typeof data['note'] === 'string' ? data['note'] : undefined,
273
- };
274
- }
275
- }
276
- function numOrUndef(v) {
277
- return typeof v === 'number' && !Number.isNaN(v) ? v : undefined;
278
- }
279
-
280
- /*
281
- * Surface publique du SDK Naya ID — Angular.
282
- *
283
- * Ce que l'application cliente importe : le service d'entrée, les modèles de
284
- * configuration et de résultat, et le type d'erreur du client HTTP.
285
- */
286
-
287
- /**
288
- * Generated bundle index. Do not edit.
289
- */
290
-
291
- export { NayaApiClient as N, NayaApiError as a, NAYA_COUNTRIES as b, countryLabel as c, documentNeedsVerso as d, errorResult as e, NAYA_DOCUMENT_TYPES as f, NayaIdService as g };
292
- //# sourceMappingURL=41devs-naya-id-angular-41devs-naya-id-angular-B7t92Ogc.mjs.map