datakeen-session-react 1.1.184 → 1.1.188
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/dist/cjs/components/selfie/selfie-flow/SelfieProcessing.js +15 -3
- package/dist/cjs/components/selfie/selfie-flow/SelfieProcessing.js.map +1 -1
- package/dist/cjs/components/session/Selfie.js +8 -2
- package/dist/cjs/components/session/Selfie.js.map +1 -1
- package/dist/cjs/components/signature-electronic/SignatureElectronic.js +1 -1
- package/dist/cjs/components/signature-electronic/SignatureElectronic.js.map +1 -1
- package/dist/cjs/components/signature-electronic/SignedDocumentPreview.js +6 -2
- package/dist/cjs/components/signature-electronic/SignedDocumentPreview.js.map +1 -1
- package/dist/cjs/i18n/en.json.js +14 -1
- package/dist/cjs/i18n/en.json.js.map +1 -1
- package/dist/cjs/i18n/fr.json.js +14 -1
- package/dist/cjs/i18n/fr.json.js.map +1 -1
- package/dist/cjs/services/analysis.js +3 -1
- package/dist/cjs/services/analysis.js.map +1 -1
- package/dist/cjs/services/sessionService.js +11 -0
- package/dist/cjs/services/sessionService.js.map +1 -1
- package/dist/cjs/types/session.js.map +1 -1
- package/dist/esm/components/selfie/selfie-flow/SelfieProcessing.js +15 -3
- package/dist/esm/components/selfie/selfie-flow/SelfieProcessing.js.map +1 -1
- package/dist/esm/components/session/Selfie.js +8 -2
- package/dist/esm/components/session/Selfie.js.map +1 -1
- package/dist/esm/components/signature-electronic/SignatureElectronic.js +1 -1
- package/dist/esm/components/signature-electronic/SignatureElectronic.js.map +1 -1
- package/dist/esm/components/signature-electronic/SignedDocumentPreview.js +6 -2
- package/dist/esm/components/signature-electronic/SignedDocumentPreview.js.map +1 -1
- package/dist/esm/i18n/en.json.js +14 -2
- package/dist/esm/i18n/en.json.js.map +1 -1
- package/dist/esm/i18n/fr.json.js +14 -2
- package/dist/esm/i18n/fr.json.js.map +1 -1
- package/dist/esm/services/analysis.js +3 -1
- package/dist/esm/services/analysis.js.map +1 -1
- package/dist/esm/services/sessionService.js +11 -1
- package/dist/esm/services/sessionService.js.map +1 -1
- package/dist/esm/types/session.js.map +1 -1
- package/docs/JOURNEY_NODE_BUILDER.md +12 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analysis.js","sources":["../../../../src/services/analysis.ts"],"sourcesContent":["import type { onUploadFiles } from \"../types/uploadFiles\";\nimport { dataURLtoFile, getMimeTypeFromDataURL } from \"./utils\";\nimport { mimeTypeToExtension } from \"../utils/mimeTypes\";\nimport { apiService } from \"./api\";\nimport type { SelfieCaptureData } from \"../types/selfie\";\nimport type {\n DocumentVideoCaptureBySide,\n DocumentVideoPreviewBySide,\n} from \"../types/documentVideo\";\nimport { getSessionMemoryUserInput } from \"./sessionMemoryStore\";\nimport {\n logDocumentUploaded,\n logSelfieCaptured,\n logAiControlled,\n logStatusModified,\n} from \"./auditTrailService\";\nimport { pollAnalysisStatus, stopPolling } from \"./pollingService\";\nimport type { PollingOptions } from \"./pollingService\";\n\n// Timeout configurations (in milliseconds)\nconst ANALYSIS_TIMEOUT = 600000; // 10 minutes for document analysis (increased for large files + ML processing)\nconst SELFIE_ANALYSIS_TIMEOUT = 600000; // 10 minutes for selfie analysis\nconst UPLOAD_TIMEOUT = 300000; // 5 minutes for file uploads\n\n// Map pour suivre les analyses en cours et éviter les doublons\nconst ongoingAnalyses = new Map<string, Promise<any>>();\n\nexport interface AnalyzeFilesOptions {\n personPhoto?: string | null;\n save?: boolean;\n incrementAnalysis?: boolean;\n forceUpload?: boolean;\n documentTypeKey?: string | null;\n requiresTwoSides?: boolean;\n enablePolling?: boolean; // Enable polling for analysis progress (default: true)\n pollingOptions?: PollingOptions; // Custom polling configuration\n collectOnly?: boolean; // Bypass AI verification — document is collected as-is\n}\n\ninterface LaunchAnalysisOptions extends AnalyzeFilesOptions {}\n\nfunction createFileName(fileURL: string, baseName: string = \"file\") {\n const mimeType = getMimeTypeFromDataURL(fileURL);\n if (!mimeType) {\n throw new Error(\"Unable to determine MIME type from file URL\");\n }\n\n const ext = mimeTypeToExtension(mimeType);\n const safeBase = baseName.replace(/\\.+$/, \"\");\n return ext ? `${safeBase}.${ext}` : safeBase;\n}\n\nfunction normalizeDocumentTypeKey(\n rawType?: string | null,\n fallback: string = \"document\",\n) {\n if (!rawType) {\n return fallback;\n }\n\n const trimmed = rawType.trim();\n if (!trimmed) {\n return fallback;\n }\n\n const withUnderscores = trimmed\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[\\s-]+/g, \"_\")\n .replace(/[^a-zA-Z0-9_]/g, \"_\")\n .replace(/_+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .toLowerCase();\n\n return withUnderscores || fallback;\n}\n\n// Fonction pour créer une clé unique pour identifier une analyse\nfunction createAnalysisKey(\n sessionId: string,\n files: onUploadFiles,\n documentTypeId: string,\n): string {\n const frontHash = files.front ? files.front.substring(0, 50) : \"no-front\";\n const backHash = files.back ? files.back.substring(0, 50) : \"no-back\";\n return `${sessionId}-${documentTypeId}-${frontHash}-${backHash}`;\n}\n\nasync function launchAnalysis(\n sessionId: string,\n nodeId: string,\n files: onUploadFiles,\n documentTypeId: string | null,\n options: LaunchAnalysisOptions = {},\n) {\n if (!sessionId || !files) {\n throw new Error(\"Invalid parameters for analysis\");\n }\n\n const {\n personPhoto = null,\n save = true,\n incrementAnalysis = true,\n forceUpload = false,\n documentTypeKey = null,\n requiresTwoSides,\n collectOnly = false,\n } = options;\n\n const formData = new FormData();\n formData.append(\"sessionId\", sessionId);\n formData.append(\"nodeId\", nodeId);\n formData.append(\"save\", String(save));\n\n const userInput = getSessionMemoryUserInput(sessionId);\n if (Object.keys(userInput).length > 0) {\n const fullName = `${userInput.firstName || \"\"} ${\n userInput.lastName || \"\"\n }`.trim();\n formData.append(\"name\", fullName || \"Unknown\");\n\n formData.append(\"firstName\", userInput.firstName || \"\");\n formData.append(\"lastName\", userInput.lastName || \"\");\n formData.append(\"birthDate\", userInput.birthDate || \"\");\n formData.append(\"countryCode\", userInput.countryCode || \"\");\n }\n\n const fileTypes: Record<string, string> = {};\n const normalizedDocumentType = normalizeDocumentTypeKey(\n documentTypeKey ?? documentTypeId ?? undefined,\n );\n const hyphenDocumentType = normalizedDocumentType.replace(/_/g, \"-\");\n const appendSide =\n typeof requiresTwoSides === \"boolean\"\n ? requiresTwoSides\n : Boolean(files.back);\n\n if (files.front) {\n const frontBaseName = appendSide\n ? `${normalizedDocumentType}_front`\n : normalizedDocumentType;\n const frontFileName = createFileName(files.front, frontBaseName);\n const frontFile = dataURLtoFile(files.front, frontFileName);\n formData.append(\"files\", frontFile, frontFileName);\n\n fileTypes[frontFileName] = appendSide\n ? `${hyphenDocumentType}-front`\n : hyphenDocumentType;\n }\n\n if (files.back) {\n const backBaseName = `${normalizedDocumentType}_back`;\n const backFileName = createFileName(files.back, backBaseName);\n const backFile = dataURLtoFile(files.back, backFileName);\n formData.append(\"files\", backFile, backFileName);\n\n fileTypes[backFileName] = `${hyphenDocumentType}-back`;\n }\n\n formData.append(\"fileTypes\", JSON.stringify(fileTypes));\n formData.append(\"incrementAnalysis\", String(incrementAnalysis));\n formData.append(\"forceUpload\", String(forceUpload));\n\n if (documentTypeId) {\n formData.append(\"documentTemplateId\", documentTypeId);\n }\n\n if (personPhoto) {\n formData.append(\"personPhoto\", personPhoto);\n }\n\n if (collectOnly) {\n formData.append(\"collectOnly\", \"true\");\n }\n\n console.debug(\"FormData prepared for analysis:\", {\n sessionId,\n documentTypeId,\n files: Object.keys(fileTypes),\n save,\n incrementAnalysis,\n forceUpload,\n collectOnly,\n });\n return formData;\n}\n\nexport async function analyzeFiles(\n sessionId: string,\n nodeId: string,\n files: onUploadFiles,\n documentTypeId: string,\n options: AnalyzeFilesOptions = {},\n): Promise<any> {\n // Validate required parameters\n if (!sessionId) {\n throw new Error(\"Missing sessionId: A valid session ID is required.\");\n }\n if (!files || Object.keys(files).length === 0) {\n throw new Error(\n \"Missing files: At least one file must be provided for analysis.\",\n );\n }\n\n const {\n personPhoto = null,\n save = true,\n incrementAnalysis = true,\n forceUpload = false,\n documentTypeKey = null,\n requiresTwoSides,\n enablePolling = true,\n pollingOptions = {},\n collectOnly = false,\n } = options;\n\n // Pour les retry, on ne force pas l'upload mais on écrase l'analyse existante\n const isRetry = !incrementAnalysis && !forceUpload;\n\n // Créer une clé unique pour cette analyse\n const analysisKey = createAnalysisKey(sessionId, files, documentTypeId);\n\n // Vérifier si une analyse identique est déjà en cours\n if (ongoingAnalyses.has(analysisKey) && !isRetry) {\n return ongoingAnalyses.get(analysisKey);\n }\n\n // Helper function for retry logic with exponential backoff\n async function submitAnalysisWithRetry(\n formData: FormData,\n maxAttempts: number = 3,\n ) {\n let lastError: any;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const rawClient = apiService.getRawClient();\n\n const response = await rawClient.post(\n `/session/sdk/${sessionId}/analysis`,\n formData,\n {\n timeout: ANALYSIS_TIMEOUT,\n },\n );\n\n return response;\n } catch (error: any) {\n lastError = error;\n\n // Check if it's a network error (likely backend didn't respond in time)\n if (\n error.code === \"ERR_NETWORK\" ||\n error.message?.includes(\"CORS request did not succeed\")\n ) {\n console.warn(\n `⚠️ Network error on attempt ${attempt}: ${error.message}`,\n );\n\n if (attempt < maxAttempts) {\n // Exponential backoff: wait 2s, 4s, 8s...\n const waitTime = Math.pow(2, attempt) * 1000;\n console.log(`⏳ Retrying in ${waitTime / 1000}s...`);\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n continue;\n }\n }\n\n // For other errors, don't retry\n throw error;\n }\n }\n\n throw lastError;\n }\n\n // Créer la promesse d'analyse et la stocker\n const analysisPromise = (async () => {\n try {\n const formData = await launchAnalysis(\n sessionId,\n nodeId,\n files,\n documentTypeId,\n {\n personPhoto,\n save,\n incrementAnalysis: isRetry ? false : incrementAnalysis,\n forceUpload: isRetry ? true : forceUpload,\n documentTypeKey,\n requiresTwoSides,\n collectOnly,\n },\n );\n\n await logDocumentUploaded(sessionId, {\n documentTypeId: documentTypeId || \"unknown\",\n ...(documentTypeKey ? { documentTypeKey } : {}),\n hasFrontImage: !!files.front,\n hasBackImage: !!files.back,\n });\n\n // Submit with automatic retry on network errors\n const response = await submitAnalysisWithRetry(formData);\n\n // Wrap response to match ApiResponse type\n const wrappedResponse = {\n data: response.data,\n success: true,\n status: response.status,\n };\n\n await logAiControlled(\n sessionId,\n {\n analysisResult: response.data.status || \"unknown\",\n documentTypeId: documentTypeId || \"unknown\",\n },\n response.data.clientInfoId || undefined,\n );\n\n if (!wrappedResponse.success) {\n throw new Error(`Analysis failed: ${response.data}`);\n }\n\n // Start polling for analysis progress if enabled\n if (enablePolling) {\n try {\n const pollConfig: PollingOptions = {\n ...pollingOptions,\n };\n\n const pollingResult = await pollAnalysisStatus(sessionId, pollConfig);\n\n return pollingResult;\n } catch (pollError) {\n console.warn(\n \"⚠️ Polling error (analysis may still be processing):\",\n pollError,\n );\n // Don't throw - polling error shouldn't fail the analysis submission\n // The backend is still processing even if polling fails\n return response.data;\n }\n }\n\n return response.data;\n } catch (error) {\n console.error(\"❌ Analysis failed:\", error);\n // Stop any ongoing polling on error\n stopPolling();\n throw error;\n } finally {\n // Nettoyer la promesse de la map une fois terminée\n ongoingAnalyses.delete(analysisKey);\n }\n })();\n\n // Stocker la promesse pour éviter les appels simultanés\n ongoingAnalyses.set(analysisKey, analysisPromise);\n\n return analysisPromise;\n}\n\nexport async function analyzeSelfie(\n sessionId: string,\n selfieFile: SelfieCaptureData,\n selfiePhoto: string,\n): Promise<any> {\n console.log(\"🤳 Starting selfie analysis for session:\", sessionId);\n console.log(\"� File size:\", selfieFile.media.size, \"bytes\");\n\n const formData = new FormData();\n formData.append(\"file\", selfieFile.media, \"selfie.mp4\");\n formData.append(\"photo\", selfiePhoto);\n\n try {\n console.log(\"🚀 Sending selfie to UNISSEY API...\");\n\n const response = await apiService.post(\n `/session/unissey/${sessionId}/analyze`,\n formData,\n {\n timeout: SELFIE_ANALYSIS_TIMEOUT,\n },\n );\n\n console.log(\"✅ Analysis response:\", response);\n\n // Si la réponse API indique un succès, traiter la réponse Unissey\n if (response.success && response.data) {\n console.log(\"🎉 Unissey analysis completed - checking results...\");\n\n // response.data contient directement la réponse Unissey avec status, message, data\n const unisseyResponse = response.data;\n\n // Vérifier si Unissey a répondu avec succès\n if (\n unisseyResponse.status === 200 &&\n (unisseyResponse.message === \"success\" ||\n unisseyResponse.message === \"ok\")\n ) {\n console.log(\"✅ Unissey returned success status\");\n\n // Utiliser les données réelles de la réponse Unissey\n const unisseyData = unisseyResponse.data;\n\n // Vérifier si la comparaison faciale a un niveau de confiance élevé\n const faceComparison = unisseyData.details?.face_comparison;\n const isHighConfidence = faceComparison?.confidence_level === \"high\";\n const isMatch =\n unisseyData.is_match && faceComparison?.result === \"match\";\n\n // is_genuine est basé sur la confiance élevée de la comparaison faciale\n const isGenuine = isHighConfidence && isMatch;\n\n // Log selfie captured in audit trail\n try {\n const analysisResponse = await apiService.get(\n `/session/sdk/${sessionId}`,\n );\n if (analysisResponse.data && analysisResponse.data.analysisId) {\n await logSelfieCaptured(\n sessionId,\n analysisResponse.data.clientInfoId || undefined,\n );\n\n // Log AI control with selfie analysis results\n await logAiControlled(\n sessionId,\n {\n selfieAnalysisResult: isGenuine ? \"genuine\" : \"not_genuine\",\n isMatch: isMatch ? \"match\" : \"no_match\",\n confidenceLevel: faceComparison?.confidence_level || \"unknown\",\n },\n analysisResponse.data.clientInfoId || undefined,\n );\n\n await logStatusModified(\n sessionId,\n {\n selfieAnalysisResult: isGenuine ? \"genuine\" : \"not_genuine\",\n isMatch: isMatch ? \"match\" : \"no_match\",\n confidenceLevel: faceComparison?.confidence_level || \"unknown\",\n },\n analysisResponse.data.clientInfoId || undefined,\n );\n }\n } catch (err) {\n console.error(\"Failed to log selfie capture in audit trail:\", err);\n // Non-blocking error - continue analysis\n }\n\n // Retourner la structure attendue par l'UI\n return {\n success: true,\n data: {\n ...unisseyData,\n is_genuine: isGenuine, // Basé sur confidence_level === \"high\"\n },\n };\n } else {\n console.error(\n \"❌ Unissey returned error status:\",\n unisseyResponse.status,\n unisseyResponse.message,\n );\n throw new Error(\n `Unissey analysis failed: ${\n unisseyResponse.message || \"Unknown Unissey error\"\n }`,\n );\n }\n }\n\n // Gestion des erreurs spécifiques API\n const errorMessage =\n response.data?.message || response.data || \"Unknown error\";\n console.error(\"❌ API call failed:\", errorMessage);\n throw new Error(`Face comparison analysis failed: ${errorMessage}`);\n } catch (error: any) {\n console.error(\"💥 Analysis error:\", error);\n\n // Améliorer le message d'erreur pour l'UI\n if (error.response?.data?.message) {\n throw new Error(`Analysis failed: ${error.response.data.message}`);\n } else if (error.message) {\n throw error; // Garder le message d'erreur original si déjà formaté\n } else {\n throw new Error(\n \"Face comparison analysis failed due to an unexpected error\",\n );\n }\n }\n}\n\nexport async function uploadConvertedIdCardImage(\n sessionId: string,\n file: File,\n): Promise<any> {\n if (!sessionId || !file) {\n throw new Error(\"Invalid parameters for uploading converted ID card image\");\n }\n\n // rename file to converted_id_card.png\n const renamedFile = new File([file], \"converted_id_card.png\", {\n type: file.type,\n });\n\n const formData = new FormData();\n formData.append(\"file\", renamedFile, renamedFile.name);\n\n try {\n console.log(\n `🚀 Uploading converted ID card image for session: ${sessionId}`,\n );\n const response = await apiService.post(\n `/session/sdk/${sessionId}/converted_id_card.png`,\n formData,\n {\n timeout: UPLOAD_TIMEOUT,\n },\n );\n console.log(\"✅ Upload response:\", response);\n return response.data;\n } catch (error) {\n console.error(\"❌ Upload error:\", error);\n throw new Error(\"Failed to upload converted ID card image\");\n }\n}\n\n/**\n * Analyzes a document video captured with Unissey DOC_VIDEO preset.\n * Sends the video file and thumbnail to the backend for document verification.\n *\n * @param sessionId - Unique identifier for the current session\n * @param nodeId - Identifier for the current node in the journey\n * @param videoData - Document video capture data containing media blob and metadata\n * @param thumbnail - Base64 thumbnail extracted from the video\n * @param documentTemplateId - Template ID for the document type being verified\n * @returns Analysis response from the backend\n */\nexport async function analyzeDocumentVideo(\n sessionId: string,\n nodeId: string,\n videoData: DocumentVideoCaptureBySide,\n previews: DocumentVideoPreviewBySide,\n documentTemplateId: string,\n options: {\n documentType?: string;\n requiresTwoSides?: boolean;\n enablePolling?: boolean;\n pollingOptions?: PollingOptions;\n } = {},\n): Promise<any> {\n if (!videoData.recto || !previews.recto) {\n throw new Error(\"Missing recto video or preview\");\n }\n\n const normalizedDocumentType = normalizeDocumentTypeKey(\n options.documentType ?? documentTemplateId ?? undefined,\n );\n const hyphenDocumentType = normalizedDocumentType.replace(/_/g, \"-\");\n const appendSide =\n typeof options.requiresTwoSides === \"boolean\"\n ? options.requiresTwoSides\n : Boolean(videoData.verso || previews.verso);\n\n const frontBaseName = appendSide\n ? `${normalizedDocumentType}_front`\n : normalizedDocumentType;\n const backBaseName = `${normalizedDocumentType}_back`;\n\n const previewFrontFileName = `${frontBaseName}.jpg`;\n const previewFrontFile = dataURLtoFile(previews.recto, previewFrontFileName);\n const previewBackFileName = `${backBaseName}.jpg`;\n const previewBackFile = previews.verso\n ? dataURLtoFile(previews.verso, previewBackFileName)\n : null;\n\n const formData = new FormData();\n\n formData.append(\n \"videoFront\",\n videoData.recto.media,\n \"document_video_recto.mp4\",\n );\n if (videoData.verso) {\n formData.append(\n \"videoBack\",\n videoData.verso.media,\n \"document_video_verso.mp4\",\n );\n }\n\n formData.append(\"previewFront\", previewFrontFile, previewFrontFileName);\n if (previewBackFile) {\n formData.append(\"previewBack\", previewBackFile, previewBackFileName);\n }\n\n const fileTypes: Record<string, string> = {};\n fileTypes[previewFrontFileName] = appendSide\n ? `${hyphenDocumentType}-front`\n : hyphenDocumentType;\n if (previewBackFile) {\n fileTypes[previewBackFileName] = `${hyphenDocumentType}-back`;\n }\n\n formData.append(\"fileTypes\", JSON.stringify(fileTypes));\n formData.append(\"sessionId\", sessionId);\n formData.append(\"nodeId\", nodeId);\n formData.append(\"documentTemplateId\", documentTemplateId);\n formData.append(\"documentType\", options.documentType || \"\");\n formData.append(\"requiresTwoSides\", String(appendSide));\n formData.append(\"save\", \"true\");\n\n const { enablePolling = true, pollingOptions = {} } = options;\n\n try {\n console.log(\"🚀 Sending document video to document-video API...\");\n const response = await apiService.post(\n `/session/sdk/${sessionId}/document-video`,\n formData,\n { timeout: ANALYSIS_TIMEOUT },\n );\n\n if (enablePolling) {\n try {\n const pollConfig: PollingOptions = {\n ...pollingOptions,\n defaultValue: {\n sessionId,\n status: \"processing\",\n progress: 50,\n currentStep: \"processing\",\n message: \"Document analysis in progress\",\n analysisId: null,\n startedAt: new Date().toISOString(),\n completedAt: null,\n error: null,\n },\n };\n const pollingResult = await pollAnalysisStatus(sessionId, pollConfig);\n return pollingResult;\n } catch (pollError) {\n console.warn(\n \"⚠️ Polling error (document-video may still be processing):\",\n pollError,\n );\n }\n }\n\n if (response?.success || response?.data?.success) {\n return response.data ?? response;\n }\n\n const errorMessage = response?.data?.message || \"Unknown error\";\n throw new Error(`Document video analysis failed: ${errorMessage}`);\n } catch (error: any) {\n stopPolling();\n if (error.response?.data?.message) {\n throw new Error(`Analysis failed: ${error.response.data.message}`);\n }\n if (error.message) {\n throw error;\n }\n throw new Error(\n \"Document video analysis failed due to an unexpected error\",\n );\n }\n}\n"],"names":["getMimeTypeFromDataURL","mimeTypeToExtension","__awaiter","getSessionMemoryUserInput","dataURLtoFile","apiService","logDocumentUploaded","logAiControlled","__assign","pollAnalysisStatus","stopPolling","logSelfieCaptured","logStatusModified"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"analysis.js","sources":["../../../../src/services/analysis.ts"],"sourcesContent":["import type { onUploadFiles } from \"../types/uploadFiles\";\nimport { dataURLtoFile, getMimeTypeFromDataURL } from \"./utils\";\nimport { mimeTypeToExtension } from \"../utils/mimeTypes\";\nimport { apiService } from \"./api\";\nimport type { SelfieCaptureData } from \"../types/selfie\";\nimport type {\n DocumentVideoCaptureBySide,\n DocumentVideoPreviewBySide,\n} from \"../types/documentVideo\";\nimport { getSessionMemoryUserInput } from \"./sessionMemoryStore\";\nimport {\n logDocumentUploaded,\n logSelfieCaptured,\n logAiControlled,\n logStatusModified,\n} from \"./auditTrailService\";\nimport { pollAnalysisStatus, stopPolling } from \"./pollingService\";\nimport type { PollingOptions } from \"./pollingService\";\n\n// Timeout configurations (in milliseconds)\nconst ANALYSIS_TIMEOUT = 600000; // 10 minutes for document analysis (increased for large files + ML processing)\nconst SELFIE_ANALYSIS_TIMEOUT = 600000; // 10 minutes for selfie analysis\nconst UPLOAD_TIMEOUT = 300000; // 5 minutes for file uploads\n\n// Map pour suivre les analyses en cours et éviter les doublons\nconst ongoingAnalyses = new Map<string, Promise<any>>();\n\nexport interface AnalyzeFilesOptions {\n personPhoto?: string | null;\n save?: boolean;\n incrementAnalysis?: boolean;\n forceUpload?: boolean;\n documentTypeKey?: string | null;\n requiresTwoSides?: boolean;\n enablePolling?: boolean; // Enable polling for analysis progress (default: true)\n pollingOptions?: PollingOptions; // Custom polling configuration\n collectOnly?: boolean; // Bypass AI verification — document is collected as-is\n}\n\ninterface LaunchAnalysisOptions extends AnalyzeFilesOptions {}\n\nfunction createFileName(fileURL: string, baseName: string = \"file\") {\n const mimeType = getMimeTypeFromDataURL(fileURL);\n if (!mimeType) {\n throw new Error(\"Unable to determine MIME type from file URL\");\n }\n\n const ext = mimeTypeToExtension(mimeType);\n const safeBase = baseName.replace(/\\.+$/, \"\");\n return ext ? `${safeBase}.${ext}` : safeBase;\n}\n\nfunction normalizeDocumentTypeKey(\n rawType?: string | null,\n fallback: string = \"document\",\n) {\n if (!rawType) {\n return fallback;\n }\n\n const trimmed = rawType.trim();\n if (!trimmed) {\n return fallback;\n }\n\n const withUnderscores = trimmed\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[\\s-]+/g, \"_\")\n .replace(/[^a-zA-Z0-9_]/g, \"_\")\n .replace(/_+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .toLowerCase();\n\n return withUnderscores || fallback;\n}\n\n// Fonction pour créer une clé unique pour identifier une analyse\nfunction createAnalysisKey(\n sessionId: string,\n files: onUploadFiles,\n documentTypeId: string,\n): string {\n const frontHash = files.front ? files.front.substring(0, 50) : \"no-front\";\n const backHash = files.back ? files.back.substring(0, 50) : \"no-back\";\n return `${sessionId}-${documentTypeId}-${frontHash}-${backHash}`;\n}\n\nasync function launchAnalysis(\n sessionId: string,\n nodeId: string,\n files: onUploadFiles,\n documentTypeId: string | null,\n options: LaunchAnalysisOptions = {},\n) {\n if (!sessionId || !files) {\n throw new Error(\"Invalid parameters for analysis\");\n }\n\n const {\n personPhoto = null,\n save = true,\n incrementAnalysis = true,\n forceUpload = false,\n documentTypeKey = null,\n requiresTwoSides,\n collectOnly = false,\n } = options;\n\n const formData = new FormData();\n formData.append(\"sessionId\", sessionId);\n formData.append(\"nodeId\", nodeId);\n formData.append(\"save\", String(save));\n\n const userInput = getSessionMemoryUserInput(sessionId);\n if (Object.keys(userInput).length > 0) {\n const fullName = `${userInput.firstName || \"\"} ${\n userInput.lastName || \"\"\n }`.trim();\n formData.append(\"name\", fullName || \"Unknown\");\n\n formData.append(\"firstName\", userInput.firstName || \"\");\n formData.append(\"lastName\", userInput.lastName || \"\");\n formData.append(\"birthDate\", userInput.birthDate || \"\");\n formData.append(\"countryCode\", userInput.countryCode || \"\");\n }\n\n const fileTypes: Record<string, string> = {};\n const normalizedDocumentType = normalizeDocumentTypeKey(\n documentTypeKey ?? documentTypeId ?? undefined,\n );\n const hyphenDocumentType = normalizedDocumentType.replace(/_/g, \"-\");\n const appendSide =\n typeof requiresTwoSides === \"boolean\"\n ? requiresTwoSides\n : Boolean(files.back);\n\n if (files.front) {\n const frontBaseName = appendSide\n ? `${normalizedDocumentType}_front`\n : normalizedDocumentType;\n const frontFileName = createFileName(files.front, frontBaseName);\n const frontFile = dataURLtoFile(files.front, frontFileName);\n formData.append(\"files\", frontFile, frontFileName);\n\n fileTypes[frontFileName] = appendSide\n ? `${hyphenDocumentType}-front`\n : hyphenDocumentType;\n }\n\n if (files.back) {\n const backBaseName = `${normalizedDocumentType}_back`;\n const backFileName = createFileName(files.back, backBaseName);\n const backFile = dataURLtoFile(files.back, backFileName);\n formData.append(\"files\", backFile, backFileName);\n\n fileTypes[backFileName] = `${hyphenDocumentType}-back`;\n }\n\n formData.append(\"fileTypes\", JSON.stringify(fileTypes));\n formData.append(\"incrementAnalysis\", String(incrementAnalysis));\n formData.append(\"forceUpload\", String(forceUpload));\n\n if (documentTypeId) {\n formData.append(\"documentTemplateId\", documentTypeId);\n }\n\n if (personPhoto) {\n formData.append(\"personPhoto\", personPhoto);\n }\n\n if (collectOnly) {\n formData.append(\"collectOnly\", \"true\");\n }\n\n console.debug(\"FormData prepared for analysis:\", {\n sessionId,\n documentTypeId,\n files: Object.keys(fileTypes),\n save,\n incrementAnalysis,\n forceUpload,\n collectOnly,\n });\n return formData;\n}\n\nexport async function analyzeFiles(\n sessionId: string,\n nodeId: string,\n files: onUploadFiles,\n documentTypeId: string,\n options: AnalyzeFilesOptions = {},\n): Promise<any> {\n // Validate required parameters\n if (!sessionId) {\n throw new Error(\"Missing sessionId: A valid session ID is required.\");\n }\n if (!files || Object.keys(files).length === 0) {\n throw new Error(\n \"Missing files: At least one file must be provided for analysis.\",\n );\n }\n\n const {\n personPhoto = null,\n save = true,\n incrementAnalysis = true,\n forceUpload = false,\n documentTypeKey = null,\n requiresTwoSides,\n enablePolling = true,\n pollingOptions = {},\n collectOnly = false,\n } = options;\n\n // Pour les retry, on ne force pas l'upload mais on écrase l'analyse existante\n const isRetry = !incrementAnalysis && !forceUpload;\n\n // Créer une clé unique pour cette analyse\n const analysisKey = createAnalysisKey(sessionId, files, documentTypeId);\n\n // Vérifier si une analyse identique est déjà en cours\n if (ongoingAnalyses.has(analysisKey) && !isRetry) {\n return ongoingAnalyses.get(analysisKey);\n }\n\n // Helper function for retry logic with exponential backoff\n async function submitAnalysisWithRetry(\n formData: FormData,\n maxAttempts: number = 3,\n ) {\n let lastError: any;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const rawClient = apiService.getRawClient();\n\n const response = await rawClient.post(\n `/session/sdk/${sessionId}/analysis`,\n formData,\n {\n timeout: ANALYSIS_TIMEOUT,\n },\n );\n\n return response;\n } catch (error: any) {\n lastError = error;\n\n // Check if it's a network error (likely backend didn't respond in time)\n if (\n error.code === \"ERR_NETWORK\" ||\n error.message?.includes(\"CORS request did not succeed\")\n ) {\n console.warn(\n `⚠️ Network error on attempt ${attempt}: ${error.message}`,\n );\n\n if (attempt < maxAttempts) {\n // Exponential backoff: wait 2s, 4s, 8s...\n const waitTime = Math.pow(2, attempt) * 1000;\n console.log(`⏳ Retrying in ${waitTime / 1000}s...`);\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n continue;\n }\n }\n\n // For other errors, don't retry\n throw error;\n }\n }\n\n throw lastError;\n }\n\n // Créer la promesse d'analyse et la stocker\n const analysisPromise = (async () => {\n try {\n const formData = await launchAnalysis(\n sessionId,\n nodeId,\n files,\n documentTypeId,\n {\n personPhoto,\n save,\n incrementAnalysis: isRetry ? false : incrementAnalysis,\n forceUpload: isRetry ? true : forceUpload,\n documentTypeKey,\n requiresTwoSides,\n collectOnly,\n },\n );\n\n await logDocumentUploaded(sessionId, {\n documentTypeId: documentTypeId || \"unknown\",\n ...(documentTypeKey ? { documentTypeKey } : {}),\n hasFrontImage: !!files.front,\n hasBackImage: !!files.back,\n });\n\n // Submit with automatic retry on network errors\n const response = await submitAnalysisWithRetry(formData);\n\n // Wrap response to match ApiResponse type\n const wrappedResponse = {\n data: response.data,\n success: true,\n status: response.status,\n };\n\n await logAiControlled(\n sessionId,\n {\n analysisResult: response.data.status || \"unknown\",\n documentTypeId: documentTypeId || \"unknown\",\n },\n response.data.clientInfoId || undefined,\n );\n\n if (!wrappedResponse.success) {\n throw new Error(`Analysis failed: ${response.data}`);\n }\n\n // Start polling for analysis progress if enabled\n if (enablePolling) {\n try {\n const pollConfig: PollingOptions = {\n ...pollingOptions,\n };\n\n const pollingResult = await pollAnalysisStatus(sessionId, pollConfig);\n\n return pollingResult;\n } catch (pollError) {\n console.warn(\n \"⚠️ Polling error (analysis may still be processing):\",\n pollError,\n );\n // Don't throw - polling error shouldn't fail the analysis submission\n // The backend is still processing even if polling fails\n return response.data;\n }\n }\n\n return response.data;\n } catch (error) {\n console.error(\"❌ Analysis failed:\", error);\n // Stop any ongoing polling on error\n stopPolling();\n throw error;\n } finally {\n // Nettoyer la promesse de la map une fois terminée\n ongoingAnalyses.delete(analysisKey);\n }\n })();\n\n // Stocker la promesse pour éviter les appels simultanés\n ongoingAnalyses.set(analysisKey, analysisPromise);\n\n return analysisPromise;\n}\n\nexport async function analyzeSelfie(\n sessionId: string,\n selfieFile: SelfieCaptureData,\n selfiePhoto: string,\n nodeId?: string,\n): Promise<any> {\n console.log(\"🤳 Starting selfie analysis for session:\", sessionId);\n console.log(\"� File size:\", selfieFile.media.size, \"bytes\");\n\n const formData = new FormData();\n formData.append(\"file\", selfieFile.media, \"selfie.mp4\");\n formData.append(\"photo\", selfiePhoto);\n if (nodeId) formData.append(\"nodeId\", nodeId);\n\n try {\n console.log(\"🚀 Sending selfie to UNISSEY API...\");\n\n const response = await apiService.post(\n `/session/unissey/${sessionId}/analyze`,\n formData,\n {\n timeout: SELFIE_ANALYSIS_TIMEOUT,\n },\n );\n\n console.log(\"✅ Analysis response:\", response);\n\n // Si la réponse API indique un succès, traiter la réponse Unissey\n if (response.success && response.data) {\n console.log(\"🎉 Unissey analysis completed - checking results...\");\n\n // response.data contient directement la réponse Unissey avec status, message, data\n const unisseyResponse = response.data;\n\n // Vérifier si Unissey a répondu avec succès\n if (\n unisseyResponse.status === 200 &&\n (unisseyResponse.message === \"success\" ||\n unisseyResponse.message === \"ok\")\n ) {\n console.log(\"✅ Unissey returned success status\");\n\n // Utiliser les données réelles de la réponse Unissey\n const unisseyData = unisseyResponse.data;\n\n // Vérifier si la comparaison faciale a un niveau de confiance élevé\n const faceComparison = unisseyData.details?.face_comparison;\n const isHighConfidence = faceComparison?.confidence_level === \"high\";\n const isMatch =\n unisseyData.is_match && faceComparison?.result === \"match\";\n\n // is_genuine est basé sur la confiance élevée de la comparaison faciale\n const isGenuine = isHighConfidence && isMatch;\n\n // Log selfie captured in audit trail\n try {\n const analysisResponse = await apiService.get(\n `/session/sdk/${sessionId}`,\n );\n if (analysisResponse.data && analysisResponse.data.analysisId) {\n await logSelfieCaptured(\n sessionId,\n analysisResponse.data.clientInfoId || undefined,\n );\n\n // Log AI control with selfie analysis results\n await logAiControlled(\n sessionId,\n {\n selfieAnalysisResult: isGenuine ? \"genuine\" : \"not_genuine\",\n isMatch: isMatch ? \"match\" : \"no_match\",\n confidenceLevel: faceComparison?.confidence_level || \"unknown\",\n },\n analysisResponse.data.clientInfoId || undefined,\n );\n\n await logStatusModified(\n sessionId,\n {\n selfieAnalysisResult: isGenuine ? \"genuine\" : \"not_genuine\",\n isMatch: isMatch ? \"match\" : \"no_match\",\n confidenceLevel: faceComparison?.confidence_level || \"unknown\",\n },\n analysisResponse.data.clientInfoId || undefined,\n );\n }\n } catch (err) {\n console.error(\"Failed to log selfie capture in audit trail:\", err);\n // Non-blocking error - continue analysis\n }\n\n // Retourner la structure attendue par l'UI\n return {\n success: true,\n data: {\n ...unisseyData,\n is_genuine: isGenuine, // Basé sur confidence_level === \"high\"\n },\n };\n } else {\n console.error(\n \"❌ Unissey returned error status:\",\n unisseyResponse.status,\n unisseyResponse.message,\n );\n throw new Error(\n `Unissey analysis failed: ${\n unisseyResponse.message || \"Unknown Unissey error\"\n }`,\n );\n }\n }\n\n // Gestion des erreurs spécifiques API\n const errorMessage =\n response.data?.message || response.data || \"Unknown error\";\n console.error(\"❌ API call failed:\", errorMessage);\n throw new Error(`Face comparison analysis failed: ${errorMessage}`);\n } catch (error: any) {\n console.error(\"💥 Analysis error:\", error);\n\n // Améliorer le message d'erreur pour l'UI\n if (error.response?.data?.message) {\n throw new Error(`Analysis failed: ${error.response.data.message}`);\n } else if (error.message) {\n throw error; // Garder le message d'erreur original si déjà formaté\n } else {\n throw new Error(\n \"Face comparison analysis failed due to an unexpected error\",\n );\n }\n }\n}\n\nexport async function uploadConvertedIdCardImage(\n sessionId: string,\n file: File,\n): Promise<any> {\n if (!sessionId || !file) {\n throw new Error(\"Invalid parameters for uploading converted ID card image\");\n }\n\n // rename file to converted_id_card.png\n const renamedFile = new File([file], \"converted_id_card.png\", {\n type: file.type,\n });\n\n const formData = new FormData();\n formData.append(\"file\", renamedFile, renamedFile.name);\n\n try {\n console.log(\n `🚀 Uploading converted ID card image for session: ${sessionId}`,\n );\n const response = await apiService.post(\n `/session/sdk/${sessionId}/converted_id_card.png`,\n formData,\n {\n timeout: UPLOAD_TIMEOUT,\n },\n );\n console.log(\"✅ Upload response:\", response);\n return response.data;\n } catch (error) {\n console.error(\"❌ Upload error:\", error);\n throw new Error(\"Failed to upload converted ID card image\");\n }\n}\n\n/**\n * Analyzes a document video captured with Unissey DOC_VIDEO preset.\n * Sends the video file and thumbnail to the backend for document verification.\n *\n * @param sessionId - Unique identifier for the current session\n * @param nodeId - Identifier for the current node in the journey\n * @param videoData - Document video capture data containing media blob and metadata\n * @param thumbnail - Base64 thumbnail extracted from the video\n * @param documentTemplateId - Template ID for the document type being verified\n * @returns Analysis response from the backend\n */\nexport async function analyzeDocumentVideo(\n sessionId: string,\n nodeId: string,\n videoData: DocumentVideoCaptureBySide,\n previews: DocumentVideoPreviewBySide,\n documentTemplateId: string,\n options: {\n documentType?: string;\n requiresTwoSides?: boolean;\n enablePolling?: boolean;\n pollingOptions?: PollingOptions;\n } = {},\n): Promise<any> {\n if (!videoData.recto || !previews.recto) {\n throw new Error(\"Missing recto video or preview\");\n }\n\n const normalizedDocumentType = normalizeDocumentTypeKey(\n options.documentType ?? documentTemplateId ?? undefined,\n );\n const hyphenDocumentType = normalizedDocumentType.replace(/_/g, \"-\");\n const appendSide =\n typeof options.requiresTwoSides === \"boolean\"\n ? options.requiresTwoSides\n : Boolean(videoData.verso || previews.verso);\n\n const frontBaseName = appendSide\n ? `${normalizedDocumentType}_front`\n : normalizedDocumentType;\n const backBaseName = `${normalizedDocumentType}_back`;\n\n const previewFrontFileName = `${frontBaseName}.jpg`;\n const previewFrontFile = dataURLtoFile(previews.recto, previewFrontFileName);\n const previewBackFileName = `${backBaseName}.jpg`;\n const previewBackFile = previews.verso\n ? dataURLtoFile(previews.verso, previewBackFileName)\n : null;\n\n const formData = new FormData();\n\n formData.append(\n \"videoFront\",\n videoData.recto.media,\n \"document_video_recto.mp4\",\n );\n if (videoData.verso) {\n formData.append(\n \"videoBack\",\n videoData.verso.media,\n \"document_video_verso.mp4\",\n );\n }\n\n formData.append(\"previewFront\", previewFrontFile, previewFrontFileName);\n if (previewBackFile) {\n formData.append(\"previewBack\", previewBackFile, previewBackFileName);\n }\n\n const fileTypes: Record<string, string> = {};\n fileTypes[previewFrontFileName] = appendSide\n ? `${hyphenDocumentType}-front`\n : hyphenDocumentType;\n if (previewBackFile) {\n fileTypes[previewBackFileName] = `${hyphenDocumentType}-back`;\n }\n\n formData.append(\"fileTypes\", JSON.stringify(fileTypes));\n formData.append(\"sessionId\", sessionId);\n formData.append(\"nodeId\", nodeId);\n formData.append(\"documentTemplateId\", documentTemplateId);\n formData.append(\"documentType\", options.documentType || \"\");\n formData.append(\"requiresTwoSides\", String(appendSide));\n formData.append(\"save\", \"true\");\n\n const { enablePolling = true, pollingOptions = {} } = options;\n\n try {\n console.log(\"🚀 Sending document video to document-video API...\");\n const response = await apiService.post(\n `/session/sdk/${sessionId}/document-video`,\n formData,\n { timeout: ANALYSIS_TIMEOUT },\n );\n\n if (enablePolling) {\n try {\n const pollConfig: PollingOptions = {\n ...pollingOptions,\n defaultValue: {\n sessionId,\n status: \"processing\",\n progress: 50,\n currentStep: \"processing\",\n message: \"Document analysis in progress\",\n analysisId: null,\n startedAt: new Date().toISOString(),\n completedAt: null,\n error: null,\n },\n };\n const pollingResult = await pollAnalysisStatus(sessionId, pollConfig);\n return pollingResult;\n } catch (pollError) {\n console.warn(\n \"⚠️ Polling error (document-video may still be processing):\",\n pollError,\n );\n }\n }\n\n if (response?.success || response?.data?.success) {\n return response.data ?? response;\n }\n\n const errorMessage = response?.data?.message || \"Unknown error\";\n throw new Error(`Document video analysis failed: ${errorMessage}`);\n } catch (error: any) {\n stopPolling();\n if (error.response?.data?.message) {\n throw new Error(`Analysis failed: ${error.response.data.message}`);\n }\n if (error.message) {\n throw error;\n }\n throw new Error(\n \"Document video analysis failed due to an unexpected error\",\n );\n }\n}\n"],"names":["getMimeTypeFromDataURL","mimeTypeToExtension","__awaiter","getSessionMemoryUserInput","dataURLtoFile","apiService","logDocumentUploaded","logAiControlled","__assign","pollAnalysisStatus","stopPolling","logSelfieCaptured","logStatusModified"],"mappings":"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"}
|
|
@@ -103,6 +103,16 @@ var skipNfcWithReason = function (sessionId, payload) { return tslib_es6.__await
|
|
|
103
103
|
}
|
|
104
104
|
});
|
|
105
105
|
}); };
|
|
106
|
+
var reportSelfieFailure = function (sessionId, payload) { return tslib_es6.__awaiter(void 0, void 0, void 0, function () {
|
|
107
|
+
return tslib_es6.__generator(this, function (_a) {
|
|
108
|
+
switch (_a.label) {
|
|
109
|
+
case 0: return [4 /*yield*/, api.apiService.post("/session/sdk/".concat(sessionId, "/selfie-failed"), payload)];
|
|
110
|
+
case 1:
|
|
111
|
+
_a.sent();
|
|
112
|
+
return [2 /*return*/];
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}); };
|
|
106
116
|
/**
|
|
107
117
|
* Resets a terminal NFC failure before the user starts again with another
|
|
108
118
|
* document. The backend keeps completed scans immutable and treats this call
|
|
@@ -466,6 +476,7 @@ exports.getOrderedJourneySteps = getOrderedJourneySteps;
|
|
|
466
476
|
exports.getRunPrefillData = getRunPrefillData;
|
|
467
477
|
exports.isSessionExpired = isSessionExpired;
|
|
468
478
|
exports.reconstructHistoryToStep = reconstructHistoryToStep;
|
|
479
|
+
exports.reportSelfieFailure = reportSelfieFailure;
|
|
469
480
|
exports.resetNfcScan = resetNfcScan;
|
|
470
481
|
exports.sendClientInfo = sendClientInfo;
|
|
471
482
|
exports.skipNfcWithReason = skipNfcWithReason;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionService.js","sources":["../../../../src/services/sessionService.ts"],"sourcesContent":["/**\n * Session Service\n *\n * Service for interacting with the Datakeen Session API.\n * Handles fetching session data by ID.\n */\n\nimport type {\n ClientInfo,\n SessionData,\n SessionTemplate,\n SessionTemplateNode,\n} from \"../types/session\";\nimport { apiService } from \"./api\";\nimport { logStatusModified } from \"./auditTrailService\";\nimport { clearSessionMemory } from \"./sessionMemoryStore\";\n\n/**\n * Fetches session data by ID from the Datakeen backend\n *\n * @param sessionId - The unique identifier of the session\n * @returns The session data\n */\nexport const fetchSessionById = async (\n sessionId: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.get(`/session/sdk/${sessionId}`);\n return response.data;\n } catch (error) {\n console.error(\"Error fetching session data:\", error);\n throw error;\n }\n};\n\n/** Sends client information (IP, device, browser, OS) to the backend for a specific session\n *\n * @param sessionId - The unique identifier of the session\n * @param clientInfo - The client information to send\n */\nexport const sendClientInfo = async (\n sessionId: string,\n clientInfo: ClientInfo,\n): Promise<void> => {\n try {\n await apiService.post(`/session/sdk/${sessionId}/client-info`, clientInfo);\n } catch (error) {\n console.error(\"Error sending client info:\", error);\n throw error;\n }\n};\n\n/**\n * Determines if the session template has a specific type of node\n *\n * @param template - The session template\n * @param nodeType - The type of node to check for\n * @returns true if the template has a node of the specified type, false otherwise\n */\nexport const hasNodeType = (\n template: SessionTemplate,\n nodeType: string,\n): boolean => {\n return template.nodes.some((node) => node.type === nodeType);\n};\n\n/**\n * Determines if the session template has a node with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to check for\n * @returns true if the template has a node with the specified requiredDocumentType, false otherwise\n */\nexport const hasDocumentTypeNode = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): boolean => {\n return template.nodes.some(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Gets all nodes of a specific type\n *\n * @param template - The session template\n * @param nodeType - The type of node to get\n * @returns Array of nodes matching the type\n */\nexport const getNodesByType = (\n template: SessionTemplate,\n nodeType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter((node) => node.type === nodeType);\n};\n\n/**\n * Gets all nodes with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to get\n * @returns Array of nodes matching the requiredDocumentType\n */\nexport const getNodesByDocumentType = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Get document options for a specific document type\n *\n * @param template - The session template\n * @param requiredDocumentType - The document type to get options for\n * @returns Array of document options (empty if none found)\n */\nexport const getDocumentOptions = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): string[] => {\n const node = template.nodes.find(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n return node?.selectedOptions || [];\n};\n\n/**\n * Determines if the session template has a selfie step\n *\n * @param template - The session template\n * @returns true if the template has a selfie step, false otherwise\n */\nexport const hasSelfieCaptureStep = (template: SessionTemplate): boolean => {\n return hasNodeType(template, \"selfie-capture\");\n};\n\n/**\n * Determines if the session template has an ID document step\n *\n * @param template - The session template\n * @returns true if the template has an ID document step, false otherwise\n */\nexport const hasDocumentStep = (template: SessionTemplate): boolean => {\n // Check if there's any document-selection node with requiredDocumentType \"id-card\"\n // or if none specified, just check for document-selection nodes\n const hasIDCard = hasDocumentTypeNode(template, \"id-card\");\n return hasIDCard || hasNodeType(template, \"document-selection\");\n};\n\n/**\n * Determines if the session template has a JDD (proof of address) step\n *\n * @param template - The session template\n * @returns true if the template has a JDD step, false otherwise\n */\nexport const hasJDDStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"jdd\");\n};\n\n/**\n * Determines if the session template has a proof of funds step\n *\n * @param template - The session template\n * @returns true if the template has a proof of funds step, false otherwise\n */\nexport const hasProofOfFundsStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"income-proof\");\n};\n\n/**\n * Determines if the session template has a document collection step\n *\n * @param template - The session template\n * @returns true if the template has a document collection step, false otherwise\n */\nexport const hasDocumentCollectionStep = (\n template: SessionTemplate,\n): boolean => {\n return hasNodeType(template, \"document-collection\");\n};\n\n/**\n * Gets all node types in the template\n *\n * @param template - The session template\n * @returns Array of node types in the template\n */\nexport const getNodeTypes = (template: SessionTemplate): string[] => {\n return Array.from(new Set(template.nodes.map((node) => node.type)));\n};\n\n/**\n * Gets all document types required in the template\n *\n * @param template - The session template\n * @returns Array of document types required in the template\n */\nexport const getRequiredDocumentTypes = (\n template: SessionTemplate,\n): string[] => {\n return Array.from(\n new Set(\n template.nodes\n .filter((node) => node.requiredDocumentType)\n .map((node) => node.requiredDocumentType!),\n ),\n );\n};\n\n/**\n * Converts template document type to internal document type\n * This helps standardize document types between the template and the application\n *\n * @param templateDocType - The document type as defined in the template\n * @returns The internal document type used by the application\n */\nexport const convertTemplateDocTypeToInternal = (\n templateDocType: string,\n): string => {\n if (!templateDocType) return \"\";\n\n // Mapping between template document types and internal document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n \"income-proof\": \"income-proof\", // Using consistent naming\n };\n\n return typeMap[templateDocType] || templateDocType;\n};\n\n/**\n * Converts internal document type to template document type\n *\n * @param internalDocType - The document type used internally by the application\n * @returns The document type as expected in the template\n */\nexport const convertInternalDocTypeToTemplate = (\n internalDocType: string,\n): string => {\n if (!internalDocType) return \"\";\n\n // Mapping between internal document types and template document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n funds: \"income-proof\", // Map funds to income-proof for backwards compatibility\n \"income-proof\": \"income-proof\",\n };\n\n return typeMap[internalDocType] || internalDocType;\n};\n\n/**\n * Updates session data with user input information\n *\n * @param sessionId - The unique identifier of the session\n * @param userInput - The user input data (firstName, lastName, birthDate)\n * @returns The updated session data\n */\nexport const updateSessionUserInput = async (\n sessionId: string,\n userInput: {\n firstName?: string;\n lastName?: string;\n birthDate?: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n userInput,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session data:\", error);\n throw error;\n }\n};\n\n/**\n * Records the NFC fallback reason when the user declares they cannot use the\n * contactless scan, and marks the NFC scan as skipped server-side.\n *\n * @param sessionId - The unique identifier of the session\n * @param payload - The selected reason (technical key), its human-readable label,\n * and an optional free-text comment.\n */\nexport const skipNfcWithReason = async (\n sessionId: string,\n payload: { reason: string; label: string; comment?: string },\n): Promise<void> => {\n await apiService.post(`/session/sdk/${sessionId}/nfc-skip`, payload);\n};\n\n/**\n * Resets a terminal NFC failure before the user starts again with another\n * document. The backend keeps completed scans immutable and treats this call\n * as a no-op when the status is not terminal.\n */\nexport const resetNfcScan = async (sessionId: string): Promise<void> => {\n await apiService.post(`/session/sdk/${sessionId}/nfc-reset`);\n};\n\n/**\n * Updates session data with contact information\n *\n * @param sessionId - The unique identifier of the session\n * @param contactInfo - The contact information data (email, phoneNumber)\n * @returns The updated session data\n */\nexport const updateSessionContactInfo = async (\n sessionId: string,\n contactInfo: {\n email: string;\n phoneNumber: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n contactInfo,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating contact information:\", error);\n throw error;\n }\n};\n\n/**\n * Updates session status\n *\n * @param sessionId - The unique identifier of the session\n * @param status - The new status for the session\n * @param reachedEndNodeId - Id of the end node actually reached (when status is \"ended\"),\n * so the backend can force the correct final status with multiple end nodes.\n * @returns The updated session data\n */\nexport const updateSessionStatus = async (\n sessionId: string,\n status: string,\n reachedEndNodeId?: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n status,\n ...(reachedEndNodeId ? { reachedEndNodeId } : {}),\n });\n\n // Log status modification in audit trail\n if (response.data && response.data.analysisId) {\n try {\n await logStatusModified(\n sessionId,\n status,\n response.data.clientInfoId || undefined,\n );\n } catch (err) {\n console.error(\"Failed to log status modification in audit trail:\", err);\n // Non-blocking error - continue session\n }\n }\n\n return response.data;\n } catch (error) {\n console.error(\"Error updating session status:\", error);\n throw error;\n }\n};\n\n/**\n * Updates the current step in the session\n *\n * @param sessionId - The unique identifier of the session\n * @param currentStep - The current step index in the workflow\n * @returns The updated session data\n */\nexport const updateSessionCurrentStep = async (\n sessionId: string,\n currentStep: number,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n currentStep,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session current step:\", error);\n throw error;\n }\n};\n\n/**\n * Gets the journey steps from the template in order\n *\n * @param template - The session template\n * @returns Array of ordered steps\n */\nexport const getOrderedJourneySteps = (\n template: SessionTemplate,\n): SessionTemplateNode[] => {\n // Filter out only start nodes, keep end nodes for proper journey completion, then sort by order.\n // Tiebreaker on id keeps the ordering deterministic when several nodes share the same `order`\n // (e.g. parallel branches of a condition), independently of their position in template.nodes.\n return template.nodes\n .filter((node) => node.type !== \"start\")\n .sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));\n};\n\nconst normalizeHandle = (value?: string): string => {\n return (value || \"\").trim().toLowerCase();\n};\n\n/**\n * Finds the outgoing edge to follow from a node.\n *\n * Resolution order:\n * 1. Exact handle match via sourceHandle/conditionValue.\n * 2. For condition:false loops, fallback to targetHandle=right.\n * 3. First outgoing edge as final fallback.\n */\nexport const findOutgoingEdge = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): SessionTemplate[\"edges\"][number] | null => {\n const outgoingEdges = (template.edges || []).filter(\n (edge) => edge.source === currentNodeId,\n );\n\n if (outgoingEdges.length === 0) {\n return null;\n }\n\n if (!handle) {\n return outgoingEdges[0];\n }\n\n const normalizedHandle = normalizeHandle(handle);\n const edgeByHandle = outgoingEdges.find((edge) => {\n return (\n normalizeHandle(edge.sourceHandle) === normalizedHandle ||\n normalizeHandle(edge.conditionValue) === normalizedHandle\n );\n });\n\n if (edgeByHandle) {\n return edgeByHandle;\n }\n\n const currentNode = template.nodes.find((node) => node.id === currentNodeId);\n if (currentNode?.type === \"condition\" && normalizedHandle === \"false\") {\n const rightHandleLoopEdge = outgoingEdges.find(\n (edge) => normalizeHandle(edge.targetHandle) === \"right\",\n );\n if (rightHandleLoopEdge) {\n return rightHandleLoopEdge;\n }\n }\n\n return outgoingEdges[0];\n};\n\n/**\n * Gets the next step index by following the graph edge from the current node\n *\n * @param currentNodeId - The ID of the current node\n * @param template - The session template\n * @returns The next step index (1-based) or null if no edge found\n */\nexport const getNextStepIndex = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): number | null => {\n const orderedNodes = getOrderedJourneySteps(template);\n const edge = findOutgoingEdge(currentNodeId, template, handle);\n\n if (!edge) {\n console.debug(\n `[sessionService] No outgoing edge found for node ${currentNodeId}${handle ? ` with handle ${handle}` : \"\"}`,\n );\n return null;\n }\n\n const targetId = edge.target;\n const targetIndex = orderedNodes.findIndex((n) => n.id === targetId);\n\n if (targetIndex === -1) {\n console.debug(\n `[sessionService] Target node ${targetId} not found in ordered steps`,\n );\n return null;\n }\n\n // steps are 1-indexed in the SDK (0 is StartSession)\n return 1 + targetIndex;\n};\n\n/**\n * Reconstructs the navigation history by following the graph from step 0\n * up to (and including) targetStep. Returns [0, ...stepIndices].\n * If the graph path cannot reach targetStep, falls back to [0, targetStep].\n */\nexport const reconstructHistoryToStep = (\n targetStep: number,\n template: SessionTemplate,\n): number[] => {\n if (targetStep <= 0) return [0];\n\n const orderedNodes = getOrderedJourneySteps(template);\n const history: number[] = [0];\n let currentStep = 1; // first node is step 1\n\n // Follow the default (first) edge from each node in sequence\n for (let safetyLimit = 0; safetyLimit < orderedNodes.length + 1; safetyLimit++) {\n if (currentStep === targetStep) {\n history.push(currentStep);\n break;\n }\n if (currentStep > targetStep) break;\n\n const nodeIndex = currentStep - 1;\n const currentNode = orderedNodes[nodeIndex];\n if (!currentNode) break;\n\n history.push(currentStep);\n\n const nextStep = getNextStepIndex(currentNode.id, template);\n if (nextStep === null) break;\n currentStep = nextStep;\n }\n\n // Fallback: if we couldn't reach targetStep via graph, use simple seed\n if (history[history.length - 1] !== targetStep) {\n return [0, targetStep];\n }\n\n return history;\n};\n\n/**\n * Maps a template node type to a step component type\n *\n * @param node - The session template node\n * @returns The step component type\n */\nexport const getStepComponentType = (node: SessionTemplateNode): string => {\n // Map from template node types to component types\n const typeMap: Record<string, string> = {\n \"document-selection\": \"document\",\n \"document-collection\": \"document-collection\",\n \"selfie-capture\": \"selfie\",\n \"contact-info\": \"contact-info\",\n \"user-input\": \"user-input\",\n \"otp-verification\": \"otp\",\n };\n\n // First check the node type\n if (node.type in typeMap) {\n return typeMap[node.type];\n }\n\n // Then check the requiredDocumentType\n if (node.requiredDocumentType) {\n return node.requiredDocumentType;\n }\n\n // Default fallback\n return node.type;\n};\n\n/**\n * Checks if a session has expired\n *\n * @param session - The session data to check\n * @returns true if the session has expired, false otherwise\n */\nexport const isSessionExpired = (session: SessionData): boolean => {\n if (!session.expireTime) {\n return false;\n }\n\n const currentTime = Date.now();\n return currentTime > session.expireTime;\n};\n\n/**\n * Stores document options in localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @param options - The options to store\n */\nexport const storeDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n options: string[],\n): void => {\n if (!sessionId || !documentTypeId || !options || options.length === 0) {\n console.warn(\"Missing data for storeDocumentOptions:\", {\n sessionId,\n documentTypeId,\n options,\n });\n return;\n }\n\n // Create a consistent key format based on document type\n let storageKey = \"\";\n\n switch (documentTypeId) {\n case \"jdd\":\n storageKey = `jddOptions_${sessionId}`;\n break;\n case \"income-proof\":\n storageKey = `fundsOptions_${sessionId}`;\n break;\n case \"id-card\":\n storageKey = `idOptions_${sessionId}`;\n break;\n case \"document-collection\":\n storageKey = `documentCollectionOptions_${sessionId}`;\n break;\n default:\n storageKey = `${documentTypeId}Options_${sessionId}`;\n }\n\n localStorage.setItem(storageKey, JSON.stringify(options));\n};\n\n/**\n * Retrieves document options from localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @returns Array of options or default options if none found\n */\nexport const retrieveDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n): string[] => {\n if (!sessionId || !documentTypeId) {\n console.warn(\"Missing data for retrieveDocumentOptions:\", {\n sessionId,\n documentTypeId,\n });\n return [];\n }\n\n // Create consistent key formats to check\n const possibleKeys = [\n `${documentTypeId}Options_${sessionId}`,\n documentTypeId === \"jdd\" ? `jddOptions_${sessionId}` : \"\",\n documentTypeId === \"income-proof\" ? `fundsOptions_${sessionId}` : \"\",\n documentTypeId === \"id-card\" ? `idOptions_${sessionId}` : \"\",\n documentTypeId === \"document-collection\"\n ? `documentCollectionOptions_${sessionId}`\n : \"\",\n ].filter(Boolean);\n\n // Try each possible key\n for (const key of possibleKeys) {\n const savedOptions = localStorage.getItem(key);\n if (savedOptions) {\n try {\n const parsedOptions = JSON.parse(savedOptions);\n\n return parsedOptions;\n } catch (e) {\n console.error(\n `Error parsing options for ${documentTypeId} with key ${key}:`,\n e,\n );\n }\n }\n }\n\n // Return default options if none found\n console.warn(`No options found for ${documentTypeId}, using defaults`);\n if (documentTypeId === \"jdd\") {\n return [\n \"Facture d'électricité (< 3 mois)\",\n \"Facture de gaz (< 3 mois)\",\n \"Facture d'eau (< 3 mois)\",\n \"Quittance de loyer (< 3 mois)\",\n \"Facture téléphone/internet (< 3 mois)\",\n \"Attestation d'assurance habitation (< 3 mois)\",\n ];\n } else if (documentTypeId === \"income-proof\") {\n return [\n \"Bulletin de salaire\",\n \"Avis d'imposition\",\n \"Relevé de compte bancaire\",\n \"Attestation de revenus\",\n \"Contrat de travail\",\n ];\n } else if (documentTypeId === \"id-card\") {\n return [\"Carte nationale d'identité\", \"Passeport\", \"Permis de conduire\"];\n } else if (documentTypeId === \"document-collection\") {\n return [\"Document administratif\", \"Justificatif\", \"Attestation\"];\n }\n\n return [];\n};\n\nconst clearStorageBySessionId = (sessionId: string): void => {\n const scopedKeys = [\n `userInput_${sessionId}`,\n `contactInfo_${sessionId}`,\n `sessionData_${sessionId}`,\n ];\n\n scopedKeys.forEach((key) => {\n localStorage.removeItem(key);\n sessionStorage.removeItem(key);\n });\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n sessionStorage.removeItem(key);\n }\n }\n\n if (localStorage.getItem(\"sessionId\") === sessionId) {\n localStorage.removeItem(\"sessionId\");\n }\n if (sessionStorage.getItem(\"sessionId\") === sessionId) {\n sessionStorage.removeItem(\"sessionId\");\n }\n};\n\n/**\n * Clears all client-side session traces (memory + browser storage)\n * for a given session. This is intentionally aggressive for security.\n */\nexport const clearSessionSensitiveData = (sessionId?: string): void => {\n clearSessionMemory(sessionId);\n\n if (sessionId) {\n clearStorageBySessionId(sessionId);\n return;\n }\n\n localStorage.removeItem(\"sessionId\");\n sessionStorage.removeItem(\"sessionId\");\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n sessionStorage.removeItem(key);\n }\n }\n};\n\n/**\n * Returns the pre-fill data for a given run index from a `userInput` object\n * that contains a `_list` array.\n *\n * Convention: when the integrator wants to pre-fill different data per run\n * (e.g. multiple persons in a loop), they pass `userInput: { _list: [...] }`\n * at session creation. Each element in `_list` corresponds to a run (0-indexed).\n *\n * @param userInput - The session's userInput object\n * @param runIndex - The current run index (0 = first pass, 1 = second pass, …)\n * @returns The pre-fill data for that run, or null if not defined\n */\nexport const getRunPrefillData = (\n userInput: Record<string, unknown>,\n runIndex: number,\n): Record<string, unknown> | null => {\n const list = userInput?._list;\n if (!Array.isArray(list)) return null;\n return (list[runIndex] as Record<string, unknown>) ?? null;\n};\n"],"names":["__awaiter","apiService","__assign","logStatusModified","clearSessionMemory"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sessionService.js","sources":["../../../../src/services/sessionService.ts"],"sourcesContent":["/**\n * Session Service\n *\n * Service for interacting with the Datakeen Session API.\n * Handles fetching session data by ID.\n */\n\nimport type {\n ClientInfo,\n SessionData,\n SessionTemplate,\n SessionTemplateNode,\n} from \"../types/session\";\nimport { apiService } from \"./api\";\nimport { logStatusModified } from \"./auditTrailService\";\nimport { clearSessionMemory } from \"./sessionMemoryStore\";\n\n/**\n * Fetches session data by ID from the Datakeen backend\n *\n * @param sessionId - The unique identifier of the session\n * @returns The session data\n */\nexport const fetchSessionById = async (\n sessionId: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.get(`/session/sdk/${sessionId}`);\n return response.data;\n } catch (error) {\n console.error(\"Error fetching session data:\", error);\n throw error;\n }\n};\n\n/** Sends client information (IP, device, browser, OS) to the backend for a specific session\n *\n * @param sessionId - The unique identifier of the session\n * @param clientInfo - The client information to send\n */\nexport const sendClientInfo = async (\n sessionId: string,\n clientInfo: ClientInfo,\n): Promise<void> => {\n try {\n await apiService.post(`/session/sdk/${sessionId}/client-info`, clientInfo);\n } catch (error) {\n console.error(\"Error sending client info:\", error);\n throw error;\n }\n};\n\n/**\n * Determines if the session template has a specific type of node\n *\n * @param template - The session template\n * @param nodeType - The type of node to check for\n * @returns true if the template has a node of the specified type, false otherwise\n */\nexport const hasNodeType = (\n template: SessionTemplate,\n nodeType: string,\n): boolean => {\n return template.nodes.some((node) => node.type === nodeType);\n};\n\n/**\n * Determines if the session template has a node with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to check for\n * @returns true if the template has a node with the specified requiredDocumentType, false otherwise\n */\nexport const hasDocumentTypeNode = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): boolean => {\n return template.nodes.some(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Gets all nodes of a specific type\n *\n * @param template - The session template\n * @param nodeType - The type of node to get\n * @returns Array of nodes matching the type\n */\nexport const getNodesByType = (\n template: SessionTemplate,\n nodeType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter((node) => node.type === nodeType);\n};\n\n/**\n * Gets all nodes with a specific requiredDocumentType\n *\n * @param template - The session template\n * @param requiredDocumentType - The requiredDocumentType to get\n * @returns Array of nodes matching the requiredDocumentType\n */\nexport const getNodesByDocumentType = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): SessionTemplateNode[] => {\n return template.nodes.filter(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n};\n\n/**\n * Get document options for a specific document type\n *\n * @param template - The session template\n * @param requiredDocumentType - The document type to get options for\n * @returns Array of document options (empty if none found)\n */\nexport const getDocumentOptions = (\n template: SessionTemplate,\n requiredDocumentType: string,\n): string[] => {\n const node = template.nodes.find(\n (node) => node.requiredDocumentType === requiredDocumentType,\n );\n return node?.selectedOptions || [];\n};\n\n/**\n * Determines if the session template has a selfie step\n *\n * @param template - The session template\n * @returns true if the template has a selfie step, false otherwise\n */\nexport const hasSelfieCaptureStep = (template: SessionTemplate): boolean => {\n return hasNodeType(template, \"selfie-capture\");\n};\n\n/**\n * Determines if the session template has an ID document step\n *\n * @param template - The session template\n * @returns true if the template has an ID document step, false otherwise\n */\nexport const hasDocumentStep = (template: SessionTemplate): boolean => {\n // Check if there's any document-selection node with requiredDocumentType \"id-card\"\n // or if none specified, just check for document-selection nodes\n const hasIDCard = hasDocumentTypeNode(template, \"id-card\");\n return hasIDCard || hasNodeType(template, \"document-selection\");\n};\n\n/**\n * Determines if the session template has a JDD (proof of address) step\n *\n * @param template - The session template\n * @returns true if the template has a JDD step, false otherwise\n */\nexport const hasJDDStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"jdd\");\n};\n\n/**\n * Determines if the session template has a proof of funds step\n *\n * @param template - The session template\n * @returns true if the template has a proof of funds step, false otherwise\n */\nexport const hasProofOfFundsStep = (template: SessionTemplate): boolean => {\n return hasDocumentTypeNode(template, \"income-proof\");\n};\n\n/**\n * Determines if the session template has a document collection step\n *\n * @param template - The session template\n * @returns true if the template has a document collection step, false otherwise\n */\nexport const hasDocumentCollectionStep = (\n template: SessionTemplate,\n): boolean => {\n return hasNodeType(template, \"document-collection\");\n};\n\n/**\n * Gets all node types in the template\n *\n * @param template - The session template\n * @returns Array of node types in the template\n */\nexport const getNodeTypes = (template: SessionTemplate): string[] => {\n return Array.from(new Set(template.nodes.map((node) => node.type)));\n};\n\n/**\n * Gets all document types required in the template\n *\n * @param template - The session template\n * @returns Array of document types required in the template\n */\nexport const getRequiredDocumentTypes = (\n template: SessionTemplate,\n): string[] => {\n return Array.from(\n new Set(\n template.nodes\n .filter((node) => node.requiredDocumentType)\n .map((node) => node.requiredDocumentType!),\n ),\n );\n};\n\n/**\n * Converts template document type to internal document type\n * This helps standardize document types between the template and the application\n *\n * @param templateDocType - The document type as defined in the template\n * @returns The internal document type used by the application\n */\nexport const convertTemplateDocTypeToInternal = (\n templateDocType: string,\n): string => {\n if (!templateDocType) return \"\";\n\n // Mapping between template document types and internal document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n \"income-proof\": \"income-proof\", // Using consistent naming\n };\n\n return typeMap[templateDocType] || templateDocType;\n};\n\n/**\n * Converts internal document type to template document type\n *\n * @param internalDocType - The document type used internally by the application\n * @returns The document type as expected in the template\n */\nexport const convertInternalDocTypeToTemplate = (\n internalDocType: string,\n): string => {\n if (!internalDocType) return \"\";\n\n // Mapping between internal document types and template document types\n const typeMap: Record<string, string> = {\n \"id-card\": \"id-card\",\n jdd: \"jdd\",\n funds: \"income-proof\", // Map funds to income-proof for backwards compatibility\n \"income-proof\": \"income-proof\",\n };\n\n return typeMap[internalDocType] || internalDocType;\n};\n\n/**\n * Updates session data with user input information\n *\n * @param sessionId - The unique identifier of the session\n * @param userInput - The user input data (firstName, lastName, birthDate)\n * @returns The updated session data\n */\nexport const updateSessionUserInput = async (\n sessionId: string,\n userInput: {\n firstName?: string;\n lastName?: string;\n birthDate?: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n userInput,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session data:\", error);\n throw error;\n }\n};\n\n/**\n * Records the NFC fallback reason when the user declares they cannot use the\n * contactless scan, and marks the NFC scan as skipped server-side.\n *\n * @param sessionId - The unique identifier of the session\n * @param payload - The selected reason (technical key), its human-readable label,\n * and an optional free-text comment.\n */\nexport const skipNfcWithReason = async (\n sessionId: string,\n payload: { reason: string; label: string; comment?: string },\n): Promise<void> => {\n await apiService.post(`/session/sdk/${sessionId}/nfc-skip`, payload);\n};\n\nexport type SelfieFailureReason =\n | \"timeout\"\n | \"network_error\"\n | \"api_error\"\n | \"user_bypassed\";\n\nexport interface SelfieFailurePayload {\n nodeId: string;\n reason?: SelfieFailureReason;\n conformityCode?: string;\n bypassed?: boolean;\n}\n\nexport const reportSelfieFailure = async (\n sessionId: string,\n payload: SelfieFailurePayload,\n): Promise<void> => {\n await apiService.post(`/session/sdk/${sessionId}/selfie-failed`, payload);\n};\n\n/**\n * Resets a terminal NFC failure before the user starts again with another\n * document. The backend keeps completed scans immutable and treats this call\n * as a no-op when the status is not terminal.\n */\nexport const resetNfcScan = async (sessionId: string): Promise<void> => {\n await apiService.post(`/session/sdk/${sessionId}/nfc-reset`);\n};\n\n/**\n * Updates session data with contact information\n *\n * @param sessionId - The unique identifier of the session\n * @param contactInfo - The contact information data (email, phoneNumber)\n * @returns The updated session data\n */\nexport const updateSessionContactInfo = async (\n sessionId: string,\n contactInfo: {\n email: string;\n phoneNumber: string;\n [key: string]: unknown;\n },\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n contactInfo,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating contact information:\", error);\n throw error;\n }\n};\n\n/**\n * Updates session status\n *\n * @param sessionId - The unique identifier of the session\n * @param status - The new status for the session\n * @param reachedEndNodeId - Id of the end node actually reached (when status is \"ended\"),\n * so the backend can force the correct final status with multiple end nodes.\n * @returns The updated session data\n */\nexport const updateSessionStatus = async (\n sessionId: string,\n status: string,\n reachedEndNodeId?: string,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n status,\n ...(reachedEndNodeId ? { reachedEndNodeId } : {}),\n });\n\n // Log status modification in audit trail\n if (response.data && response.data.analysisId) {\n try {\n await logStatusModified(\n sessionId,\n status,\n response.data.clientInfoId || undefined,\n );\n } catch (err) {\n console.error(\"Failed to log status modification in audit trail:\", err);\n // Non-blocking error - continue session\n }\n }\n\n return response.data;\n } catch (error) {\n console.error(\"Error updating session status:\", error);\n throw error;\n }\n};\n\n/**\n * Updates the current step in the session\n *\n * @param sessionId - The unique identifier of the session\n * @param currentStep - The current step index in the workflow\n * @returns The updated session data\n */\nexport const updateSessionCurrentStep = async (\n sessionId: string,\n currentStep: number,\n): Promise<SessionData> => {\n try {\n const response = await apiService.patch(`/session/sdk/${sessionId}`, {\n currentStep,\n });\n return response.data;\n } catch (error) {\n console.error(\"Error updating session current step:\", error);\n throw error;\n }\n};\n\n/**\n * Gets the journey steps from the template in order\n *\n * @param template - The session template\n * @returns Array of ordered steps\n */\nexport const getOrderedJourneySteps = (\n template: SessionTemplate,\n): SessionTemplateNode[] => {\n // Filter out only start nodes, keep end nodes for proper journey completion, then sort by order.\n // Tiebreaker on id keeps the ordering deterministic when several nodes share the same `order`\n // (e.g. parallel branches of a condition), independently of their position in template.nodes.\n return template.nodes\n .filter((node) => node.type !== \"start\")\n .sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));\n};\n\nconst normalizeHandle = (value?: string): string => {\n return (value || \"\").trim().toLowerCase();\n};\n\n/**\n * Finds the outgoing edge to follow from a node.\n *\n * Resolution order:\n * 1. Exact handle match via sourceHandle/conditionValue.\n * 2. For condition:false loops, fallback to targetHandle=right.\n * 3. First outgoing edge as final fallback.\n */\nexport const findOutgoingEdge = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): SessionTemplate[\"edges\"][number] | null => {\n const outgoingEdges = (template.edges || []).filter(\n (edge) => edge.source === currentNodeId,\n );\n\n if (outgoingEdges.length === 0) {\n return null;\n }\n\n if (!handle) {\n return outgoingEdges[0];\n }\n\n const normalizedHandle = normalizeHandle(handle);\n const edgeByHandle = outgoingEdges.find((edge) => {\n return (\n normalizeHandle(edge.sourceHandle) === normalizedHandle ||\n normalizeHandle(edge.conditionValue) === normalizedHandle\n );\n });\n\n if (edgeByHandle) {\n return edgeByHandle;\n }\n\n const currentNode = template.nodes.find((node) => node.id === currentNodeId);\n if (currentNode?.type === \"condition\" && normalizedHandle === \"false\") {\n const rightHandleLoopEdge = outgoingEdges.find(\n (edge) => normalizeHandle(edge.targetHandle) === \"right\",\n );\n if (rightHandleLoopEdge) {\n return rightHandleLoopEdge;\n }\n }\n\n return outgoingEdges[0];\n};\n\n/**\n * Gets the next step index by following the graph edge from the current node\n *\n * @param currentNodeId - The ID of the current node\n * @param template - The session template\n * @returns The next step index (1-based) or null if no edge found\n */\nexport const getNextStepIndex = (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n): number | null => {\n const orderedNodes = getOrderedJourneySteps(template);\n const edge = findOutgoingEdge(currentNodeId, template, handle);\n\n if (!edge) {\n console.debug(\n `[sessionService] No outgoing edge found for node ${currentNodeId}${handle ? ` with handle ${handle}` : \"\"}`,\n );\n return null;\n }\n\n const targetId = edge.target;\n const targetIndex = orderedNodes.findIndex((n) => n.id === targetId);\n\n if (targetIndex === -1) {\n console.debug(\n `[sessionService] Target node ${targetId} not found in ordered steps`,\n );\n return null;\n }\n\n // steps are 1-indexed in the SDK (0 is StartSession)\n return 1 + targetIndex;\n};\n\n/**\n * Reconstructs the navigation history by following the graph from step 0\n * up to (and including) targetStep. Returns [0, ...stepIndices].\n * If the graph path cannot reach targetStep, falls back to [0, targetStep].\n */\nexport const reconstructHistoryToStep = (\n targetStep: number,\n template: SessionTemplate,\n): number[] => {\n if (targetStep <= 0) return [0];\n\n const orderedNodes = getOrderedJourneySteps(template);\n const history: number[] = [0];\n let currentStep = 1; // first node is step 1\n\n // Follow the default (first) edge from each node in sequence\n for (let safetyLimit = 0; safetyLimit < orderedNodes.length + 1; safetyLimit++) {\n if (currentStep === targetStep) {\n history.push(currentStep);\n break;\n }\n if (currentStep > targetStep) break;\n\n const nodeIndex = currentStep - 1;\n const currentNode = orderedNodes[nodeIndex];\n if (!currentNode) break;\n\n history.push(currentStep);\n\n const nextStep = getNextStepIndex(currentNode.id, template);\n if (nextStep === null) break;\n currentStep = nextStep;\n }\n\n // Fallback: if we couldn't reach targetStep via graph, use simple seed\n if (history[history.length - 1] !== targetStep) {\n return [0, targetStep];\n }\n\n return history;\n};\n\n/**\n * Maps a template node type to a step component type\n *\n * @param node - The session template node\n * @returns The step component type\n */\nexport const getStepComponentType = (node: SessionTemplateNode): string => {\n // Map from template node types to component types\n const typeMap: Record<string, string> = {\n \"document-selection\": \"document\",\n \"document-collection\": \"document-collection\",\n \"selfie-capture\": \"selfie\",\n \"contact-info\": \"contact-info\",\n \"user-input\": \"user-input\",\n \"otp-verification\": \"otp\",\n };\n\n // First check the node type\n if (node.type in typeMap) {\n return typeMap[node.type];\n }\n\n // Then check the requiredDocumentType\n if (node.requiredDocumentType) {\n return node.requiredDocumentType;\n }\n\n // Default fallback\n return node.type;\n};\n\n/**\n * Checks if a session has expired\n *\n * @param session - The session data to check\n * @returns true if the session has expired, false otherwise\n */\nexport const isSessionExpired = (session: SessionData): boolean => {\n if (!session.expireTime) {\n return false;\n }\n\n const currentTime = Date.now();\n return currentTime > session.expireTime;\n};\n\n/**\n * Stores document options in localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @param options - The options to store\n */\nexport const storeDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n options: string[],\n): void => {\n if (!sessionId || !documentTypeId || !options || options.length === 0) {\n console.warn(\"Missing data for storeDocumentOptions:\", {\n sessionId,\n documentTypeId,\n options,\n });\n return;\n }\n\n // Create a consistent key format based on document type\n let storageKey = \"\";\n\n switch (documentTypeId) {\n case \"jdd\":\n storageKey = `jddOptions_${sessionId}`;\n break;\n case \"income-proof\":\n storageKey = `fundsOptions_${sessionId}`;\n break;\n case \"id-card\":\n storageKey = `idOptions_${sessionId}`;\n break;\n case \"document-collection\":\n storageKey = `documentCollectionOptions_${sessionId}`;\n break;\n default:\n storageKey = `${documentTypeId}Options_${sessionId}`;\n }\n\n localStorage.setItem(storageKey, JSON.stringify(options));\n};\n\n/**\n * Retrieves document options from localStorage for a specific document type\n *\n * @param sessionId - The session ID\n * @param documentTypeId - The document type ID (e.g., 'jdd', 'income-proof')\n * @returns Array of options or default options if none found\n */\nexport const retrieveDocumentOptions = (\n sessionId: string,\n documentTypeId: string,\n): string[] => {\n if (!sessionId || !documentTypeId) {\n console.warn(\"Missing data for retrieveDocumentOptions:\", {\n sessionId,\n documentTypeId,\n });\n return [];\n }\n\n // Create consistent key formats to check\n const possibleKeys = [\n `${documentTypeId}Options_${sessionId}`,\n documentTypeId === \"jdd\" ? `jddOptions_${sessionId}` : \"\",\n documentTypeId === \"income-proof\" ? `fundsOptions_${sessionId}` : \"\",\n documentTypeId === \"id-card\" ? `idOptions_${sessionId}` : \"\",\n documentTypeId === \"document-collection\"\n ? `documentCollectionOptions_${sessionId}`\n : \"\",\n ].filter(Boolean);\n\n // Try each possible key\n for (const key of possibleKeys) {\n const savedOptions = localStorage.getItem(key);\n if (savedOptions) {\n try {\n const parsedOptions = JSON.parse(savedOptions);\n\n return parsedOptions;\n } catch (e) {\n console.error(\n `Error parsing options for ${documentTypeId} with key ${key}:`,\n e,\n );\n }\n }\n }\n\n // Return default options if none found\n console.warn(`No options found for ${documentTypeId}, using defaults`);\n if (documentTypeId === \"jdd\") {\n return [\n \"Facture d'électricité (< 3 mois)\",\n \"Facture de gaz (< 3 mois)\",\n \"Facture d'eau (< 3 mois)\",\n \"Quittance de loyer (< 3 mois)\",\n \"Facture téléphone/internet (< 3 mois)\",\n \"Attestation d'assurance habitation (< 3 mois)\",\n ];\n } else if (documentTypeId === \"income-proof\") {\n return [\n \"Bulletin de salaire\",\n \"Avis d'imposition\",\n \"Relevé de compte bancaire\",\n \"Attestation de revenus\",\n \"Contrat de travail\",\n ];\n } else if (documentTypeId === \"id-card\") {\n return [\"Carte nationale d'identité\", \"Passeport\", \"Permis de conduire\"];\n } else if (documentTypeId === \"document-collection\") {\n return [\"Document administratif\", \"Justificatif\", \"Attestation\"];\n }\n\n return [];\n};\n\nconst clearStorageBySessionId = (sessionId: string): void => {\n const scopedKeys = [\n `userInput_${sessionId}`,\n `contactInfo_${sessionId}`,\n `sessionData_${sessionId}`,\n ];\n\n scopedKeys.forEach((key) => {\n localStorage.removeItem(key);\n sessionStorage.removeItem(key);\n });\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (key.endsWith(`_${sessionId}`)) {\n sessionStorage.removeItem(key);\n }\n }\n\n if (localStorage.getItem(\"sessionId\") === sessionId) {\n localStorage.removeItem(\"sessionId\");\n }\n if (sessionStorage.getItem(\"sessionId\") === sessionId) {\n sessionStorage.removeItem(\"sessionId\");\n }\n};\n\n/**\n * Clears all client-side session traces (memory + browser storage)\n * for a given session. This is intentionally aggressive for security.\n */\nexport const clearSessionSensitiveData = (sessionId?: string): void => {\n clearSessionMemory(sessionId);\n\n if (sessionId) {\n clearStorageBySessionId(sessionId);\n return;\n }\n\n localStorage.removeItem(\"sessionId\");\n sessionStorage.removeItem(\"sessionId\");\n\n for (let i = localStorage.length - 1; i >= 0; i -= 1) {\n const key = localStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n localStorage.removeItem(key);\n }\n }\n\n for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {\n const key = sessionStorage.key(i);\n if (!key) {\n continue;\n }\n if (\n key.startsWith(\"userInput_\") ||\n key.startsWith(\"contactInfo_\") ||\n key.includes(\"Options_\")\n ) {\n sessionStorage.removeItem(key);\n }\n }\n};\n\n/**\n * Returns the pre-fill data for a given run index from a `userInput` object\n * that contains a `_list` array.\n *\n * Convention: when the integrator wants to pre-fill different data per run\n * (e.g. multiple persons in a loop), they pass `userInput: { _list: [...] }`\n * at session creation. Each element in `_list` corresponds to a run (0-indexed).\n *\n * @param userInput - The session's userInput object\n * @param runIndex - The current run index (0 = first pass, 1 = second pass, …)\n * @returns The pre-fill data for that run, or null if not defined\n */\nexport const getRunPrefillData = (\n userInput: Record<string, unknown>,\n runIndex: number,\n): Record<string, unknown> | null => {\n const list = userInput?._list;\n if (!Array.isArray(list)) return null;\n return (list[runIndex] as Record<string, unknown>) ?? null;\n};\n"],"names":["__awaiter","apiService","__assign","logStatusModified","clearSessionMemory"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sources":["../../../../src/types/session.ts"],"sourcesContent":["import type React from \"react\";\n\nexport interface SessionConfig {\n selfie?: boolean;\n requireMobile?: boolean;\n}\n\nexport interface DatakeenSessionProps {\n sessionId: string;\n sessionConfig?: SessionConfig;\n apiBaseUrl?: string; // Optional API base URL for dynamic environment configuration\n}\n\nexport interface UseSessionReturn {\n SessionComponent: React.ReactElement;\n}\n\nexport type stepObject = {\n setStep: (step: number, skipHistory?: boolean) => void;\n goBack: () => void;\n /** Retour arrière vers un nœud précis (ex: \"Corriger ma saisie\") :\n * tronque l'historique jusqu'à `targetStep` au lieu de l'empiler. */\n goBackToStep: (targetStep: number) => void;\n goToNextStep: (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n ) => void;\n /** Avance via le graphe et tronque l'historique au nœud d'arrivée. */\n goToNextStepCommitted: (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n ) => void;\n step: number;\n canGoBack: boolean;\n};\n\nexport interface ProcessingStep {\n title: string;\n subtitle: string;\n hasError?: boolean;\n}\n\nexport type ConditionTokenType = \"variable\" | \"control\" | \"operator\" | \"input\";\n\nexport interface ConditionToken {\n type: ConditionTokenType;\n value: string;\n label?: string;\n sourceNodeId?: string;\n}\n\n/**\n * Type for custom field value types\n */\nexport type CustomFieldValueType =\n | \"text\"\n | \"enum\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"email\"\n | \"address\"\n | \"list\";\n\n/**\n * Display formats supported for date fields (top-level and list columns).\n */\nexport type DateDisplayFormat = \"dd/mm/yyyy\" | \"mm/dd/yyyy\" | \"yyyy-mm-dd\";\n\nexport const DEFAULT_DATE_DISPLAY_FORMAT: DateDisplayFormat = \"dd/mm/yyyy\";\n\n/**\n * Column definition for a list-type custom field\n */\nexport interface ListColumn {\n label: string;\n type: \"text\" | \"enum\" | \"date\" | \"email\";\n options?: string[]; // required when type === 'enum'\n placeholder?: string; // text/email/date — shown to the end user\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n}\n\n/**\n * Interface for custom field definition\n */\nexport interface CustomField {\n id: string;\n label: string;\n placeholder?: string;\n description?: string;\n valueType: CustomFieldValueType;\n enumOptions?: string[];\n listColumns?: ListColumn[]; // for list type: column definitions\n minRows?: number; // for list type: minimum rows expected\n required?: boolean;\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n lockedFromApi?: boolean;\n editableIfMissing?: boolean; // soft lock — éditable si la valeur API est absente\n userInputKey?: string;\n}\n\n/**\n * Interface for session template node\n */\nexport interface SessionTemplateNode {\n id: string;\n type: string;\n title: string;\n description: string;\n informationType?:\n | \"identity\"\n | \"identity-legal\"\n | \"contact\"\n | \"address\"\n | \"nationality\"\n | \"custom\";\n position: {\n x: number;\n y: number;\n };\n options: unknown[];\n selectedOptions: string[];\n requiredDocumentType?: string;\n isRequired: boolean;\n order: number;\n optionalFields?: string[];\n requiredFields?: string[];\n pageTitle?: string;\n pageDescription?: string;\n // Properties for document-collection node type\n allowedDocumentTypes?: Array<{\n id: string;\n name: string;\n /**\n * Optional side information coming from the template.\n * When provided and equals to two (\"two\", 2, \"double\", \"recto-verso\"),\n * consumers should allow uploading two sides (front/back).\n */\n side?: string | number;\n }>;\n allowedAddingMethods?: string[];\n introductionPage?: {\n title?: string;\n description?: string;\n };\n documentSelection?: {\n title?: string;\n description?: string;\n };\n // Start node specific properties\n welcomeTitle?: string;\n welcomeSubtitle?: string;\n welcomeDescription?: string;\n welcomeImage?: string;\n qrCodeTitle?: string;\n qrCodeDescription?: string;\n showLegacyCGU?: boolean; // default: true — rétrocompatibilité\n\n // Legal consent node specific properties\n consentDescription?: string;\n consentDescription2?: string;\n cguUrl?: string;\n privacyPolicyUrl?: string;\n cguLinkLabel?: string;\n privacyLinkLabel?: string;\n checkboxText?: string;\n // Identity control specific properties\n automaticPhotoCapture?: boolean;\n nfcEnabled?: boolean;\n // \"nfcAndApi\" reste accepté pour rétrocompat (parcours legacy) ; à normaliser à la lecture.\n nfcMode?: \"nfcOnly\" | \"nfcOrPhoto\" | \"nfcAndApi\";\n acceptedCountries?: AcceptedCountry[];\n // End node specific properties\n callbackURL?: string | null;\n // Résultat forcé par le nœud `end` (configuré dans le builder). Sert au SDK à\n // afficher la variante « erreur conservée » de l'écran de fin quand la branche\n // fausse d'une condition pointe directement vers un end non_compliant.\n expectedResult?: string;\n // Condition node specific properties\n conditionExpression?: string;\n conditionTokens?: ConditionToken[];\n conditionFalseErrorMessage?: string;\n conditionMaxRetries?: number;\n conditionMaxRetryAction?: \"end-journey\" | \"force-true\";\n // Undefined is treated as \"loop\" by the SDK for legacy templates.\n conditionFalseMode?: \"retry\" | \"loop\";\n\n // External verification specific properties\n targetApi?: \"INSEE\" | \"INPI_RBE\";\n /** INPI_RBE only. Opt-in: retry against the RNA (associations) when the RNE finds nothing. */\n rnaFallbackEnabled?: boolean;\n referenceNodeId?: string;\n referenceNodeType?:\n | \"information-input\"\n | \"document-collection\"\n | \"identity-control\";\n referenceField?: \"siren\" | \"siret\";\n referenceVariable?: string;\n // Custom form fields (for information-input with type 'custom')\n customFields?: CustomField[];\n\n // Electronic signature specific properties\n templateId?: string;\n external_id?: string;\n fieldMappings?: Array<{\n sourceFieldId: string;\n label: string;\n docusealType: string;\n readonly: boolean;\n role?: string;\n sourceNodeId?: string;\n }>;\n /** If set, the generated PDF from this upstream pdf-generation node will be used as the document to sign */\n sourcePdfNodeId?: string;\n\n // PDF generation node specific properties\n // Note: htmlTemplate is intentionally NOT included — it is server-side only and never sent to the client\n pdfMode?: \"upload\" | \"html-template\";\n sourceNodeIds?: string[];\n\n // retry properties\n allowResubmission: boolean;\n maxResubmissionAttempts?: number;\n\n /**\n * Paramétrable par nœud depuis le journey builder : autorise ou non le\n * bouton \"Poursuivre quand même\" en cas d'échec. S'applique aux nœuds\n * identity-control, document-collection, biometric-capture (selfie/video)\n * et external-verification. Absent/true = comportement actuel inchangé\n * (bouton proposé), false = masqué.\n */\n allowContinueOnFailure?: boolean;\n}\n\n/**\n * Interface for accepted countries\n */\nexport interface AcceptedCountry {\n code: string;\n documents: {\n passport: string[];\n idCard: string[];\n driverLicense: string[];\n residencePermit: string[];\n pinkDriverLicense: string[];\n };\n}\n\n/**\n * Interface for session template edge\n */\nexport interface SessionTemplateEdge {\n id: string;\n source: string;\n target: string;\n sourceHandle?: string;\n targetHandle?: string;\n conditionValue?: string;\n}\n\n/**\n * Interface for platform information\n */\nexport interface PlatformInfo {\n mobile: boolean;\n desktop: boolean;\n backoffice: boolean;\n}\n\n/**\n * Interface for session template\n */\n/** Clé du catalogue d'icônes des écrans de fin (mappée vers lucide-react au rendu). */\nexport type EndScreenIcon =\n | \"thanks\"\n | \"send\"\n | \"mail\"\n | \"check\"\n | \"clock\"\n | \"shield\"\n | \"user\"\n | \"info\";\n\nexport interface EndScreenItem {\n icon: EndScreenIcon;\n text: string;\n}\n\nexport interface EndScreenCase {\n title?: string;\n items: EndScreenItem[];\n}\n\n/** Textes de fin personnalisés (config globale du journey). Vide → fallback standard. */\nexport interface EndScreenConfig {\n compliant?: EndScreenCase;\n nonCompliant?: EndScreenCase;\n}\n\nexport interface SessionTemplate {\n id: string;\n name: string;\n description: string;\n version: string;\n languages: string[];\n nodes: SessionTemplateNode[];\n edges: SessionTemplateEdge[];\n groupId: string;\n userId: string | null;\n created_at: string;\n updated_at: string;\n platforms?: PlatformInfo;\n logo?: string;\n showQRCode?: boolean;\n buttonBgColor?: string;\n buttonTextColor?: string;\n endScreenConfig?: EndScreenConfig;\n}\n\n/**\n * Interface for session data\n */\nexport interface SessionData {\n id: string;\n userId: string | null;\n token: string;\n templateId: string;\n templateKey: string;\n expireTime: number;\n status: string;\n result: Record<string, unknown>;\n landingPage: unknown;\n withSelfie: boolean | null;\n groupId: string | null;\n userInput: Record<string, unknown>;\n contactInfo?: {\n email: string;\n phoneNumber: string;\n };\n callbackURL?: string | null;\n webhookURL: string;\n analysisTemplateId: string | null;\n userAgent: unknown[];\n mobile: boolean;\n analysisId: string | null;\n currentStep?: number;\n nfcStatus?: \"pending\" | \"opened\" | \"completed\" | \"skipped\" | \"failed\";\n createdAt: string;\n updatedAt: string;\n auditTrail: unknown[];\n user: unknown | null;\n analysis: unknown[];\n documents: unknown[];\n template: SessionTemplate;\n retryCounts?: Record<string, number>; // nodeId -> retry count\n}\n\nexport interface ClientInfo {\n ip?: string;\n location?: string;\n device: string;\n browser: string;\n os: string;\n}\n"],"names":[],"mappings":";;AAuEO,IAAM,2BAA2B,GAAsB;;;;"}
|
|
1
|
+
{"version":3,"file":"session.js","sources":["../../../../src/types/session.ts"],"sourcesContent":["import type React from \"react\";\n\nexport interface SessionConfig {\n selfie?: boolean;\n requireMobile?: boolean;\n}\n\nexport interface DatakeenSessionProps {\n sessionId: string;\n sessionConfig?: SessionConfig;\n apiBaseUrl?: string; // Optional API base URL for dynamic environment configuration\n}\n\nexport interface UseSessionReturn {\n SessionComponent: React.ReactElement;\n}\n\nexport type stepObject = {\n setStep: (step: number, skipHistory?: boolean) => void;\n goBack: () => void;\n /** Retour arrière vers un nœud précis (ex: \"Corriger ma saisie\") :\n * tronque l'historique jusqu'à `targetStep` au lieu de l'empiler. */\n goBackToStep: (targetStep: number) => void;\n goToNextStep: (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n ) => void;\n /** Avance via le graphe et tronque l'historique au nœud d'arrivée. */\n goToNextStepCommitted: (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n ) => void;\n step: number;\n canGoBack: boolean;\n};\n\nexport interface ProcessingStep {\n title: string;\n subtitle: string;\n hasError?: boolean;\n}\n\nexport type ConditionTokenType = \"variable\" | \"control\" | \"operator\" | \"input\";\n\nexport interface ConditionToken {\n type: ConditionTokenType;\n value: string;\n label?: string;\n sourceNodeId?: string;\n}\n\n/**\n * Type for custom field value types\n */\nexport type CustomFieldValueType =\n | \"text\"\n | \"enum\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"email\"\n | \"address\"\n | \"list\";\n\n/**\n * Display formats supported for date fields (top-level and list columns).\n */\nexport type DateDisplayFormat = \"dd/mm/yyyy\" | \"mm/dd/yyyy\" | \"yyyy-mm-dd\";\n\nexport const DEFAULT_DATE_DISPLAY_FORMAT: DateDisplayFormat = \"dd/mm/yyyy\";\n\n/**\n * Column definition for a list-type custom field\n */\nexport interface ListColumn {\n label: string;\n type: \"text\" | \"enum\" | \"date\" | \"email\";\n options?: string[]; // required when type === 'enum'\n placeholder?: string; // text/email/date — shown to the end user\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n}\n\n/**\n * Interface for custom field definition\n */\nexport interface CustomField {\n id: string;\n label: string;\n placeholder?: string;\n description?: string;\n valueType: CustomFieldValueType;\n enumOptions?: string[];\n listColumns?: ListColumn[]; // for list type: column definitions\n minRows?: number; // for list type: minimum rows expected\n required?: boolean;\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n lockedFromApi?: boolean;\n editableIfMissing?: boolean; // soft lock — éditable si la valeur API est absente\n userInputKey?: string;\n}\n\n/**\n * Interface for session template node\n */\nexport interface SessionTemplateNode {\n id: string;\n type: string;\n title: string;\n description: string;\n informationType?:\n | \"identity\"\n | \"identity-legal\"\n | \"contact\"\n | \"address\"\n | \"nationality\"\n | \"custom\";\n position: {\n x: number;\n y: number;\n };\n options: unknown[];\n selectedOptions: string[];\n requiredDocumentType?: string;\n isRequired: boolean;\n order: number;\n optionalFields?: string[];\n requiredFields?: string[];\n pageTitle?: string;\n pageDescription?: string;\n // Properties for document-collection node type\n allowedDocumentTypes?: Array<{\n id: string;\n name: string;\n /**\n * Optional side information coming from the template.\n * When provided and equals to two (\"two\", 2, \"double\", \"recto-verso\"),\n * consumers should allow uploading two sides (front/back).\n */\n side?: string | number;\n }>;\n allowedAddingMethods?: string[];\n introductionPage?: {\n title?: string;\n description?: string;\n };\n documentSelection?: {\n title?: string;\n description?: string;\n };\n // Start node specific properties\n welcomeTitle?: string;\n welcomeSubtitle?: string;\n welcomeDescription?: string;\n welcomeImage?: string;\n qrCodeTitle?: string;\n qrCodeDescription?: string;\n showLegacyCGU?: boolean; // default: true — rétrocompatibilité\n\n // Legal consent node specific properties\n consentDescription?: string;\n consentDescription2?: string;\n cguUrl?: string;\n privacyPolicyUrl?: string;\n cguLinkLabel?: string;\n privacyLinkLabel?: string;\n checkboxText?: string;\n // Identity control specific properties\n automaticPhotoCapture?: boolean;\n nfcEnabled?: boolean;\n // \"nfcAndApi\" reste accepté pour rétrocompat (parcours legacy) ; à normaliser à la lecture.\n nfcMode?: \"nfcOnly\" | \"nfcOrPhoto\" | \"nfcAndApi\";\n acceptedCountries?: AcceptedCountry[];\n // End node specific properties\n callbackURL?: string | null;\n // Résultat forcé par le nœud `end` (configuré dans le builder). Sert au SDK à\n // afficher la variante « erreur conservée » de l'écran de fin quand la branche\n // fausse d'une condition pointe directement vers un end non_compliant.\n expectedResult?: string;\n // Condition node specific properties\n conditionExpression?: string;\n conditionTokens?: ConditionToken[];\n conditionFalseErrorMessage?: string;\n conditionMaxRetries?: number;\n conditionMaxRetryAction?: \"end-journey\" | \"force-true\";\n // Undefined is treated as \"loop\" by the SDK for legacy templates.\n conditionFalseMode?: \"retry\" | \"loop\";\n\n // External verification specific properties\n targetApi?: \"INSEE\" | \"INPI_RBE\";\n /** INPI_RBE only. Opt-in: retry against the RNA (associations) when the RNE finds nothing. */\n rnaFallbackEnabled?: boolean;\n referenceNodeId?: string;\n referenceNodeType?:\n | \"information-input\"\n | \"document-collection\"\n | \"identity-control\";\n referenceField?: \"siren\" | \"siret\";\n referenceVariable?: string;\n // Custom form fields (for information-input with type 'custom')\n customFields?: CustomField[];\n\n // Electronic signature specific properties\n templateId?: string;\n external_id?: string;\n /** Écran affiché après la signature. Valeurs vides : textes standard traduits. */\n signedScreenTitle?: string;\n signedScreenDescription?: string;\n signedScreenDownloadHint?: string;\n fieldMappings?: Array<{\n sourceFieldId: string;\n label: string;\n docusealType: string;\n readonly: boolean;\n role?: string;\n sourceNodeId?: string;\n }>;\n /** If set, the generated PDF from this upstream pdf-generation node will be used as the document to sign */\n sourcePdfNodeId?: string;\n\n // PDF generation node specific properties\n // Note: htmlTemplate is intentionally NOT included — it is server-side only and never sent to the client\n pdfMode?: \"upload\" | \"html-template\";\n sourceNodeIds?: string[];\n\n // retry properties\n allowResubmission: boolean;\n maxResubmissionAttempts?: number;\n\n /**\n * Paramétrable par nœud depuis le journey builder : autorise ou non le\n * bouton \"Poursuivre quand même\" en cas d'échec. S'applique aux nœuds\n * identity-control, document-collection, biometric-capture (selfie/video)\n * et external-verification. Absent/true = comportement actuel inchangé\n * (bouton proposé), false = masqué.\n */\n allowContinueOnFailure?: boolean;\n}\n\n/**\n * Interface for accepted countries\n */\nexport interface AcceptedCountry {\n code: string;\n documents: {\n passport: string[];\n idCard: string[];\n driverLicense: string[];\n residencePermit: string[];\n pinkDriverLicense: string[];\n };\n}\n\n/**\n * Interface for session template edge\n */\nexport interface SessionTemplateEdge {\n id: string;\n source: string;\n target: string;\n sourceHandle?: string;\n targetHandle?: string;\n conditionValue?: string;\n}\n\n/**\n * Interface for platform information\n */\nexport interface PlatformInfo {\n mobile: boolean;\n desktop: boolean;\n backoffice: boolean;\n}\n\n/**\n * Interface for session template\n */\n/** Clé du catalogue d'icônes des écrans de fin (mappée vers lucide-react au rendu). */\nexport type EndScreenIcon =\n | \"thanks\"\n | \"send\"\n | \"mail\"\n | \"check\"\n | \"clock\"\n | \"shield\"\n | \"user\"\n | \"info\";\n\nexport interface EndScreenItem {\n icon: EndScreenIcon;\n text: string;\n}\n\nexport interface EndScreenCase {\n title?: string;\n items: EndScreenItem[];\n}\n\n/** Textes de fin personnalisés (config globale du journey). Vide → fallback standard. */\nexport interface EndScreenConfig {\n compliant?: EndScreenCase;\n nonCompliant?: EndScreenCase;\n}\n\nexport interface SessionTemplate {\n id: string;\n name: string;\n description: string;\n version: string;\n languages: string[];\n nodes: SessionTemplateNode[];\n edges: SessionTemplateEdge[];\n groupId: string;\n userId: string | null;\n created_at: string;\n updated_at: string;\n platforms?: PlatformInfo;\n logo?: string;\n showQRCode?: boolean;\n buttonBgColor?: string;\n buttonTextColor?: string;\n endScreenConfig?: EndScreenConfig;\n}\n\n/**\n * Interface for session data\n */\nexport interface SessionData {\n id: string;\n userId: string | null;\n token: string;\n templateId: string;\n templateKey: string;\n expireTime: number;\n status: string;\n result: Record<string, unknown>;\n landingPage: unknown;\n withSelfie: boolean | null;\n groupId: string | null;\n userInput: Record<string, unknown>;\n contactInfo?: {\n email: string;\n phoneNumber: string;\n };\n callbackURL?: string | null;\n webhookURL: string;\n analysisTemplateId: string | null;\n userAgent: unknown[];\n mobile: boolean;\n analysisId: string | null;\n currentStep?: number;\n nfcStatus?: \"pending\" | \"opened\" | \"completed\" | \"skipped\" | \"failed\";\n createdAt: string;\n updatedAt: string;\n auditTrail: unknown[];\n user: unknown | null;\n analysis: unknown[];\n documents: unknown[];\n template: SessionTemplate;\n retryCounts?: Record<string, number>; // nodeId -> retry count\n}\n\nexport interface ClientInfo {\n ip?: string;\n location?: string;\n device: string;\n browser: string;\n os: string;\n}\n"],"names":[],"mappings":";;AAuEO,IAAM,2BAA2B,GAAsB;;;;"}
|
|
@@ -8,6 +8,7 @@ import { codeToStep } from '../../../services/utils.js';
|
|
|
8
8
|
import { analyzeSelfie } from '../../../services/analysis.js';
|
|
9
9
|
import { getActiveSessionId } from '../../../services/sessionMemoryStore.js';
|
|
10
10
|
import ButtonDesktop from '../../ui/ButtonDesktop.js';
|
|
11
|
+
import { reportSelfieFailure } from '../../../services/sessionService.js';
|
|
11
12
|
|
|
12
13
|
var processingSteps = [
|
|
13
14
|
{ key: "analysis" },
|
|
@@ -16,7 +17,7 @@ var processingSteps = [
|
|
|
16
17
|
{ key: "finalization" },
|
|
17
18
|
];
|
|
18
19
|
var SelfieProcessing = function (_a) {
|
|
19
|
-
var onProcessingComplete = _a.onProcessingComplete, selfieVideo = _a.selfieVideo, selfiePhoto = _a.selfiePhoto, onRetake = _a.onRetake, onContinueAnyway = _a.onContinueAnyway;
|
|
20
|
+
var onProcessingComplete = _a.onProcessingComplete, selfieVideo = _a.selfieVideo, selfiePhoto = _a.selfiePhoto, onRetake = _a.onRetake, onContinueAnyway = _a.onContinueAnyway, nodeId = _a.nodeId;
|
|
20
21
|
var t = useI18n().t;
|
|
21
22
|
var _b = useState(0), currentStep = _b[0], setCurrentStep = _b[1];
|
|
22
23
|
var _c = useState(false), hasError = _c[0], setHasError = _c[1];
|
|
@@ -34,6 +35,13 @@ var SelfieProcessing = function (_a) {
|
|
|
34
35
|
var timeoutId = setTimeout(function () {
|
|
35
36
|
if (!isDone) {
|
|
36
37
|
console.error("⏰ Selfie analysis timeout after 60 seconds");
|
|
38
|
+
var sessionId = getActiveSessionId();
|
|
39
|
+
if (sessionId) {
|
|
40
|
+
void reportSelfieFailure(sessionId, {
|
|
41
|
+
nodeId: nodeId,
|
|
42
|
+
reason: "timeout",
|
|
43
|
+
}).catch(function () { return undefined; });
|
|
44
|
+
}
|
|
37
45
|
setHasError(true);
|
|
38
46
|
setIsDone(true);
|
|
39
47
|
onProcessingComplete(false);
|
|
@@ -59,7 +67,7 @@ var SelfieProcessing = function (_a) {
|
|
|
59
67
|
case 1:
|
|
60
68
|
_h.trys.push([1, 3, , 4]);
|
|
61
69
|
return [4 /*yield*/, Promise.all([
|
|
62
|
-
analyzeSelfie(sessionId, selfieVideo, selfiePhoto),
|
|
70
|
+
analyzeSelfie(sessionId, selfieVideo, selfiePhoto, nodeId),
|
|
63
71
|
new Promise(function (resolve) { return setTimeout(resolve, 2000); }),
|
|
64
72
|
])];
|
|
65
73
|
case 2:
|
|
@@ -106,6 +114,10 @@ var SelfieProcessing = function (_a) {
|
|
|
106
114
|
case 3:
|
|
107
115
|
error_1 = _h.sent();
|
|
108
116
|
console.error("💥 Selfie analysis failed:", error_1);
|
|
117
|
+
void reportSelfieFailure(sessionId, {
|
|
118
|
+
nodeId: nodeId,
|
|
119
|
+
reason: "network_error",
|
|
120
|
+
}).catch(function () { return undefined; });
|
|
109
121
|
clearTimeout(timeoutId);
|
|
110
122
|
setHasError(true);
|
|
111
123
|
setIsDone(true);
|
|
@@ -119,7 +131,7 @@ var SelfieProcessing = function (_a) {
|
|
|
119
131
|
return function () {
|
|
120
132
|
clearTimeout(timeoutId);
|
|
121
133
|
};
|
|
122
|
-
}, [onProcessingComplete, selfieVideo, selfiePhoto, isDone]);
|
|
134
|
+
}, [onProcessingComplete, selfieVideo, selfiePhoto, isDone, nodeId]);
|
|
123
135
|
useEffect(function () {
|
|
124
136
|
// While analysis is not finished, stay at step 0
|
|
125
137
|
if (!isDone && !hasError) {
|