@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/README.md +84 -193
- package/fesm2022/41devs-naya-id-angular.mjs +197 -1
- package/fesm2022/41devs-naya-id-angular.mjs.map +1 -1
- package/index.d.ts +88 -198
- package/package.json +5 -5
- package/fesm2022/41devs-naya-id-angular-41devs-naya-id-angular-B7t92Ogc.mjs +0 -292
- package/fesm2022/41devs-naya-id-angular-41devs-naya-id-angular-B7t92Ogc.mjs.map +0 -1
- package/fesm2022/41devs-naya-id-angular-naya-flow.launcher-xIwcsV6g.mjs +0 -2066
- package/fesm2022/41devs-naya-id-angular-naya-flow.launcher-xIwcsV6g.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,30 +1,23 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @41devs/naya-id-angular
|
|
2
2
|
|
|
3
|
-
SDK Angular officiel de **Naya ID
|
|
4
|
-
main pour l'Afrique de l'Ouest (zone CEDEAO). Votre application appelle **une
|
|
5
|
-
seule méthode** ; l'interface Naya s'ouvre en plein écran, prend en charge la
|
|
6
|
-
capture du document, la détection de vivacité et la décision, puis vous rend le
|
|
7
|
-
résultat et rend la main à votre application.
|
|
3
|
+
SDK Angular officiel de **[Naya ID](https://naya.41devs.com)** — vérification d'identité (eKYC) clé en main pour l'Afrique de l'Ouest.
|
|
8
4
|
|
|
9
|
-
|
|
10
|
-
parcours, mêmes écrans, même contrat d'API.
|
|
5
|
+
Un service injectable, un appel : consentement, capture guidée du document, selfie avec **défi de vivacité imposé par le serveur**, confirmation des données lues, décision expliquée — puis un `NayaResult` typé.
|
|
11
6
|
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
**Pays** : Bénin, Côte d'Ivoire, Sénégal, Mali, Burkina Faso, Togo.
|
|
8
|
+
**Documents** : CNI (CEDEAO), CIP (Bénin), passeport, permis de conduire.
|
|
9
|
+
**Langues** : français, anglais, portugais.
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
## Comment c'est construit
|
|
16
12
|
|
|
17
|
-
|
|
13
|
+
Le parcours est celui du SDK navigateur [`@41devs/naya-id-js`](https://www.npmjs.com/package/@41devs/naya-id-js) : **une seule implémentation**, partagée avec les intégrations sans framework. Cette bibliothèque y ajoute ce qu'attend une application Angular :
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
| **Entreprise vérifiée (KYB)** | La société propriétaire de la clé doit être **KYB-vérifiée**, sinon l'API renvoie `403`. |
|
|
24
|
-
| **HTTPS** | La caméra (`getUserMedia`) exige un **contexte sécurisé** : `https://` en production, ou `http://localhost` en développement. Sur `http://` distant, la caméra ne démarre pas. |
|
|
25
|
-
| **CORS** | L'origine de votre application doit être autorisée côté API Naya (liste `ALLOWED_ORIGINS`). |
|
|
15
|
+
- **injection** — un service `providedIn: 'root'`, testable et remplaçable ;
|
|
16
|
+
- **chargement différé** — le SDK n'entre pas dans le bundle initial (voir plus bas) ;
|
|
17
|
+
- **zone Angular** — le parcours tourne hors zone, sans quoi le flux caméra déclencherait une détection de changements à chaque trame ; vos rappels y sont ramenés, donc signaux et vues se mettent à jour normalement ;
|
|
18
|
+
- **rendu serveur** — sans `document`, le service rend une erreur typée au lieu de lever.
|
|
26
19
|
|
|
27
|
-
|
|
20
|
+
Conséquence utile : les correctifs et les nouveautés du parcours arrivent chez vous au prochain `npm update`, sans publication de cette bibliothèque.
|
|
28
21
|
|
|
29
22
|
## Installation
|
|
30
23
|
|
|
@@ -32,221 +25,119 @@ parcours, mêmes écrans, même contrat d'API.
|
|
|
32
25
|
npm install @41devs/naya-id-angular
|
|
33
26
|
```
|
|
34
27
|
|
|
35
|
-
|
|
36
|
-
Aucune configuration Angular supplémentaire : le SDK est *standalone*, il
|
|
37
|
-
s'injecte directement.
|
|
28
|
+
`@41devs/naya-id-js` est installé automatiquement. Angular 19 ou 20.
|
|
38
29
|
|
|
39
|
-
|
|
30
|
+
## Utilisation
|
|
40
31
|
|
|
41
|
-
|
|
32
|
+
### Session ouverte par votre backend (production)
|
|
42
33
|
|
|
43
|
-
|
|
44
|
-
quand l'utilisateur ressort du parcours, avec le résultat.
|
|
34
|
+
Votre serveur ouvre la vérification avec sa clé d'API — qui ne quitte jamais le serveur — puis ne confie au navigateur que `verificationId` et `sessionToken`.
|
|
45
35
|
|
|
46
36
|
```ts
|
|
47
|
-
import {
|
|
37
|
+
import { Component, inject, signal } from '@angular/core';
|
|
48
38
|
import { NayaIdService, type NayaResult } from '@41devs/naya-id-angular';
|
|
49
39
|
|
|
50
|
-
@Component({
|
|
51
|
-
|
|
52
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
53
|
-
template: `
|
|
54
|
-
<button (click)="verifier()" [disabled]="enCours()">
|
|
55
|
-
{{ enCours() ? 'Vérification…' : 'Vérifier mon identité' }}
|
|
56
|
-
</button>
|
|
57
|
-
`,
|
|
58
|
-
})
|
|
59
|
-
export class VerifyComponent {
|
|
40
|
+
@Component({ /* … */ })
|
|
41
|
+
export class KycComponent {
|
|
60
42
|
private readonly naya = inject(NayaIdService);
|
|
61
|
-
readonly
|
|
62
|
-
|
|
63
|
-
async
|
|
64
|
-
this.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
callbackUrl: 'https://votre-backend.com/naya/hook', // notification serveur (optionnel)
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
switch (result.status) {
|
|
75
|
-
case 'approved':
|
|
76
|
-
// Identité vérifiée. result.ocrData contient les champs extraits.
|
|
77
|
-
console.log('Approuvé', result.verificationId, result.ocrData);
|
|
78
|
-
break;
|
|
79
|
-
case 'review':
|
|
80
|
-
// Revue manuelle : décision finale notifiée plus tard via callbackUrl.
|
|
81
|
-
break;
|
|
82
|
-
case 'rejected':
|
|
83
|
-
// Refus (result.note explique pourquoi).
|
|
84
|
-
break;
|
|
85
|
-
case 'cancelled':
|
|
86
|
-
// L'utilisateur a fermé le parcours avant la fin.
|
|
87
|
-
break;
|
|
88
|
-
case 'error':
|
|
89
|
-
// Problème technique : result.errorMessage.
|
|
90
|
-
console.error(result.errorMessage);
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
} finally {
|
|
94
|
-
this.enCours.set(false);
|
|
95
|
-
}
|
|
43
|
+
readonly result = signal<NayaResult | null>(null);
|
|
44
|
+
|
|
45
|
+
async verify(session: { verificationId: string; sessionToken: string }) {
|
|
46
|
+
this.result.set(
|
|
47
|
+
await this.naya.startVerification({
|
|
48
|
+
auth: session,
|
|
49
|
+
config: { locale: 'fr' },
|
|
50
|
+
}),
|
|
51
|
+
);
|
|
96
52
|
}
|
|
97
53
|
}
|
|
98
54
|
```
|
|
99
55
|
|
|
100
|
-
|
|
101
|
-
revient toujours sous forme de `NayaResult` (`status: 'error'` ou `'cancelled'`).
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
## Le parcours vu par l'utilisateur
|
|
106
|
-
|
|
107
|
-
Une fois `startVerification` appelée, l'interface Naya enchaîne seule :
|
|
108
|
-
|
|
109
|
-
1. **Bienvenue** — écran d'accueil.
|
|
110
|
-
2. **Sélection** — pays et type de document (sautée si `country` + un seul `documentTypes`).
|
|
111
|
-
3. **Capture du document** — recto, puis verso pour la CNI (bande MRZ). Cadre vert quand l'image est nette ; l'utilisateur déclenche.
|
|
112
|
-
4. **Vivacité** — selfie avec défi actif : regarder droit → cligner → tourner la tête.
|
|
113
|
-
5. **Traitement** — OCR, biométrie, décision côté serveur.
|
|
114
|
-
6. **Résultat** — approuvé / en revue / rejeté, puis retour à votre application.
|
|
115
|
-
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
## Configuration (`config`)
|
|
119
|
-
|
|
120
|
-
Tous les champs sont optionnels — le SDK a des défauts raisonnables (tous pays,
|
|
121
|
-
tous documents, français).
|
|
122
|
-
|
|
123
|
-
| Champ | Type | Défaut | Rôle |
|
|
124
|
-
|---|---|---|---|
|
|
125
|
-
| `country` | `'BJ'\|'CI'\|'SN'\|'ML'\|'BF'\|'TG'` | — | Pré-sélectionne le pays ; l'utilisateur ne le choisit plus. |
|
|
126
|
-
| `documentTypes` | `('cni'\|'passeport'\|'permis')[]` | les trois | Types proposés. Un seul + `country` défini ⇒ écran de sélection sauté. |
|
|
127
|
-
| `countries` | `NayaCountryCode[]` | les six | Pays proposés quand `country` n'est pas fixé. |
|
|
128
|
-
| `locale` | `'fr' \| 'en'` | `'fr'` | Langue de l'interface. |
|
|
129
|
-
| `callbackUrl` | `string` | — | URL HTTPS notifiée par le serveur Naya à chaque décision (voir plus bas). |
|
|
130
|
-
| `maxAttempts` | `number` | `2` | Nombre d'essais autorisés après un rejet (bouton « Réessayer »). |
|
|
131
|
-
| `theme` | `{ primaryColor?, accentColor? }` | navy / ambre | Surcharge des couleurs de marque. |
|
|
132
|
-
| `clientLogoUrl` | `string` | — | Logo affiché à côté de « Propulsé par Naya ID ». |
|
|
133
|
-
| `livenessAssets` | `{ wasmBaseUrl?, modelUrl? }` | CDN public | Auto-hébergement MediaPipe (CSP stricte — voir plus bas). |
|
|
134
|
-
| `baseUrl` | `string` | API de prod | À ne changer que pour un environnement de test. |
|
|
135
|
-
|
|
136
|
-
---
|
|
137
|
-
|
|
138
|
-
## Résultat (`NayaResult`)
|
|
139
|
-
|
|
140
|
-
| Champ | Type | Présent quand |
|
|
141
|
-
|---|---|---|
|
|
142
|
-
| `status` | `'approved'\|'review'\|'rejected'\|'cancelled'\|'error'` | toujours |
|
|
143
|
-
| `verificationId` | `string` | dès qu'une session a été créée — à conserver pour rapprocher notifications et dashboard |
|
|
144
|
-
| `riskScore` | `number` (0-100) | après traitement — score de confiance agrégé |
|
|
145
|
-
| `matchScore` | `number` (0-100) | concordance visage document ↔ selfie |
|
|
146
|
-
| `authenticityScore` | `number` (0-100) | intégrité du document |
|
|
147
|
-
| `livenessScore` | `number` (0-100) | vivacité |
|
|
148
|
-
| `ocrConfidence` | `number` (0-100) | confiance de l'OCR |
|
|
149
|
-
| `ocrData` | `NayaOcrData` | champs extraits (nom, prénoms, date de naissance, n° document, NPI…) |
|
|
150
|
-
| `note` | `string` | note d'analyse du pipeline |
|
|
151
|
-
| `errorMessage` | `string` | uniquement si `status === 'error'` |
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## Authentification
|
|
156
|
-
|
|
157
|
-
Un seul des deux champs de `auth` est à renseigner :
|
|
158
|
-
|
|
159
|
-
| Mode | Usage |
|
|
160
|
-
|---|---|
|
|
161
|
-
| `apiKey` | Simple, mais la clé est **lisible dans le navigateur** (outils de dev). À réserver aux démos et aux intégrations où le front est maîtrisé. |
|
|
162
|
-
| `sessionToken` | Jeton éphémère obtenu par **votre backend**, limité à une vérification. **À privilégier en production** : la clé ne quitte jamais votre serveur. |
|
|
56
|
+
### Clé de test (démo)
|
|
163
57
|
|
|
164
58
|
```ts
|
|
165
|
-
// Production : votre backend échange sa clé contre un jeton de session, que
|
|
166
|
-
// vous passez au SDK.
|
|
167
59
|
await this.naya.startVerification({
|
|
168
|
-
auth: {
|
|
169
|
-
config: { country: 'BJ' },
|
|
60
|
+
auth: { apiKey: 'naya_test_xxx' },
|
|
61
|
+
config: { country: 'BJ', documentTypes: ['cni'] },
|
|
170
62
|
});
|
|
171
63
|
```
|
|
172
64
|
|
|
173
|
-
|
|
65
|
+
Une clé **live** utilisée depuis un navigateur doit déclarer ses origines dans le dashboard, sinon l'API répond `403`. Préférez la session serveur.
|
|
66
|
+
|
|
67
|
+
### Instance réutilisable
|
|
174
68
|
|
|
175
|
-
|
|
69
|
+
```ts
|
|
70
|
+
const verification = await this.naya.create({ auth, config });
|
|
71
|
+
verification.on('step', (e) => console.log(e));
|
|
72
|
+
const result = await verification.open();
|
|
73
|
+
verification.destroy();
|
|
74
|
+
```
|
|
176
75
|
|
|
177
|
-
|
|
76
|
+
### Résultat
|
|
178
77
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
78
|
+
`startVerification` **ne rejette jamais** : annulation et erreurs reviennent dans le `NayaResult`.
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
switch (result.status) {
|
|
82
|
+
case 'approved': break; // result.riskScore, result.ocrData…
|
|
83
|
+
case 'review': break; // décision finale notifiée sur callbackUrl
|
|
84
|
+
case 'rejected': break; // result.reasonCodes
|
|
85
|
+
case 'cancelled': break;
|
|
86
|
+
case 'error': break; // result.errorCode, result.requestId
|
|
87
|
+
}
|
|
88
|
+
```
|
|
184
89
|
|
|
185
|
-
|
|
90
|
+
Ne vous fiez jamais au résultat rendu par le navigateur pour décider : seul le webhook (ou `GET /verifications/:id` avec votre clé) fait foi.
|
|
186
91
|
|
|
187
|
-
##
|
|
92
|
+
## Configuration
|
|
188
93
|
|
|
189
|
-
La
|
|
190
|
-
défaut, le modèle et son binaire WASM sont chargés depuis un CDN public —
|
|
191
|
-
aucune configuration requise. L'analyse est **locale** : la photo n'est
|
|
192
|
-
transmise qu'à la fin du défi.
|
|
94
|
+
`config` est le `NayaConfig` du SDK navigateur — pays, documents, langue, consentement, confirmation des données lues, capture, vivacité, relais QR, thème, libellés surchargeables, télémétrie, `onEvent`. La liste complète et à jour est dans la [documentation du SDK navigateur](https://www.npmjs.com/package/@41devs/naya-id-js).
|
|
193
95
|
|
|
194
|
-
|
|
195
|
-
ces ressources et indiquez leurs URL :
|
|
96
|
+
Utile côté Angular :
|
|
196
97
|
|
|
197
98
|
```ts
|
|
198
99
|
config: {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
},
|
|
100
|
+
container: this.host.nativeElement, // monte le parcours dans votre page
|
|
101
|
+
theme: { primaryColor: '#172062', mode: 'auto', radius: 'soft' },
|
|
102
|
+
strings: { welcomeTitle: 'Vérifions votre identité' },
|
|
103
|
+
onEvent: (e) => this.analytics.track(e.type), // rappelé dans la zone Angular
|
|
204
104
|
}
|
|
205
105
|
```
|
|
206
106
|
|
|
207
|
-
|
|
208
|
-
`face_landmarker.task` dans les `assets` de votre application.
|
|
209
|
-
|
|
210
|
-
[MediaPipe Face Landmarker]: https://ai.google.dev/edge/mediapipe/solutions/vision/face_landmarker
|
|
211
|
-
|
|
212
|
-
---
|
|
107
|
+
## Pourquoi la bibliothèque n'exporte que des types
|
|
213
108
|
|
|
214
|
-
|
|
109
|
+
`public-api.ts` réexporte les **types** du SDK navigateur, jamais de valeurs. Une constante ou une fonction réexportée placerait le SDK dans le graphe statique du module, et donc dans le bundle **initial** de votre application : mesuré sur l'application de démonstration, **308 ko au lieu de 154 ko**, soit 39 ko de transfert supplémentaires chargés par tous vos visiteurs, y compris ceux qui ne lancent jamais de vérification.
|
|
215
110
|
|
|
216
|
-
|
|
217
|
-
- Testé sur Chrome et Safari (desktop et iOS). Les webviews in-app (Instagram,
|
|
218
|
-
Facebook…) restreignent souvent `getUserMedia` — orientez l'utilisateur vers
|
|
219
|
-
le navigateur système si la caméra ne démarre pas.
|
|
220
|
-
- L'interface s'ouvre en superposition plein écran et fige le défilement de la
|
|
221
|
-
page tant que le parcours est ouvert.
|
|
111
|
+
Les types disparaissent à la compilation : ils ne coûtent rien. Pour les rares valeurs utiles à un hôte, le service expose des accesseurs asynchrones :
|
|
222
112
|
|
|
223
|
-
|
|
113
|
+
```ts
|
|
114
|
+
const countries = await this.naya.countries(); // sélecteur maison
|
|
115
|
+
const support = await this.naya.isSupported(); // avant d'ouvrir
|
|
116
|
+
```
|
|
224
117
|
|
|
225
|
-
|
|
118
|
+
Dans la plupart des cas vous n'en avez pas besoin : `config` accepte directement les codes (`country: 'BJ'`), typés par `NayaCountryCode`.
|
|
226
119
|
|
|
227
|
-
|
|
228
|
-
|---|---|
|
|
229
|
-
| `status: 'error'`, message « clé API invalide » (401) | Clé absente/révoquée, ou coquille. |
|
|
230
|
-
| `status: 'error'`, « KYB… » (403) | La société de la clé n'est pas KYB-vérifiée. |
|
|
231
|
-
| `status: 'error'`, « CORS » | L'origine de votre app n'est pas dans `ALLOWED_ORIGINS` côté API. |
|
|
232
|
-
| La caméra ne démarre pas | Page servie en `http://` distant (contexte non sécurisé), permission refusée, ou webview in-app. |
|
|
233
|
-
| Score de vivacité anormalement bas | Selfie de mauvaise qualité (contre-jour, reflets d'écran) ou caméra défectueuse — l'anti-fraude serveur le pénalise. |
|
|
120
|
+
## Rendu serveur (SSR)
|
|
234
121
|
|
|
235
|
-
|
|
122
|
+
Le service détecte l'absence de navigateur (`PLATFORM_ID`) et rend un `NayaResult` en erreur `unsupported_browser` au lieu de lever. Le SDK n'est jamais importé côté serveur, puisque l'import est différé au premier lancement.
|
|
236
123
|
|
|
237
|
-
##
|
|
124
|
+
## Vérifier la compatibilité du navigateur
|
|
238
125
|
|
|
126
|
+
```ts
|
|
127
|
+
const s = await this.naya.isSupported();
|
|
128
|
+
if (!s.ok) {
|
|
129
|
+
// s.code : in_app_browser | insecure_context | unsupported_browser
|
|
130
|
+
}
|
|
239
131
|
```
|
|
240
|
-
projects/
|
|
241
|
-
naya-id/ — la librairie publiée (@41devs/naya-id-angular)
|
|
242
|
-
demo/ — application de démonstration
|
|
243
|
-
```
|
|
244
132
|
|
|
245
|
-
|
|
246
|
-
|
|
133
|
+
## Démonstration
|
|
134
|
+
|
|
135
|
+
`projects/demo` contient une application avec tous les réglages du parcours.
|
|
247
136
|
|
|
248
|
-
|
|
137
|
+
```bash
|
|
138
|
+
npm start
|
|
139
|
+
```
|
|
249
140
|
|
|
250
141
|
## Licence
|
|
251
142
|
|
|
252
|
-
|
|
143
|
+
Voir `LICENSE`.
|
|
@@ -1,2 +1,198 @@
|
|
|
1
|
-
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, NgZone, PLATFORM_ID, Injectable } from '@angular/core';
|
|
3
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Point d'entrée du SDK Naya ID pour Angular.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* const result = await this.naya.startVerification({
|
|
10
|
+
* auth: { verificationId, sessionToken },
|
|
11
|
+
* config: { locale: 'fr' },
|
|
12
|
+
* });
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Le parcours (consentement, capture, vivacité, décision) est celui du SDK
|
|
16
|
+
* navigateur `@41devs/naya-id-js` : une seule implémentation, partagée avec
|
|
17
|
+
* les intégrations sans framework. Cette bibliothèque y ajoute ce qu'attend
|
|
18
|
+
* une application Angular :
|
|
19
|
+
*
|
|
20
|
+
* • **injection** — un service `providedIn: 'root'`, testable et
|
|
21
|
+
* remplaçable ;
|
|
22
|
+
* • **chargement différé** — le SDK n'entre pas dans le bundle initial ;
|
|
23
|
+
* il est importé au premier lancement ;
|
|
24
|
+
* • **zone** — le parcours tourne hors de la zone Angular (le flux caméra
|
|
25
|
+
* déclencherait sinon une détection de changements par trame), et les
|
|
26
|
+
* rappels de l'hôte y sont ramenés pour que signaux et vues se mettent
|
|
27
|
+
* à jour normalement ;
|
|
28
|
+
* • **rendu serveur** — sans `document`, le service rend une erreur typée
|
|
29
|
+
* au lieu de lever.
|
|
30
|
+
*/
|
|
31
|
+
class NayaIdService {
|
|
32
|
+
zone = inject(NgZone);
|
|
33
|
+
platformId = inject(PLATFORM_ID);
|
|
34
|
+
/** Chargé une seule fois, au premier usage. */
|
|
35
|
+
sdk;
|
|
36
|
+
load() {
|
|
37
|
+
return (this.sdk ??= import('@41devs/naya-id-js'));
|
|
38
|
+
}
|
|
39
|
+
get isBrowser() {
|
|
40
|
+
return isPlatformBrowser(this.platformId) && typeof document !== 'undefined';
|
|
41
|
+
}
|
|
42
|
+
serverSideResult() {
|
|
43
|
+
return {
|
|
44
|
+
status: 'error',
|
|
45
|
+
errorCode: 'unsupported_browser',
|
|
46
|
+
errorMessage: 'Le SDK Naya nécessite un environnement navigateur.',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Enveloppe la configuration de l'hôte pour ramener ses rappels dans la
|
|
51
|
+
* zone Angular. Sans cela, un `onEvent` qui écrit dans un signal ne
|
|
52
|
+
* déclencherait aucun rafraîchissement : le parcours tourne hors zone.
|
|
53
|
+
*/
|
|
54
|
+
withZone(config) {
|
|
55
|
+
const onEvent = config?.onEvent;
|
|
56
|
+
if (!onEvent)
|
|
57
|
+
return config;
|
|
58
|
+
return {
|
|
59
|
+
...config,
|
|
60
|
+
onEvent: (event) => this.zone.run(() => onEvent(event)),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Lance le parcours de vérification d'identité.
|
|
65
|
+
*
|
|
66
|
+
* Authentification, au choix :
|
|
67
|
+
* • `auth.verificationId` + `auth.sessionToken`, rendus à votre backend
|
|
68
|
+
* par `POST /verifications/start` — à privilégier en production, la
|
|
69
|
+
* clé ne quitte pas le serveur ;
|
|
70
|
+
* • `auth.apiKey` — démos et fronts maîtrisés. Une clé live doit
|
|
71
|
+
* déclarer ses origines dans le dashboard.
|
|
72
|
+
*
|
|
73
|
+
* **Ne rejette jamais** : une erreur ou une annulation revient sous forme
|
|
74
|
+
* de `NayaResult` (`status: 'error'` avec `errorCode`, ou `'cancelled'`).
|
|
75
|
+
*/
|
|
76
|
+
async startVerification(params) {
|
|
77
|
+
if (!this.isBrowser)
|
|
78
|
+
return this.serverSideResult();
|
|
79
|
+
const sdk = await this.load();
|
|
80
|
+
return this.zone.runOutsideAngular(() => sdk.startVerification({ ...params, config: this.withZone(params.config) }));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Instance réutilisable, pour piloter l'ouverture et la fermeture depuis
|
|
84
|
+
* un composant et suivre les événements du parcours.
|
|
85
|
+
*/
|
|
86
|
+
async create(params) {
|
|
87
|
+
if (!this.isBrowser) {
|
|
88
|
+
const result = this.serverSideResult();
|
|
89
|
+
return {
|
|
90
|
+
open: async () => result,
|
|
91
|
+
close: () => { },
|
|
92
|
+
on: () => () => { },
|
|
93
|
+
destroy: () => { },
|
|
94
|
+
get isOpen() {
|
|
95
|
+
return false;
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const sdk = await this.load();
|
|
100
|
+
const instance = this.zone.runOutsideAngular(() => sdk.create({ ...params, config: this.withZone(params.config) }));
|
|
101
|
+
return {
|
|
102
|
+
open: () => this.zone.runOutsideAngular(() => instance.open()),
|
|
103
|
+
close: () => instance.close(),
|
|
104
|
+
on: (event, cb) => instance.on(event, (payload) => this.zone.run(() => cb(payload))),
|
|
105
|
+
destroy: () => instance.destroy(),
|
|
106
|
+
get isOpen() {
|
|
107
|
+
return instance.isOpen;
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Vérifie que le navigateur peut exécuter le parcours (caméra, contexte
|
|
113
|
+
* sécurisé, navigateur intégré) avant de l'ouvrir.
|
|
114
|
+
*/
|
|
115
|
+
async isSupported() {
|
|
116
|
+
if (!this.isBrowser) {
|
|
117
|
+
// Rendu serveur : aucune capacité n'est mesurable, on rend un état
|
|
118
|
+
// complet et négatif plutôt que de lever.
|
|
119
|
+
return {
|
|
120
|
+
ok: false,
|
|
121
|
+
code: 'unsupported_browser',
|
|
122
|
+
reason: 'Aucun environnement navigateur.',
|
|
123
|
+
secureContext: false,
|
|
124
|
+
mediaDevices: false,
|
|
125
|
+
webAssembly: false,
|
|
126
|
+
webGL: false,
|
|
127
|
+
inAppBrowser: false,
|
|
128
|
+
inAppBrowserName: null,
|
|
129
|
+
mobile: false,
|
|
130
|
+
ios: false,
|
|
131
|
+
android: false,
|
|
132
|
+
deviceClass: 'desktop',
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const sdk = await this.load();
|
|
136
|
+
return sdk.isSupported();
|
|
137
|
+
}
|
|
138
|
+
/** Version du SDK navigateur effectivement chargé. */
|
|
139
|
+
async version() {
|
|
140
|
+
const sdk = await this.load();
|
|
141
|
+
return sdk.version;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Pays couverts, avec leur libellé — pour un sélecteur affiché par l'hôte
|
|
145
|
+
* avant d'ouvrir le parcours.
|
|
146
|
+
*
|
|
147
|
+
* Accesseur asynchrone, et non constante réexportée : une valeur importée
|
|
148
|
+
* statiquement depuis cette bibliothèque entraînerait tout le SDK
|
|
149
|
+
* navigateur dans le bundle initial de votre application. Vous n'en avez
|
|
150
|
+
* besoin que si vous construisez votre propre sélection ; sinon `config`
|
|
151
|
+
* accepte directement les codes (`country: 'BJ'`), typés par
|
|
152
|
+
* `NayaCountryCode`.
|
|
153
|
+
*/
|
|
154
|
+
async countries() {
|
|
155
|
+
const sdk = await this.load();
|
|
156
|
+
return sdk.NAYA_COUNTRIES;
|
|
157
|
+
}
|
|
158
|
+
/** Types de pièces acceptés. Même remarque que [countries]. */
|
|
159
|
+
async documentTypes() {
|
|
160
|
+
const sdk = await this.load();
|
|
161
|
+
return sdk.NAYA_DOCUMENT_TYPES;
|
|
162
|
+
}
|
|
163
|
+
/** Libellé lisible d'un code pays. */
|
|
164
|
+
async countryLabel(code) {
|
|
165
|
+
const sdk = await this.load();
|
|
166
|
+
return sdk.countryLabel(code);
|
|
167
|
+
}
|
|
168
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.28", ngImport: i0, type: NayaIdService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
169
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.28", ngImport: i0, type: NayaIdService, providedIn: 'root' });
|
|
170
|
+
}
|
|
171
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.28", ngImport: i0, type: NayaIdService, decorators: [{
|
|
172
|
+
type: Injectable,
|
|
173
|
+
args: [{ providedIn: 'root' }]
|
|
174
|
+
}] });
|
|
175
|
+
|
|
176
|
+
/*
|
|
177
|
+
* Surface publique du SDK Naya ID — Angular.
|
|
178
|
+
*
|
|
179
|
+
* Le service d'entrée est propre à Angular ; les modèles sont **réexportés
|
|
180
|
+
* depuis `@41devs/naya-id-js`** plutôt que redéclarés. Les deux SDK ne
|
|
181
|
+
* peuvent donc pas diverger : une option ajoutée au parcours navigateur est
|
|
182
|
+
* disponible ici au prochain `npm update`, sans publication de cette
|
|
183
|
+
* bibliothèque.
|
|
184
|
+
*
|
|
185
|
+
* ⚠️ **Types uniquement.** Réexporter une valeur (une constante, une
|
|
186
|
+
* fonction) placerait le SDK navigateur dans le graphe statique du module,
|
|
187
|
+
* et donc dans le bundle **initial** de l'application cliente — 154 ko qui
|
|
188
|
+
* ne servent qu'au lancement du parcours. Les types disparaissent à la
|
|
189
|
+
* compilation ; le SDK reste chargé à la demande. Les rares valeurs utiles
|
|
190
|
+
* à un hôte sont exposées par des accesseurs asynchrones du service.
|
|
191
|
+
*/
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Generated bundle index. Do not edit.
|
|
195
|
+
*/
|
|
196
|
+
|
|
197
|
+
export { NayaIdService };
|
|
2
198
|
//# sourceMappingURL=41devs-naya-id-angular.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"41devs-naya-id-angular.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"41devs-naya-id-angular.mjs","sources":["../../../projects/naya-id/src/lib/naya-id.service.ts","../../../projects/naya-id/src/public-api.ts","../../../projects/naya-id/src/41devs-naya-id-angular.ts"],"sourcesContent":["import { Injectable, NgZone, PLATFORM_ID, inject } from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport type {\n NayaConfig,\n NayaCountryCode,\n NayaDocumentType,\n NayaEvent,\n NayaResult,\n NayaSupport,\n StartVerificationParams,\n} from '@41devs/naya-id-js';\n\n/**\n * Parcours réutilisable : une instance qu'on ouvre, ferme et écoute.\n * Miroir de `create()` du SDK Naya, avec les rappels ramenés dans la zone\n * Angular.\n */\nexport interface NayaVerification {\n /** Monte l'interface et résout à la fermeture. Un seul `open` à la fois. */\n open(): Promise<NayaResult>;\n /** Ferme le parcours (résultat `cancelled`). */\n close(): void;\n /** Abonne un écouteur ; rend la fonction de désabonnement. */\n on(\n event: NayaEvent['type'] | 'result',\n cb: (payload: NayaEvent | NayaResult) => void,\n ): () => void;\n /** Ferme et libère les écouteurs. */\n destroy(): void;\n readonly isOpen: boolean;\n}\n\n/**\n * Point d'entrée du SDK Naya ID pour Angular.\n *\n * ```ts\n * const result = await this.naya.startVerification({\n * auth: { verificationId, sessionToken },\n * config: { locale: 'fr' },\n * });\n * ```\n *\n * Le parcours (consentement, capture, vivacité, décision) est celui du SDK\n * navigateur `@41devs/naya-id-js` : une seule implémentation, partagée avec\n * les intégrations sans framework. Cette bibliothèque y ajoute ce qu'attend\n * une application Angular :\n *\n * • **injection** — un service `providedIn: 'root'`, testable et\n * remplaçable ;\n * • **chargement différé** — le SDK n'entre pas dans le bundle initial ;\n * il est importé au premier lancement ;\n * • **zone** — le parcours tourne hors de la zone Angular (le flux caméra\n * déclencherait sinon une détection de changements par trame), et les\n * rappels de l'hôte y sont ramenés pour que signaux et vues se mettent\n * à jour normalement ;\n * • **rendu serveur** — sans `document`, le service rend une erreur typée\n * au lieu de lever.\n */\n@Injectable({ providedIn: 'root' })\nexport class NayaIdService {\n private readonly zone = inject(NgZone);\n private readonly platformId = inject(PLATFORM_ID);\n\n /** Chargé une seule fois, au premier usage. */\n private sdk?: Promise<typeof import('@41devs/naya-id-js')>;\n\n private load(): Promise<typeof import('@41devs/naya-id-js')> {\n return (this.sdk ??= import('@41devs/naya-id-js'));\n }\n\n private get isBrowser(): boolean {\n return isPlatformBrowser(this.platformId) && typeof document !== 'undefined';\n }\n\n private serverSideResult(): NayaResult {\n return {\n status: 'error',\n errorCode: 'unsupported_browser',\n errorMessage: 'Le SDK Naya nécessite un environnement navigateur.',\n };\n }\n\n /**\n * Enveloppe la configuration de l'hôte pour ramener ses rappels dans la\n * zone Angular. Sans cela, un `onEvent` qui écrit dans un signal ne\n * déclencherait aucun rafraîchissement : le parcours tourne hors zone.\n */\n private withZone(config?: NayaConfig): NayaConfig | undefined {\n const onEvent = config?.onEvent;\n if (!onEvent) return config;\n return {\n ...config,\n onEvent: (event) => this.zone.run(() => onEvent(event)),\n };\n }\n\n /**\n * Lance le parcours de vérification d'identité.\n *\n * Authentification, au choix :\n * • `auth.verificationId` + `auth.sessionToken`, rendus à votre backend\n * par `POST /verifications/start` — à privilégier en production, la\n * clé ne quitte pas le serveur ;\n * • `auth.apiKey` — démos et fronts maîtrisés. Une clé live doit\n * déclarer ses origines dans le dashboard.\n *\n * **Ne rejette jamais** : une erreur ou une annulation revient sous forme\n * de `NayaResult` (`status: 'error'` avec `errorCode`, ou `'cancelled'`).\n */\n async startVerification(params: StartVerificationParams): Promise<NayaResult> {\n if (!this.isBrowser) return this.serverSideResult();\n const sdk = await this.load();\n return this.zone.runOutsideAngular(() =>\n sdk.startVerification({ ...params, config: this.withZone(params.config) }),\n );\n }\n\n /**\n * Instance réutilisable, pour piloter l'ouverture et la fermeture depuis\n * un composant et suivre les événements du parcours.\n */\n async create(params: StartVerificationParams): Promise<NayaVerification> {\n if (!this.isBrowser) {\n const result = this.serverSideResult();\n return {\n open: async () => result,\n close: () => {},\n on: () => () => {},\n destroy: () => {},\n get isOpen() {\n return false;\n },\n };\n }\n const sdk = await this.load();\n const instance = this.zone.runOutsideAngular(() =>\n sdk.create({ ...params, config: this.withZone(params.config) }),\n );\n return {\n open: () => this.zone.runOutsideAngular(() => instance.open()),\n close: () => instance.close(),\n on: (event, cb) => instance.on(event, (payload) => this.zone.run(() => cb(payload))),\n destroy: () => instance.destroy(),\n get isOpen() {\n return instance.isOpen;\n },\n };\n }\n\n /**\n * Vérifie que le navigateur peut exécuter le parcours (caméra, contexte\n * sécurisé, navigateur intégré) avant de l'ouvrir.\n */\n async isSupported(): Promise<NayaSupport> {\n if (!this.isBrowser) {\n // Rendu serveur : aucune capacité n'est mesurable, on rend un état\n // complet et négatif plutôt que de lever.\n return {\n ok: false,\n code: 'unsupported_browser',\n reason: 'Aucun environnement navigateur.',\n secureContext: false,\n mediaDevices: false,\n webAssembly: false,\n webGL: false,\n inAppBrowser: false,\n inAppBrowserName: null,\n mobile: false,\n ios: false,\n android: false,\n deviceClass: 'desktop',\n };\n }\n const sdk = await this.load();\n return sdk.isSupported();\n }\n\n /** Version du SDK navigateur effectivement chargé. */\n async version(): Promise<string> {\n const sdk = await this.load();\n return sdk.version;\n }\n\n /**\n * Pays couverts, avec leur libellé — pour un sélecteur affiché par l'hôte\n * avant d'ouvrir le parcours.\n *\n * Accesseur asynchrone, et non constante réexportée : une valeur importée\n * statiquement depuis cette bibliothèque entraînerait tout le SDK\n * navigateur dans le bundle initial de votre application. Vous n'en avez\n * besoin que si vous construisez votre propre sélection ; sinon `config`\n * accepte directement les codes (`country: 'BJ'`), typés par\n * `NayaCountryCode`.\n */\n async countries(): Promise<readonly { code: NayaCountryCode; label: string }[]> {\n const sdk = await this.load();\n return sdk.NAYA_COUNTRIES;\n }\n\n /** Types de pièces acceptés. Même remarque que [countries]. */\n async documentTypes(): Promise<readonly NayaDocumentType[]> {\n const sdk = await this.load();\n return sdk.NAYA_DOCUMENT_TYPES;\n }\n\n /** Libellé lisible d'un code pays. */\n async countryLabel(code: NayaCountryCode): Promise<string> {\n const sdk = await this.load();\n return sdk.countryLabel(code);\n }\n}\n","/*\n * Surface publique du SDK Naya ID — Angular.\n *\n * Le service d'entrée est propre à Angular ; les modèles sont **réexportés\n * depuis `@41devs/naya-id-js`** plutôt que redéclarés. Les deux SDK ne\n * peuvent donc pas diverger : une option ajoutée au parcours navigateur est\n * disponible ici au prochain `npm update`, sans publication de cette\n * bibliothèque.\n *\n * ⚠️ **Types uniquement.** Réexporter une valeur (une constante, une\n * fonction) placerait le SDK navigateur dans le graphe statique du module,\n * et donc dans le bundle **initial** de l'application cliente — 154 ko qui\n * ne servent qu'au lancement du parcours. Les types disparaissent à la\n * compilation ; le SDK reste chargé à la demande. Les rares valeurs utiles\n * à un hôte sont exposées par des accesseurs asynchrones du service.\n */\n\nexport { NayaIdService, type NayaVerification } from './lib/naya-id.service';\n\nexport type {\n NayaAuth,\n NayaCaptureOptions,\n NayaConfig,\n NayaConsentOptions,\n NayaCountryCode,\n NayaDocumentType,\n NayaDocumentTypeMismatchPolicy,\n NayaErrorCode,\n NayaEvent,\n NayaEventName,\n NayaHandoffOptions,\n NayaLivenessAssets,\n NayaLivenessOptions,\n NayaLocale,\n NayaOcrData,\n NayaResult,\n NayaStatus,\n NayaSupport,\n NayaThemeOverrides,\n ResolvedNayaConfig,\n StartVerificationParams,\n} from '@41devs/naya-id-js';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|