@incodetech/core 2.0.0-rc.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/package.json +3 -3
  2. package/dist/Actor-CI32dTbG.d.ts +0 -2
  3. package/dist/BaseWasmProvider-C_DLEI40.esm.js +0 -1118
  4. package/dist/BrowserStorageProvider-CuOW1Er2.esm.js +0 -55
  5. package/dist/BrowserTimerProvider-DhNc_x02.esm.js +0 -22
  6. package/dist/ITimerCapability-C67ZRskg.esm.js +0 -7
  7. package/dist/IpifyProvider-D7jx52AL.esm.js +0 -139
  8. package/dist/Manager-C8PrhBOx.d.ts +0 -19
  9. package/dist/MotionSensorProvider-4v7xkqAp.esm.js +0 -254
  10. package/dist/OpenViduRecordingProvider-CMu6XVdc.esm.js +0 -87
  11. package/dist/StateMachine-BCQrZJhf.d.ts +0 -2
  12. package/dist/WasmUtilProvider-j98OJf-S.esm.js +0 -114
  13. package/dist/addressSearch-BpTbTWCa.esm.js +0 -430
  14. package/dist/ae-signature-DDDZmWXj.esm.js +0 -12
  15. package/dist/ae-signature.d.ts +0 -25
  16. package/dist/ae-signature.esm.js +0 -8
  17. package/dist/antifraud.d.ts +0 -57
  18. package/dist/antifraud.esm.js +0 -45
  19. package/dist/antifraudStateMachine-O0TMf6yc.esm.js +0 -39
  20. package/dist/api-CESGtpbH.esm.js +0 -53
  21. package/dist/authentication.d.ts +0 -12
  22. package/dist/authentication.esm.js +0 -25
  23. package/dist/authenticationManager-5M-fKzXx.esm.js +0 -67
  24. package/dist/authenticationManager-C83GNIhl.d.ts +0 -66
  25. package/dist/authenticationStateMachine-BMZqatiF.esm.js +0 -139
  26. package/dist/backCameraStream-DMdMeGk2.esm.js +0 -346
  27. package/dist/browserSimulation-gxD8cSpM.esm.js +0 -20
  28. package/dist/camera-DBSxa6ML.d.ts +0 -4
  29. package/dist/camera-PA2Ljri3.esm.js +0 -22
  30. package/dist/camera.d.ts +0 -15
  31. package/dist/camera.esm.js +0 -5
  32. package/dist/chunk-CRF6K_H_.esm.js +0 -49
  33. package/dist/consent.d.ts +0 -398
  34. package/dist/consent.esm.js +0 -79
  35. package/dist/consentStateMachine-CCT-B60O.esm.js +0 -151
  36. package/dist/cpf-PPz2Njto.esm.js +0 -38
  37. package/dist/cpf-ocr.d.ts +0 -204
  38. package/dist/cpf-ocr.esm.js +0 -177
  39. package/dist/cross-document-data-match.d.ts +0 -34
  40. package/dist/cross-document-data-match.esm.js +0 -71
  41. package/dist/curp-validation.d.ts +0 -188
  42. package/dist/curp-validation.esm.js +0 -110
  43. package/dist/curpValidationStateMachine-CitWLr2c.esm.js +0 -595
  44. package/dist/custom-fields.d.ts +0 -115
  45. package/dist/custom-fields.esm.js +0 -177
  46. package/dist/custom-watchlist.d.ts +0 -66
  47. package/dist/custom-watchlist.esm.js +0 -86
  48. package/dist/dateUtils-UoN5xswP.esm.js +0 -23
  49. package/dist/deepsightLoader-Cm4JIT_z.esm.js +0 -52
  50. package/dist/deepsightService-CEVxzehb.d.ts +0 -412
  51. package/dist/deepsightService-O74l4Y__.esm.js +0 -489
  52. package/dist/device.d.ts +0 -46
  53. package/dist/device.esm.js +0 -106
  54. package/dist/displayErrors-DqJ_IbsG.d.ts +0 -39
  55. package/dist/document-capture.d.ts +0 -906
  56. package/dist/document-capture.esm.js +0 -156
  57. package/dist/document-upload.d.ts +0 -331
  58. package/dist/document-upload.esm.js +0 -203
  59. package/dist/documentCaptureStateMachine-BqzTDy9k.esm.js +0 -394
  60. package/dist/dynamic-forms.d.ts +0 -178
  61. package/dist/dynamic-forms.esm.js +0 -323
  62. package/dist/ekyb.d.ts +0 -148
  63. package/dist/ekyb.esm.js +0 -127
  64. package/dist/ekybStateMachine-B59rQjgj.esm.js +0 -674
  65. package/dist/ekyc.d.ts +0 -164
  66. package/dist/ekyc.esm.js +0 -104
  67. package/dist/ekycStateMachine-oeO0Iekd.esm.js +0 -10626
  68. package/dist/electronic-signature.d.ts +0 -4
  69. package/dist/electronic-signature.esm.js +0 -7
  70. package/dist/electronicSignatureManager-D9OHzTpG.esm.js +0 -428
  71. package/dist/email.d.ts +0 -4
  72. package/dist/email.esm.js +0 -9
  73. package/dist/emailManager-DIfnS5g1.d.ts +0 -352
  74. package/dist/emailManager-wAV0LE-H.esm.js +0 -238
  75. package/dist/emailStateMachine-DOf4j58N.esm.js +0 -292
  76. package/dist/endpoints-CnN3SyDa.esm.js +0 -87
  77. package/dist/events-D6-e4vok.esm.js +0 -596
  78. package/dist/events.d.ts +0 -265
  79. package/dist/events.esm.js +0 -4
  80. package/dist/extensibility.d.ts +0 -122
  81. package/dist/extensibility.esm.js +0 -43
  82. package/dist/face-match.d.ts +0 -228
  83. package/dist/face-match.esm.js +0 -173
  84. package/dist/faceCaptureManagerFactory-Dh2PdGlF.esm.js +0 -290
  85. package/dist/faceCaptureManagerFactory-yqtpxjnN.d.ts +0 -690
  86. package/dist/faceCaptureSetup-B3faSpYA.esm.js +0 -873
  87. package/dist/faceMatchStateMachine-DNFrxTFS.esm.js +0 -127
  88. package/dist/flow-events.d.ts +0 -6
  89. package/dist/flow-events.esm.js +0 -0
  90. package/dist/flow.d.ts +0 -358
  91. package/dist/flow.esm.js +0 -825
  92. package/dist/flowCompletionService-DhkT4SRY.d.ts +0 -10
  93. package/dist/flowCompletionService-P54yzGvA.esm.js +0 -13
  94. package/dist/flowServices-DTsm-Vf1.esm.js +0 -188
  95. package/dist/geolocation.d.ts +0 -127
  96. package/dist/geolocation.esm.js +0 -89
  97. package/dist/geolocationStateMachine-asasuHY2.esm.js +0 -105
  98. package/dist/getBrowser-BSXUTWXw.esm.js +0 -41
  99. package/dist/getDeviceClass-BSntT9_j.esm.js +0 -14
  100. package/dist/government-validation.d.ts +0 -67
  101. package/dist/government-validation.esm.js +0 -81
  102. package/dist/governmentValidationStateMachine-BDDYrJTo.esm.js +0 -271
  103. package/dist/home.d.ts +0 -99
  104. package/dist/home.esm.js +0 -61
  105. package/dist/http.d.ts +0 -68
  106. package/dist/http.esm.js +0 -3
  107. package/dist/id-ocr.d.ts +0 -635
  108. package/dist/id-ocr.esm.js +0 -86
  109. package/dist/id-verification.d.ts +0 -190
  110. package/dist/id-verification.esm.js +0 -43
  111. package/dist/id.d.ts +0 -24
  112. package/dist/id.esm.js +0 -164
  113. package/dist/idCaptureManager-B9TGA5dq.d.ts +0 -956
  114. package/dist/idCaptureManager-DMK0GIt3.esm.js +0 -581
  115. package/dist/idCaptureStateMachine-Bq0fVZXl.esm.js +0 -2954
  116. package/dist/idOcrStateMachine-YbjjC_Gg.esm.js +0 -388
  117. package/dist/idVerificationStateMachine-xbw9HP1Z.esm.js +0 -71
  118. package/dist/identity-reuse.d.ts +0 -530
  119. package/dist/identity-reuse.esm.js +0 -274
  120. package/dist/index-BLKtMA0g.d.ts +0 -1177
  121. package/dist/index-BcRG8rtJ.d.ts +0 -97
  122. package/dist/index.d.ts +0 -3
  123. package/dist/index.esm.js +0 -12
  124. package/dist/invokeOnCaptureCallback-rc6kBHo5.esm.js +0 -30
  125. package/dist/lib-BB0B_qQX.esm.js +0 -12499
  126. package/dist/mandatory-consent.d.ts +0 -412
  127. package/dist/mandatory-consent.esm.js +0 -78
  128. package/dist/mandatoryConsentStateMachine-Cnco1jvn.esm.js +0 -126
  129. package/dist/openviduLazy-Cm0XFh_v.esm.js +0 -3
  130. package/dist/openviduLazy-Cok70ZSg.esm.js +0 -12
  131. package/dist/permissionServices-D_i6nzEw.esm.js +0 -50
  132. package/dist/phone.d.ts +0 -4
  133. package/dist/phone.esm.js +0 -9
  134. package/dist/phoneManager-B6M30hKE.d.ts +0 -397
  135. package/dist/phoneManager-DAJbGhlY.esm.js +0 -256
  136. package/dist/phoneStateMachine-CuPARRaT.esm.js +0 -351
  137. package/dist/platform-CfrjKhmi.esm.js +0 -83
  138. package/dist/qe-signature-DFo_Cc-I.esm.js +0 -12
  139. package/dist/qe-signature.d.ts +0 -25
  140. package/dist/qe-signature.esm.js +0 -8
  141. package/dist/recordingService-Ig2UgbLv.esm.js +0 -1003
  142. package/dist/redirect-to-mobile.d.ts +0 -107
  143. package/dist/redirect-to-mobile.esm.js +0 -102
  144. package/dist/redirectToMobileStateMachine-BOEqe46A.esm.js +0 -249
  145. package/dist/runChildModule-CqqwqAkW.esm.js +0 -219
  146. package/dist/selfie.d.ts +0 -26
  147. package/dist/selfie.esm.js +0 -146
  148. package/dist/selfieManager-D0lSgd-J.d.ts +0 -68
  149. package/dist/selfieManager-Duisl7qN.esm.js +0 -60
  150. package/dist/selfieStateMachine-D76whWEf.esm.js +0 -68
  151. package/dist/session-BS-d_vuE.esm.js +0 -3206
  152. package/dist/session.d.ts +0 -217
  153. package/dist/session.esm.js +0 -9
  154. package/dist/setup-Buy-hyj4.esm.js +0 -887
  155. package/dist/setup-C5AITV8m.d.ts +0 -254
  156. package/dist/signature.d.ts +0 -94
  157. package/dist/signature.esm.js +0 -66
  158. package/dist/signatureStateMachine-B5-QVUve.esm.js +0 -132
  159. package/dist/stats-CIfiPzb1.esm.js +0 -16
  160. package/dist/stats.d.ts +0 -16
  161. package/dist/stats.esm.js +0 -4
  162. package/dist/trust-graph.d.ts +0 -54
  163. package/dist/trust-graph.esm.js +0 -56
  164. package/dist/types-B06Ypu2F.d.ts +0 -49
  165. package/dist/types-BP1m8VRw.d.ts +0 -340
  166. package/dist/types-CAD4va6a.d.ts +0 -5
  167. package/dist/types-CFV9G_7j.d.ts +0 -24
  168. package/dist/warmup-CEcppFiS.d.ts +0 -63
  169. package/dist/wasm.d.ts +0 -15
  170. package/dist/wasm.esm.js +0 -12
  171. package/dist/watchlist-for-business.d.ts +0 -79
  172. package/dist/watchlist-for-business.esm.js +0 -148
  173. package/dist/watchlist.d.ts +0 -62
  174. package/dist/watchlist.esm.js +0 -86
  175. package/dist/watchlistServices-DMbUhkBX.esm.js +0 -12
  176. package/dist/workflow.d.ts +0 -907
  177. package/dist/workflow.esm.js +0 -702
  178. package/dist/xstate.esm-B70JrNqo.esm.js +0 -3404
@@ -1,2954 +0,0 @@
1
- import { l as WasmPipelineType, r as mlWasmJSApi_default, t as BaseWasmProvider, u as IdCaptureModelType } from "./BaseWasmProvider-C_DLEI40.esm.js";
2
- import { t as BrowserTimerProvider } from "./BrowserTimerProvider-DhNc_x02.esm.js";
3
- import { r as getToken, t as api } from "./api-CESGtpbH.esm.js";
4
- import { S as revokeObjectURL } from "./events-D6-e4vok.esm.js";
5
- import { t as endpoints } from "./endpoints-CnN3SyDa.esm.js";
6
- import { t as getDisableIpify } from "./session-BS-d_vuE.esm.js";
7
- import { a as fromPromise, i as fromCallback, n as sendTo, o as and, r as assign, t as setup } from "./xstate.esm-B70JrNqo.esm.js";
8
- import { n as IncodeCanvas } from "./deepsightService-O74l4Y__.esm.js";
9
- import { _ as stopRecording$1, a as StreamCanvasCapture, g as startRecording, h as createRecordingSession, i as flagIdManualReview, n as preloadOpenViduProvider, v as StreamCanvasProcessingSession } from "./recordingService-Ig2UgbLv.esm.js";
10
- import { n as isDesktop } from "./platform-CfrjKhmi.esm.js";
11
- import { t as getBackCameraStream } from "./backCameraStream-DMdMeGk2.esm.js";
12
- import { r as getWindowDimensions } from "./getBrowser-BSXUTWXw.esm.js";
13
- import { t as addDeviceStats } from "./stats-CIfiPzb1.esm.js";
14
- import { t as getDeviceClass } from "./getDeviceClass-BSntT9_j.esm.js";
15
- import { n as requestPermission, t as checkPermission } from "./permissionServices-D_i6nzEw.esm.js";
16
-
17
- //#region src/modules/id/digitalUpload/digitalUploadErrors.ts
18
- const TERMINAL_FAIL_REASONS = new Set(["DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED", "ID_TYPE_UNACCEPTABLE"]);
19
- function isKnownFailReason(reason) {
20
- return reason === "DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED" || reason === "ID_TYPE_UNACCEPTABLE" || reason === "FILE_CHANGED_ERROR" || reason === "NETWORK_ERROR" || reason === "GENERIC";
21
- }
22
- function mapDigitalIdFailReason(response) {
23
- const failReason = response?.failReason;
24
- if (typeof failReason !== "string" || failReason.length === 0) return null;
25
- if (isKnownFailReason(failReason)) return failReason;
26
- return "GENERIC";
27
- }
28
- function isTerminalDigitalIdFailReason(response) {
29
- return typeof response?.failReason === "string" && TERMINAL_FAIL_REASONS.has(response.failReason);
30
- }
31
- function classifyNetworkError(err) {
32
- const message = err instanceof Error ? err.message : String(err);
33
- if (message.includes("ERR_UPLOAD_FILE_CHANGED") || message.includes("file changed") || message.includes("FILE_CHANGED")) return "FILE_CHANGED_ERROR";
34
- return "NETWORK_ERROR";
35
- }
36
-
37
- //#endregion
38
- //#region src/modules/id/digitalUpload/digitalUploadServices.ts
39
- const DIGITAL_ID_UPLOAD_PATH = "/omni/add/front-id";
40
- async function uploadDigitalIdFile(params) {
41
- const { file, signal, onProgress } = params;
42
- const response = await api.post(DIGITAL_ID_UPLOAD_PATH, file, {
43
- query: { idType: "DigitalId" },
44
- headers: { "Content-Type": file.type || "application/pdf" },
45
- onUploadProgress: onProgress,
46
- signal
47
- });
48
- if (!response.ok) throw new Error(`POST ${DIGITAL_ID_UPLOAD_PATH} failed: ${response.status}`);
49
- return {
50
- ...response.data,
51
- uploadDurationMs: 0
52
- };
53
- }
54
-
55
- //#endregion
56
- //#region src/modules/id/digitalUpload/types.ts
57
- const DIGITAL_UPLOAD_MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
58
- const DIGITAL_UPLOAD_HOLDING_TIMEOUT_MS = 8e3;
59
- const DIGITAL_UPLOAD_ALLOWED_MIME_TYPES = ["application/pdf"];
60
-
61
- //#endregion
62
- //#region src/modules/id/digitalUpload/digitalUploadStateMachine.ts
63
- const uploadDigitalIdActor = fromPromise(async ({ input, signal }) => {
64
- return uploadDigitalIdFile({
65
- file: input.file,
66
- signal: input.signal ?? signal,
67
- onProgress: input.onProgress
68
- });
69
- });
70
- const getUploadResponseFromEvent$1 = (event) => {
71
- if (!("output" in event)) return;
72
- return event.output;
73
- };
74
- const _digitalUploadMachine = setup({
75
- types: {
76
- context: {},
77
- events: {},
78
- input: {},
79
- output: {}
80
- },
81
- actors: { uploadDigitalId: uploadDigitalIdActor },
82
- actions: {
83
- requestPickerIfPending: assign(({ context }) => {
84
- if (!context.pendingPickerAutoOpen) return {};
85
- return {
86
- pickerRequestId: context.pickerRequestId + 1,
87
- pendingPickerAutoOpen: false
88
- };
89
- }),
90
- setPendingPickerAutoOpen: assign(() => ({ pendingPickerAutoOpen: true })),
91
- storeSelectedFile: assign(({ event }) => {
92
- if (event.type !== "FILE_PICKED") return {};
93
- return {
94
- file: event.file,
95
- failReason: null
96
- };
97
- }),
98
- clearSelectedFile: assign(() => ({
99
- file: null,
100
- uploadProgress: 0,
101
- failReason: null,
102
- response: void 0,
103
- uploadDurationMs: void 0
104
- })),
105
- setInvalidFileTypeError: assign(() => ({ failReason: "INVALID_FILE_TYPE" })),
106
- setUploadProgressCapped: assign(({ event }) => {
107
- if (event.type !== "UPLOAD_PROGRESS") return {};
108
- return { uploadProgress: Math.min(90, Math.max(0, event.progress)) };
109
- }),
110
- setUploadProgressCompleted: assign(() => ({ uploadProgress: 100 })),
111
- storeUploadResponse: assign(({ event }) => {
112
- if (!("output" in event)) return {};
113
- const output = event;
114
- return {
115
- response: output.output,
116
- uploadDurationMs: output.output.uploadDurationMs
117
- };
118
- }),
119
- setFailReasonFromResponse: assign(({ event }) => {
120
- if (!("output" in event)) return {};
121
- const response = event.output;
122
- return { failReason: mapDigitalIdFailReason(response) ?? "GENERIC" };
123
- }),
124
- setFailReasonFromNetworkError: assign(({ event }) => {
125
- if (!("error" in event)) return {};
126
- return { failReason: classifyNetworkError(event.error) };
127
- }),
128
- decrementAttemptOnRetry: assign(({ context }) => {
129
- if (!(context.failReason !== "INVALID_FILE_TYPE" && context.failReason !== null && context.failReason !== "DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED" && context.failReason !== "ID_TYPE_UNACCEPTABLE")) return {};
130
- return { attemptsRemaining: Math.max(0, context.attemptsRemaining - 1) };
131
- })
132
- },
133
- guards: {
134
- isSelectedFileTooLarge: ({ event }) => event.type === "FILE_PICKED" && event.file.size > DIGITAL_UPLOAD_MAX_FILE_SIZE_BYTES,
135
- isSelectedFileMimeInvalid: ({ event }) => event.type === "FILE_PICKED" && !DIGITAL_UPLOAD_ALLOWED_MIME_TYPES.includes(event.file.type),
136
- hasSelectedFile: ({ context }) => context.file !== null,
137
- responseHasFailReason: ({ event }) => mapDigitalIdFailReason(getUploadResponseFromEvent$1(event)) !== null,
138
- hasAttemptsRemaining: ({ context }) => context.attemptsRemaining > 0,
139
- isTerminalFailReason: ({ event }) => {
140
- return isTerminalDigitalIdFailReason(getUploadResponseFromEvent$1(event));
141
- },
142
- isCurrentFailReasonTerminal: ({ context }) => {
143
- const terminalReasons = new Set(["DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED", "ID_TYPE_UNACCEPTABLE"]);
144
- return context.failReason !== null && terminalReasons.has(context.failReason);
145
- }
146
- }
147
- }).createMachine({
148
- id: "digitalUpload",
149
- initial: "decideStart",
150
- context: ({ input }) => ({
151
- showTutorial: input.showTutorial,
152
- file: null,
153
- uploadProgress: 0,
154
- attemptsRemaining: input.captureAttempts,
155
- failReason: null,
156
- response: void 0,
157
- uploadDurationMs: void 0,
158
- pickerRequestId: 0,
159
- pendingPickerAutoOpen: !input.showTutorial,
160
- resultType: null
161
- }),
162
- output: ({ context }) => ({ result: context.resultType ?? "exhausted" }),
163
- states: {
164
- decideStart: { always: [{
165
- guard: ({ context }) => context.showTutorial,
166
- target: "tutorial"
167
- }, { target: "selecting" }] },
168
- tutorial: { on: { NEXT_STEP: {
169
- target: "selecting",
170
- actions: ["setPendingPickerAutoOpen"]
171
- } } },
172
- selecting: {
173
- entry: ["requestPickerIfPending"],
174
- on: { FILE_PICKED: [
175
- {
176
- guard: "isSelectedFileTooLarge",
177
- target: "fileTooLarge",
178
- actions: ["clearSelectedFile"]
179
- },
180
- {
181
- guard: "isSelectedFileMimeInvalid",
182
- target: "error",
183
- actions: ["setInvalidFileTypeError"]
184
- },
185
- {
186
- target: "reviewing",
187
- actions: ["storeSelectedFile"]
188
- }
189
- ] }
190
- },
191
- fileTooLarge: { on: { CHOOSE_ANOTHER: {
192
- target: "selecting",
193
- actions: ["clearSelectedFile", "setPendingPickerAutoOpen"]
194
- } } },
195
- reviewing: { on: {
196
- CONFIRM: {
197
- target: "uploading",
198
- guard: "hasSelectedFile"
199
- },
200
- REPLACE: {
201
- target: "selecting",
202
- actions: ["setPendingPickerAutoOpen"]
203
- }
204
- } },
205
- uploading: {
206
- invoke: {
207
- id: "uploadDigitalId",
208
- src: "uploadDigitalId",
209
- input: ({ context, self }) => ({
210
- file: context.file,
211
- onProgress: (progress) => {
212
- self.send({
213
- type: "UPLOAD_PROGRESS",
214
- progress
215
- });
216
- }
217
- }),
218
- onDone: [
219
- {
220
- guard: "isTerminalFailReason",
221
- target: "retriesExhausted",
222
- actions: ["storeUploadResponse", "setFailReasonFromResponse"]
223
- },
224
- {
225
- guard: "responseHasFailReason",
226
- target: "checkRetries",
227
- actions: ["storeUploadResponse", "setFailReasonFromResponse"]
228
- },
229
- {
230
- target: "success",
231
- actions: ["storeUploadResponse", "setUploadProgressCompleted"]
232
- }
233
- ],
234
- onError: {
235
- target: "checkRetries",
236
- actions: ["setFailReasonFromNetworkError"]
237
- }
238
- },
239
- initial: "analyzing",
240
- states: {
241
- analyzing: { after: { [DIGITAL_UPLOAD_HOLDING_TIMEOUT_MS]: { target: "holding" } } },
242
- holding: {}
243
- },
244
- on: { UPLOAD_PROGRESS: { actions: ["setUploadProgressCapped"] } }
245
- },
246
- checkRetries: { always: [
247
- {
248
- guard: "isCurrentFailReasonTerminal",
249
- target: "retriesExhausted"
250
- },
251
- {
252
- guard: "hasAttemptsRemaining",
253
- target: "error"
254
- },
255
- { target: "retriesExhausted" }
256
- ] },
257
- error: { on: {
258
- RETRY: {
259
- target: "selecting",
260
- actions: [
261
- "decrementAttemptOnRetry",
262
- "setPendingPickerAutoOpen",
263
- "clearSelectedFile"
264
- ]
265
- },
266
- SCAN_INSTEAD: { target: "closed" }
267
- } },
268
- retriesExhausted: {
269
- type: "final",
270
- entry: assign({ resultType: "exhausted" })
271
- },
272
- closed: {
273
- type: "final",
274
- entry: assign({ resultType: "closed" })
275
- },
276
- success: { on: { NEXT_STEP: { target: "completed" } } },
277
- completed: {
278
- type: "final",
279
- entry: assign({ resultType: "success" })
280
- }
281
- }
282
- });
283
- const digitalUploadMachine = _digitalUploadMachine;
284
-
285
- //#endregion
286
- //#region src/modules/id/digitalUpload/instrumentation.ts
287
- const TERMINAL_REASONS = new Set(["DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED", "ID_TYPE_UNACCEPTABLE"]);
288
- function isHoldingState(value) {
289
- if (value === "holding") return true;
290
- if (typeof value !== "object" || value === null) return false;
291
- const uploadingState = value.uploading;
292
- if (uploadingState === "holding") return true;
293
- if (typeof uploadingState === "object" && uploadingState !== null) return Object.prototype.hasOwnProperty.call(uploadingState, "holding");
294
- return false;
295
- }
296
- function mapDigitalIdScreenName(value, failReason) {
297
- if (value === "tutorial") return "uploadDigitalid.tutorial.default";
298
- if (value === "selecting" || value === "reviewing") return "uploadDigitalid.review.default";
299
- if (value === "uploading" || isHoldingState(value)) return "uploadDigitalid.analyzing.default";
300
- if (value === "success") return "uploadDigitalid.success.default";
301
- if (value === "fileTooLarge") return "uploadDigitalid.error.filetoolarge";
302
- if (value === "error") {
303
- if (failReason !== null && TERMINAL_REASONS.has(failReason)) return "uploadDigitalid.error.notaccepted";
304
- return "uploadDigitalid.error.default";
305
- }
306
- return "uploadDigitalid.review.default";
307
- }
308
-
309
- //#endregion
310
- //#region src/modules/id/idCaptureHelpers.ts
311
- /**
312
- * Map of config properties received from the backend to adjusted, internal document types.
313
- */
314
- const DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP = [
315
- ["enableId", "id"],
316
- ["enablePassport", "passport"],
317
- ["manualUploadIdCapture", "manualIdUpload"],
318
- ["digitalIdsUpload", "digitalIdUpload"],
319
- ["deviceWallet", "digitalId"]
320
- ];
321
- /**
322
- * Returns the list of document types enabled by config for the chooser screen, in display order.
323
- * Used to populate chooser state so UI and headless consumers can render the correct options.
324
- *
325
- * @param config - ID capture configuration (from flow or init)
326
- * @returns Array of IdDocumentType values that should be shown in the document type chooser
327
- */
328
- function getAvailableDocumentTypes(config) {
329
- const adjustedDocumentTypes = [];
330
- for (const [configProperty, adjustedType] of DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP) if (config[configProperty]) adjustedDocumentTypes.push(adjustedType);
331
- return adjustedDocumentTypes;
332
- }
333
-
334
- //#endregion
335
- //#region ../infra/src/providers/wasm/IdCaptureProvider.ts
336
- var IdCaptureProvider = class extends BaseWasmProvider {
337
- constructor() {
338
- super(WasmPipelineType.IdBlurGlarePipeline);
339
- this.lastProcessResult = null;
340
- this.capturedCanvas = null;
341
- this.originalCapturedCanvas = null;
342
- }
343
- async initialize(config) {
344
- await this.initializeBase(config, "idCapture");
345
- }
346
- setCallbacks(callbacks) {
347
- this.ensureInitialized();
348
- const onCaptureWrapper = () => {
349
- callbacks.onCapture?.();
350
- };
351
- mlWasmJSApi_default.setIdCaptureCallbacks(this.getPipelineType(), callbacks.onFarAway ?? (() => {}), callbacks.onDetectionStarted ?? (() => {}), callbacks.onMaskChange ? (show, mask, top, orientation) => callbacks.onMaskChange?.(show, mask, top, orientation) : () => {}, callbacks.onBlur ?? (() => {}), callbacks.onGlare ?? (() => {}), callbacks.onCapturing ?? (() => {}), callbacks.onCapture ? onCaptureWrapper : () => {}, callbacks.onBestFrame ? (blur, glare, orientation) => callbacks.onBestFrame?.(blur, glare, orientation) : () => {}, callbacks.onIdNotDetected ?? (() => {}), callbacks.onSwitchToManualCapture ?? (() => {}), callbacks.onIdTypeChange ? (idType) => callbacks.onIdTypeChange?.(idType) : () => {}, callbacks.onIdSideChange ? (side) => callbacks.onIdSideChange?.(side) : () => {}, callbacks.onCapturingCounterValueChange ? (value) => callbacks.onCapturingCounterValueChange?.(value) : () => {});
352
- }
353
- setThresholds(thresholds) {
354
- this.ensureInitialized();
355
- mlWasmJSApi_default.setIdCaptureThresholds(this.getPipelineType(), thresholds.blurThreshold, thresholds.blurChangeThreshold, thresholds.glareThreshold, thresholds.clsThreshold, thresholds.sideThreshold, thresholds.iouThreshold, thresholds.idDetectedTimeout, thresholds.autocaptureTimeout, thresholds.framesAggregationInterval);
356
- }
357
- setGeometry(geometry) {
358
- this.ensureInitialized();
359
- mlWasmJSApi_default.setIdCaptureGeometryParams(this.getPipelineType(), geometry.areaDown, geometry.areaUp, geometry.areaIOSPassportUp, geometry.areaIOSPassportDown, geometry.widthIOSUp, geometry.widthIOSDown, geometry.widthDown, geometry.widthUp, geometry.windowOuterWidth, geometry.windowOuterHeight, geometry.windowInnerWidth, geometry.windowInnerHeight);
360
- }
361
- setSettings(settings) {
362
- this.ensureInitialized();
363
- mlWasmJSApi_default.setIdCaptureConfigParams(this.getPipelineType(), settings.isFixedMask, settings.isIPhone14OrHigher, settings.idType, settings.blurCheckEnabled, settings.glareCheckEnabled, settings.faceQualityCheckEnabled, settings.iouCheckEnabled, settings.fpsLimitEnabled);
364
- }
365
- setModelType(modelType) {
366
- this.ensureInitialized();
367
- let wasmModelType;
368
- switch (modelType) {
369
- case "v1":
370
- wasmModelType = IdCaptureModelType.IdCaptureV1x;
371
- break;
372
- case "v2":
373
- wasmModelType = IdCaptureModelType.IdCaptureV2x;
374
- break;
375
- case "v3":
376
- wasmModelType = IdCaptureModelType.IdCaptureV3x;
377
- break;
378
- default: throw new Error(`Unknown model type: ${modelType}`);
379
- }
380
- mlWasmJSApi_default.setIdCaptureModelType(this.getPipelineType(), wasmModelType);
381
- }
382
- /**
383
- * Processes a frame through the WASM pipeline and stores the result.
384
- */
385
- async processFrame(image) {
386
- const result = await this.processFrameWasm(image);
387
- const pipelineType = this.getPipelineType();
388
- if (result && pipelineType === WasmPipelineType.IdBlurGlarePipeline) this.lastProcessResult = result;
389
- else this.lastProcessResult = null;
390
- }
391
- /**
392
- * Gets the last process result from the most recent frame processing.
393
- * @returns The last process result with quad coordinates, or null if not available
394
- */
395
- getLastProcessResult() {
396
- return this.lastProcessResult;
397
- }
398
- transformPerspective(canvas, frameRect) {
399
- this.ensureInitialized();
400
- const originalWidth = canvas.width();
401
- const originalHeight = canvas.height();
402
- try {
403
- const imageData = canvas.getImageData();
404
- if (!imageData) return canvas;
405
- const transformedCanvas = mlWasmJSApi_default.IdPerspectiveTransform(imageData, frameRect);
406
- if (transformedCanvas) {
407
- const wrappedCanvas = new IncodeCanvas(transformedCanvas);
408
- const wrappedWidth = wrappedCanvas.width();
409
- const wrappedHeight = wrappedCanvas.height();
410
- if (wrappedWidth === originalWidth && wrappedHeight === originalHeight) {
411
- const croppedCanvas = this.cropCanvasToRect(wrappedCanvas, {
412
- x: Math.round(frameRect.x),
413
- y: Math.round(frameRect.y),
414
- w: Math.round(frameRect.w),
415
- h: Math.round(frameRect.h)
416
- });
417
- if (croppedCanvas) return croppedCanvas;
418
- }
419
- return wrappedCanvas;
420
- }
421
- return canvas;
422
- } catch (_error) {
423
- return canvas;
424
- }
425
- }
426
- /**
427
- * Crops a canvas to the specified rectangle region.
428
- * @param canvas - The canvas to crop
429
- * @param rect - The rectangle to crop to (x, y, w, h)
430
- * @returns A new IncodeCanvas with the cropped region, or null if cropping fails
431
- */
432
- cropCanvasToRect(canvas, rect) {
433
- const canvasWidth = canvas.width();
434
- const canvasHeight = canvas.height();
435
- if (!canvasWidth || !canvasHeight) return null;
436
- const x = Math.max(0, Math.min(rect.x, canvasWidth));
437
- const y = Math.max(0, Math.min(rect.y, canvasHeight));
438
- const w = Math.max(1, Math.min(rect.w, canvasWidth - x));
439
- const h = Math.max(1, Math.min(rect.h, canvasHeight - y));
440
- const croppedCanvasElement = document.createElement("canvas");
441
- croppedCanvasElement.width = w;
442
- croppedCanvasElement.height = h;
443
- const ctx = croppedCanvasElement.getContext("2d");
444
- if (!ctx) return null;
445
- ctx.drawImage(canvas.canvas, x, y, w, h, 0, 0, w, h);
446
- return new IncodeCanvas(croppedCanvasElement);
447
- }
448
- /**
449
- * Gets the captured canvas (transformed for preview).
450
- * @returns The captured canvas, or null if not available
451
- */
452
- getCapturedCanvas() {
453
- return this.capturedCanvas;
454
- }
455
- /**
456
- * Gets the original captured canvas (full frame for upload).
457
- * @returns The original captured canvas, or null if not available
458
- */
459
- getOriginalCapturedCanvas() {
460
- return this.originalCapturedCanvas;
461
- }
462
- /**
463
- * Sets the captured canvases (original and transformed).
464
- * @param original - The original full-frame canvas (for upload)
465
- * @param transformed - The transformed canvas (for preview)
466
- */
467
- setCapturedCanvases(original, transformed) {
468
- this.originalCapturedCanvas = original;
469
- this.capturedCanvas = transformed;
470
- }
471
- reset() {
472
- super.reset();
473
- this.lastProcessResult = null;
474
- this.capturedCanvas = null;
475
- this.originalCapturedCanvas = null;
476
- }
477
- };
478
-
479
- //#endregion
480
- //#region src/internal/analytics/deviceStats.ts
481
- async function postDeviceStats(stats) {
482
- try {
483
- await api.post(endpoints.deviceStats, stats);
484
- } catch {}
485
- }
486
-
487
- //#endregion
488
- //#region src/modules/id/idCameraStream.ts
489
- async function getIdCameraStream(deviceId) {
490
- return getBackCameraStream(deviceId);
491
- }
492
-
493
- //#endregion
494
- //#region src/modules/id/manualUpload/types.ts
495
- const MANUAL_UPLOAD_MAX_RETRIES = 3;
496
- const MANUAL_UPLOAD_MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
497
- const MANUAL_UPLOAD_EXHAUSTION_FORWARD_MS = 5e3;
498
-
499
- //#endregion
500
- //#region src/modules/id/types.ts
501
- const ID_ERROR_CODES = {
502
- UPLOAD_ERROR: "UPLOAD_ERROR",
503
- CLASSIFICATION_FAILED: "CLASSIFICATION_FAILED",
504
- LOW_SHARPNESS: "LOW_SHARPNESS",
505
- GLARE_DETECTED: "GLARE_DETECTED",
506
- WRONG_DOCUMENT_SIDE: "WRONG_DOCUMENT_SIDE",
507
- ID_TYPE_UNACCEPTABLE: "ID_TYPE_UNACCEPTABLE",
508
- READABILITY_ISSUE: "READABILITY_ISSUE",
509
- RETRY_EXHAUSTED_CONTINUE_TO_BACK: "RETRY_EXHAUSTED_CONTINUE_TO_BACK",
510
- RETRY_EXHAUSTED_SKIP_BACK: "RETRY_EXHAUSTED_SKIP_BACK",
511
- NO_MORE_TRIES: "NO_MORE_TRIES",
512
- UNEXPECTED_ERROR: "UNEXPECTED_ERROR",
513
- NO_TOKEN: "NO_TOKEN",
514
- PERMISSION_DENIED: "PERMISSION_DENIED",
515
- USER_CANCELLED: "USER_CANCELLED",
516
- SERVER: "SERVER_ERROR"
517
- };
518
-
519
- //#endregion
520
- //#region src/modules/id/idCaptureServices.ts
521
- /**
522
- * Camera constraints used for PRC warmup before ID capture.
523
- * Uses environment-facing camera on mobile devices (for back camera ID capture)
524
- * and user-facing camera on desktop.
525
- */
526
- function getPrcCameraConstraints() {
527
- if (isDesktop()) return { video: {
528
- facingMode: "user",
529
- height: { ideal: 480 },
530
- width: { ideal: 640 }
531
- } };
532
- return { video: {
533
- facingMode: "environment",
534
- height: { ideal: 720 }
535
- } };
536
- }
537
- function getUploadEndpoint(type, isSecondId) {
538
- if (isSecondId) return type === "front" ? endpoints.frontSecondId : endpoints.backSecondId;
539
- return type === "front" ? endpoints.frontId : endpoints.backId;
540
- }
541
- const SHARPNESS_THRESHOLD = 10;
542
- const GLARE_THRESHOLD = 10;
543
- const DEFAULT_ID_CAPTURE_THRESHOLDS$1 = {
544
- blurThreshold: .2,
545
- blurChangeThreshold: .2,
546
- glareThreshold: .3,
547
- clsThreshold: .98,
548
- sideThreshold: .8,
549
- iouThreshold: .8,
550
- framesAggregationInterval: 3e3
551
- };
552
- const DEFAULT_ID_CAPTURE_SETTINGS = {
553
- isFixedMask: false,
554
- isIPhone14OrHigher: false,
555
- idType: "",
556
- blurCheckEnabled: false,
557
- glareCheckEnabled: false,
558
- faceQualityCheckEnabled: true,
559
- iouCheckEnabled: true,
560
- fpsLimitEnabled: false
561
- };
562
- async function initializeIdCapture(params) {
563
- const { config, deepsightService } = params;
564
- const provider = new IdCaptureProvider();
565
- await provider.initialize({});
566
- provider.setThresholds({
567
- ...DEFAULT_ID_CAPTURE_THRESHOLDS$1,
568
- ...config.thresholds,
569
- idDetectedTimeout: config.thresholds?.idDetectedTimeout ?? config.deviceIdleTimeout * 1e3,
570
- autocaptureTimeout: config.thresholds?.autocaptureTimeout ?? config.autoCaptureTimeout * 1e3
571
- });
572
- if (config.settings) provider.setSettings({
573
- ...DEFAULT_ID_CAPTURE_SETTINGS,
574
- ...config.settings
575
- });
576
- if (deepsightService) try {
577
- await deepsightService.performPrcCheck({ constraints: getPrcCameraConstraints() });
578
- } catch {}
579
- const { stream, fallbackLevel } = await getIdCameraStream();
580
- const videoTrack = stream.getVideoTracks()[0];
581
- let captureResolution;
582
- if (videoTrack) {
583
- const settings = videoTrack.getSettings();
584
- if (typeof settings.width === "number" && typeof settings.height === "number") captureResolution = `${settings.width}x${settings.height}`;
585
- }
586
- if (deepsightService && videoTrack) deepsightService.metadata.updateCameraInfo(videoTrack);
587
- return {
588
- stream,
589
- provider,
590
- captureResolution,
591
- cameraFallbackLevel: fallbackLevel
592
- };
593
- }
594
- function stopStream(stream) {
595
- for (const track of stream.getTracks()) track.stop();
596
- }
597
- function validateUploadResponse(response, sessionState) {
598
- if (response.failReason === "ID_TYPE_UNACCEPTABLE") return {
599
- error: true,
600
- message: "ID type is not acceptable",
601
- messageDescription: "Please use a valid ID type",
602
- errorKey: ID_ERROR_CODES.ID_TYPE_UNACCEPTABLE
603
- };
604
- if (response.failReason === "WRONG_DOCUMENT_SIDE") return {
605
- error: true,
606
- message: "Wrong side of document",
607
- messageDescription: response.side === "back" ? "Please show the back side of your ID" : "Please show the front side of your ID",
608
- errorKey: ID_ERROR_CODES.WRONG_DOCUMENT_SIDE
609
- };
610
- if (!response.classification) return {
611
- error: true,
612
- message: "ID classification failed",
613
- errorKey: ID_ERROR_CODES.CLASSIFICATION_FAILED
614
- };
615
- const sharpnessThreshold = getDeviceClass() === "desktop" ? -1 : SHARPNESS_THRESHOLD;
616
- if (response.sharpness !== void 0 && sharpnessThreshold >= 0 && response.sharpness < sharpnessThreshold) return {
617
- error: true,
618
- message: "Image is not sharp enough",
619
- messageDescription: "Please ensure the image is clear and well-focused",
620
- errorKey: ID_ERROR_CODES.LOW_SHARPNESS
621
- };
622
- if (response.glare !== void 0 && response.glare < GLARE_THRESHOLD && !sessionState?.skipGlareFront && !sessionState?.skipGlareBack) return {
623
- error: true,
624
- message: "Glare detected on ID",
625
- messageDescription: "Please avoid bright reflections on your ID",
626
- errorKey: ID_ERROR_CODES.GLARE_DETECTED
627
- };
628
- }
629
- async function getExtraImages(params) {
630
- const extraImages = params.ageAssurance ? [params.type === "back" ? "croppedBackID" : "croppedFrontID"] : [];
631
- try {
632
- const res = await api.post(endpoints.getImages, { images: ["croppedIDFace", ...extraImages] }, { signal: params.signal });
633
- if (!res.ok) throw new Error(`Failed to get extra images: ${res.status}`);
634
- return res.data ?? {
635
- croppedIDFace: "",
636
- croppedFrontID: "",
637
- croppedBackID: ""
638
- };
639
- } catch {
640
- return {
641
- croppedIDFace: "",
642
- croppedFrontID: "",
643
- croppedBackID: ""
644
- };
645
- }
646
- }
647
- const getRealQualityValue = (value) => (1 - value) * 100;
648
- async function uploadIdImage(params) {
649
- const { type, image, onProgress, signal, metadata, ageAssurance, glare, sharpness, shouldSkipGlareBack, analyticsProvider, imageData, isSecondId, onlyFront } = params;
650
- let finalMetadata = metadata;
651
- if (analyticsProvider && imageData) try {
652
- await analyticsProvider.analyzeFrame(imageData);
653
- analyticsProvider.update();
654
- const analysisStatus = analyticsProvider.getAnalysisStatus();
655
- const motionStatus = analyticsProvider.getMotionStatus();
656
- await postDeviceStats({
657
- frontIdStatsAnalysisStatus: type === "front" ? analysisStatus : void 0,
658
- backIdStatsAnalysisStatus: type === "back" ? analysisStatus : void 0,
659
- motionStatus
660
- });
661
- finalMetadata = analyticsProvider.getMetadata();
662
- } catch (error) {
663
- console.warn("[IdCapture] Analytics failed:", error);
664
- }
665
- const endpoint = getUploadEndpoint(type, isSecondId);
666
- const body = {
667
- base64Image: image,
668
- metadata: finalMetadata
669
- };
670
- const queryParams = { imageType: "id" };
671
- if (onlyFront && type === "front") queryParams.onlyFront = true;
672
- if (shouldSkipGlareBack && type === "back") queryParams.glare = 0;
673
- else if (glare !== void 0) queryParams.glare = getRealQualityValue(glare);
674
- if (sharpness !== void 0) queryParams.sharpness = getRealQualityValue(sharpness);
675
- try {
676
- const res = await api.post(endpoint, body, {
677
- signal,
678
- query: queryParams,
679
- onUploadProgress: onProgress
680
- });
681
- if (!res.ok) throw new Error(`POST ${endpoint} failed: ${res.status} ${res.statusText}`);
682
- const response = res.data;
683
- const extraImages = await getExtraImages({
684
- type,
685
- ageAssurance,
686
- signal
687
- });
688
- const fullResponse = {
689
- ...response,
690
- originalImage: image,
691
- frontIdImage: type === "front" ? image : void 0,
692
- backIdImage: extraImages.croppedBackID,
693
- ...extraImages
694
- };
695
- onProgress?.(100);
696
- return fullResponse;
697
- } catch (error) {
698
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
699
- throw new Error(`${ID_ERROR_CODES.UPLOAD_ERROR}: ${errorMessage}`);
700
- }
701
- }
702
- function buildStandardResolution(width, height) {
703
- return height > width ? {
704
- width: 1080,
705
- height: 1920
706
- } : {
707
- width: 1920,
708
- height: 1080
709
- };
710
- }
711
- function buildResolutionFromStream(stream) {
712
- const track = stream.getVideoTracks()[0];
713
- if (!track) return "1080x1920";
714
- const settings = track.getSettings();
715
- const width = settings.width;
716
- const height = settings.height;
717
- if (typeof width === "number" && typeof height === "number") {
718
- const standard = buildStandardResolution(width, height);
719
- return `${standard.width}x${standard.height}`;
720
- }
721
- return "1080x1920";
722
- }
723
- function preloadIdRecordingProvider(config) {
724
- if (config.enableIdRecording !== true) return;
725
- preloadOpenViduProvider();
726
- }
727
- async function createOpenViduRecordingProvider() {
728
- const { OpenViduRecordingProvider } = await import("./OpenViduRecordingProvider-CMu6XVdc.esm.js");
729
- return new OpenViduRecordingProvider();
730
- }
731
- async function startRecordingSession(params) {
732
- if (params.config.enableIdRecording !== true) return;
733
- if (params.existing) return params.existing;
734
- const provider = params.config.recording?.capability ?? await createOpenViduRecordingProvider();
735
- const clonedStream = params.stream.clone();
736
- const hasAudio = clonedStream.getAudioTracks().length > 0;
737
- const resolution = buildResolutionFromStream(clonedStream);
738
- const session = await createRecordingSession(params.type);
739
- const connection = await provider.connect({
740
- sessionToken: session.token,
741
- stream: clonedStream,
742
- events: {}
743
- });
744
- await startRecording({
745
- videoRecordingId: session.videoRecordingId,
746
- type: params.type,
747
- resolution,
748
- hasAudio
749
- });
750
- return {
751
- token: session.token,
752
- sessionId: session.sessionId,
753
- videoRecordingId: session.videoRecordingId,
754
- connection,
755
- resolution,
756
- hasAudio
757
- };
758
- }
759
- function stopRecording(session) {
760
- (async () => {
761
- try {
762
- await stopRecording$1(session.videoRecordingId);
763
- } finally {
764
- await session.connection.disconnect();
765
- }
766
- })();
767
- }
768
- async function processId(isSecondId = false, queueName = "", signal) {
769
- const endpoint = isSecondId ? endpoints.processSecondId : endpoints.processId;
770
- const url = queueName ? `${endpoint}?queueName=${queueName}` : endpoint;
771
- return { isDocumentExpired: (await api.post(url, {}, { signal })).data?.isDocumentExpired ?? false };
772
- }
773
- /**
774
- * Upload a user-selected image as front / back / passport ID.
775
- *
776
- * Uses the same request shape as the live-camera path (`uploadIdImage`):
777
- * JSON body `{ base64Image }` with default application/json Content-Type,
778
- * `captureType=UPLOAD` query param, `retry=true` when retrying.
779
- * Back is POSTed to `/omni/add/back-id/v2` (or `/omni/add/back-second-id/v2`
780
- * when `isSecondId`); front and passport go to `/omni/add/front-id/v2` (or
781
- * `/omni/add/front-second-id/v2` when `isSecondId`).
782
- *
783
- * The v2 endpoints reject raw `image/jpeg` bodies with 415, so the caller
784
- * must convert the File to base64 before calling this service.
785
- */
786
- async function uploadManualIdFile(params) {
787
- const { side, base64Image, retry, onlyFront, signal, isSecondId } = params;
788
- const endpoint = getUploadEndpoint(side === "back" ? "back" : "front", isSecondId);
789
- const queryParams = { captureType: "UPLOAD" };
790
- if (retry) queryParams.retry = true;
791
- if (onlyFront && side === "front") queryParams.onlyFront = true;
792
- const res = await api.post(endpoint, { base64Image }, {
793
- signal,
794
- query: queryParams
795
- });
796
- if (!res.ok) throw new Error(`POST ${endpoint} failed: ${res.status} ${res.statusText}`);
797
- return res.data;
798
- }
799
-
800
- //#endregion
801
- //#region src/modules/id/manualUpload/manualUploadErrors.ts
802
- /**
803
- * i18n keys for manual-upload user-facing error copy.
804
- * Keep in sync with `packages/ui/src/i18n/**.json` under the `manualIdUpload.*` namespace.
805
- */
806
- const MANUAL_UPLOAD_ERROR_KEYS = {
807
- wrongSide: "manualIdUpload.wrongSide",
808
- wrongDocument: "manualIdUpload.wrongDocument",
809
- fileTooBig: "manualIdUpload.fileTooBig",
810
- generic: "manualIdUpload.generic",
811
- lowSharpness: "manualIdUpload.lowSharpness",
812
- glareDetected: "manualIdUpload.glareDetected",
813
- readabilityIssue: "manualIdUpload.readabilityIssue",
814
- qualityRejected: "manualIdUpload.qualityRejected"
815
- };
816
- /**
817
- * Map the server's `failReason` (plus client-side passport/ID tab mismatch and
818
- * per-image quality flags) onto an i18n key. Mirrors v1's `shouldUploadAgain`
819
- * branch logic in
820
- * `ms-incodesmile-web/packages/incode-welcome/src/manualIdUpload/manuaIdUpload.tsx`,
821
- * extended to also reject responses where the backend flagged a per-image
822
- * quality issue (`correctSharpness`, `correctGlare`, `readability`, or
823
- * `idQualityAttemptApproved` set to `false`).
824
- *
825
- * Quality flags are checked with `=== false` so missing/undefined values
826
- * (older backends, partial payloads) keep the legacy "trust the server"
827
- * behaviour and do not produce false positives.
828
- *
829
- * Returns `null` when the response represents a successful upload — the caller
830
- * should treat `null` as "no error, advance to next slot".
831
- */
832
- function mapFailReasonToErrorKey(response, expectedTab) {
833
- const failReason = response.failReason;
834
- if (failReason === "WRONG_DOCUMENT_SIDE") return MANUAL_UPLOAD_ERROR_KEYS.wrongSide;
835
- if (failReason === "WRONG_ONE_SIDED_DOCUMENT" || failReason === "UNKNOWN_DOCUMENT_TYPE") return MANUAL_UPLOAD_ERROR_KEYS.wrongDocument;
836
- if (failReason === "ID_TYPE_UNACCEPTABLE") return MANUAL_UPLOAD_ERROR_KEYS.wrongDocument;
837
- if (expectedTab === "passport" && response.typeOfId && response.typeOfId.toLowerCase() !== "passport") return MANUAL_UPLOAD_ERROR_KEYS.wrongDocument;
838
- if (expectedTab === "id" && response.typeOfId?.toLowerCase() === "passport") return MANUAL_UPLOAD_ERROR_KEYS.wrongDocument;
839
- if (response.correctSharpness === false) return MANUAL_UPLOAD_ERROR_KEYS.lowSharpness;
840
- if (response.correctGlare === false) return MANUAL_UPLOAD_ERROR_KEYS.glareDetected;
841
- if (response.readability === false) return MANUAL_UPLOAD_ERROR_KEYS.readabilityIssue;
842
- if (response.idQualityAttemptApproved === false) return MANUAL_UPLOAD_ERROR_KEYS.qualityRejected;
843
- return null;
844
- }
845
-
846
- //#endregion
847
- //#region src/modules/id/manualUpload/manualUploadServices.ts
848
- /**
849
- * Read a File's bytes and return the raw base64 payload (the portion after
850
- * `data:<mime>;base64,`). The backend's `/omni/add/*-id/v2` endpoints reject
851
- * full data-URLs with `IllegalArgumentException: Illegal base64 character 3a`,
852
- * so the prefix must be stripped before posting. Mirrors the live-camera
853
- * path in `packages/infra/src/media/canvas.ts:getBase64Image()`.
854
- */
855
- function fileToBase64Payload(file) {
856
- return new Promise((resolve, reject) => {
857
- const reader = new FileReader();
858
- reader.onload = () => {
859
- const result = reader.result;
860
- if (typeof result !== "string") {
861
- reject(/* @__PURE__ */ new Error("FileReader produced non-string result"));
862
- return;
863
- }
864
- const commaIndex = result.indexOf(",");
865
- resolve(commaIndex === -1 ? result : result.slice(commaIndex + 1));
866
- };
867
- reader.onerror = () => {
868
- reject(reader.error ?? /* @__PURE__ */ new Error("FileReader failed"));
869
- };
870
- reader.readAsDataURL(file);
871
- });
872
- }
873
-
874
- //#endregion
875
- //#region src/modules/id/manualUpload/manualUploadStateMachine.ts
876
- const uploadManualFileActor = fromPromise(async ({ input, signal }) => {
877
- const base64Image = await fileToBase64Payload(input.file);
878
- return uploadManualIdFile({
879
- side: input.side,
880
- base64Image,
881
- retry: input.retry,
882
- onlyFront: input.onlyFront,
883
- isSecondId: input.isSecondId,
884
- signal
885
- });
886
- });
887
- const getUploadResponseFromEvent = (event) => {
888
- if ("output" in event) return event.output;
889
- };
890
- const _manualUploadMachine = setup({
891
- types: {
892
- context: {},
893
- events: {},
894
- input: {},
895
- output: {}
896
- },
897
- actors: { uploadManualFile: uploadManualFileActor },
898
- actions: {
899
- setManualUploadActiveTab: assign(({ context, event }) => {
900
- if (event.type !== "MANUAL_UPLOAD_TAB_CHANGED") return {};
901
- return {
902
- activeTab: event.tab,
903
- frontFile: null,
904
- backFile: null,
905
- passportFile: null,
906
- frontUploaded: false,
907
- backUploaded: false,
908
- passportUploaded: false,
909
- skipBackFromServer: false,
910
- errorMessage: null,
911
- retriesLeft: context.captureAttempts
912
- };
913
- }),
914
- resetManualUpload: assign(({ context }) => ({
915
- frontFile: null,
916
- backFile: null,
917
- passportFile: null,
918
- frontUploaded: false,
919
- backUploaded: false,
920
- passportUploaded: false,
921
- skipBackFromServer: false,
922
- errorMessage: null,
923
- retriesLeft: context.captureAttempts
924
- })),
925
- storeSelectedFile: assign(({ event }) => {
926
- if (event.type !== "MANUAL_UPLOAD_FILE_SELECTED") return {};
927
- const updated = { errorMessage: null };
928
- if (event.side === "front") updated.frontFile = event.file;
929
- else if (event.side === "back") updated.backFile = event.file;
930
- else updated.passportFile = event.file;
931
- return updated;
932
- }),
933
- markFrontUploaded: assign(() => ({
934
- frontUploaded: true,
935
- errorMessage: null
936
- })),
937
- markBackUploaded: assign(() => ({
938
- backUploaded: true,
939
- errorMessage: null
940
- })),
941
- markPassportUploaded: assign(() => ({
942
- passportUploaded: true,
943
- errorMessage: null
944
- })),
945
- recordSkipBackFromResponse: assign(({ event }) => {
946
- if (!("output" in event)) return {};
947
- if (!event.output.skipBackIdCapture) return {};
948
- return { skipBackFromServer: true };
949
- }),
950
- decrementManualUploadRetries: assign(({ context }) => ({ retriesLeft: Math.max(0, context.retriesLeft - 1) })),
951
- setManualUploadErrorFromResponse: assign(({ context, event }) => {
952
- if (!("output" in event)) return {};
953
- const response = event.output;
954
- return { errorMessage: mapFailReasonToErrorKey(response, context.activeTab) ?? "manualIdUpload.generic" };
955
- }),
956
- setManualUploadGenericError: assign(() => ({ errorMessage: "manualIdUpload.generic" })),
957
- setManualUploadFileTooLargeError: assign(() => ({ errorMessage: "manualIdUpload.fileTooBig" })),
958
- clearManualUploadError: assign(() => ({ errorMessage: null }))
959
- },
960
- guards: {
961
- isSelectedFileTooLarge: ({ event }) => {
962
- if (event.type !== "MANUAL_UPLOAD_FILE_SELECTED") return false;
963
- return event.file.size > MANUAL_UPLOAD_MAX_FILE_SIZE_BYTES;
964
- },
965
- isFrontFileSelection: ({ event }) => event.type === "MANUAL_UPLOAD_FILE_SELECTED" && event.side === "front",
966
- isBackFileSelection: ({ event }) => event.type === "MANUAL_UPLOAD_FILE_SELECTED" && event.side === "back",
967
- isPassportFileSelection: ({ event }) => event.type === "MANUAL_UPLOAD_FILE_SELECTED" && event.side === "passport",
968
- manualUploadRetriesExhausted: ({ context }) => context.retriesLeft <= 0,
969
- canContinueFromIdTab: ({ context }) => {
970
- if (context.activeTab !== "id") return false;
971
- if (!context.frontUploaded) return false;
972
- if (context.onlyFront) return true;
973
- if (context.skipBackFromServer) return true;
974
- return context.backUploaded;
975
- },
976
- canContinueFromPassportTab: ({ context }) => context.activeTab === "passport" && context.passportUploaded,
977
- manualUploadResponseHasError: ({ context, event }) => {
978
- const response = getUploadResponseFromEvent(event);
979
- if (!response) return false;
980
- return mapFailReasonToErrorKey(response, context.activeTab) !== null;
981
- }
982
- }
983
- }).createMachine({
984
- id: "manualUpload",
985
- initial: "selecting",
986
- context: ({ input }) => ({
987
- onlyFront: input.onlyFront,
988
- isSecondId: input.isSecondId,
989
- captureAttempts: input.captureAttempts,
990
- frontFile: null,
991
- backFile: null,
992
- passportFile: null,
993
- activeTab: "id",
994
- retriesLeft: input.captureAttempts,
995
- errorMessage: null,
996
- skipBackFromServer: false,
997
- frontUploaded: false,
998
- backUploaded: false,
999
- passportUploaded: false
1000
- }),
1001
- on: {
1002
- MANUAL_UPLOAD_TAB_CHANGED: {
1003
- target: ".selecting",
1004
- actions: ["setManualUploadActiveTab"]
1005
- },
1006
- MANUAL_UPLOAD_RESET: {
1007
- target: ".selecting",
1008
- actions: ["resetManualUpload"]
1009
- }
1010
- },
1011
- states: {
1012
- selecting: { on: {
1013
- MANUAL_UPLOAD_FILE_SELECTED: [
1014
- {
1015
- guard: "isSelectedFileTooLarge",
1016
- actions: ["setManualUploadFileTooLargeError"]
1017
- },
1018
- {
1019
- guard: "isFrontFileSelection",
1020
- target: "uploadingFront",
1021
- actions: ["storeSelectedFile"]
1022
- },
1023
- {
1024
- guard: "isBackFileSelection",
1025
- target: "uploadingBack",
1026
- actions: ["storeSelectedFile"]
1027
- },
1028
- {
1029
- guard: "isPassportFileSelection",
1030
- target: "uploadingPassport",
1031
- actions: ["storeSelectedFile"]
1032
- }
1033
- ],
1034
- MANUAL_UPLOAD_CONTINUE: [{
1035
- guard: "canContinueFromIdTab",
1036
- target: "finished"
1037
- }, {
1038
- guard: "canContinueFromPassportTab",
1039
- target: "finished"
1040
- }]
1041
- } },
1042
- uploadingFront: { invoke: {
1043
- id: "uploadManualFile",
1044
- src: "uploadManualFile",
1045
- input: ({ context }) => ({
1046
- side: "front",
1047
- file: context.frontFile,
1048
- retry: context.retriesLeft < context.captureAttempts,
1049
- onlyFront: context.onlyFront,
1050
- isSecondId: context.isSecondId
1051
- }),
1052
- onDone: [{
1053
- guard: "manualUploadResponseHasError",
1054
- target: "checkRetries",
1055
- actions: ["decrementManualUploadRetries", "setManualUploadErrorFromResponse"]
1056
- }, {
1057
- target: "selecting",
1058
- actions: [
1059
- "markFrontUploaded",
1060
- "recordSkipBackFromResponse",
1061
- "clearManualUploadError"
1062
- ]
1063
- }],
1064
- onError: {
1065
- target: "checkRetries",
1066
- actions: ["decrementManualUploadRetries", "setManualUploadGenericError"]
1067
- }
1068
- } },
1069
- uploadingBack: { invoke: {
1070
- id: "uploadManualFile",
1071
- src: "uploadManualFile",
1072
- input: ({ context }) => ({
1073
- side: "back",
1074
- file: context.backFile,
1075
- retry: context.retriesLeft < context.captureAttempts,
1076
- onlyFront: false,
1077
- isSecondId: context.isSecondId
1078
- }),
1079
- onDone: [{
1080
- guard: "manualUploadResponseHasError",
1081
- target: "checkRetries",
1082
- actions: ["decrementManualUploadRetries", "setManualUploadErrorFromResponse"]
1083
- }, {
1084
- target: "selecting",
1085
- actions: ["markBackUploaded", "clearManualUploadError"]
1086
- }],
1087
- onError: {
1088
- target: "checkRetries",
1089
- actions: ["decrementManualUploadRetries", "setManualUploadGenericError"]
1090
- }
1091
- } },
1092
- uploadingPassport: { invoke: {
1093
- id: "uploadManualFile",
1094
- src: "uploadManualFile",
1095
- input: ({ context }) => ({
1096
- side: "passport",
1097
- file: context.passportFile,
1098
- retry: context.retriesLeft < context.captureAttempts,
1099
- onlyFront: false,
1100
- isSecondId: context.isSecondId
1101
- }),
1102
- onDone: [{
1103
- guard: "manualUploadResponseHasError",
1104
- target: "checkRetries",
1105
- actions: ["decrementManualUploadRetries", "setManualUploadErrorFromResponse"]
1106
- }, {
1107
- target: "selecting",
1108
- actions: ["markPassportUploaded", "clearManualUploadError"]
1109
- }],
1110
- onError: {
1111
- target: "checkRetries",
1112
- actions: ["decrementManualUploadRetries", "setManualUploadGenericError"]
1113
- }
1114
- } },
1115
- checkRetries: { always: [{
1116
- guard: "manualUploadRetriesExhausted",
1117
- target: "retriesExhausted"
1118
- }, { target: "selecting" }] },
1119
- retriesExhausted: { after: { [MANUAL_UPLOAD_EXHAUSTION_FORWARD_MS]: { target: "exhausted" } } },
1120
- exhausted: {
1121
- type: "final",
1122
- output: { result: "exhausted" }
1123
- },
1124
- finished: {
1125
- type: "final",
1126
- output: { result: "success" }
1127
- }
1128
- }
1129
- });
1130
- const manualUploadMachine = _manualUploadMachine;
1131
-
1132
- //#endregion
1133
- //#region ../infra/src/wasm/idCaptureDefaults.ts
1134
- /**
1135
- * Default WASM thresholds for ID capture quality checks.
1136
- * Based on legacy pipelinesConfig.ts values.
1137
- */
1138
- const DEFAULT_ID_CAPTURE_THRESHOLDS = {
1139
- blurThreshold: .2,
1140
- blurChangeThreshold: .2,
1141
- glareThreshold: .3,
1142
- clsThreshold: .98,
1143
- sideThreshold: .8,
1144
- iouThreshold: .8,
1145
- idDetectedTimeout: 1e4,
1146
- autocaptureTimeout: 5e3,
1147
- framesAggregationInterval: 3e3
1148
- };
1149
- /**
1150
- * Default model version for ID capture.
1151
- */
1152
- const DEFAULT_ID_CAPTURE_MODEL_VERSION = "v2";
1153
-
1154
- //#endregion
1155
- //#region src/modules/id/idCaptureActors.ts
1156
- const checkPermissionActor = fromPromise(async () => {
1157
- return checkPermission();
1158
- });
1159
- const requestPermissionActor = fromPromise(async ({ input }) => {
1160
- return requestPermission({ requestMotion: input.requestMotionPermission });
1161
- });
1162
- const initializeCameraActor = fromPromise(async ({ input }) => {
1163
- return initializeIdCapture(input);
1164
- });
1165
- const runDetectionActor = fromCallback(({ input, sendBack }) => {
1166
- if (!input.frameCapturer || !input.provider) {
1167
- sendBack({
1168
- type: "DETECTION_UPDATE",
1169
- status: "error"
1170
- });
1171
- return () => {};
1172
- }
1173
- const provider = input.provider;
1174
- let currentCanvas = null;
1175
- let bestCanvas = null;
1176
- let storedQualityElements = {};
1177
- let isCapturing = false;
1178
- const timer = BrowserTimerProvider.getInstance();
1179
- let notificationTimeout = null;
1180
- let currentNotificationStatus = null;
1181
- let lastReportedSide = null;
1182
- const NOTIFICATION_DURATION_MS = 500;
1183
- const isReportedSideWrong = () => {
1184
- if (!lastReportedSide) return false;
1185
- const detectedSide = lastReportedSide.toLowerCase();
1186
- if (detectedSide === "wrong") return true;
1187
- const isBackDetected = detectedSide.includes("back") && !detectedSide.includes("front");
1188
- const isFrontDetected = detectedSide.includes("front") && !detectedSide.includes("back");
1189
- return input.currentMode === "front" && isBackDetected || input.currentMode === "back" && isFrontDetected;
1190
- };
1191
- const clearNotificationTimeout = () => {
1192
- if (notificationTimeout) {
1193
- timer.clearTimeout(notificationTimeout);
1194
- notificationTimeout = null;
1195
- currentNotificationStatus = null;
1196
- }
1197
- };
1198
- const sendNotification = (status) => {
1199
- if (isReportedSideWrong()) return;
1200
- if (notificationTimeout && currentNotificationStatus !== status) return;
1201
- if (notificationTimeout && currentNotificationStatus === status) timer.clearTimeout(notificationTimeout);
1202
- currentNotificationStatus = status;
1203
- sendBack({
1204
- type: "DETECTION_UPDATE",
1205
- status
1206
- });
1207
- notificationTimeout = timer.setTimeout(() => {
1208
- notificationTimeout = null;
1209
- currentNotificationStatus = null;
1210
- sendBack({
1211
- type: "DETECTION_UPDATE",
1212
- status: "detecting"
1213
- });
1214
- }, NOTIFICATION_DURATION_MS);
1215
- };
1216
- const canvas = input.frameCapturer.getLatestCanvas();
1217
- const windowDimensions = getWindowDimensions(canvas?.width() ?? 1280, canvas?.height() ?? 720);
1218
- const DEFAULT_GEOMETRY = {
1219
- areaDown: 25e3,
1220
- areaUp: 55e3,
1221
- areaIOSPassportUp: 3e4,
1222
- areaIOSPassportDown: 2e4,
1223
- widthIOSUp: 160,
1224
- widthIOSDown: 85,
1225
- widthDown: 110,
1226
- widthUp: 205
1227
- };
1228
- if (input.config.geometry) provider.setGeometry({
1229
- ...input.config.geometry,
1230
- windowOuterWidth: windowDimensions.outerWidth,
1231
- windowOuterHeight: windowDimensions.outerHeight,
1232
- windowInnerWidth: windowDimensions.innerWidth,
1233
- windowInnerHeight: windowDimensions.innerHeight
1234
- });
1235
- else provider.setGeometry({
1236
- ...DEFAULT_GEOMETRY,
1237
- windowOuterWidth: windowDimensions.outerWidth,
1238
- windowOuterHeight: windowDimensions.outerHeight,
1239
- windowInnerWidth: windowDimensions.innerWidth,
1240
- windowInnerHeight: windowDimensions.innerHeight
1241
- });
1242
- const idType = input.currentMode === "back" ? "BackId" : input.currentMode === "passport" ? "Passport" : "FrontId";
1243
- provider.setSettings({
1244
- isFixedMask: input.config.settings?.isFixedMask ?? false,
1245
- isIPhone14OrHigher: input.config.settings?.isIPhone14OrHigher ?? false,
1246
- idType,
1247
- blurCheckEnabled: input.config.settings?.blurCheckEnabled ?? false,
1248
- glareCheckEnabled: input.config.settings?.glareCheckEnabled ?? false,
1249
- faceQualityCheckEnabled: input.config.settings?.faceQualityCheckEnabled ?? true,
1250
- iouCheckEnabled: input.config.settings?.iouCheckEnabled ?? true,
1251
- fpsLimitEnabled: input.config.settings?.fpsLimitEnabled ?? false
1252
- });
1253
- const thresholds = {
1254
- ...DEFAULT_ID_CAPTURE_THRESHOLDS,
1255
- ...input.config.thresholds,
1256
- idDetectedTimeout: (input.config.deviceIdleTimeout ?? 10) * 1e3,
1257
- autocaptureTimeout: (input.config.autoCaptureTimeout ?? 5) * 1e3
1258
- };
1259
- provider.setThresholds(thresholds);
1260
- const modelType = input.config.modelVersion ?? DEFAULT_ID_CAPTURE_MODEL_VERSION;
1261
- provider.setModelType(modelType);
1262
- provider.setCallbacks({
1263
- onFarAway: () => {
1264
- if (!isCapturing) sendNotification("farAway");
1265
- },
1266
- onDetectionStarted: () => {},
1267
- onMaskChange: (_show, _mask, _top, orientation) => {
1268
- sendBack({
1269
- type: "ORIENTATION_CHANGE",
1270
- orientation
1271
- });
1272
- },
1273
- onBlur: () => {
1274
- if (!isCapturing) sendNotification("blur");
1275
- },
1276
- onGlare: () => {
1277
- if (!isCapturing) sendNotification("glare");
1278
- },
1279
- onIdNotDetected: () => {
1280
- if (!isCapturing) sendBack({
1281
- type: "DETECTION_UPDATE",
1282
- status: "idNotDetected"
1283
- });
1284
- },
1285
- onSwitchToManualCapture: () => {
1286
- isCapturing = false;
1287
- sendBack({ type: "SWITCH_TO_MANUAL_CAPTURE" });
1288
- },
1289
- onCapturing: () => {
1290
- clearNotificationTimeout();
1291
- lastReportedSide = null;
1292
- isCapturing = true;
1293
- sendBack({
1294
- type: "DETECTION_UPDATE",
1295
- status: "capturing"
1296
- });
1297
- },
1298
- onBestFrame: (blur, glare, orientation) => {
1299
- if (currentCanvas) {
1300
- bestCanvas = currentCanvas.clone();
1301
- storedQualityElements = {
1302
- glare,
1303
- sharpness: blur
1304
- };
1305
- }
1306
- if (orientation === "horizontal" || orientation === "vertical") sendBack({
1307
- type: "ORIENTATION_CHANGE",
1308
- orientation
1309
- });
1310
- },
1311
- onCapture: () => {
1312
- isCapturing = false;
1313
- if (bestCanvas) sendBack({
1314
- type: "DETECTION_SUCCESS",
1315
- canvas: bestCanvas,
1316
- qualityElements: storedQualityElements
1317
- });
1318
- else if (currentCanvas) sendBack({
1319
- type: "DETECTION_SUCCESS",
1320
- canvas: currentCanvas.clone(),
1321
- qualityElements: {}
1322
- });
1323
- },
1324
- onIdTypeChange: (idType$1) => {
1325
- sendBack({
1326
- type: "ID_TYPE_CHANGE",
1327
- idType: idType$1
1328
- });
1329
- },
1330
- onIdSideChange: (side) => {
1331
- if (isCapturing) return;
1332
- lastReportedSide = side;
1333
- if (isReportedSideWrong()) clearNotificationTimeout();
1334
- sendBack({
1335
- type: "ID_SIDE_CHANGE",
1336
- side
1337
- });
1338
- },
1339
- onCapturingCounterValueChange: (value) => {
1340
- sendBack({
1341
- type: "COUNTER_VALUE_CHANGE",
1342
- value
1343
- });
1344
- }
1345
- });
1346
- sendBack({
1347
- type: "DETECTION_UPDATE",
1348
- status: "detecting"
1349
- });
1350
- const session = new StreamCanvasProcessingSession({
1351
- capturer: input.frameCapturer,
1352
- provider: {
1353
- processFrame: async (frame) => {
1354
- currentCanvas = IncodeCanvas.fromImageData(frame);
1355
- sendBack({
1356
- type: "DETECTION_FRAME",
1357
- frame
1358
- });
1359
- await provider.processFrame(frame);
1360
- },
1361
- reset: () => {
1362
- if (notificationTimeout) {
1363
- timer.clearTimeout(notificationTimeout);
1364
- notificationTimeout = null;
1365
- currentNotificationStatus = null;
1366
- }
1367
- currentCanvas = null;
1368
- bestCanvas = null;
1369
- storedQualityElements = {};
1370
- isCapturing = false;
1371
- lastReportedSide = null;
1372
- provider.reset();
1373
- }
1374
- },
1375
- onFrame: (frame) => sendBack({
1376
- type: "DETECTION_FRAME",
1377
- frame
1378
- })
1379
- });
1380
- sendBack({
1381
- type: "DETECTION_RESET_READY",
1382
- reset: () => {
1383
- provider.reset();
1384
- }
1385
- });
1386
- return () => {
1387
- clearNotificationTimeout();
1388
- session?.dispose();
1389
- };
1390
- });
1391
- const uploadIdImageActor = fromPromise(async ({ input, signal }) => {
1392
- const image = input.canvas.getBase64Image();
1393
- if (!image) throw new Error(ID_ERROR_CODES.UPLOAD_ERROR);
1394
- let metadata;
1395
- if (input.deepsightService) try {
1396
- const sessionToken = getToken();
1397
- const frameSource = input.type === "back" ? "BACK_ID" : "FRONT_ID";
1398
- await input.deepsightService.performVirtualCameraCheck(sessionToken, frameSource);
1399
- const imageData$1 = input.canvas.getImageData();
1400
- if (imageData$1) await input.deepsightService.analyzeFrame(imageData$1);
1401
- const analysisStatus = input.deepsightService.getAnalysisStatus();
1402
- const motionStatus = input.deepsightService.getMotionStatus();
1403
- if (input.type === "front") await addDeviceStats({
1404
- frontIdStatsAnalysisStatus: analysisStatus,
1405
- backIdStatsAnalysisStatus: "",
1406
- selfieStatsAnalysisStatus: "",
1407
- motionStatus
1408
- });
1409
- else await addDeviceStats({
1410
- frontIdStatsAnalysisStatus: "",
1411
- backIdStatsAnalysisStatus: analysisStatus,
1412
- selfieStatsAnalysisStatus: "",
1413
- motionStatus
1414
- });
1415
- metadata = input.deepsightService.getMetadata();
1416
- } catch {}
1417
- const imageData = input.canvas?.getImageData() ?? void 0;
1418
- const logs = input.deepsightService?.getPipelineState() ?? "";
1419
- input.dependencies?.trackCaptureAttemptFinished?.({
1420
- logs,
1421
- resolution: input.captureResolution,
1422
- fallbackLevel: input.cameraFallbackLevel
1423
- });
1424
- return uploadIdImage({
1425
- image,
1426
- type: input.type,
1427
- sendBase64: true,
1428
- glare: input.qualityElements?.glare,
1429
- sharpness: input.qualityElements?.sharpness,
1430
- ageAssurance: input.ageAssurance,
1431
- signal,
1432
- onProgress: input.onProgress,
1433
- metadata,
1434
- analyticsProvider: input.analyticsProvider,
1435
- imageData,
1436
- isSecondId: input.isSecondId,
1437
- onlyFront: input.onlyFront
1438
- });
1439
- });
1440
- const processIdActor = fromPromise(async ({ input, signal }) => {
1441
- return processId(input.isSecondId, "", signal);
1442
- });
1443
- const startRecordingActor = fromPromise(async ({ input }) => {
1444
- if (!input.stream) return;
1445
- const type = input.currentMode === "back" ? "backId" : "frontId";
1446
- return startRecordingSession({
1447
- config: input.config,
1448
- stream: input.stream,
1449
- existing: input.existing,
1450
- type
1451
- });
1452
- });
1453
- const checkMotionSensorActor = fromCallback(({ input, sendBack }) => {
1454
- if (!input.motionProvider) {
1455
- sendBack({
1456
- type: "MOTION_STATUS",
1457
- status: "UNCLEAR"
1458
- });
1459
- return () => {};
1460
- }
1461
- const timer = BrowserTimerProvider.getInstance();
1462
- const interval = timer.setInterval(() => {
1463
- sendBack({
1464
- type: "MOTION_STATUS",
1465
- status: input.motionProvider.check()
1466
- });
1467
- }, 500);
1468
- return () => timer.clearInterval(interval);
1469
- });
1470
- const initializeDeepsightSessionActor = fromPromise(async ({ input }) => {
1471
- if (!input.dependencies) return;
1472
- const { loadDeepsightSession } = await import("./deepsightLoader-Cm4JIT_z.esm.js");
1473
- return loadDeepsightSession({
1474
- ds: input.ds,
1475
- storage: input.dependencies.storage,
1476
- disableIpify: input.disableIpify
1477
- });
1478
- });
1479
- const checkVirtualCameraActor = fromPromise(async ({ input }) => {
1480
- if (!input.deepsightService || !input.stream) return false;
1481
- const videoTrack = input.stream.getVideoTracks()[0];
1482
- if (!videoTrack) return false;
1483
- return input.deepsightService.checkVirtualCamera(videoTrack);
1484
- });
1485
-
1486
- //#endregion
1487
- //#region src/modules/id/idCaptureActions.ts
1488
- function performStopMediaStream(context) {
1489
- context.frameCapturer?.dispose();
1490
- if (context.stream) stopStream(context.stream);
1491
- }
1492
- function performDisposeProvider(context) {
1493
- context.provider?.dispose?.();
1494
- }
1495
- function performCleanupDeepsight(context) {
1496
- context.deepsightService?.cleanup();
1497
- }
1498
- function performResetForBackCapture(context) {
1499
- context.frameCapturer?.dispose();
1500
- if (context.stream) stopStream(context.stream);
1501
- context.provider?.reset();
1502
- }
1503
- function performResetForFrontCapture(context) {
1504
- context.frameCapturer?.dispose();
1505
- if (context.stream) stopStream(context.stream);
1506
- context.provider?.reset();
1507
- }
1508
- function performResetDetection(context) {
1509
- context.resetDetection?.();
1510
- }
1511
- function performTrackTutorialId() {}
1512
- function performTrackContinue() {}
1513
- function performTrackCameraId(context) {}
1514
- function performStopMediaRecording(context) {
1515
- if (context.recordingSession) stopRecording(context.recordingSession);
1516
- }
1517
- function getStreamFromEvent(event) {
1518
- if ("output" in event) return event.output.stream;
1519
- }
1520
- function getProviderFromEvent(event) {
1521
- if ("output" in event) return event.output.provider;
1522
- }
1523
- function getCaptureResolutionFromEvent(event) {
1524
- if ("output" in event) return event.output.captureResolution;
1525
- }
1526
- function getCameraFallbackLevelFromEvent(event) {
1527
- if ("output" in event) return event.output.cameraFallbackLevel;
1528
- }
1529
- function getFrameCapturerFromEvent(event) {
1530
- if ("output" in event) {
1531
- const output = event.output;
1532
- if (output.stream) return new StreamCanvasCapture(output.stream);
1533
- }
1534
- }
1535
- function getResetContextValues(context) {
1536
- context.provider?.reset();
1537
- const currentMode = context.config.onlyBack ? "back" : !context.config.enableId && context.config.enablePassport ? "passport" : context.config.usSmartCapture ? "back" : "front";
1538
- return {
1539
- stream: void 0,
1540
- provider: context.provider,
1541
- frameCapturer: void 0,
1542
- error: void 0,
1543
- detectionStatus: "idle",
1544
- counterValue: 0,
1545
- orientation: void 0,
1546
- capturedImages: {},
1547
- captureOnlyImages: {},
1548
- uploadResponse: void 0,
1549
- recordingSession: void 0,
1550
- attemptsRemaining: context.config.captureAttempts,
1551
- expiredAttempts: 0,
1552
- skipProcessId: false,
1553
- expiredFromUpload: false,
1554
- isDigitalUpload: false,
1555
- exhaustedFromUpload: false,
1556
- forceFinishAfterProcessing: false,
1557
- uploadError: void 0,
1558
- permissionResult: void 0,
1559
- resetDetection: void 0,
1560
- idType: void 0,
1561
- qualityElements: void 0,
1562
- previewImageUrl: void 0,
1563
- uploadProgress: void 0,
1564
- currentMode,
1565
- selectedDocumentType: void 0,
1566
- manualCaptureTriggered: false,
1567
- captureResolution: void 0,
1568
- cameraFallbackLevel: void 0
1569
- };
1570
- }
1571
- function getClearUploadFailureValues(context) {
1572
- if (context.previewImageUrl) revokeObjectURL(context.previewImageUrl);
1573
- return {
1574
- uploadError: void 0,
1575
- detectionStatus: "idle",
1576
- previewImageUrl: void 0,
1577
- uploadProgress: void 0
1578
- };
1579
- }
1580
- function getUploadValidationError(context) {
1581
- if (!context.uploadResponse) return ID_ERROR_CODES.SERVER;
1582
- return validateUploadResponse(context.uploadResponse, {
1583
- skipGlareFront: context.uploadResponse.skipGlareFront,
1584
- skipGlareBack: context.uploadResponse.skipGlareBack
1585
- })?.errorKey ?? ID_ERROR_CODES.SERVER;
1586
- }
1587
- function storeCapturedCanvasInProviderLogic(context, event) {
1588
- let canvas = null;
1589
- if ("canvas" in event && event.canvas) canvas = event.canvas;
1590
- else canvas = context.frameCapturer?.getLatestCanvas() ?? null;
1591
- if (!canvas || !context.provider) return;
1592
- const canvasWidth = canvas.width();
1593
- const canvasHeight = canvas.height();
1594
- if (!canvasWidth || !canvasHeight) return;
1595
- const originalCanvas = canvas;
1596
- let frameRect;
1597
- const { innerWidth: viewportWidth, innerHeight: viewportHeight } = getWindowDimensions();
1598
- if (context.detectionArea) {
1599
- const scaleX = viewportWidth / canvasWidth;
1600
- const scaleY = viewportHeight / canvasHeight;
1601
- const scale = Math.max(scaleX, scaleY);
1602
- const displayedWidth = canvasWidth * scale;
1603
- const displayedHeight = canvasHeight * scale;
1604
- const offsetX = (viewportWidth - displayedWidth) / 2;
1605
- const offsetY = (viewportHeight - displayedHeight) / 2;
1606
- frameRect = {
1607
- x: (context.detectionArea.x - offsetX) / scale,
1608
- y: (context.detectionArea.y - offsetY) / scale,
1609
- w: context.detectionArea.width / scale,
1610
- h: context.detectionArea.height / scale
1611
- };
1612
- } else if (context.frameRect) {
1613
- const scaleX = viewportWidth / canvasWidth;
1614
- const scaleY = viewportHeight / canvasHeight;
1615
- const scale = Math.max(scaleX, scaleY);
1616
- const displayedWidth = canvasWidth * scale;
1617
- const displayedHeight = canvasHeight * scale;
1618
- const offsetX = (viewportWidth - displayedWidth) / 2;
1619
- const offsetY = (viewportHeight - displayedHeight) / 2;
1620
- frameRect = {
1621
- x: (context.frameRect.x - offsetX) / scale,
1622
- y: (context.frameRect.y - offsetY) / scale,
1623
- w: context.frameRect.w / scale,
1624
- h: context.frameRect.h / scale
1625
- };
1626
- } else {
1627
- const quadValue = (context.provider.getLastProcessResult?.())?.quad;
1628
- const hasQuad = !!quadValue;
1629
- const quadSize = quadValue?.size ? quadValue.size() : quadValue?.length ?? 0;
1630
- if (hasQuad && quadSize >= 4 && quadValue.get) {
1631
- const p0 = quadValue.get(0);
1632
- const p1 = quadValue.get(1);
1633
- const p2 = quadValue.get(2);
1634
- const p3 = quadValue.get(3);
1635
- const minX = Math.min(p0.x, p1.x, p2.x, p3.x);
1636
- const maxX = Math.max(p0.x, p1.x, p2.x, p3.x);
1637
- const minY = Math.min(p0.y, p1.y, p2.y, p3.y);
1638
- const maxY = Math.max(p0.y, p1.y, p2.y, p3.y);
1639
- frameRect = {
1640
- x: minX,
1641
- y: minY,
1642
- w: maxX - minX,
1643
- h: maxY - minY
1644
- };
1645
- } else {
1646
- const frameViewportWidth = Math.min(387, viewportWidth * .9);
1647
- const frameViewportHeight = frameViewportWidth / (35 / 22);
1648
- const frameViewportX = (viewportWidth - frameViewportWidth) / 2;
1649
- const frameViewportY = (viewportHeight - frameViewportHeight) / 2;
1650
- frameRect = {
1651
- x: canvasWidth * frameViewportX / viewportWidth,
1652
- y: canvasHeight * frameViewportY / viewportHeight,
1653
- w: canvasWidth * frameViewportWidth / viewportWidth,
1654
- h: canvasHeight * frameViewportHeight / viewportHeight
1655
- };
1656
- }
1657
- }
1658
- const transformedCanvas = context.provider.transformPerspective(originalCanvas, frameRect);
1659
- context.provider.setCapturedCanvases(originalCanvas, transformedCanvas);
1660
- }
1661
- function getStoreCapturedImageValues(context, event) {
1662
- if (!context.currentMode) return {
1663
- capturedImages: context.capturedImages,
1664
- previewImageUrl: context.previewImageUrl
1665
- };
1666
- const transformedCanvas = context.provider?.getCapturedCanvas();
1667
- const transformedImage = transformedCanvas?.getBase64Image(1, true);
1668
- let fallbackImage = "";
1669
- if ("output" in event) fallbackImage = event.output.originalImage ?? "";
1670
- const imageData = { imageBase64: transformedImage ?? fallbackImage };
1671
- let capturedImages = context.capturedImages;
1672
- if (context.currentMode === "front" || context.currentMode === "passport") capturedImages = {
1673
- ...context.capturedImages,
1674
- front: imageData
1675
- };
1676
- else capturedImages = {
1677
- ...context.capturedImages,
1678
- back: imageData
1679
- };
1680
- let previewImageUrl = context.previewImageUrl;
1681
- if (transformedCanvas) {
1682
- transformedCanvas.updateBlob();
1683
- const blobData = transformedCanvas.getBlobData();
1684
- if (blobData?.url) previewImageUrl = blobData.url;
1685
- } else if ("canvas" in event && event.canvas) {
1686
- const canvas = event.canvas;
1687
- canvas.updateBlob();
1688
- const blobData = canvas.getBlobData();
1689
- if (blobData?.url) previewImageUrl = blobData.url;
1690
- }
1691
- return {
1692
- capturedImages,
1693
- previewImageUrl
1694
- };
1695
- }
1696
- function getDetectionStatusFromUpdate(context, event) {
1697
- if (event.type === "DETECTION_UPDATE") {
1698
- const newStatus = event.status;
1699
- const currentStatus = context.detectionStatus;
1700
- if (currentStatus === "wrongSide") {
1701
- if (!(newStatus === "capturing" || newStatus === "manualCapture" || newStatus === "offline")) return currentStatus;
1702
- return newStatus;
1703
- }
1704
- if ((newStatus === "blur" || newStatus === "glare") && currentStatus === "farAway") return currentStatus;
1705
- if ((newStatus === "wrongSide" || newStatus === "farAway") && (currentStatus === "blur" || currentStatus === "glare")) return newStatus;
1706
- return newStatus;
1707
- }
1708
- return "idle";
1709
- }
1710
- function getDetectionStatusFromSideChange(context, side) {
1711
- const detectedSide = side?.toLowerCase() || "";
1712
- const currentMode = context.currentMode;
1713
- if (detectedSide === "wrong") return "wrongSide";
1714
- const isBackDetected = detectedSide.includes("back") && !detectedSide.includes("front");
1715
- const isFrontDetected = detectedSide.includes("front") && !detectedSide.includes("back");
1716
- if (currentMode === "front" && isBackDetected || currentMode === "back" && isFrontDetected) return "wrongSide";
1717
- if (currentMode === "front" && isFrontDetected || currentMode === "back" && isBackDetected || currentMode === "passport") return "detecting";
1718
- return "detecting";
1719
- }
1720
- function getCurrentModeFromEvent(context, event) {
1721
- if ("documentType" in event) {
1722
- if (event.documentType === "passport") return "passport";
1723
- return context.config.usSmartCapture ? "back" : "front";
1724
- }
1725
- if (event.type === "FRONT_COMPLETE") return "back";
1726
- return context.currentMode;
1727
- }
1728
-
1729
- //#endregion
1730
- //#region src/modules/id/idCaptureGuards.ts
1731
- const hasShowTutorialGuard = ({ context }) => context.config.showTutorial;
1732
- const hasAgeAssuranceGuard = ({ context }) => context.config.ageAssurance === true;
1733
- const hasShowDocumentChooserGuard = ({ context }) => !context.config.onlyBack && (context.config.showDocumentChooserScreen ?? false);
1734
- const isPermissionGrantedGuard = ({ event }) => {
1735
- if ("output" in event) return event.output === "granted";
1736
- return false;
1737
- };
1738
- const isPermissionDeniedErrorGuard = ({ event }) => {
1739
- if ("error" in event) {
1740
- const error = event.error;
1741
- return error?.name === "NotAllowedError" || error?.name === "PermissionDeniedError";
1742
- }
1743
- return false;
1744
- };
1745
- const hasStreamGuard = ({ context }) => context.stream !== void 0;
1746
- const hasAttemptsRemainingGuard = ({ context }) => context.attemptsRemaining > 0;
1747
- const hasCapturedImageGuard = ({ context }) => {
1748
- return context.provider?.getCapturedCanvas() !== null;
1749
- };
1750
- const hasUploadValidationErrorGuard = ({ context }) => {
1751
- if (!context.uploadResponse) return false;
1752
- return validateUploadResponse(context.uploadResponse, {
1753
- skipGlareFront: context.uploadResponse.skipGlareFront,
1754
- skipGlareBack: context.uploadResponse.skipGlareBack
1755
- }) !== void 0;
1756
- };
1757
- const isFrontModeGuard = ({ context }) => context.currentMode === "front" || context.currentMode === "passport";
1758
- /**
1759
- * `config.onlyFront` from the orchestrated flow JSON is intentionally not
1760
- * read here: the flow value cannot account for per-document overrides, so the
1761
- * backend resolves the real policy per document at upload time
1762
- * (via `skipBackIdCapture` on the upload response). Standalone
1763
- * `idCaptureManager` consumers that pass `onlyFront: true` directly will
1764
- * therefore also be ignored — re-wire this guard if that capability is needed
1765
- * again.
1766
- */
1767
- const isOnlyFrontGuard = (_args) => false;
1768
- const shouldContinueToBackGuard = ({ context }) => {
1769
- if (context.currentMode !== "front" && context.currentMode !== "passport") return false;
1770
- if (context.config.onlyBack) return false;
1771
- if (context.config.usSmartCapture) return false;
1772
- if (context.uploadResponse?.skipBackIdCapture) {
1773
- if (!(context.config.alwaysCaptureBackOfId === true && context.currentMode !== "passport")) return false;
1774
- }
1775
- return true;
1776
- };
1777
- const shouldContinueToFrontGuard = ({ context }) => context.config.usSmartCapture === true && context.currentMode === "back" && context.uploadResponse?.forceFrontIdCapture === true;
1778
- const hasMandatoryConsentGuard = ({ context }) => context.uploadResponse?.showMandatoryConsent === true;
1779
- const isDeepsightEnabledGuard = ({ context }) => context.dependencies !== void 0;
1780
- const isDeepsightReadyGuard = ({ context }) => context.deepsightService !== void 0;
1781
- const needsDeepsightInitGuard = ({ context }) => context.dependencies !== void 0 && context.deepsightService === void 0 && !context.deepsightInitAttempted;
1782
- const hasOnlyManualUploadAvailableGuard = ({ context }) => context.availableDocumentTypes.length === 1 && context.availableDocumentTypes[0] === "manualIdUpload";
1783
- const isManualIdUploadSelectedGuard = ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "manualIdUpload";
1784
- const isDigitalIdUploadSelectedGuard = ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "digitalIdUpload";
1785
- const isUploadExpiredGuard = ({ context }) => context.uploadResponse?.isDocumentExpired === true;
1786
- /**
1787
- * True when *this* expired upload will exhaust the budget. Compares the
1788
- * post-increment count, so the exhaustion branch can be picked in the same
1789
- * tick that runs `incrementExpiredAttempts`. With `captureAttempts=3`:
1790
- * - attempt 1 → 0+1=1 (not exhausted)
1791
- * - attempt 2 → 1+1=2 (not exhausted)
1792
- * - attempt 3 → 2+1=3 (exhausted, force-back / finish)
1793
- */
1794
- const isExpiredAttemptsExhaustedGuard = ({ context }) => context.expiredAttempts + 1 >= context.config.captureAttempts;
1795
- const isNotPassportModeGuard = ({ context }) => context.currentMode !== "passport";
1796
- /**
1797
- * V1 parity for `shouldApplyAlwaysCaptureBackOverride` — force-redirects to
1798
- * back capture after expired-front-attempts exhaust, but only when:
1799
- * - we're on the front side
1800
- * - `alwaysCaptureBackOfId` is set
1801
- * - the flow isn't single-side (onlyBack / usSmartCapture)
1802
- * - the session isn't a Digital ID upload (digital IDs are PDFs — no back
1803
- * side exists, so the override never applies regardless of config)
1804
- */
1805
- const shouldForceBackOnExpiredGuard = ({ context }) => context.currentMode === "front" && context.config.alwaysCaptureBackOfId === true && !context.config.onlyBack && !context.config.usSmartCapture && !context.isDigitalUpload;
1806
- const wasExpiredFromUploadGuard = ({ context }) => context.expiredFromUpload === true;
1807
- const shouldSkipProcessIdGuard = ({ context }) => context.skipProcessId === true;
1808
- /**
1809
- * Bug 4 fix: when `expiredExhausted` is reached via the per-upload-expired
1810
- * exhaustion path with a back side captured (or the entire single-side back
1811
- * flow), we want `processId` to run once on Continue so the backend
1812
- * processes whatever sides were uploaded. Front-only exhaustion (no back to
1813
- * process) and the force-back V1 path keep using `setSkipProcessId` instead.
1814
- */
1815
- const shouldProcessAfterExhaustionGuard = ({ context }) => context.exhaustedFromUpload === true && context.currentMode === "back";
1816
- /**
1817
- * `processing.onDone` reads this to short-circuit straight to `finished`
1818
- * after the post-exhaustion `processId` call returns — without it, an
1819
- * `isDocumentExpired:true` response would loop back to the Expired screen
1820
- * we just terminated.
1821
- */
1822
- const forceFinishAfterProcessingGuard = ({ context }) => context.forceFinishAfterProcessing === true;
1823
- /**
1824
- * Cap on the end-of-flow expired path. All capture types (camera, digital,
1825
- * manual) share `config.captureAttempts` for consistency — the user-visible
1826
- * "X attempts remaining" counter is the same regardless of how the document
1827
- * was submitted.
1828
- */
1829
- const isProcessingExpiredExhaustedGuard = ({ context }) => context.processingExpiredAttempts + 1 >= context.config.captureAttempts;
1830
-
1831
- //#endregion
1832
- //#region src/modules/id/idCaptureStateMachine.ts
1833
- function getIdErrorCodeFromUnknown(error) {
1834
- if (error instanceof Error) {
1835
- const message = error.message;
1836
- return Object.values(ID_ERROR_CODES).find((value) => message.includes(value));
1837
- }
1838
- }
1839
- const _idCaptureMachine = setup({
1840
- types: {
1841
- context: {},
1842
- events: {},
1843
- input: {}
1844
- },
1845
- actors: {
1846
- checkPermission: checkPermissionActor,
1847
- requestPermission: requestPermissionActor,
1848
- initializeCamera: initializeCameraActor,
1849
- runDetection: runDetectionActor,
1850
- uploadIdImage: uploadIdImageActor,
1851
- processId: processIdActor,
1852
- startRecording: startRecordingActor,
1853
- checkMotionSensor: checkMotionSensorActor,
1854
- initializeDeepsightSession: initializeDeepsightSessionActor,
1855
- checkVirtualCamera: checkVirtualCameraActor,
1856
- manualUploadMachine,
1857
- digitalUploadMachine
1858
- },
1859
- actions: {
1860
- stopMediaStream: assign(({ context }) => {
1861
- performStopMediaStream(context);
1862
- return {
1863
- stream: void 0,
1864
- frameCapturer: void 0
1865
- };
1866
- }),
1867
- disposeProvider: ({ context }) => {
1868
- performDisposeProvider(context);
1869
- },
1870
- cleanupDeepsight: ({ context }) => {
1871
- performCleanupDeepsight(context);
1872
- },
1873
- flagIdManualReview: () => {
1874
- flagIdManualReview();
1875
- },
1876
- resetForBackCapture: assign(({ context }) => {
1877
- performResetForBackCapture(context);
1878
- return {
1879
- stream: void 0,
1880
- frameCapturer: void 0,
1881
- detectionStatus: "idle",
1882
- counterValue: 0,
1883
- orientation: void 0,
1884
- resetDetection: void 0,
1885
- idType: void 0,
1886
- qualityElements: void 0,
1887
- debugFrame: void 0,
1888
- frameRect: void 0,
1889
- previewImageUrl: void 0,
1890
- uploadProgress: void 0,
1891
- manualCaptureTriggered: false,
1892
- attemptsRemaining: context.config.captureAttempts,
1893
- expiredAttempts: 0,
1894
- expiredFromUpload: false,
1895
- exhaustedFromUpload: false,
1896
- forceFinishAfterProcessing: false,
1897
- captureResolution: void 0,
1898
- cameraFallbackLevel: void 0
1899
- };
1900
- }),
1901
- resetForFrontCapture: assign(({ context }) => {
1902
- performResetForFrontCapture(context);
1903
- return {
1904
- stream: void 0,
1905
- frameCapturer: void 0,
1906
- detectionStatus: "idle",
1907
- counterValue: 0,
1908
- orientation: void 0,
1909
- resetDetection: void 0,
1910
- idType: void 0,
1911
- qualityElements: void 0,
1912
- debugFrame: void 0,
1913
- frameRect: void 0,
1914
- previewImageUrl: void 0,
1915
- uploadProgress: void 0,
1916
- manualCaptureTriggered: false,
1917
- attemptsRemaining: context.config.captureAttempts,
1918
- expiredAttempts: 0,
1919
- expiredFromUpload: false,
1920
- exhaustedFromUpload: false,
1921
- forceFinishAfterProcessing: false,
1922
- captureResolution: void 0,
1923
- cameraFallbackLevel: void 0
1924
- };
1925
- }),
1926
- prepareForBackCapture: assign(({ context }) => {
1927
- context.provider?.reset();
1928
- return {
1929
- detectionStatus: "idle",
1930
- counterValue: 0,
1931
- orientation: void 0,
1932
- resetDetection: void 0,
1933
- idType: void 0,
1934
- qualityElements: void 0,
1935
- debugFrame: void 0,
1936
- frameRect: void 0,
1937
- previewImageUrl: void 0,
1938
- uploadProgress: void 0,
1939
- manualCaptureTriggered: false,
1940
- attemptsRemaining: context.config.captureAttempts
1941
- };
1942
- }),
1943
- setStreamAndCapturer: assign({
1944
- stream: ({ event }) => getStreamFromEvent(event),
1945
- provider: ({ event }) => getProviderFromEvent(event),
1946
- frameCapturer: ({ event }) => getFrameCapturerFromEvent(event),
1947
- captureResolution: ({ event }) => getCaptureResolutionFromEvent(event),
1948
- cameraFallbackLevel: ({ event }) => getCameraFallbackLevelFromEvent(event)
1949
- }),
1950
- trackTutorialId: () => {
1951
- /* @__PURE__ */ performTrackTutorialId();
1952
- },
1953
- trackContinue: () => {
1954
- /* @__PURE__ */ performTrackContinue();
1955
- },
1956
- trackCameraId: ({ context }) => {
1957
- /* @__PURE__ */ performTrackCameraId(context);
1958
- },
1959
- preloadRecordingProvider: ({ context }) => {
1960
- preloadIdRecordingProvider(context.config);
1961
- },
1962
- resetContext: assign(({ context }) => getResetContextValues(context)),
1963
- resetDetection: ({ context }) => {
1964
- performResetDetection(context);
1965
- },
1966
- captureImage: assign({ qualityElements: ({ event }) => {
1967
- if ("qualityElements" in event) return event.qualityElements;
1968
- } }),
1969
- storeCapturedCanvasInProvider: ({ context, event }) => {
1970
- storeCapturedCanvasInProviderLogic(context, event);
1971
- },
1972
- captureLatestFrame: ({ context }) => {
1973
- context.frameCapturer?.getLatestCanvas();
1974
- },
1975
- clearUploadFailure: assign(({ context }) => getClearUploadFailureValues(context)),
1976
- clearStreamForRetry: assign(({ context }) => {
1977
- performStopMediaStream(context);
1978
- performDisposeProvider(context);
1979
- return {
1980
- stream: void 0,
1981
- provider: void 0,
1982
- frameCapturer: void 0,
1983
- captureResolution: void 0,
1984
- cameraFallbackLevel: void 0
1985
- };
1986
- }),
1987
- decrementAttemptsRemaining: assign(({ context }) => ({ attemptsRemaining: context.attemptsRemaining - 1 })),
1988
- setUploadErrorFromUploadValidation: assign({ uploadError: ({ context }) => getUploadValidationError(context) }),
1989
- stopMediaRecording: ({ context }) => {
1990
- performStopMediaRecording(context);
1991
- },
1992
- clearRecordingSession: assign({ recordingSession: () => void 0 }),
1993
- setSelectedDocument: assign({ selectedDocumentType: ({ event }) => {
1994
- if ("documentType" in event) return event.documentType;
1995
- } }),
1996
- setCurrentMode: assign({ currentMode: ({ event, context }) => getCurrentModeFromEvent(context, event) }),
1997
- storeCapturedImage: assign(({ context, event }) => getStoreCapturedImageValues(context, event)),
1998
- setDetectionStatus: assign({ detectionStatus: ({ event, context }) => getDetectionStatusFromUpdate(context, event) }),
1999
- setCounterValue: assign({ counterValue: ({ event }) => {
2000
- if ("value" in event) return event.value;
2001
- return 0;
2002
- } }),
2003
- setIdType: assign({ idType: ({ event }) => {
2004
- if ("idType" in event) return event.idType;
2005
- } }),
2006
- setOrientation: assign({ orientation: ({ event }) => {
2007
- if ("orientation" in event) return event.orientation;
2008
- } }),
2009
- setFrameRect: assign({ frameRect: ({ event }) => {
2010
- if ("frameRect" in event) return event.frameRect;
2011
- } }),
2012
- setDetectionArea: assign({ detectionArea: ({ event }) => {
2013
- if ("detectionArea" in event) return event.detectionArea;
2014
- } }),
2015
- setMotionStatus: assign({ motionStatus: ({ event }) => {
2016
- if ("status" in event && event.type === "MOTION_STATUS") return event.status;
2017
- } }),
2018
- incrementExpiredAttempts: assign(({ context }) => ({ expiredAttempts: context.expiredAttempts + 1 })),
2019
- storeDigitalUploadResponse: assign(({ self }) => {
2020
- const response = ((self.getSnapshot().children?.["digitalIdUpload"]?.getSnapshot())?.context)?.response;
2021
- if (!response) return { isDigitalUpload: true };
2022
- return {
2023
- uploadResponse: response,
2024
- isDigitalUpload: true
2025
- };
2026
- }),
2027
- incrementProcessingExpiredAttempts: assign(({ context }) => ({ processingExpiredAttempts: context.processingExpiredAttempts + 1 })),
2028
- setSkipProcessId: assign({ skipProcessId: () => true }),
2029
- setExpiredFromUpload: assign({ expiredFromUpload: () => true }),
2030
- setExhaustedFromUpload: assign({ exhaustedFromUpload: () => true }),
2031
- setForceFinishAfterProcessing: assign({ forceFinishAfterProcessing: () => true }),
2032
- clearExpiredFromUpload: assign({ expiredFromUpload: () => false })
2033
- },
2034
- guards: {
2035
- hasShowTutorial: hasShowTutorialGuard,
2036
- hasAgeAssurance: hasAgeAssuranceGuard,
2037
- hasShowDocumentChooser: hasShowDocumentChooserGuard,
2038
- isPermissionGranted: isPermissionGrantedGuard,
2039
- isPermissionDeniedError: isPermissionDeniedErrorGuard,
2040
- hasStream: hasStreamGuard,
2041
- hasAttemptsRemaining: hasAttemptsRemainingGuard,
2042
- hasCapturedImage: hasCapturedImageGuard,
2043
- hasUploadValidationError: hasUploadValidationErrorGuard,
2044
- isFrontMode: isFrontModeGuard,
2045
- isOnlyFront: isOnlyFrontGuard,
2046
- shouldContinueToBack: shouldContinueToBackGuard,
2047
- shouldContinueToFront: shouldContinueToFrontGuard,
2048
- hasMandatoryConsent: hasMandatoryConsentGuard,
2049
- isDeepsightEnabled: isDeepsightEnabledGuard,
2050
- isDeepsightReady: isDeepsightReadyGuard,
2051
- needsDeepsightInit: needsDeepsightInitGuard,
2052
- hasOnlyManualUploadAvailable: hasOnlyManualUploadAvailableGuard,
2053
- isManualIdUploadSelected: isManualIdUploadSelectedGuard,
2054
- isDigitalIdUploadSelected: isDigitalIdUploadSelectedGuard,
2055
- isUploadExpired: isUploadExpiredGuard,
2056
- isExpiredAttemptsExhausted: isExpiredAttemptsExhaustedGuard,
2057
- isNotPassportMode: isNotPassportModeGuard,
2058
- shouldForceBackOnExpired: shouldForceBackOnExpiredGuard,
2059
- wasExpiredFromUpload: wasExpiredFromUploadGuard,
2060
- shouldSkipProcessId: shouldSkipProcessIdGuard,
2061
- isProcessingExpiredExhausted: isProcessingExpiredExhaustedGuard,
2062
- shouldProcessAfterExhaustion: shouldProcessAfterExhaustionGuard,
2063
- forceFinishAfterProcessing: forceFinishAfterProcessingGuard,
2064
- isManualUploadExhausted: ({ event }) => event.output?.result === "exhausted",
2065
- isDigitalUploadExhausted: ({ event }) => event.output?.result === "exhausted",
2066
- isDigitalUploadClosed: ({ event }) => event.output?.result === "closed",
2067
- isDigitalUploadSuccessful: ({ event }) => event.output?.result === "success"
2068
- }
2069
- }).createMachine({
2070
- id: "idCapture",
2071
- initial: "idle",
2072
- context: ({ input }) => {
2073
- const currentMode = input.config.onlyBack ? "back" : !input.config.enableId && input.config.enablePassport ? "passport" : input.config.usSmartCapture ? "back" : "front";
2074
- return {
2075
- config: input.config,
2076
- currentMode,
2077
- selectedDocumentType: void 0,
2078
- stream: void 0,
2079
- provider: void 0,
2080
- frameCapturer: void 0,
2081
- error: void 0,
2082
- detectionStatus: "idle",
2083
- counterValue: 0,
2084
- orientation: void 0,
2085
- capturedImages: {},
2086
- captureOnlyImages: {},
2087
- uploadResponse: void 0,
2088
- recordingSession: void 0,
2089
- attemptsRemaining: input.config.captureAttempts,
2090
- expiredAttempts: 0,
2091
- processingExpiredAttempts: 0,
2092
- skipProcessId: input.config.skipProcessId === true,
2093
- expiredFromUpload: false,
2094
- isDigitalUpload: false,
2095
- exhaustedFromUpload: false,
2096
- forceFinishAfterProcessing: false,
2097
- uploadError: void 0,
2098
- permissionResult: void 0,
2099
- resetDetection: void 0,
2100
- idType: void 0,
2101
- qualityElements: void 0,
2102
- debugFrame: void 0,
2103
- frameRect: void 0,
2104
- detectionArea: void 0,
2105
- previewImageUrl: void 0,
2106
- uploadProgress: void 0,
2107
- motionStatus: void 0,
2108
- manualCaptureTriggered: false,
2109
- deepsightService: void 0,
2110
- analyticsProvider: input.analyticsProvider,
2111
- dependencies: input.dependencies,
2112
- disableIpify: getDisableIpify(),
2113
- deepsightInitAttempted: false,
2114
- availableDocumentTypes: getAvailableDocumentTypes(input.config),
2115
- captureResolution: void 0,
2116
- cameraFallbackLevel: void 0
2117
- };
2118
- },
2119
- on: {
2120
- QUIT: { target: "#idCapture.closed" },
2121
- UPDATE_DETECTION_AREA: { actions: "setDetectionArea" }
2122
- },
2123
- states: {
2124
- idle: { on: { LOAD: [
2125
- {
2126
- target: "manualIdUpload",
2127
- guard: "hasOnlyManualUploadAvailable"
2128
- },
2129
- {
2130
- target: "chooser",
2131
- guard: "hasShowDocumentChooser"
2132
- },
2133
- {
2134
- target: "ageVerification",
2135
- guard: "hasAgeAssurance"
2136
- },
2137
- {
2138
- target: "tutorial",
2139
- guard: "hasShowTutorial"
2140
- },
2141
- { target: "loading" }
2142
- ] } },
2143
- chooser: { on: { SELECT_DOCUMENT: [
2144
- {
2145
- target: "digitalIdUpload",
2146
- guard: "isDigitalIdUploadSelected",
2147
- actions: ["setSelectedDocument"]
2148
- },
2149
- {
2150
- target: "manualIdUpload",
2151
- guard: "isManualIdUploadSelected",
2152
- actions: ["setSelectedDocument"]
2153
- },
2154
- {
2155
- target: "ageVerification",
2156
- guard: "hasAgeAssurance",
2157
- actions: ["setSelectedDocument", "setCurrentMode"]
2158
- },
2159
- {
2160
- target: "tutorial",
2161
- guard: "hasShowTutorial",
2162
- actions: ["setSelectedDocument", "setCurrentMode"]
2163
- },
2164
- {
2165
- target: "loading",
2166
- actions: ["setSelectedDocument", "setCurrentMode"]
2167
- }
2168
- ] } },
2169
- ageVerification: { on: { NEXT_STEP: [{
2170
- target: "tutorial",
2171
- guard: "hasShowTutorial",
2172
- actions: "trackContinue"
2173
- }, {
2174
- target: "loading",
2175
- actions: "trackContinue"
2176
- }] } },
2177
- loading: {
2178
- entry: "preloadRecordingProvider",
2179
- type: "parallel",
2180
- states: {
2181
- permissionCheck: {
2182
- initial: "checking",
2183
- states: {
2184
- checking: { invoke: {
2185
- id: "checkPermissionLoading",
2186
- src: "checkPermission",
2187
- onDone: {
2188
- target: "done",
2189
- actions: assign({ permissionResult: ({ event }) => event.output })
2190
- },
2191
- onError: {
2192
- target: "done",
2193
- actions: assign({ permissionResult: () => "prompt" })
2194
- }
2195
- } },
2196
- done: { type: "final" }
2197
- }
2198
- },
2199
- deepsightInit: {
2200
- initial: "initializing",
2201
- states: {
2202
- initializing: { invoke: {
2203
- id: "initDeepsightLoading",
2204
- src: "initializeDeepsightSession",
2205
- input: ({ context }) => ({
2206
- ds: context.config.ds,
2207
- dependencies: context.dependencies,
2208
- disableIpify: context.disableIpify
2209
- }),
2210
- onDone: {
2211
- target: "done",
2212
- actions: assign({
2213
- deepsightService: ({ event }) => event.output,
2214
- deepsightInitAttempted: () => true
2215
- })
2216
- },
2217
- onError: {
2218
- target: "done",
2219
- actions: [assign({ deepsightInitAttempted: () => true }), () => console.warn("Deepsight initialization failed")]
2220
- }
2221
- } },
2222
- done: { type: "final" }
2223
- }
2224
- }
2225
- },
2226
- onDone: [{
2227
- target: "capture",
2228
- guard: "isPermissionGranted"
2229
- }, { target: "permissions" }]
2230
- },
2231
- tutorial: {
2232
- initial: "checkingPermission",
2233
- entry: ["trackTutorialId", "preloadRecordingProvider"],
2234
- states: {
2235
- checkingPermission: {
2236
- invoke: {
2237
- id: "checkPermissionTutorial",
2238
- src: "checkPermission",
2239
- onDone: [{
2240
- target: "initializingCamera",
2241
- guard: "isPermissionGranted",
2242
- actions: assign({ permissionResult: ({ event }) => event.output })
2243
- }, {
2244
- target: "ready",
2245
- actions: assign({ permissionResult: ({ event }) => event.output })
2246
- }]
2247
- },
2248
- on: { NEXT_STEP: {
2249
- target: "#idCapture.capture",
2250
- actions: "trackContinue"
2251
- } }
2252
- },
2253
- initializingCamera: {
2254
- type: "parallel",
2255
- states: {
2256
- cameraInit: {
2257
- initial: "initializingDeepsight",
2258
- states: {
2259
- initializingDeepsight: { invoke: {
2260
- id: "tutorialInitDeepsight",
2261
- src: "initializeDeepsightSession",
2262
- input: ({ context }) => ({
2263
- ds: context.config.ds,
2264
- dependencies: context.dependencies,
2265
- disableIpify: context.disableIpify
2266
- }),
2267
- onDone: {
2268
- target: "initializingStream",
2269
- actions: assign({
2270
- deepsightService: ({ event }) => event.output,
2271
- deepsightInitAttempted: () => true
2272
- })
2273
- },
2274
- onError: {
2275
- target: "initializingStream",
2276
- actions: [assign({ deepsightInitAttempted: () => true }), () => console.warn("Deepsight initialization failed in tutorial")]
2277
- }
2278
- } },
2279
- initializingStream: { invoke: {
2280
- id: "tutorialInitCamera",
2281
- src: "initializeCamera",
2282
- input: ({ context }) => ({
2283
- config: context.config,
2284
- deepsightService: context.deepsightService
2285
- }),
2286
- onDone: {
2287
- target: "ready",
2288
- actions: "setStreamAndCapturer"
2289
- },
2290
- onError: [{
2291
- target: "#idCapture.tutorial.ready",
2292
- guard: "isPermissionDeniedError",
2293
- actions: assign({ permissionResult: () => {
2294
- return "denied";
2295
- } })
2296
- }, {
2297
- target: "#idCapture.tutorial.ready",
2298
- actions: assign({ error: ({ event }) => String(event.error) })
2299
- }]
2300
- } },
2301
- ready: { type: "final" }
2302
- }
2303
- },
2304
- userIntent: {
2305
- initial: "booting",
2306
- states: {
2307
- booting: { on: { NEXT_STEP: {
2308
- target: "clicked",
2309
- actions: "trackContinue"
2310
- } } },
2311
- clicked: { type: "final" }
2312
- }
2313
- }
2314
- },
2315
- onDone: { target: "#idCapture.capture" }
2316
- },
2317
- ready: { on: { NEXT_STEP: {
2318
- target: "waitingForPermission",
2319
- actions: "trackContinue"
2320
- } } },
2321
- waitingForPermission: { invoke: {
2322
- id: "checkPermissionWaiting",
2323
- src: "checkPermission",
2324
- onDone: [{
2325
- target: "#idCapture.capture",
2326
- guard: "isPermissionGranted",
2327
- actions: assign({ permissionResult: ({ event }) => event.output })
2328
- }, {
2329
- target: "#idCapture.permissions",
2330
- actions: assign({ permissionResult: ({ event }) => event.output })
2331
- }]
2332
- } }
2333
- }
2334
- },
2335
- permissions: {
2336
- entry: "preloadRecordingProvider",
2337
- initial: "idle",
2338
- states: {
2339
- idle: {
2340
- invoke: {
2341
- id: "checkPermissionIdle",
2342
- src: "checkPermission",
2343
- onDone: [
2344
- {
2345
- target: "#idCapture.capture",
2346
- guard: "isPermissionGranted",
2347
- actions: assign({ permissionResult: ({ event }) => event.output })
2348
- },
2349
- {
2350
- target: "denied",
2351
- guard: ({ event }) => event.output === "denied",
2352
- actions: assign({ permissionResult: ({ event }) => event.output })
2353
- },
2354
- {
2355
- target: "waitingForUser",
2356
- actions: assign({ permissionResult: ({ event }) => event.output })
2357
- }
2358
- ],
2359
- onError: {
2360
- target: "waitingForUser",
2361
- actions: assign({ permissionResult: () => "prompt" })
2362
- }
2363
- },
2364
- on: {
2365
- REQUEST_PERMISSION: "requesting",
2366
- GO_TO_LEARN_MORE: "learnMore"
2367
- }
2368
- },
2369
- waitingForUser: { on: {
2370
- REQUEST_PERMISSION: "requesting",
2371
- GO_TO_LEARN_MORE: "learnMore"
2372
- } },
2373
- learnMore: { on: {
2374
- BACK: "idle",
2375
- REQUEST_PERMISSION: "requesting"
2376
- } },
2377
- requesting: { invoke: {
2378
- id: "requestPermission",
2379
- src: "requestPermission",
2380
- input: ({ context }) => ({ requestMotionPermission: context.config.ds === true }),
2381
- onDone: [
2382
- {
2383
- target: "#idCapture.capture",
2384
- guard: "isPermissionGranted",
2385
- actions: assign({ permissionResult: ({ event }) => event.output })
2386
- },
2387
- {
2388
- target: "denied",
2389
- guard: ({ event }) => event.output === "denied",
2390
- actions: assign({ permissionResult: ({ event }) => event.output })
2391
- },
2392
- {
2393
- target: "idle",
2394
- actions: assign({ permissionResult: ({ event }) => event.output })
2395
- }
2396
- ],
2397
- onError: { target: "denied" }
2398
- } },
2399
- denied: { entry: assign({ permissionResult: () => "refresh" }) }
2400
- }
2401
- },
2402
- capture: {
2403
- initial: "checkingStream",
2404
- entry: ["trackCameraId", "preloadRecordingProvider"],
2405
- exit: ["stopMediaRecording", "clearRecordingSession"],
2406
- on: { SET_FRAME_RECT: { actions: "setFrameRect" } },
2407
- states: {
2408
- checkingStream: { always: [
2409
- {
2410
- target: "initializingDeepsight",
2411
- guard: "needsDeepsightInit"
2412
- },
2413
- {
2414
- target: "detecting",
2415
- guard: "hasStream"
2416
- },
2417
- { target: "initializing" }
2418
- ] },
2419
- initializingDeepsight: { invoke: {
2420
- id: "initDeepsightCapture",
2421
- src: "initializeDeepsightSession",
2422
- input: ({ context }) => ({
2423
- ds: context.config.ds,
2424
- dependencies: context.dependencies,
2425
- disableIpify: context.disableIpify
2426
- }),
2427
- onDone: {
2428
- target: "checkingStream",
2429
- actions: assign({
2430
- deepsightService: ({ event }) => event.output,
2431
- deepsightInitAttempted: () => true
2432
- })
2433
- },
2434
- onError: {
2435
- target: "checkingStream",
2436
- actions: [assign({ deepsightInitAttempted: () => true }), () => console.warn("Deepsight initialization failed in capture")]
2437
- }
2438
- } },
2439
- initializing: { invoke: {
2440
- id: "initializeCamera",
2441
- src: "initializeCamera",
2442
- input: ({ context }) => ({
2443
- config: context.config,
2444
- deepsightService: context.deepsightService
2445
- }),
2446
- onDone: {
2447
- target: "detecting",
2448
- actions: "setStreamAndCapturer"
2449
- },
2450
- onError: [{
2451
- target: "#idCapture.permissions",
2452
- guard: "isPermissionDeniedError",
2453
- actions: assign({ permissionResult: () => "denied" })
2454
- }, {
2455
- target: "#idCapture.error",
2456
- actions: assign({ error: ({ event }) => String(event.error) })
2457
- }]
2458
- } },
2459
- detecting: {
2460
- always: [{
2461
- target: "manualCaptureWaiting",
2462
- guard: ({ context }) => context.manualCaptureTriggered,
2463
- actions: assign({ detectionStatus: () => "manualCapture" })
2464
- }],
2465
- entry: [assign({ detectionStatus: () => "detecting" })],
2466
- invoke: [{
2467
- id: "startRecording",
2468
- src: "startRecording",
2469
- input: ({ context }) => ({
2470
- config: context.config,
2471
- stream: context.stream,
2472
- existing: context.recordingSession,
2473
- currentMode: context.currentMode
2474
- }),
2475
- onDone: { actions: assign({ recordingSession: ({ context, event }) => {
2476
- return event.output ?? context.recordingSession;
2477
- } }) },
2478
- onError: { actions: () => void 0 }
2479
- }, {
2480
- id: "runDetection",
2481
- src: "runDetection",
2482
- input: ({ context }) => ({
2483
- frameCapturer: context.frameCapturer,
2484
- provider: context.provider,
2485
- config: context.config,
2486
- currentMode: context.currentMode,
2487
- detectionArea: context.detectionArea ?? context.config.detectionArea
2488
- })
2489
- }],
2490
- on: {
2491
- DETECTION_UPDATE: { actions: "setDetectionStatus" },
2492
- DETECTION_FRAME: { actions: assign({ debugFrame: ({ event }) => event.frame }) },
2493
- DETECTION_RESET_READY: { actions: assign({ resetDetection: ({ event }) => event.reset }) },
2494
- DETECTION_SUCCESS: {
2495
- target: "capturing",
2496
- actions: assign({ qualityElements: ({ event }) => event.qualityElements })
2497
- },
2498
- MANUAL_CAPTURE: { target: "capturingManual" },
2499
- SWITCH_TO_MANUAL_CAPTURE: {
2500
- target: "manualCaptureWaiting",
2501
- actions: assign({
2502
- detectionStatus: () => "manualCapture",
2503
- manualCaptureTriggered: () => true
2504
- })
2505
- },
2506
- COUNTER_VALUE_CHANGE: { actions: "setCounterValue" },
2507
- ID_TYPE_CHANGE: { actions: "setIdType" },
2508
- ID_SIDE_CHANGE: { actions: assign({ detectionStatus: ({ event, context }) => getDetectionStatusFromSideChange(context, event.side) }) },
2509
- ORIENTATION_CHANGE: { actions: "setOrientation" }
2510
- }
2511
- },
2512
- manualCaptureWaiting: { on: { MANUAL_CAPTURE: { target: "capturingManual" } } },
2513
- capturing: {
2514
- entry: [
2515
- "captureImage",
2516
- "storeCapturedCanvasInProvider",
2517
- "storeCapturedImage"
2518
- ],
2519
- always: [{
2520
- target: "uploading",
2521
- guard: "hasCapturedImage"
2522
- }, {
2523
- target: "uploadError",
2524
- actions: assign(({ context }) => ({
2525
- uploadError: ID_ERROR_CODES.UPLOAD_ERROR,
2526
- attemptsRemaining: context.attemptsRemaining - 1
2527
- }))
2528
- }]
2529
- },
2530
- capturingManual: {
2531
- entry: [
2532
- "captureLatestFrame",
2533
- "storeCapturedCanvasInProvider",
2534
- "storeCapturedImage"
2535
- ],
2536
- always: [{
2537
- target: "uploading",
2538
- guard: "hasCapturedImage"
2539
- }, {
2540
- target: "uploadError",
2541
- actions: assign(({ context }) => ({
2542
- uploadError: ID_ERROR_CODES.UPLOAD_ERROR,
2543
- attemptsRemaining: context.attemptsRemaining - 1
2544
- }))
2545
- }]
2546
- },
2547
- uploading: {
2548
- entry: assign({ uploadProgress: () => 0 }),
2549
- invoke: {
2550
- id: "uploadIdImage",
2551
- src: "uploadIdImage",
2552
- input: ({ context, self }) => {
2553
- const canvas = context.provider?.getOriginalCapturedCanvas();
2554
- if (!canvas) throw new Error(ID_ERROR_CODES.UPLOAD_ERROR);
2555
- return {
2556
- canvas,
2557
- type: context.currentMode === "back" ? "back" : "front",
2558
- qualityElements: context.qualityElements,
2559
- onProgress: (progress) => {
2560
- self.send({
2561
- type: "UPLOAD_PROGRESS",
2562
- progress
2563
- });
2564
- },
2565
- deepsightService: context.deepsightService,
2566
- stream: context.stream,
2567
- isSecondId: context.config.isSecondId ?? false,
2568
- onlyFront: false,
2569
- ageAssurance: context.config.ageAssurance,
2570
- dependencies: context.dependencies,
2571
- captureResolution: context.captureResolution,
2572
- cameraFallbackLevel: context.cameraFallbackLevel,
2573
- croppedCanvas: context.provider?.getCapturedCanvas() ?? null
2574
- };
2575
- },
2576
- onDone: {
2577
- target: "validatingUpload",
2578
- actions: [assign({
2579
- uploadResponse: ({ event }) => event.output,
2580
- uploadProgress: () => 100
2581
- }), "storeCapturedImage"]
2582
- },
2583
- onError: {
2584
- target: "uploadError",
2585
- actions: assign(({ context, event }) => ({
2586
- uploadError: getIdErrorCodeFromUnknown(event.error) ?? ID_ERROR_CODES.UPLOAD_ERROR,
2587
- attemptsRemaining: context.attemptsRemaining - 1
2588
- }))
2589
- }
2590
- },
2591
- on: { UPLOAD_PROGRESS: { actions: assign({ uploadProgress: ({ event }) => event.progress }) } }
2592
- },
2593
- validatingUpload: { always: [
2594
- {
2595
- target: "uploadError",
2596
- guard: "hasUploadValidationError",
2597
- actions: ["setUploadErrorFromUploadValidation", "decrementAttemptsRemaining"]
2598
- },
2599
- {
2600
- target: "#idCapture.finished",
2601
- guard: and(["shouldSkipProcessId", "isUploadExpired"])
2602
- },
2603
- {
2604
- target: "#idCapture.expiredExhausted",
2605
- guard: and([
2606
- "isNotPassportMode",
2607
- "isUploadExpired",
2608
- "isExpiredAttemptsExhausted"
2609
- ]),
2610
- actions: ["incrementExpiredAttempts", "setExhaustedFromUpload"]
2611
- },
2612
- {
2613
- target: "#idCapture.expired",
2614
- guard: and(["isNotPassportMode", "isUploadExpired"]),
2615
- actions: ["incrementExpiredAttempts", "setExpiredFromUpload"]
2616
- },
2617
- { target: "success" }
2618
- ] },
2619
- uploadError: { on: { CONTINUE_FROM_ERROR: [
2620
- {
2621
- target: "checkingStream",
2622
- guard: "hasAttemptsRemaining",
2623
- actions: [
2624
- "resetDetection",
2625
- "clearUploadFailure",
2626
- "clearStreamForRetry"
2627
- ]
2628
- },
2629
- {
2630
- target: "#idCapture.frontFinished",
2631
- guard: "shouldContinueToBack",
2632
- actions: ["flagIdManualReview"]
2633
- },
2634
- {
2635
- target: "#idCapture.backFinished",
2636
- guard: "shouldContinueToFront",
2637
- actions: ["flagIdManualReview"]
2638
- },
2639
- {
2640
- target: "#idCapture.processing",
2641
- actions: ["flagIdManualReview"]
2642
- }
2643
- ] } },
2644
- success: { on: { NEXT_STEP: [
2645
- {
2646
- target: "#idCapture.mandatoryConsent",
2647
- guard: "hasMandatoryConsent"
2648
- },
2649
- {
2650
- target: "#idCapture.frontFinished",
2651
- guard: "shouldContinueToBack"
2652
- },
2653
- {
2654
- target: "#idCapture.backFinished",
2655
- guard: "shouldContinueToFront"
2656
- },
2657
- { target: "#idCapture.processing" }
2658
- ] } }
2659
- }
2660
- },
2661
- mandatoryConsent: { on: {
2662
- CONSENT_ACCEPT: [
2663
- {
2664
- target: "frontFinished",
2665
- guard: "shouldContinueToBack"
2666
- },
2667
- {
2668
- target: "backFinished",
2669
- guard: "shouldContinueToFront"
2670
- },
2671
- { target: "processing" }
2672
- ],
2673
- CONSENT_CANCEL: { target: "closed" }
2674
- } },
2675
- frontFinished: {
2676
- entry: ["stopMediaRecording", "resetForBackCapture"],
2677
- type: "parallel",
2678
- states: {
2679
- cameraInit: {
2680
- initial: "checking",
2681
- states: {
2682
- checking: { always: [{
2683
- target: "ready",
2684
- guard: "hasStream"
2685
- }, { target: "initializingStream" }] },
2686
- initializingStream: { invoke: {
2687
- id: "frontFinishedInitCamera",
2688
- src: "initializeCamera",
2689
- input: ({ context }) => ({
2690
- config: context.config,
2691
- deepsightService: context.deepsightService
2692
- }),
2693
- onDone: {
2694
- target: "ready",
2695
- actions: "setStreamAndCapturer"
2696
- },
2697
- onError: {
2698
- target: "ready",
2699
- actions: () => {
2700
- console.warn("Camera initialization failed during flip transition");
2701
- }
2702
- }
2703
- } },
2704
- ready: { type: "final" }
2705
- }
2706
- },
2707
- userIntent: {
2708
- initial: "waiting",
2709
- states: {
2710
- waiting: { on: { CONTINUE_TO_BACK: {
2711
- target: "clicked",
2712
- actions: assign({ currentMode: () => "back" })
2713
- } } },
2714
- clicked: { type: "final" }
2715
- }
2716
- }
2717
- },
2718
- onDone: [{
2719
- target: "#idCapture.capture.detecting",
2720
- guard: "hasStream"
2721
- }, { target: "#idCapture.capture" }]
2722
- },
2723
- backFinished: {
2724
- entry: ["stopMediaRecording", "resetForFrontCapture"],
2725
- type: "parallel",
2726
- states: {
2727
- cameraInit: {
2728
- initial: "checking",
2729
- states: {
2730
- checking: { always: [{
2731
- target: "ready",
2732
- guard: "hasStream"
2733
- }, { target: "initializingStream" }] },
2734
- initializingStream: { invoke: {
2735
- id: "backFinishedInitCamera",
2736
- src: "initializeCamera",
2737
- input: ({ context }) => ({
2738
- config: context.config,
2739
- deepsightService: context.deepsightService
2740
- }),
2741
- onDone: {
2742
- target: "ready",
2743
- actions: "setStreamAndCapturer"
2744
- },
2745
- onError: {
2746
- target: "ready",
2747
- actions: () => {
2748
- console.warn("Camera initialization failed during flip transition");
2749
- }
2750
- }
2751
- } },
2752
- ready: { type: "final" }
2753
- }
2754
- },
2755
- userIntent: {
2756
- initial: "waiting",
2757
- states: {
2758
- waiting: { on: { CONTINUE_TO_FRONT: {
2759
- target: "clicked",
2760
- actions: assign({ currentMode: () => "front" })
2761
- } } },
2762
- clicked: { type: "final" }
2763
- }
2764
- }
2765
- },
2766
- onDone: [{
2767
- target: "#idCapture.capture.detecting",
2768
- guard: "hasStream"
2769
- }, { target: "#idCapture.capture" }]
2770
- },
2771
- processing: {
2772
- entry: "stopMediaStream",
2773
- always: [{
2774
- target: "finished",
2775
- guard: "shouldSkipProcessId"
2776
- }],
2777
- invoke: {
2778
- id: "processId",
2779
- src: "processId",
2780
- input: ({ context }) => ({ isSecondId: context.config.isSecondId ?? false }),
2781
- onDone: [
2782
- {
2783
- target: "finished",
2784
- guard: "forceFinishAfterProcessing"
2785
- },
2786
- {
2787
- target: "expiredExhausted",
2788
- guard: and([({ event }) => event.output.isDocumentExpired, "isProcessingExpiredExhausted"]),
2789
- actions: ["incrementProcessingExpiredAttempts"]
2790
- },
2791
- {
2792
- target: "expired",
2793
- guard: ({ event }) => event.output.isDocumentExpired,
2794
- actions: ["incrementProcessingExpiredAttempts", "clearExpiredFromUpload"]
2795
- },
2796
- { target: "finished" }
2797
- ],
2798
- onError: { target: "finished" }
2799
- }
2800
- },
2801
- expired: { on: { RETRY_CAPTURE: [
2802
- {
2803
- target: "#idCapture.capture",
2804
- guard: "wasExpiredFromUpload",
2805
- actions: [
2806
- "resetDetection",
2807
- "clearExpiredFromUpload",
2808
- "clearUploadFailure"
2809
- ]
2810
- },
2811
- {
2812
- target: "chooser",
2813
- guard: "hasShowDocumentChooser",
2814
- actions: ["resetContext"]
2815
- },
2816
- {
2817
- target: "ageVerification",
2818
- guard: "hasAgeAssurance",
2819
- actions: "resetContext"
2820
- },
2821
- {
2822
- target: "tutorial",
2823
- guard: "hasShowTutorial",
2824
- actions: "resetContext"
2825
- },
2826
- {
2827
- target: "loading",
2828
- actions: "resetContext"
2829
- }
2830
- ] } },
2831
- expiredExhausted: { on: { CONTINUE_EXHAUSTED: [
2832
- {
2833
- target: "#idCapture.frontFinished",
2834
- guard: "shouldForceBackOnExpired",
2835
- actions: ["setSkipProcessId"]
2836
- },
2837
- {
2838
- target: "#idCapture.processing",
2839
- guard: "shouldProcessAfterExhaustion",
2840
- actions: ["setForceFinishAfterProcessing"]
2841
- },
2842
- {
2843
- target: "#idCapture.finished",
2844
- actions: ["setSkipProcessId"]
2845
- }
2846
- ] } },
2847
- finished: {
2848
- entry: [
2849
- "stopMediaRecording",
2850
- "stopMediaStream",
2851
- "disposeProvider",
2852
- "cleanupDeepsight"
2853
- ],
2854
- type: "final"
2855
- },
2856
- closed: {
2857
- entry: [
2858
- "stopMediaStream",
2859
- "disposeProvider",
2860
- "cleanupDeepsight"
2861
- ],
2862
- type: "final"
2863
- },
2864
- error: {
2865
- entry: [
2866
- "stopMediaStream",
2867
- "disposeProvider",
2868
- "cleanupDeepsight"
2869
- ],
2870
- on: { RESET: {
2871
- target: "idle",
2872
- actions: "resetContext"
2873
- } }
2874
- },
2875
- manualIdUpload: {
2876
- invoke: {
2877
- id: "manualIdUpload",
2878
- src: "manualUploadMachine",
2879
- input: ({ context }) => ({
2880
- isSecondId: context.config.isSecondId ?? false,
2881
- onlyFront: false,
2882
- captureAttempts: context.config.captureAttempts
2883
- }),
2884
- onSnapshot: { actions: () => {} },
2885
- onDone: [{
2886
- guard: "isManualUploadExhausted",
2887
- target: "#idCapture.finished"
2888
- }, { target: "#idCapture.processing" }],
2889
- onError: {
2890
- target: "#idCapture.error",
2891
- actions: assign({ error: ({ event }) => String(event.error) })
2892
- }
2893
- },
2894
- on: {
2895
- QUIT: { target: "closed" },
2896
- MANUAL_UPLOAD_TAB_CHANGED: { actions: sendTo("manualIdUpload", ({ event }) => event) },
2897
- MANUAL_UPLOAD_FILE_SELECTED: { actions: sendTo("manualIdUpload", ({ event }) => event) },
2898
- MANUAL_UPLOAD_CONTINUE: { actions: sendTo("manualIdUpload", ({ event }) => event) },
2899
- MANUAL_UPLOAD_RESET: { actions: sendTo("manualIdUpload", ({ event }) => event) }
2900
- }
2901
- },
2902
- digitalIdUpload: {
2903
- invoke: {
2904
- id: "digitalIdUpload",
2905
- src: "digitalUploadMachine",
2906
- input: ({ context }) => ({
2907
- showTutorial: context.config.showTutorial,
2908
- captureAttempts: context.config.captureAttempts
2909
- }),
2910
- onSnapshot: { actions: () => {} },
2911
- onDone: [
2912
- {
2913
- guard: "isDigitalUploadExhausted",
2914
- target: "#idCapture.finished"
2915
- },
2916
- {
2917
- guard: "isDigitalUploadClosed",
2918
- target: "#idCapture.chooser"
2919
- },
2920
- {
2921
- guard: "isDigitalUploadSuccessful",
2922
- target: "#idCapture.processing",
2923
- actions: ["storeDigitalUploadResponse"]
2924
- },
2925
- {
2926
- target: "#idCapture.error",
2927
- actions: assign({ error: () => "Digital upload finished without output" })
2928
- }
2929
- ],
2930
- onError: {
2931
- target: "#idCapture.error",
2932
- actions: assign({ error: ({ event }) => String(event.error) })
2933
- }
2934
- },
2935
- on: {
2936
- QUIT: { target: "closed" },
2937
- DIGITAL_UPLOAD_NEXT_STEP: { actions: sendTo("digitalIdUpload", { type: "NEXT_STEP" }) },
2938
- DIGITAL_UPLOAD_FILE_PICKED: { actions: sendTo("digitalIdUpload", ({ event }) => ({
2939
- type: "FILE_PICKED",
2940
- file: event.file
2941
- })) },
2942
- DIGITAL_UPLOAD_CONFIRM: { actions: sendTo("digitalIdUpload", { type: "CONFIRM" }) },
2943
- DIGITAL_UPLOAD_REPLACE: { actions: sendTo("digitalIdUpload", { type: "REPLACE" }) },
2944
- DIGITAL_UPLOAD_RETRY: { actions: sendTo("digitalIdUpload", { type: "RETRY" }) },
2945
- DIGITAL_UPLOAD_SCAN_INSTEAD: { actions: sendTo("digitalIdUpload", { type: "SCAN_INSTEAD" }) },
2946
- DIGITAL_UPLOAD_CHOOSE_ANOTHER: { actions: sendTo("digitalIdUpload", { type: "CHOOSE_ANOTHER" }) }
2947
- }
2948
- }
2949
- }
2950
- });
2951
- const idCaptureMachine = _idCaptureMachine;
2952
-
2953
- //#endregion
2954
- export { startRecordingSession as a, uploadIdImage as c, ID_ERROR_CODES as d, MANUAL_UPLOAD_EXHAUSTION_FORWARD_MS as f, mapDigitalIdScreenName as h, processId as i, uploadManualIdFile as l, MANUAL_UPLOAD_MAX_RETRIES as m, initializeIdCapture as n, stopRecording as o, MANUAL_UPLOAD_MAX_FILE_SIZE_BYTES as p, preloadIdRecordingProvider as r, stopStream as s, idCaptureMachine as t, validateUploadResponse as u };