datakeen-session-react 1.1.140-dev.71 → 1.1.140-dev.73

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/CLAUDE.md ADDED
@@ -0,0 +1,227 @@
1
+ # CLAUDE.md — Client Sessions React SDK
2
+
3
+ ## Vue d'ensemble
4
+
5
+ Librairie React TypeScript servant d'orchestrateur côté client pour les parcours d'onboarding Datakeen (journeys). Publiée sur npm sous `datakeen-session-react`. Elle gère la navigation entre nœuds, la collecte de données (formulaires, documents, biométrique), le polling asynchrone des analyses et l'historique de navigation.
6
+
7
+ **Stack :** React 18 (peer dep), TypeScript, Axios, i18next, Radix UI, TensorFlow (ML documents), Rollup (build ESM + CJS).
8
+
9
+ **Tests :** Jest + React Testing Library.
10
+
11
+ **Point d'entrée :** `src/components/DatakeenSession.tsx`
12
+
13
+ ---
14
+
15
+ ## Structure du projet
16
+
17
+ ```
18
+ client-sessions-react-sdk/
19
+ ├── src/
20
+ │ ├── components/
21
+ │ │ ├── session/ # Orchestration session (SessionContent, UserInputForm)
22
+ │ │ ├── template/ # Rendu nœuds (TemplateNodeRenderer, ConditionNodeHandler)
23
+ │ │ ├── document-collection/
24
+ │ │ ├── selfie/, id-check/, jdi/, signature-electronic/
25
+ │ │ ├── start-flow/, end-flow/
26
+ │ │ └── ui/ # Composants réutilisables internes
27
+ │ ├── hooks/
28
+ │ │ ├── useStepNavigation.ts # Historique + navigation (CRITIQUE)
29
+ │ │ ├── useSessionData.ts # Chargement et synchro données
30
+ │ │ ├── useTemplateLoader.ts # Résolution template
31
+ │ │ └── useStepCSS.ts # Styles dynamiques par nœud
32
+ │ ├── services/
33
+ │ │ ├── sessionService.ts # API session + getOrderedJourneySteps
34
+ │ │ ├── pollingService.ts # Polling analyses documentaires
35
+ │ │ ├── retryService.ts # Gestion retryCounts
36
+ │ │ └── ...
37
+ │ ├── context/
38
+ │ │ ├── SessionContext.tsx # État session global
39
+ │ │ ├── ConfigContext.tsx
40
+ │ │ └── DocumentContext.tsx
41
+ │ ├── types/
42
+ │ │ ├── session.ts # SessionTemplateNode, SessionTemplateEdge, CustomField
43
+ │ │ └── ...
44
+ │ ├── utils/
45
+ │ │ ├── conditionEvaluator.ts # Évaluation conditions
46
+ │ │ ├── cssLoader.ts # Injection CSS dynamique
47
+ │ │ └── documentLabels.ts
48
+ │ └── i18n/
49
+ │ ├── fr.json, en.json
50
+ │ └── country/, documents/
51
+ ├── docs/ # Documentation — LIRE EN PREMIER
52
+ ├── rollup.config.js # Build production (ESM + CJS)
53
+ └── dist/ # Artefacts buildés (ne pas modifier)
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Règles impératives
59
+
60
+ ### Avant de coder
61
+
62
+ **Lire `docs/`** en premier :
63
+ - `POLLING_SYSTEM.md` — spec complète polling v2.0.0
64
+ - `navigation-history.md` — pièges navigation
65
+ - `multi-runs.md` — convention `_list`
66
+ - `JOURNEY_NODE_BUILDER.md` — checklist ajout nœud
67
+ - `sdk_integration_guide.md` — intégration consommateur
68
+
69
+ ### Navigation entre nœuds
70
+
71
+ Le fichier central est `src/hooks/useStepNavigation.ts`. Respecter strictement l'API :
72
+
73
+ ```typescript
74
+ // ✅ Avancer vers le prochain nœud (résout via les edges du graphe)
75
+ goToNextStep(nodeId, template, handle?)
76
+
77
+ // ✅ Revenir en arrière (dépile l'historique)
78
+ goBack()
79
+
80
+ // ✅ Naviguer directement (cas spéciaux uniquement)
81
+ setStep(n, skipHistory?)
82
+
83
+ // ❌ Ne jamais faire ça
84
+ setStep(step - 1) // arithmétique manuelle = bugs de navigation
85
+ ```
86
+
87
+ **Index de navigation :**
88
+ - `step=0` : écran de démarrage
89
+ - `step=0.5` : QR code (si configuré)
90
+ - `step≥1` : nœuds du template (1-indexed, triés par `order`)
91
+
92
+ ### Types de nœuds
93
+
94
+ | Type | Description | Sorties |
95
+ |------|-------------|---------|
96
+ | `information-input` | Formulaires avec champs optionnellement verrouillés | 1 |
97
+ | `document-selection` | Choix de document | 1 |
98
+ | `document-collection` | Upload document + polling | 1 |
99
+ | `controle-jdi` | Analyse JDI avec polling | 1 |
100
+ | `selfie-capture` / `biometric-capture` | Biométrie | 1 |
101
+ | `condition` | Branchement conditionnel (évalue `conditionTokens`) | 2 : `true` / `false` |
102
+ | `end` | Fin de session | 0 |
103
+
104
+ Le dispatcher est `src/components/template/TemplateNodeRenderer.tsx`.
105
+
106
+ **Checklist ajout d'un nœud :**
107
+ 1. Ajouter le type dans `src/types/session.ts`
108
+ 2. Créer le composant dans `src/components/`
109
+ 3. Ajouter le case dans `TemplateNodeRenderer.tsx`
110
+ 4. Ajouter les traductions FR/EN dans `src/i18n/`
111
+ 5. Gérer `goToNextStep` à la complétion du nœud
112
+ 6. Gérer `goBack()` si le nœud a un bouton retour
113
+ 7. Tester avec les cas : nœud auto-exécutant → doit être sauté par `goBack()`
114
+
115
+ ### Système de polling
116
+
117
+ Codes de résultat d'une analyse documentaire :
118
+
119
+ | Code | Signification | Action |
120
+ |------|---------------|--------|
121
+ | `1.0` | Approuvé | `goToNextStep` |
122
+ | `2.0` | Rejeté | Retry possible |
123
+ | `3.0` | Erreur | Retry possible |
124
+ | `4.0` | En vérification manuelle | Attendre |
125
+
126
+ ```typescript
127
+ // Pattern polling
128
+ pollingService.poll(analysisId, {
129
+ onProgress: (pct) => setProgress(pct), // 50% → analysisId absent, 100% → résultat
130
+ onComplete: (code, message) => handleResult(code),
131
+ interval: 2000,
132
+ });
133
+ ```
134
+
135
+ ### Champs verrouillés (`lockedFromApi`)
136
+
137
+ Définis dans `CustomField.lockedFromApi`. Le SDK **ne doit pas les afficher** à l'utilisateur :
138
+
139
+ ```typescript
140
+ // Dans CustomFormFields.tsx — filtrer avant rendu
141
+ const visibleFields = fields.filter(f => !f.lockedFromApi);
142
+ ```
143
+
144
+ Le backend réinjecte la valeur originale via `stripLockedFields()` (protection côté serveur contre la manipulation). Ne jamais contourner ce mécanisme.
145
+
146
+ ### Multi-runs (convention `_list`)
147
+
148
+ Cas : session avec plusieurs bénéficiaires passés à la création.
149
+
150
+ ```json
151
+ {
152
+ "userInput": {
153
+ "_list": [
154
+ { "firstName": "Alice", "lastName": "Dupont" },
155
+ { "firstName": "Bob", "lastName": "Martin" }
156
+ ]
157
+ }
158
+ }
159
+ ```
160
+
161
+ - `session.retryCounts[nodeId]` = index du run courant (0-indexed)
162
+ - Incrémenté automatiquement par `ConditionNodeHandler` en mode boucle
163
+ - SDK sélectionne `_list[runIndex]` pour pré-remplir les formulaires
164
+ - Si hors borne → formulaire vide (comportement attendu)
165
+
166
+ ### Historique de navigation (reconstruction)
167
+
168
+ Au rechargement, l'historique est reconstruit depuis `initialStep` via `reconstructHistoryToStep()` dans `sessionService.ts`. La reconstruction suit la **première edge sortante** de chaque nœud — elle **ne reconnaît pas** les branches conditionnelles complexes. C'est une limitation connue et documentée.
169
+
170
+ ### Internationalisation
171
+
172
+ - Toutes les chaînes visibles dans `src/i18n/fr.json` et `en.json`.
173
+ - Ne jamais hardcoder de texte affiché à l'utilisateur.
174
+
175
+ ### Styles dynamiques
176
+
177
+ - CSS chargé via `cssLoader.ts` selon `node.styles` (injection dynamique).
178
+ - Fallback sur Tailwind pour les composants par défaut.
179
+ - Ne pas utiliser de style inline.
180
+
181
+ ---
182
+
183
+ ## Build et publication
184
+
185
+ ```bash
186
+ # Build de la librairie (ESM + CJS)
187
+ npm run build # ou pnpm build
188
+
189
+ # Tests
190
+ npm test
191
+
192
+ # Développement avec watch
193
+ npm run dev
194
+ ```
195
+
196
+ Rollup génère deux artifacts dans `dist/` :
197
+ - `dist/esm/index.js` — pour les bundlers modernes (import)
198
+ - `dist/cjs/index.js` — pour CommonJS (require)
199
+ - `dist/types/index.d.ts` — typages TypeScript
200
+
201
+ **Ne jamais modifier `dist/` manuellement** — régénéré à chaque build.
202
+
203
+ ---
204
+
205
+ ## Fichiers critiques
206
+
207
+ | Fichier | Rôle |
208
+ |---------|------|
209
+ | `src/components/DatakeenSession.tsx` | Point d'entrée public de la librairie |
210
+ | `src/hooks/useStepNavigation.ts` | Navigation + historique (NE PAS casser l'API) |
211
+ | `src/hooks/useSessionData.ts` | Chargement et synchro état session |
212
+ | `src/components/template/TemplateNodeRenderer.tsx` | Dispatcher de rendu par type de nœud |
213
+ | `src/services/sessionService.ts` | API session + `getOrderedJourneySteps` + `reconstructHistoryToStep` |
214
+ | `src/services/pollingService.ts` | Polling analyses (voir `docs/POLLING_SYSTEM.md`) |
215
+ | `src/utils/conditionEvaluator.ts` | Évaluation des conditions de branchement |
216
+ | `src/types/session.ts` | Contrats de données principaux |
217
+
218
+ ---
219
+
220
+ ## À ne jamais faire
221
+
222
+ - Utiliser `setStep(step - 1)` pour le retour — utiliser `goBack()`.
223
+ - Appeler `setStep` directement pour avancer — utiliser `goToNextStep`.
224
+ - Afficher un champ avec `lockedFromApi: true`.
225
+ - Modifier les fichiers dans `dist/` — ils sont générés.
226
+ - Introduire une dépendance directe vers le backend ou le frontend Datakeen — le SDK est agnostique.
227
+ - Ajouter des dépendances `dependencies` qui devraient être en `peerDependencies` (React, Axios).
package/README.md CHANGED
@@ -90,7 +90,7 @@ const VerificationPage = () => {
90
90
  const { SessionComponent } = useSession(
91
91
  "votre-session-id",
92
92
  { selfie: false, requireMobile: false }, // optionnel
93
- "https://app-v3.datakeen.co/backend" // optionnel
93
+ "https://app.datakeen.co/backend" // optionnel
94
94
  );
95
95
 
96
96
  return <div>{SessionComponent}</div>;
@@ -106,7 +106,7 @@ const VerificationPage = () => (
106
106
  <DatakeenSession
107
107
  sessionId="votre-session-id"
108
108
  sessionConfig={{ selfie: false, requireMobile: false }}
109
- apiBaseUrl="https://app-v3.datakeen.co/backend"
109
+ apiBaseUrl="https://app.datakeen.co/backend"
110
110
  />
111
111
  );
112
112
  ```
@@ -117,7 +117,7 @@ const VerificationPage = () => (
117
117
  import { DatakeenSession, ConfigProvider } from "datakeen-session-react";
118
118
 
119
119
  const App = () => (
120
- <ConfigProvider apiBaseUrl="https://app-v3.datakeen.co/backend">
120
+ <ConfigProvider apiBaseUrl="https://app.datakeen.co/backend">
121
121
  <DatakeenSession sessionId="votre-session-id" />
122
122
  </ConfigProvider>
123
123
  );
@@ -164,7 +164,7 @@ import { DatakeenSession } from "datakeen-session-react";
164
164
  <DatakeenSession
165
165
  sessionId="votre-session-id"
166
166
  sessionConfig={{ selfie: true }}
167
- apiBaseUrl="https://app-v3.datakeen.co/backend"
167
+ apiBaseUrl="https://app.datakeen.co/backend"
168
168
  />
169
169
  ```
170
170
 
@@ -177,7 +177,7 @@ Gère automatiquement : loading/erreur/expiration, layouts mobile/desktop, coule
177
177
  ```tsx
178
178
  import { ConfigProvider } from "datakeen-session-react";
179
179
 
180
- <ConfigProvider apiBaseUrl="https://app-v3.datakeen.co/backend">
180
+ <ConfigProvider apiBaseUrl="https://app.datakeen.co/backend">
181
181
  {/* Tous les DatakeenSession enfants utilisent cette URL */}
182
182
  <DatakeenSession sessionId="session-1" />
183
183
  </ConfigProvider>
@@ -191,7 +191,7 @@ import { ConfigProvider } from "datakeen-session-react";
191
191
  import { configureApiBaseURL } from "datakeen-session-react";
192
192
 
193
193
  // À appeler une fois au démarrage de l'application
194
- configureApiBaseURL("https://app-v3.datakeen.co/backend");
194
+ configureApiBaseURL("https://app.datakeen.co/backend");
195
195
  ```
196
196
 
197
197
  ---
@@ -322,7 +322,7 @@ Le SDK résout l'URL API dans cet ordre de priorité :
322
322
  import { configureApiBaseURL } from "datakeen-session-react";
323
323
 
324
324
  const urls = {
325
- production: "https://app-v3.datakeen.co/backend",
325
+ production: "https://app.datakeen.co/backend",
326
326
  staging: "https://app.staging.datakeen.co/backend",
327
327
  development:"https://app.dev.datakeen.co/backend",
328
328
  };
@@ -333,7 +333,7 @@ configureApiBaseURL(urls[process.env.NODE_ENV] ?? urls.development);
333
333
  ### Via `.env` (Vite)
334
334
 
335
335
  ```env
336
- VITE_API_BASE_URL=https://app-v3.datakeen.co/backend
336
+ VITE_API_BASE_URL=https://app.datakeen.co/backend
337
337
  ```
338
338
 
339
339
  Commande de setup rapide :
@@ -16,7 +16,7 @@ export const configureSDKForEnvironment = () => {
16
16
 
17
17
  switch (environment) {
18
18
  case "production":
19
- apiBaseURL = "https://app-v3.datakeen.co/backend";
19
+ apiBaseURL = "https://app.datakeen.co/backend";
20
20
  break;
21
21
 
22
22
  case "staging":
@@ -64,9 +64,9 @@ export const configureSDKDynamically = () => {
64
64
 
65
65
  let apiBaseURL: string;
66
66
 
67
- if (hostname.includes("app-v3.datakeen.co")) {
67
+ if (hostname.includes("app.datakeen.co")) {
68
68
  // Production
69
- apiBaseURL = "https://app-v3.datakeen.co/backend";
69
+ apiBaseURL = "https://app.datakeen.co/backend";
70
70
  } else if (hostname.includes("app.staging.datakeen.co")) {
71
71
  // Staging
72
72
  apiBaseURL = "https://app.staging.datakeen.co/backend";
@@ -115,7 +115,7 @@ export const configureSDKAdvanced = (options: {
115
115
  if (!apiBaseURL && environment) {
116
116
  switch (environment) {
117
117
  case "production":
118
- apiBaseURL = "https://app-v3.datakeen.co/backend";
118
+ apiBaseURL = "https://app.datakeen.co/backend";
119
119
  break;
120
120
  case "staging":
121
121
  apiBaseURL = "https://app.staging.datakeen.co/backend";
@@ -13,7 +13,7 @@ import {
13
13
 
14
14
  // URLs attendues pour chaque environnement
15
15
  const EXPECTED_URLS = {
16
- production: "https://app-v3.datakeen.co/backend/session",
16
+ production: "https://app.datakeen.co/backend/session",
17
17
  staging: "https://app.staging.datakeen.co/backend/session",
18
18
  development: "https://app.dev.datakeen.co/backend/session",
19
19
  localhost: "http://localhost:8888/backend/session",
@@ -63,7 +63,7 @@ const testDynamicConfiguration = () => {
63
63
  const originalLocation = window.location;
64
64
 
65
65
  const testCases = [
66
- { hostname: "app-v3.datakeen.co", expected: EXPECTED_URLS.production },
66
+ { hostname: "app.datakeen.co", expected: EXPECTED_URLS.production },
67
67
  { hostname: "app.staging.datakeen.co", expected: EXPECTED_URLS.staging },
68
68
  { hostname: "app.dev.datakeen.co", expected: EXPECTED_URLS.development },
69
69
  { hostname: "localhost", expected: EXPECTED_URLS.localhost },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datakeen-session-react",
3
- "version": "1.1.140-dev.71",
3
+ "version": "1.1.140-dev.73",
4
4
  "description": "React SDK component to manage and render Datakeen session experiences easily.",
5
5
  "publishConfig": {
6
6
  "access": "public",