@41devs/naya-id-angular 0.1.0 → 0.3.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 +114 -34
- 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 +6 -6
- package/fesm2022/41devs-naya-id-angular-41devs-naya-id-angular-YjgS6TVl.mjs +0 -292
- package/fesm2022/41devs-naya-id-angular-41devs-naya-id-angular-YjgS6TVl.mjs.map +0 -1
- package/fesm2022/41devs-naya-id-angular-naya-flow.launcher-vxGQo8yK.mjs +0 -2066
- package/fesm2022/41devs-naya-id-angular-naya-flow.launcher-vxGQo8yK.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,63 +1,143 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @41devs/naya-id-angular
|
|
2
2
|
|
|
3
|
-
|
|
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.
|
|
4
4
|
|
|
5
|
-
|
|
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é.
|
|
6
6
|
|
|
7
|
-
|
|
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.
|
|
10
|
+
|
|
11
|
+
## Comment c'est construit
|
|
12
|
+
|
|
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 :
|
|
14
|
+
|
|
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.
|
|
19
|
+
|
|
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.
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
8
23
|
|
|
9
24
|
```bash
|
|
10
|
-
|
|
25
|
+
npm install @41devs/naya-id-angular
|
|
11
26
|
```
|
|
12
27
|
|
|
13
|
-
|
|
28
|
+
`@41devs/naya-id-js` est installé automatiquement. Angular 19 ou 20.
|
|
14
29
|
|
|
15
|
-
|
|
16
|
-
|
|
30
|
+
## Utilisation
|
|
31
|
+
|
|
32
|
+
### Session ouverte par votre backend (production)
|
|
33
|
+
|
|
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`.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { Component, inject, signal } from '@angular/core';
|
|
38
|
+
import { NayaIdService, type NayaResult } from '@41devs/naya-id-angular';
|
|
39
|
+
|
|
40
|
+
@Component({ /* … */ })
|
|
41
|
+
export class KycComponent {
|
|
42
|
+
private readonly naya = inject(NayaIdService);
|
|
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
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
17
54
|
```
|
|
18
55
|
|
|
19
|
-
|
|
56
|
+
### Clé de test (démo)
|
|
20
57
|
|
|
21
|
-
|
|
58
|
+
```ts
|
|
59
|
+
await this.naya.startVerification({
|
|
60
|
+
auth: { apiKey: 'naya_test_xxx' },
|
|
61
|
+
config: { country: 'BJ', documentTypes: ['cni'] },
|
|
62
|
+
});
|
|
63
|
+
```
|
|
22
64
|
|
|
23
|
-
|
|
24
|
-
|
|
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
|
|
68
|
+
|
|
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();
|
|
25
74
|
```
|
|
26
75
|
|
|
27
|
-
|
|
76
|
+
### Résultat
|
|
28
77
|
|
|
29
|
-
|
|
78
|
+
`startVerification` **ne rejette jamais** : annulation et erreurs reviennent dans le `NayaResult`.
|
|
30
79
|
|
|
31
|
-
|
|
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
|
+
```
|
|
32
89
|
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
cd dist/naya-id
|
|
36
|
-
```
|
|
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.
|
|
37
91
|
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
npm publish
|
|
41
|
-
```
|
|
92
|
+
## Configuration
|
|
42
93
|
|
|
43
|
-
|
|
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).
|
|
44
95
|
|
|
45
|
-
|
|
96
|
+
Utile côté Angular :
|
|
46
97
|
|
|
47
|
-
```
|
|
48
|
-
|
|
98
|
+
```ts
|
|
99
|
+
config: {
|
|
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
|
|
104
|
+
}
|
|
49
105
|
```
|
|
50
106
|
|
|
51
|
-
##
|
|
107
|
+
## Pourquoi la bibliothèque n'exporte que des types
|
|
52
108
|
|
|
53
|
-
|
|
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.
|
|
54
110
|
|
|
55
|
-
|
|
56
|
-
|
|
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 :
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
const countries = await this.naya.countries(); // sélecteur maison
|
|
115
|
+
const support = await this.naya.isSupported(); // avant d'ouvrir
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Dans la plupart des cas vous n'en avez pas besoin : `config` accepte directement les codes (`country: 'BJ'`), typés par `NayaCountryCode`.
|
|
119
|
+
|
|
120
|
+
## Rendu serveur (SSR)
|
|
121
|
+
|
|
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.
|
|
123
|
+
|
|
124
|
+
## Vérifier la compatibilité du navigateur
|
|
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
|
+
}
|
|
57
131
|
```
|
|
58
132
|
|
|
59
|
-
|
|
133
|
+
## Démonstration
|
|
134
|
+
|
|
135
|
+
`projects/demo` contient une application avec tous les réglages du parcours.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npm start
|
|
139
|
+
```
|
|
60
140
|
|
|
61
|
-
##
|
|
141
|
+
## Licence
|
|
62
142
|
|
|
63
|
-
|
|
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 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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"}
|