@incodetech/core 2.0.0-alpha.8 → 2.0.0-rc.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 (184) hide show
  1. package/dist/Actor-CI32dTbG.d.ts +2 -0
  2. package/dist/BaseWasmProvider-C_DLEI40.esm.js +1118 -0
  3. package/dist/BrowserStorageProvider-CuOW1Er2.esm.js +55 -0
  4. package/dist/BrowserTimerProvider-DhNc_x02.esm.js +22 -0
  5. package/dist/ITimerCapability-C67ZRskg.esm.js +7 -0
  6. package/dist/IpifyProvider-D7jx52AL.esm.js +139 -0
  7. package/dist/MotionSensorProvider-4v7xkqAp.esm.js +254 -0
  8. package/dist/OpenViduRecordingProvider-CMu6XVdc.esm.js +87 -0
  9. package/dist/StateMachine-BCQrZJhf.d.ts +2 -0
  10. package/dist/WasmUtilProvider-j98OJf-S.esm.js +114 -0
  11. package/dist/addressSearch-BpTbTWCa.esm.js +430 -0
  12. package/dist/ae-signature-DDDZmWXj.esm.js +12 -0
  13. package/dist/ae-signature.d.ts +25 -0
  14. package/dist/ae-signature.esm.js +8 -0
  15. package/dist/antifraud.d.ts +57 -0
  16. package/dist/antifraud.esm.js +45 -0
  17. package/dist/antifraudStateMachine-O0TMf6yc.esm.js +39 -0
  18. package/dist/api-CESGtpbH.esm.js +53 -0
  19. package/dist/authentication.d.ts +12 -0
  20. package/dist/authentication.esm.js +25 -0
  21. package/dist/authenticationManager-5M-fKzXx.esm.js +67 -0
  22. package/dist/authenticationManager-C83GNIhl.d.ts +66 -0
  23. package/dist/authenticationStateMachine-BMZqatiF.esm.js +139 -0
  24. package/dist/backCameraStream-DMdMeGk2.esm.js +346 -0
  25. package/dist/browserSimulation-gxD8cSpM.esm.js +20 -0
  26. package/dist/camera-DBSxa6ML.d.ts +4 -0
  27. package/dist/camera-PA2Ljri3.esm.js +22 -0
  28. package/dist/camera.d.ts +15 -0
  29. package/dist/camera.esm.js +5 -0
  30. package/dist/consent.d.ts +398 -0
  31. package/dist/consent.esm.js +79 -0
  32. package/dist/consentStateMachine-CCT-B60O.esm.js +151 -0
  33. package/dist/cpf-PPz2Njto.esm.js +38 -0
  34. package/dist/cpf-ocr.d.ts +204 -0
  35. package/dist/cpf-ocr.esm.js +177 -0
  36. package/dist/cross-document-data-match.d.ts +34 -0
  37. package/dist/cross-document-data-match.esm.js +71 -0
  38. package/dist/curp-validation.d.ts +188 -0
  39. package/dist/curp-validation.esm.js +110 -0
  40. package/dist/curpValidationStateMachine-CitWLr2c.esm.js +595 -0
  41. package/dist/custom-fields.d.ts +115 -0
  42. package/dist/custom-fields.esm.js +177 -0
  43. package/dist/custom-watchlist.d.ts +66 -0
  44. package/dist/custom-watchlist.esm.js +86 -0
  45. package/dist/dateUtils-UoN5xswP.esm.js +23 -0
  46. package/dist/deepsightLoader-Cm4JIT_z.esm.js +52 -0
  47. package/dist/deepsightService-CEVxzehb.d.ts +412 -0
  48. package/dist/deepsightService-O74l4Y__.esm.js +489 -0
  49. package/dist/device.d.ts +46 -0
  50. package/dist/device.esm.js +106 -0
  51. package/dist/displayErrors-DqJ_IbsG.d.ts +39 -0
  52. package/dist/document-capture.d.ts +906 -0
  53. package/dist/document-capture.esm.js +156 -0
  54. package/dist/document-upload.d.ts +331 -0
  55. package/dist/document-upload.esm.js +203 -0
  56. package/dist/documentCaptureStateMachine-BqzTDy9k.esm.js +394 -0
  57. package/dist/dynamic-forms.d.ts +178 -0
  58. package/dist/dynamic-forms.esm.js +323 -0
  59. package/dist/ekyb.d.ts +148 -0
  60. package/dist/ekyb.esm.js +127 -0
  61. package/dist/ekybStateMachine-B59rQjgj.esm.js +674 -0
  62. package/dist/ekyc.d.ts +164 -0
  63. package/dist/ekyc.esm.js +104 -0
  64. package/dist/ekycStateMachine-oeO0Iekd.esm.js +10626 -0
  65. package/dist/electronic-signature.d.ts +4 -0
  66. package/dist/electronic-signature.esm.js +7 -0
  67. package/dist/electronicSignatureManager-D9OHzTpG.esm.js +428 -0
  68. package/dist/email.d.ts +3 -263
  69. package/dist/email.esm.js +7 -477
  70. package/dist/emailManager-DIfnS5g1.d.ts +352 -0
  71. package/dist/emailManager-wAV0LE-H.esm.js +238 -0
  72. package/dist/emailStateMachine-DOf4j58N.esm.js +292 -0
  73. package/dist/endpoints-CnN3SyDa.esm.js +87 -0
  74. package/dist/events-D6-e4vok.esm.js +596 -0
  75. package/dist/events.d.ts +265 -0
  76. package/dist/events.esm.js +4 -0
  77. package/dist/extensibility.d.ts +122 -0
  78. package/dist/extensibility.esm.js +43 -0
  79. package/dist/face-match.d.ts +228 -0
  80. package/dist/face-match.esm.js +173 -0
  81. package/dist/faceCaptureManagerFactory-Dh2PdGlF.esm.js +290 -0
  82. package/dist/faceCaptureManagerFactory-yqtpxjnN.d.ts +690 -0
  83. package/dist/faceCaptureSetup-B3faSpYA.esm.js +873 -0
  84. package/dist/faceMatchStateMachine-DNFrxTFS.esm.js +127 -0
  85. package/dist/flow-events.d.ts +6 -0
  86. package/dist/flow-events.esm.js +0 -0
  87. package/dist/flow.d.ts +101 -321
  88. package/dist/flow.esm.js +370 -173
  89. package/dist/flowCompletionService-DhkT4SRY.d.ts +10 -0
  90. package/dist/flowCompletionService-P54yzGvA.esm.js +13 -0
  91. package/dist/flowServices-DTsm-Vf1.esm.js +188 -0
  92. package/dist/geolocation.d.ts +127 -0
  93. package/dist/geolocation.esm.js +89 -0
  94. package/dist/geolocationStateMachine-asasuHY2.esm.js +105 -0
  95. package/dist/getBrowser-BSXUTWXw.esm.js +41 -0
  96. package/dist/getDeviceClass-BSntT9_j.esm.js +14 -0
  97. package/dist/government-validation.d.ts +67 -0
  98. package/dist/government-validation.esm.js +81 -0
  99. package/dist/governmentValidationStateMachine-BDDYrJTo.esm.js +271 -0
  100. package/dist/home.d.ts +99 -0
  101. package/dist/home.esm.js +61 -0
  102. package/dist/http.d.ts +68 -0
  103. package/dist/http.esm.js +3 -0
  104. package/dist/id-ocr.d.ts +635 -0
  105. package/dist/id-ocr.esm.js +86 -0
  106. package/dist/id-verification.d.ts +190 -0
  107. package/dist/id-verification.esm.js +43 -0
  108. package/dist/id.d.ts +24 -0
  109. package/dist/id.esm.js +164 -0
  110. package/dist/idCaptureManager-B9TGA5dq.d.ts +956 -0
  111. package/dist/idCaptureManager-DMK0GIt3.esm.js +581 -0
  112. package/dist/idCaptureStateMachine-Bq0fVZXl.esm.js +2954 -0
  113. package/dist/idOcrStateMachine-YbjjC_Gg.esm.js +388 -0
  114. package/dist/idVerificationStateMachine-xbw9HP1Z.esm.js +71 -0
  115. package/dist/identity-reuse.d.ts +530 -0
  116. package/dist/identity-reuse.esm.js +274 -0
  117. package/dist/index-BLKtMA0g.d.ts +1177 -0
  118. package/dist/index-BcRG8rtJ.d.ts +97 -0
  119. package/dist/index.d.ts +3 -226
  120. package/dist/index.esm.js +11 -154
  121. package/dist/invokeOnCaptureCallback-rc6kBHo5.esm.js +30 -0
  122. package/dist/{lib-Bu9XGMBW.esm.js → lib-BB0B_qQX.esm.js} +801 -2
  123. package/dist/mandatory-consent.d.ts +412 -0
  124. package/dist/mandatory-consent.esm.js +78 -0
  125. package/dist/mandatoryConsentStateMachine-Cnco1jvn.esm.js +126 -0
  126. package/dist/openviduLazy-Cm0XFh_v.esm.js +3 -0
  127. package/dist/openviduLazy-Cok70ZSg.esm.js +12 -0
  128. package/dist/permissionServices-D_i6nzEw.esm.js +50 -0
  129. package/dist/phone.d.ts +3 -291
  130. package/dist/phone.esm.js +7 -548
  131. package/dist/phoneManager-B6M30hKE.d.ts +397 -0
  132. package/dist/phoneManager-DAJbGhlY.esm.js +256 -0
  133. package/dist/phoneStateMachine-CuPARRaT.esm.js +351 -0
  134. package/dist/platform-CfrjKhmi.esm.js +83 -0
  135. package/dist/qe-signature-DFo_Cc-I.esm.js +12 -0
  136. package/dist/qe-signature.d.ts +25 -0
  137. package/dist/qe-signature.esm.js +8 -0
  138. package/dist/recordingService-Ig2UgbLv.esm.js +1003 -0
  139. package/dist/redirect-to-mobile.d.ts +107 -0
  140. package/dist/redirect-to-mobile.esm.js +102 -0
  141. package/dist/redirectToMobileStateMachine-BOEqe46A.esm.js +249 -0
  142. package/dist/runChildModule-CqqwqAkW.esm.js +219 -0
  143. package/dist/selfie.d.ts +21 -754
  144. package/dist/selfie.esm.js +113 -962
  145. package/dist/selfieManager-D0lSgd-J.d.ts +68 -0
  146. package/dist/selfieManager-Duisl7qN.esm.js +60 -0
  147. package/dist/selfieStateMachine-D76whWEf.esm.js +68 -0
  148. package/dist/session-BS-d_vuE.esm.js +3206 -0
  149. package/dist/session.d.ts +217 -0
  150. package/dist/session.esm.js +9 -0
  151. package/dist/setup-Buy-hyj4.esm.js +887 -0
  152. package/dist/setup-C5AITV8m.d.ts +254 -0
  153. package/dist/signature.d.ts +94 -0
  154. package/dist/signature.esm.js +66 -0
  155. package/dist/signatureStateMachine-B5-QVUve.esm.js +132 -0
  156. package/dist/stats-CIfiPzb1.esm.js +16 -0
  157. package/dist/stats.d.ts +16 -0
  158. package/dist/stats.esm.js +4 -0
  159. package/dist/trust-graph.d.ts +54 -0
  160. package/dist/trust-graph.esm.js +56 -0
  161. package/dist/types-B06Ypu2F.d.ts +49 -0
  162. package/dist/types-BP1m8VRw.d.ts +340 -0
  163. package/dist/types-CFV9G_7j.d.ts +24 -0
  164. package/dist/{warmup-CEJTfxQr.d.ts → warmup-CEcppFiS.d.ts} +11 -3
  165. package/dist/wasm.d.ts +15 -0
  166. package/dist/wasm.esm.js +12 -0
  167. package/dist/watchlist-for-business.d.ts +79 -0
  168. package/dist/watchlist-for-business.esm.js +148 -0
  169. package/dist/watchlist.d.ts +62 -0
  170. package/dist/watchlist.esm.js +86 -0
  171. package/dist/watchlistServices-DMbUhkBX.esm.js +12 -0
  172. package/dist/workflow.d.ts +907 -0
  173. package/dist/workflow.esm.js +702 -0
  174. package/dist/{xstate.esm-B_rda9yU.esm.js → xstate.esm-B70JrNqo.esm.js} +144 -1
  175. package/package.json +203 -6
  176. package/dist/OpenViduLogger-BdPfiZO6.esm.js +0 -3
  177. package/dist/OpenViduLogger-CQyDxBvM.esm.js +0 -803
  178. package/dist/StateMachine-DRE1oH2B.d.ts +0 -2
  179. package/dist/addEvent-W0ORK0jT.esm.js +0 -16
  180. package/dist/endpoints-BSTFaHYo.esm.js +0 -1706
  181. package/dist/permissionServices-I6vX6DBy.esm.js +0 -72
  182. /package/dist/{Manager-BGfxEmyv.d.ts → Manager-C8PrhBOx.d.ts} +0 -0
  183. /package/dist/{chunk-C_Yo44FK.esm.js → chunk-CRF6K_H_.esm.js} +0 -0
  184. /package/dist/{types-iZi2rawo.d.ts → types-CAD4va6a.d.ts} +0 -0
@@ -0,0 +1,1118 @@
1
+ //#region ../infra/src/providers/browser/SemaphoreProvider.ts
2
+ const DEFAULT_ACQUIRE_TIMEOUT_MS = 3e4;
3
+ /**
4
+ * Counting-semaphore implementation of {@link IConcurrencyCapability}.
5
+ *
6
+ * Default `maxConcurrent=1` makes it behave as a mutex; set higher for
7
+ * parallel-bounded access. Each acquire returns a numeric `threadId` for
8
+ * tracing — the slot index, in `[0, maxConcurrent)` — that must be passed back
9
+ * to `release`.
10
+ *
11
+ * If all slots stay occupied longer than `acquireTimeoutMs` (default 30s), the
12
+ * pending wait still resolves when a slot frees, but `console.error` is logged
13
+ * as a deadlock-watchdog signal. Misuse — out-of-range or double-released
14
+ * `threadId`s — is also logged and treated as a no-op rather than thrown.
15
+ */
16
+ var SemaphoreProvider = class {
17
+ constructor(maxConcurrent = 1, acquireTimeoutMs = DEFAULT_ACQUIRE_TIMEOUT_MS) {
18
+ this.pending = [];
19
+ this.available = [];
20
+ this.processing = /* @__PURE__ */ new Set();
21
+ this.maxId = maxConcurrent - 1;
22
+ this.acquireTimeoutMs = acquireTimeoutMs;
23
+ for (let i = 0; i < maxConcurrent; i++) this.available.push(i);
24
+ }
25
+ /**
26
+ * Acquire a slot. Resolves immediately with the slot's `threadId` if one is
27
+ * free, otherwise queues FIFO and resolves when a holder releases.
28
+ */
29
+ async acquire() {
30
+ if (this.available.length > 0) {
31
+ const threadId = this.available.shift();
32
+ this.processing.add(threadId);
33
+ return threadId;
34
+ }
35
+ return new Promise((resolve, reject) => {
36
+ const entry = {
37
+ resolve: (threadId) => {
38
+ clearTimeout(entry.timer);
39
+ this.processing.add(threadId);
40
+ resolve(threadId);
41
+ },
42
+ reject: (error) => {
43
+ clearTimeout(entry.timer);
44
+ reject(error);
45
+ },
46
+ timer: setTimeout(() => {
47
+ console.error(`SemaphoreProvider: all slots occupied for ${this.acquireTimeoutMs}ms, ${this.pending.length} request(s) waiting`);
48
+ }, this.acquireTimeoutMs)
49
+ };
50
+ this.pending.push(entry);
51
+ });
52
+ }
53
+ /**
54
+ * Return a slot to the pool. The next pending waiter (if any) is resolved
55
+ * with this `threadId`; otherwise the slot is added back to `available`.
56
+ * Releasing an out-of-range or already-released `threadId` logs an error and
57
+ * is otherwise a no-op.
58
+ */
59
+ release(threadId) {
60
+ if (threadId < 0 || threadId > this.maxId) {
61
+ console.error(`SemaphoreProvider: invalid threadId ${threadId}`);
62
+ return;
63
+ }
64
+ if (!this.processing.has(threadId)) {
65
+ console.error(`SemaphoreProvider: double-release of threadId ${threadId}`);
66
+ return;
67
+ }
68
+ this.processing.delete(threadId);
69
+ if (this.pending.length > 0) this.pending.shift().resolve(threadId);
70
+ else this.available.unshift(threadId);
71
+ }
72
+ /**
73
+ * Cancel all pending acquires with a reset error and replenish all slots.
74
+ * Existing holders are not contacted — a `release` after reset will log a
75
+ * double-release warning rather than disrupt the new pool.
76
+ */
77
+ reset() {
78
+ const waiters = this.pending;
79
+ this.pending = [];
80
+ this.available = [];
81
+ this.processing = /* @__PURE__ */ new Set();
82
+ for (let i = 0; i <= this.maxId; i++) this.available.push(i);
83
+ for (const waiter of waiters) waiter.reject(/* @__PURE__ */ new Error("SemaphoreProvider reset: pending acquire cancelled"));
84
+ }
85
+ /**
86
+ * Acquire a slot, invoke `fn(threadId, ...args)`, then release the slot in a
87
+ * `finally` block. Errors thrown by `fn` propagate to the caller after the
88
+ * slot is released.
89
+ */
90
+ async withLock(fn, ...args) {
91
+ const threadId = await this.acquire();
92
+ try {
93
+ return await fn(threadId, ...args);
94
+ } finally {
95
+ this.release(threadId);
96
+ }
97
+ }
98
+ };
99
+
100
+ //#endregion
101
+ //#region ../infra/src/wasm/apiUtilities.ts
102
+ if (typeof window !== "undefined" && window.wasmArrayBuffer === void 0) window.wasmArrayBuffer = null;
103
+ let loadPromise = null;
104
+ let loadedResult = null;
105
+ async function importGlue(glueCodePath) {
106
+ const mod = await import(
107
+ /* @vite-ignore */
108
+ /* webpackIgnore: true */
109
+ glueCodePath
110
+ );
111
+ if (typeof mod.Module !== "function") throw new Error(`WASM glue at ${glueCodePath} did not export a Module factory`);
112
+ return mod.Module;
113
+ }
114
+ async function fetchWasmBinary(libPath) {
115
+ const response = await fetch(libPath);
116
+ if (!response.ok) throw new Error(`Failed to fetch WASM binary at ${libPath}: ${response.status} ${response.statusText}`);
117
+ const buffer = await response.arrayBuffer();
118
+ return new Uint8Array(buffer);
119
+ }
120
+ async function instantiate(factory, libPath) {
121
+ window.wasmArrayBuffer = await fetchWasmBinary(libPath);
122
+ return await factory();
123
+ }
124
+ /**
125
+ * Derive a sibling `.js` path from a `.wasm` path by replacing the trailing
126
+ * extension. Used as a last-resort default when callers pass a `wasmSimdPath`
127
+ * without an accompanying `glueCodeSimdPath` — matches the legacy CDN naming
128
+ * convention (`webLibSimd.wasm` <-> `webLibSimd.js`).
129
+ */
130
+ function deriveSiblingJsPath(wasmPath) {
131
+ return wasmPath.replace(/\.wasm($|\?)/, ".js$1");
132
+ }
133
+ /**
134
+ * Load the WASM module, memoized. Subsequent calls return the same instance.
135
+ *
136
+ * SIMD-first with fallback: if `useSimd !== false` and a `wasmSimdPath` is
137
+ * provided, the SIMD binary + SIMD glue are tried first; on instantiation
138
+ * failure the non-SIMD binary + non-SIMD glue are used. Each `.wasm` is
139
+ * paired with its matching `.js` glue — they cannot be mixed.
140
+ */
141
+ async function loadWasmModule(config) {
142
+ if (loadedResult) return loadedResult;
143
+ if (loadPromise) return loadPromise;
144
+ loadPromise = (async () => {
145
+ try {
146
+ const wantSimd = config.useSimd !== false;
147
+ const simdBinary = config.wasmSimdPath ?? config.wasmPath;
148
+ if (wantSimd && simdBinary !== config.wasmPath) try {
149
+ const simdFactory = await importGlue(config.glueCodeSimdPath ?? deriveSiblingJsPath(simdBinary));
150
+ window.Module = simdFactory;
151
+ const result$1 = {
152
+ wasmModule: await instantiate(simdFactory, simdBinary),
153
+ simdUsed: true
154
+ };
155
+ loadedResult = result$1;
156
+ return result$1;
157
+ } catch (simdError) {
158
+ console.warn("[Incode SDK] SIMD WASM load failed, falling back to non-SIMD", simdError);
159
+ }
160
+ const nonSimdFactory = await importGlue(config.glueCodePath);
161
+ window.Module = nonSimdFactory;
162
+ const result = {
163
+ wasmModule: await instantiate(nonSimdFactory, config.wasmPath),
164
+ simdUsed: false
165
+ };
166
+ loadedResult = result;
167
+ return result;
168
+ } catch (error) {
169
+ loadPromise = null;
170
+ throw error;
171
+ }
172
+ })();
173
+ return loadPromise;
174
+ }
175
+
176
+ //#endregion
177
+ //#region ../infra/src/wasm/IdCaptureModelType.ts
178
+ let IdCaptureModelType = /* @__PURE__ */ function(IdCaptureModelType$1) {
179
+ IdCaptureModelType$1[IdCaptureModelType$1["IdCaptureV1x"] = 0] = "IdCaptureV1x";
180
+ IdCaptureModelType$1[IdCaptureModelType$1["IdCaptureV2x"] = 1] = "IdCaptureV2x";
181
+ IdCaptureModelType$1[IdCaptureModelType$1["IdCaptureV3x"] = 2] = "IdCaptureV3x";
182
+ return IdCaptureModelType$1;
183
+ }({});
184
+
185
+ //#endregion
186
+ //#region ../infra/src/wasm/WasmPipelineType.ts
187
+ let WasmPipelineType = /* @__PURE__ */ function(WasmPipelineType$1) {
188
+ WasmPipelineType$1[WasmPipelineType$1["IdBlurGlarePipeline"] = 0] = "IdBlurGlarePipeline";
189
+ WasmPipelineType$1[WasmPipelineType$1["IdBarcodeAndTextQualityPipeline"] = 1] = "IdBarcodeAndTextQualityPipeline";
190
+ WasmPipelineType$1[WasmPipelineType$1["IdVideoSelfiePipeline"] = 2] = "IdVideoSelfiePipeline";
191
+ WasmPipelineType$1[WasmPipelineType$1["SelfieWithAggregationMetrics"] = 3] = "SelfieWithAggregationMetrics";
192
+ WasmPipelineType$1[WasmPipelineType$1["SelfieWithQualityMetrics"] = 4] = "SelfieWithQualityMetrics";
193
+ WasmPipelineType$1[WasmPipelineType$1["OnDeviceSelfieWorkflow"] = 5] = "OnDeviceSelfieWorkflow";
194
+ return WasmPipelineType$1;
195
+ }({});
196
+
197
+ //#endregion
198
+ //#region ../infra/src/wasm/wasmCallUtils.ts
199
+ async function wasmCallWrapper(concurrency, wasmMethod, useSemaphore = true, ...args) {
200
+ const innerCall = async () => {
201
+ while (true) {
202
+ if (wasmMethod(...args)) return;
203
+ await new Promise((resolve) => setTimeout(resolve, 0));
204
+ }
205
+ };
206
+ if (useSemaphore) {
207
+ await concurrency.withLock(innerCall);
208
+ return;
209
+ }
210
+ await innerCall();
211
+ }
212
+
213
+ //#endregion
214
+ //#region ../infra/src/wasm/wasmWebClient.ts
215
+ /**
216
+ * JavaScript bridge for the C++ `WebClient` exposed by `webLib.wasm`.
217
+ *
218
+ * The pinned WASM bundle ships a `WebClient` class alongside the ML pipeline
219
+ * APIs. This module instantiates it once (sharing the singleton `wasmModule`
220
+ * with `mlWasmJSApi`) and exposes a small TypeScript-friendly surface that
221
+ * `createWasmApi` can drive.
222
+ *
223
+ * Concurrency model mirrors the legacy implementation:
224
+ * - 4-slot semaphore keyed by per-request `threadId` so multiple HTTP calls
225
+ * can run in parallel without trampling shared C++ state.
226
+ * - Each WASM-side method that performs in-binary HTTP (request methods AND
227
+ * `createApi`'s in-binary `/e2ee/key` handshake) returns `false` while in
228
+ * flight and `true` once the C++ side has finished; the JS bridge awaits
229
+ * completion via {@link wasmCallWrapper}.
230
+ * - Result extraction (`getRequestResult`) is per-thread for HTTP requests
231
+ * and uses `threadId = -1` for the session-level `createApi` handshake.
232
+ *
233
+ * Encryption support: `setupConnection` accepts an `encryptionEnabled` flag
234
+ * that triggers the in-binary RSA/AES handshake. The OAEP MGF1 hash is
235
+ * controlled by the `useSha256` flag forwarded to the C++ `createApi`:
236
+ * `true` = SHA-256 MGF1, `false` = SHA-1 MGF1 (Java-compat default).
237
+ * State lives in the C++ binary and (for SDK config) in
238
+ * `@incodetech/core`'s `setup.ts` — this module caches nothing.
239
+ */
240
+ const HTTP_CONCURRENCY = 4;
241
+ /**
242
+ * Sentinel `threadId` used by the session-level `createApi` handshake when we
243
+ * read its result via `getRequestResult`. Per-request HTTP traffic uses real
244
+ * thread ids handed out by the semaphore; the handshake has no slot of its
245
+ * own, so the C++ side stores its result under `-1`. Mirrors legacy
246
+ * `checkError(threadId = -1)`.
247
+ */
248
+ const SETUP_THREAD_ID = -1;
249
+ var WasmWebClientError = class extends Error {
250
+ constructor(message, statusCode, data) {
251
+ super(message);
252
+ this.name = "WasmWebClientError";
253
+ this.status = statusCode;
254
+ this.statusCode = statusCode;
255
+ if (statusCode > 0 || data !== void 0) this.response = {
256
+ status: statusCode,
257
+ data
258
+ };
259
+ }
260
+ };
261
+ let webClientApi = null;
262
+ let initPromise = null;
263
+ let semaphore = new SemaphoreProvider(HTTP_CONCURRENCY);
264
+ const isWebClientWasm = (mod) => {
265
+ return typeof mod.WebClient === "function";
266
+ };
267
+ const toStringRecord = (obj) => {
268
+ if (!obj) return void 0;
269
+ const result = {};
270
+ for (const key of Object.keys(obj)) {
271
+ const value = obj[key];
272
+ if (value === void 0 || value === null) continue;
273
+ result[key] = String(value);
274
+ }
275
+ return result;
276
+ };
277
+ /**
278
+ * Loads the shared WASM module (if not already loaded) and instantiates the
279
+ * C++ `WebClient`. Idempotent — repeated calls reuse the existing instance.
280
+ *
281
+ * `glueCodeSimdPath` is paired with `wasmSimdPath` (`webLibSimd.js` for
282
+ * `webLibSimd.wasm`). Pass `''` to derive it automatically from
283
+ * `wasmSimdPath` by replacing the `.wasm` extension with `.js`.
284
+ */
285
+ async function initializeWasmWebClient(wasmPath, wasmSimdPath, glueCodePath, glueCodeSimdPath, useSimd) {
286
+ if (webClientApi) return;
287
+ if (initPromise) return initPromise;
288
+ initPromise = (async () => {
289
+ try {
290
+ const { wasmModule } = await loadWasmModule({
291
+ wasmPath,
292
+ wasmSimdPath,
293
+ glueCodePath,
294
+ glueCodeSimdPath: glueCodeSimdPath || void 0,
295
+ useSimd
296
+ });
297
+ if (!isWebClientWasm(wasmModule)) throw new Error("WASM module does not expose a WebClient class. Update webLib.wasm to a build that includes WebClient.");
298
+ webClientApi = new wasmModule.WebClient();
299
+ } catch (error) {
300
+ initPromise = null;
301
+ throw error;
302
+ }
303
+ })();
304
+ return initPromise;
305
+ }
306
+ /**
307
+ * Configures the C++ WebClient connection. Safe to call multiple times — each
308
+ * call resets the underlying session and re-applies default headers.
309
+ *
310
+ * `defaultHeaders` are applied **before** `createApi`, so the in-binary RSA
311
+ * handshake (`GET /e2ee/key/v2` + `POST /e2ee/key`) sees the same headers as
312
+ * data requests. Without this ordering, environments that require auth/version
313
+ * headers on the handshake (e.g. `x-api-key`, `api-version`) would 401/4xx
314
+ * before any encrypted traffic ever flowed.
315
+ *
316
+ * The C++ `createApi` returns `false` while the in-binary handshake is still
317
+ * in flight and `true` once both the `/e2ee/key/v2` GET and the `/e2ee/key`
318
+ * POST have completed (encryption on) or once the WebClient is configured
319
+ * (encryption off — same boolean convention, just no network traffic). The
320
+ * JS bridge waits on that boolean via {@link wasmCallWrapper}, then surfaces
321
+ * any handshake error captured on the session-level (`threadId = -1`)
322
+ * request slot. Mirrors legacy
323
+ * `ms-incodesmile-web/packages/incode-welcome/src/wasmUtils/webClientApi.ts`
324
+ * `setupConnection`.
325
+ *
326
+ * `useSha256` selects the OAEP MGF1 hash for the in-binary RSA wrap:
327
+ * - `true` → MGF1 = SHA-256. Caller is responsible for attaching the
328
+ * `X-RSA-Encryption-Scheme: RSA/NONE/OAEPWITHSHA-256ANDMGF1PADDING`
329
+ * header on subsequent encrypted requests so the server matches.
330
+ * - `false` → MGF1 = SHA-1 (Java-compat default). No scheme header needed;
331
+ * the server falls back to the legacy Java default.
332
+ */
333
+ async function setupWasmConnection(apiURL, token, encryptionEnabled, defaultHeaders, useSha256) {
334
+ const api = ensureReady();
335
+ api.resetSessionState?.();
336
+ api.setDefaultHeaders?.(defaultHeaders);
337
+ await wasmCallWrapper(semaphore, () => api.createApi(apiURL, token, useSha256, encryptionEnabled), false);
338
+ const result = api.getRequestResult(SETUP_THREAD_ID);
339
+ if (result.hasError) throw new WasmWebClientError(result.errorMessage || "WebClient handshake failed", result.statusCode, result.result);
340
+ }
341
+ /**
342
+ * Executes a single HTTP request through the WASM WebClient.
343
+ *
344
+ * Acquires a semaphore slot for `threadId`, registers progress callbacks, runs
345
+ * the request via {@link wasmCallWrapper} (busy-polls until the WASM method
346
+ * returns `true`), then extracts the per-thread result. Throws
347
+ * {@link WasmWebClientError} on non-2xx or transport errors.
348
+ *
349
+ * The `ie` (inline-encryption) flag is forwarded to the C++ WebClient for
350
+ * mutating methods. Default `false` — the SDK HTTP path leaves payloads
351
+ * unencrypted at the WebClient layer. The C++ `WebApi.postFaceResults`
352
+ * pre-encrypts its JSON via `SessionEncryptor` and calls back into this
353
+ * function with `ie=true`; see {@link createWebApiHostAdapter}.
354
+ */
355
+ async function executeWasmRequest(method, url, body, headers, params, timeout, onUploadProgress, ie = false) {
356
+ const api = ensureReady();
357
+ const stringParams = toStringRecord(params);
358
+ return semaphore.withLock(async (threadId) => {
359
+ if (onUploadProgress && api.setOnUploadProgress) api.setOnUploadProgress((event) => {
360
+ try {
361
+ onUploadProgress(event);
362
+ } catch (error) {
363
+ console.error("WasmWebClient: error in onUploadProgress callback", error);
364
+ }
365
+ });
366
+ try {
367
+ await wasmCallWrapper(semaphore, () => callWasmMethod(api, method, threadId, url, body, headers, stringParams, timeout, ie), false);
368
+ return readResult(api, threadId);
369
+ } finally {
370
+ api.clearOnUploadProgress?.(threadId);
371
+ api.clearOnDownloadProgress?.(threadId);
372
+ }
373
+ });
374
+ }
375
+ function callWasmMethod(api, method, threadId, url, body, headers, params, timeout, ie) {
376
+ switch (method) {
377
+ case "GET": return api.get(threadId, url, params, headers, timeout);
378
+ case "POST": return api.post(threadId, url, body ?? {}, headers, params, timeout, ie);
379
+ case "PUT": return api.put(threadId, url, body ?? {}, headers, params, timeout, ie);
380
+ case "PATCH": return api.patch(threadId, url, body ?? {}, headers, params, timeout, ie);
381
+ case "DELETE": return api.del(threadId, url, body ?? {}, headers, params, timeout, ie);
382
+ default: throw new Error(`Unsupported WASM HTTP method: ${method}`);
383
+ }
384
+ }
385
+ const DEFAULT_WEBAPI_TIMEOUT_MS = 3e4;
386
+ let webApiHttpTransport = null;
387
+ function setWebApiHttpTransport(transport) {
388
+ webApiHttpTransport = transport;
389
+ }
390
+ function createWebApiHostAdapter() {
391
+ return { post(url, body, config) {
392
+ const effectiveConfig = config ?? {};
393
+ const transport = webApiHttpTransport;
394
+ if (transport) return transport(url, body, effectiveConfig);
395
+ return executeWasmRequest("POST", url, body, effectiveConfig.headers ?? {}, effectiveConfig.params, effectiveConfig.timeout ?? DEFAULT_WEBAPI_TIMEOUT_MS, void 0, effectiveConfig.ie === true);
396
+ } };
397
+ }
398
+ function readResult(api, threadId) {
399
+ const response = api.getRequestResult(threadId);
400
+ if (response.hasError) throw new WasmWebClientError(response.errorMessage || "WasmWebClient request failed", response.statusCode, response.result);
401
+ return {
402
+ data: response.result,
403
+ status: response.statusCode
404
+ };
405
+ }
406
+ function ensureReady() {
407
+ if (!webClientApi) throw new Error("WasmWebClient not initialized. Call initializeWasmWebClient() first.");
408
+ return webClientApi;
409
+ }
410
+
411
+ //#endregion
412
+ //#region ../infra/src/wasm/mlWasmJSApi.ts
413
+ var MlWasmJSApi = class MlWasmJSApi {
414
+ constructor() {
415
+ this.versionsFile = null;
416
+ this.modelsBuffers = null;
417
+ this.inputImageBuffer = null;
418
+ this.wasmModule = null;
419
+ this.workflowApiUtilities = null;
420
+ this.utilityApi = null;
421
+ this.idCaptureWasmApi = null;
422
+ this.faceProcessingWasmApi = null;
423
+ this.webApi = null;
424
+ this.imageWidth_ = null;
425
+ this.imageHeight_ = null;
426
+ this.pipelines_ = null;
427
+ this.isInitialized_ = false;
428
+ this.inspectorOpened_ = false;
429
+ this.wasmCallSemaphore = new SemaphoreProvider();
430
+ this.Module = null;
431
+ }
432
+ /**
433
+ * Initiallization method, use it when the application starts
434
+ * TODO: this method can return the list of promises to be awaited together with other initialization code
435
+ * @param {string} webLibPath - The path to the webassembly binary
436
+ * @param {string} webLibPathSimd - The path to the SIMD version webassembly binary
437
+ * @param {string} glueCodePath - The path to the non-SIMD glue (`webLib.js`)
438
+ * @param {string} glueCodeSimdPath - The path to the SIMD-paired glue (`webLibSimd.js`); pass `''` to derive from `webLibPathSimd`
439
+ * @param {boolean} useSimd - Indicates whether SIMD optimizations should be used
440
+ * @param {string} versionsFile - The path to the file containing versioning information
441
+ * @param {Map.<WasmPipelineType, Array<string>>} pipelines - pipelines for initialization and corresponding models paths
442
+ * @returns {Promise<boolean>} A promise that resolves to a boolean indicating whether SIMD is enabled once the initialization is complete.
443
+ * @throws {Error} Throws an error if the initialization fails.
444
+ */
445
+ async initialize(webLibPath, webLibPathSimd, glueCodePath, glueCodeSimdPath, useSimd, versionsFile, pipelines) {
446
+ await this.freeResources();
447
+ this.pipelines_ = pipelines;
448
+ this.versionsFile = versionsFile;
449
+ const { wasmModule, simdUsed } = await loadWasmModule({
450
+ glueCodePath,
451
+ glueCodeSimdPath: glueCodeSimdPath || void 0,
452
+ wasmPath: webLibPath,
453
+ wasmSimdPath: webLibPathSimd,
454
+ useSimd
455
+ });
456
+ this.wasmModule = wasmModule;
457
+ this.Module = window.Module;
458
+ this.workflowApiUtilities = new this.wasmModule.WorkflowApiUtilities();
459
+ this.utilityApi = new this.wasmModule.UtilityApi();
460
+ this.idCaptureWasmApi = new this.wasmModule.IdCaptureApi();
461
+ this.faceProcessingWasmApi = new this.wasmModule.FaceProcessingApi();
462
+ this.webApi = new this.wasmModule.WebApi(createWebApiHostAdapter());
463
+ this.isInitialized_ = true;
464
+ return simdUsed;
465
+ }
466
+ static getInstance() {
467
+ if (!MlWasmJSApi.instance) MlWasmJSApi.instance = new MlWasmJSApi();
468
+ return MlWasmJSApi.instance;
469
+ }
470
+ /**
471
+ * Returns initialization status
472
+ * @returns
473
+ */
474
+ isInitialized() {
475
+ return this.workflowApiUtilities != null && this.utilityApi != null && this.idCaptureWasmApi != null && this.faceProcessingWasmApi != null && this.isInitialized_;
476
+ }
477
+ /**
478
+ * Allocate shared memory for image buffers (RGBA format)
479
+ * Use it every time when the frame dimentions changes
480
+ * @param {number} imageWidth - image width
481
+ * @param {number} imageHeight - image height
482
+ */
483
+ async allocateImageBuffers(imageWidth, imageHeight) {
484
+ this.checkWasmInitialization("Unable to allocate image buffers, cpp API hasn't been initialized");
485
+ if (imageWidth && imageHeight && imageWidth == this.imageWidth_ && imageHeight == this.imageHeight_ && this.inputImageBuffer && imageWidth * imageHeight * 4 === this.inputImageBuffer.length) return;
486
+ this.imageWidth_ = imageWidth;
487
+ this.imageHeight_ = imageHeight;
488
+ this.inputImageBuffer = this.workflowApiUtilities.allocateInputImageBuffer(imageWidth, imageHeight, 4);
489
+ }
490
+ async handleDetectionCallAndUpdateState(type) {
491
+ this.checkWasmInitialization("Unable to update pipeline state, cpp API hasn't been initialized");
492
+ this.workflowApiUtilities.handleDetectionCallAndUpdateState(this.pipelineTypeToWasmEnum(type));
493
+ }
494
+ ens(image) {
495
+ this.checkWasmInitialization("Unable to encrypt the image, cpp API hasn't been initialized");
496
+ return this.utilityApi.ens(image);
497
+ }
498
+ isVirtualCamera(label) {
499
+ this.checkWasmInitialization("Unable to check if the camera is virtual, cpp API hasn't been initialized");
500
+ if (label) return this.utilityApi.isVirtualCamera(label);
501
+ return false;
502
+ }
503
+ estimatePerformance() {
504
+ this.checkWasmInitialization("Unable to estimate performance, cpp API hasn't been initialized");
505
+ return this.utilityApi.estimatePerformance();
506
+ }
507
+ async analyzeFrame(image) {
508
+ this.checkWasmInitialization("Unable to analyze the frame, cpp API hasn't been initialized");
509
+ await this.allocateImageBuffers(image.width, image.height);
510
+ this.inputImageBuffer.set(image.data);
511
+ this.utilityApi.analyzeFrame();
512
+ }
513
+ /**
514
+ * Free allocated memory
515
+ */
516
+ async freeResources() {
517
+ this.versionsFile = null;
518
+ this.modelsBuffers = null;
519
+ this.inputImageBuffer = null;
520
+ this.imageWidth_ = null;
521
+ this.imageHeight_ = null;
522
+ this.pipelines_ = null;
523
+ window.wasmArrayBuffer = null;
524
+ if (this.workflowApiUtilities && typeof this.workflowApiUtilities.delete === "function") {
525
+ this.workflowApiUtilities.delete();
526
+ this.workflowApiUtilities = null;
527
+ }
528
+ if (this.utilityApi && typeof this.utilityApi.delete === "function") {
529
+ this.utilityApi.delete();
530
+ this.utilityApi = null;
531
+ }
532
+ if (this.idCaptureWasmApi && typeof this.idCaptureWasmApi.delete === "function") {
533
+ this.idCaptureWasmApi.delete();
534
+ this.idCaptureWasmApi = null;
535
+ }
536
+ if (this.faceProcessingWasmApi && typeof this.faceProcessingWasmApi.delete === "function") {
537
+ this.faceProcessingWasmApi.delete();
538
+ this.faceProcessingWasmApi = null;
539
+ }
540
+ if (this.webApi && typeof this.webApi.delete === "function") this.webApi.delete();
541
+ this.webApi = null;
542
+ this.wasmModule = null;
543
+ this.isInitialized_ = false;
544
+ }
545
+ /**
546
+ * Clear pipeline state
547
+ */
548
+ resetPipeline(type) {
549
+ this.checkWasmInitialization("Unable to reset pipeline, cpp API hasn't been initialized");
550
+ this.workflowApiUtilities.resetWorkflow(this.pipelineTypeToWasmEnum(type));
551
+ }
552
+ /**
553
+ * Clear all pipelines states
554
+ */
555
+ resetAllPipelines() {
556
+ this.checkWasmInitialization("Unable to reset pipelines, cpp API hasn't been initialized");
557
+ for (const [type, model] of this.pipelines_) this.resetPipeline(type);
558
+ }
559
+ /**
560
+ * Clear all states, not related to ml pipelines
561
+ */
562
+ resetOther() {
563
+ this.checkWasmInitialization("Unable to reset other states, cpp API hasn't been initialized");
564
+ this.utilityApi.resetOther();
565
+ }
566
+ /**
567
+ * Full reset
568
+ */
569
+ reset() {
570
+ this.resetAllPipelines();
571
+ this.resetOther();
572
+ }
573
+ /**
574
+ * Process one frame using one of the pipelines
575
+ * @param {ImageData} image - input image
576
+ * @param {WasmPipelineType} type - pipeline type
577
+ * @returns
578
+ */
579
+ async process(image, type) {
580
+ this.checkWasmInitialization("Unable to process the image, cpp API hasn't been initialized");
581
+ if (this.inputImageBuffer === null) throw new Error("Unable to process the image, buffers haven't been allocated!");
582
+ this.inputImageBuffer.set(image.data);
583
+ switch (type) {
584
+ case WasmPipelineType.IdBlurGlarePipeline:
585
+ case WasmPipelineType.IdBarcodeAndTextQualityPipeline: return this.idCaptureWasmApi.runIdCaptureWorkflow(this.pipelineTypeToWasmEnum(type));
586
+ case WasmPipelineType.IdVideoSelfiePipeline: return this.idCaptureWasmApi.runIdVideoSelfieWorkflow();
587
+ case WasmPipelineType.SelfieWithAggregationMetrics:
588
+ case WasmPipelineType.SelfieWithQualityMetrics:
589
+ case WasmPipelineType.OnDeviceSelfieWorkflow: return this.faceProcessingWasmApi.runSelfieWorkflow(this.pipelineTypeToWasmEnum(type));
590
+ default: throw new Error("Unknown pipeline type");
591
+ }
592
+ }
593
+ async runIdCapture(image) {
594
+ this.checkWasmInitialization("Unable to run Id Capture, cpp API hasn't been initialized");
595
+ if (this.inputImageBuffer === null) throw new Error("Unable to process the image, buffers haven't been allocated!");
596
+ this.inputImageBuffer.set(image.data);
597
+ return this.idCaptureWasmApi.runIdCapture();
598
+ }
599
+ async runSelfieCapture(image) {
600
+ this.checkWasmInitialization("Unable to run Selfie Capture, cpp API hasn't been initialized");
601
+ if (this.inputImageBuffer === null) throw new Error("Unable to process the image, buffers haven't been allocated!");
602
+ this.inputImageBuffer.set(image.data);
603
+ return this.faceProcessingWasmApi.runSelfieCapture();
604
+ }
605
+ async setFacePositionConstraints(type, minX, minY, maxX, maxY) {
606
+ this.checkWasmInitialization("Unable to set face position constraints, cpp API hasn't been initialized");
607
+ this.faceProcessingWasmApi.setFacePositionConstraints(this.pipelineTypeToWasmEnum(type), minX, minY, maxX, maxY);
608
+ }
609
+ async setFaceDetectionThresholds(type, brightnessThreshold, blurrinessThreshold, tiltRotationAngleThreshold, minMagicCropSize, autocaptureInterval, minFaceQualityScore, faceOcclusionThreshold, getReadyDelay, framesAggregationInterval, minFramesWithFace) {
610
+ this.checkWasmInitialization("Unable to set face detection thresholds, cpp API hasn't been initialized");
611
+ this.faceProcessingWasmApi.setFaceProcessingThresholds(this.pipelineTypeToWasmEnum(type), brightnessThreshold, blurrinessThreshold, tiltRotationAngleThreshold, minMagicCropSize, autocaptureInterval, minFaceQualityScore, faceOcclusionThreshold, getReadyDelay, framesAggregationInterval, minFramesWithFace);
612
+ }
613
+ async setFaceAttributesThresholds(type, headwearThreshold, lensesThreshold, closedEyesThreshold, maskThreshold) {
614
+ this.checkWasmInitialization("Unable to set face attributes thresholds, cpp API hasn't been initialized");
615
+ this.faceProcessingWasmApi.setFaceAttributesThresholds(this.pipelineTypeToWasmEnum(type), headwearThreshold, lensesThreshold, closedEyesThreshold, maskThreshold);
616
+ }
617
+ async setFaceChecksEnabled(type, isLensesCheckEnabled, isMaskCheckEnabled, isClosedEyesCheckEnabled, isHeadWearCheckEnabled, isOcclusionCheckEnabled) {
618
+ this.checkWasmInitialization("Unable to set face checks enabled flags, cpp API hasn't been initialized");
619
+ this.faceProcessingWasmApi.setFaceChecksEnabled(this.pipelineTypeToWasmEnum(type), isLensesCheckEnabled, isMaskCheckEnabled, isClosedEyesCheckEnabled, isHeadWearCheckEnabled, isOcclusionCheckEnabled);
620
+ }
621
+ async setFaceDetectionMode(type, isVideoSelfie) {
622
+ this.checkWasmInitialization("Unable to set face detection mode, cpp API hasn't been initialized");
623
+ this.faceProcessingWasmApi.setFaceProcessingMode(this.pipelineTypeToWasmEnum(type), isVideoSelfie);
624
+ }
625
+ async setFaceDetectionCallbacks(type, onFarAway, onTooClose, onTooManyFaces, onNoFace, onCapture, onGetReady, onGetReadyFinished, onCenterFace, onDark, onBlur, onFaceAngle, onLenses, onMask, onEyesClosed, onHeadWear, onSwitchToManualCapture, onFaceOccluded) {
626
+ this.checkWasmInitialization("Unable to set face detection callbacks, cpp API hasn't been initialized");
627
+ this.faceProcessingWasmApi.setFaceProcessingCallbacks(this.pipelineTypeToWasmEnum(type), onFarAway, onTooClose, onTooManyFaces, onNoFace, onCapture, onGetReady, onGetReadyFinished, onCenterFace, onDark, onBlur, onFaceAngle, onLenses, onMask, onEyesClosed, onHeadWear, onSwitchToManualCapture, onFaceOccluded);
628
+ }
629
+ async setIdCaptureThresholds(type, blurThreshold, blurChangeThreshold, glareThreshold, clsThreshold, sideThreshold, iouThreshold, idDetectedTimeout, autocaptureTimeout, framesAggregationInterval) {
630
+ this.checkWasmInitialization("Unable to set thresholds, cpp API hasn't been initialized");
631
+ this.idCaptureWasmApi.setIdCaptureThresholds(this.pipelineTypeToWasmEnum(type), blurThreshold, blurChangeThreshold, glareThreshold, clsThreshold, sideThreshold, iouThreshold, idDetectedTimeout, autocaptureTimeout, framesAggregationInterval);
632
+ }
633
+ async setIdCaptureCallbacks(type, onFarAway, onDetectionStarted, onMaskChange, onBlur, onGlare, onCapturing, onCapture, onBestFrame, onIDNotDetected, onSwitchToManualCapture, onIDTypeChange, onIDSideChange, onCapturingCounterValueChange) {
634
+ this.checkWasmInitialization("Unable to set callbacks, cpp API hasn't been initialized");
635
+ this.idCaptureWasmApi.setIdCaptureCallbacks(this.pipelineTypeToWasmEnum(type), onFarAway, onDetectionStarted, onMaskChange, onBlur, onGlare, onCapturing, onCapture, onBestFrame, onIDNotDetected, onSwitchToManualCapture, onIDTypeChange, onIDSideChange, onCapturingCounterValueChange);
636
+ }
637
+ async setIdCaptureGeometryParams(type, areaDown, areaUp, areaIOSPassportUp, areaIOSPassportDown, widthIOSUp, widthIOSDown, widthDown, widthUp, windowOuterWidth, windowOuterHeight, windowInnerWidth, windowInnerHeight) {
638
+ this.checkWasmInitialization("Unable to set geometry params, cpp API hasn't been initialized");
639
+ this.idCaptureWasmApi.setIdCaptureGeometryParams(this.pipelineTypeToWasmEnum(type), areaDown, areaUp, areaIOSPassportUp, areaIOSPassportDown, widthIOSUp, widthIOSDown, widthDown, widthUp, windowOuterWidth, windowOuterHeight, windowInnerWidth, windowInnerHeight);
640
+ }
641
+ async setIdCaptureConfigParams(type, isFixedMask, isIPhone14OrHigher, idType, isBlurCheckEnabled, isGlareCheckEnabled, _isIdFaceQualityCheckEnabled, isIouCheckEnabled, isFPSLimitEnabled) {
642
+ this.checkWasmInitialization("Unable to set config params, cpp API hasn't been initialized");
643
+ this.idCaptureWasmApi.setIdCaptureConfigParams(this.pipelineTypeToWasmEnum(type), isFixedMask, isIPhone14OrHigher, idType, isBlurCheckEnabled, isGlareCheckEnabled, isIouCheckEnabled, isFPSLimitEnabled);
644
+ }
645
+ setIdCaptureModelType(pipelineType, modelType) {
646
+ this.checkWasmInitialization("Unable to set model type, cpp API hasn't been initialized");
647
+ this.idCaptureWasmApi.setIdCaptureModelType(this.pipelineTypeToWasmEnum(pipelineType), this.IdCaptureModelTypeToWasmEnum(modelType));
648
+ }
649
+ IdPerspectiveTransform(image, frameRect) {
650
+ this.checkWasmInitialization("Unable to perform perspective transform, cpp API hasn't been initialized");
651
+ return this.idCaptureWasmApi.IdPerspectiveTransform(image, frameRect);
652
+ }
653
+ async getVersions() {
654
+ const text = await (await fetch(this.versionsFile)).text();
655
+ return JSON.parse(text);
656
+ }
657
+ async loadModels() {
658
+ this.checkWasmInitialization("Unable load the models, cpp API hasn't been initialized");
659
+ const buffSizes = new this.wasmModule.WorkflowTypeToIntMap();
660
+ const modelData = /* @__PURE__ */ new Map();
661
+ const loadedModels = /* @__PURE__ */ new Map();
662
+ for (const [type, modelsPaths] of this.pipelines_) {
663
+ const wasmType = this.pipelineTypeToWasmEnum(type);
664
+ const pipelineBuffers = [];
665
+ const sizes = new this.wasmModule.VectorInt();
666
+ for (const path of modelsPaths) {
667
+ if (!loadedModels.has(path)) {
668
+ const model$1 = await fetch(path).then((response) => response.arrayBuffer()).then((buffer) => new Uint8Array(buffer));
669
+ loadedModels.set(path, model$1);
670
+ }
671
+ const model = loadedModels.get(path);
672
+ sizes.push_back(model.byteLength);
673
+ pipelineBuffers.push(model);
674
+ }
675
+ buffSizes.set(wasmType, sizes);
676
+ modelData.set(wasmType, pipelineBuffers);
677
+ }
678
+ this.modelsBuffers = this.workflowApiUtilities.allocateModelsBuffers(buffSizes);
679
+ for (const [type, data] of modelData) {
680
+ const buffers = this.modelsBuffers?.get(type);
681
+ for (let k = 0; k < buffers.size(); k++) {
682
+ const buffer = buffers?.get(k);
683
+ if (buffer) buffer.set(data[k]);
684
+ else throw new Error("Unable to get model buffer from shared memory!");
685
+ }
686
+ }
687
+ }
688
+ async initializePipelines() {
689
+ this.checkWasmInitialization("Unable to initialize pipelines, cpp API hasn't been initialized");
690
+ if (!this.modelsBuffers) await this.loadModels();
691
+ this.workflowApiUtilities.initializeWorkflows();
692
+ }
693
+ async setProductionMode(productionMode) {
694
+ this.checkWasmInitialization("Unable to set production mode, cpp API hasn't been initialized");
695
+ this.utilityApi.setProductionMode(productionMode);
696
+ }
697
+ getPipelineState() {
698
+ this.checkWasmInitialization("Unable to get pipeline state, cpp API hasn't been initialized");
699
+ return this.workflowApiUtilities.getWorkflowState();
700
+ }
701
+ getCurrentPipeline() {
702
+ this.checkWasmInitialization("Unable to get current pipeline, cpp API hasn't been initialized");
703
+ return this.pipelineTypeFromWasmEnum(this.workflowApiUtilities.getCurrentWorkflow());
704
+ }
705
+ setSdkVersion(sdkVersion) {
706
+ this.checkWasmInitialization("Unable to set sdk version, cpp API hasn't been initialized");
707
+ this.utilityApi.setSdkVersion(sdkVersion);
708
+ }
709
+ setSdkPlatform(sdkPlatform) {
710
+ this.checkWasmInitialization("Unable to set device type, cpp API hasn't been initialized");
711
+ this.utilityApi.setSdkPlatform(sdkPlatform);
712
+ }
713
+ setDeviceInfo(deviceInfo, overrideExisting = true) {
714
+ this.checkWasmInitialization("Unable to set device info, cpp API hasn't been initialized");
715
+ this.utilityApi.setDeviceInfo(deviceInfo, overrideExisting);
716
+ }
717
+ setBrowserInfo(browserInfo, overrideExisting = true) {
718
+ this.checkWasmInitialization("Unable to set browser info, cpp API hasn't been initialized");
719
+ this.utilityApi.setBrowserInfo(browserInfo, overrideExisting);
720
+ }
721
+ setCameraInfo(cameraInfo, overrideExisting = true) {
722
+ this.checkWasmInitialization("Unable to set camera info, cpp API hasn't been initialized");
723
+ this.utilityApi.setCameraInfo(cameraInfo, overrideExisting);
724
+ }
725
+ setZc(zc) {
726
+ this.checkWasmInitialization("Unable to set zc, cpp API hasn't been initialized");
727
+ this.utilityApi.setZc(zc);
728
+ }
729
+ setMotionStatus(motionStatus) {
730
+ this.checkWasmInitialization("Unable to set motion status, cpp API hasn't been initialized");
731
+ this.utilityApi.setMotionStatus(motionStatus);
732
+ }
733
+ setMetadataField(key, value) {
734
+ this.checkWasmInitialization("Unable to set metadata field, cpp API hasn't been initialized");
735
+ this.utilityApi.setMetadataField(key, value);
736
+ }
737
+ setInspectorOpened(inspectorOpened) {
738
+ this.inspectorOpened_ = inspectorOpened;
739
+ }
740
+ setBackgroundMode(backgroundMode) {
741
+ this.checkWasmInitialization("Unable to set background mode, cpp API hasn't been initialized");
742
+ this.utilityApi.setBackgroundMode(backgroundMode);
743
+ }
744
+ getCheck() {
745
+ this.checkWasmInitialization("Unable to get check, cpp API hasn't been initialized");
746
+ return this.utilityApi.getCheck();
747
+ }
748
+ getMetadata() {
749
+ this.checkWasmInitialization("Unable to get metadata, cpp API hasn't been initialized");
750
+ this.utilityApi.setInspectorOpened(this.inspectorOpened_);
751
+ return this.utilityApi.getMetadata();
752
+ }
753
+ async prc() {
754
+ this.checkWasmInitialization("Unable to prc, cpp API hasn't been initialized");
755
+ await wasmCallWrapper(this.wasmCallSemaphore, () => this.utilityApi.prc(), true);
756
+ }
757
+ async poc(output) {
758
+ this.checkWasmInitialization("Unable to poc, cpp API hasn't been initialized");
759
+ await wasmCallWrapper(this.wasmCallSemaphore, () => this.utilityApi.poc(output), true);
760
+ }
761
+ ckvcks(data) {
762
+ this.checkWasmInitialization("Unable to ckvcks, cpp API hasn't been initialized");
763
+ this.utilityApi.ckvcks(data);
764
+ }
765
+ /**
766
+ * Synchronous manual-capture entry point for the OnDevice selfie workflow.
767
+ * Runs face detection + the full on-device quality / liveness / age pipeline
768
+ * on a single canvas image and stages the results inside the WASM `WebApi`
769
+ * for the next {@link postFaceResults} call. No polling, no semaphore wrap.
770
+ *
771
+ * Mirrors `ml-wasm-kit/WasmApi.processPhoto`.
772
+ */
773
+ processPhoto(canvas) {
774
+ this.checkWasmInitialization("Unable to process photo, cpp API hasn't been initialized");
775
+ this.faceProcessingWasmApi.processPhoto(canvas);
776
+ }
777
+ /**
778
+ * POSTs the staged on-device face-results JSON to `/omni/add/face-results`
779
+ * via the C++ `WebApi`. The C++ side encrypts the body with
780
+ * `SessionEncryptor` and routes through the WASM `WebClient` with inline
781
+ * encryption (`ie=true`) — this does NOT depend on the WebClient E2EE
782
+ * session setup, so it works whether `setupWasmConnection` was called with
783
+ * `encryptionEnabled` true or false.
784
+ *
785
+ * Reads from the `WebApi` instance constructed in {@link initialize}. The
786
+ * C++ `OnDeviceSelfieWorkflow` has already staged the aggregated best-shot
787
+ * results into that instance via `WebApi::setFaceResults(...)` during
788
+ * per-frame processing (auto-capture) or via {@link processPhoto}
789
+ * (manual-capture).
790
+ */
791
+ postFaceResults(config) {
792
+ this.checkWasmInitialization("Unable to post face results, cpp API hasn't been initialized");
793
+ return this.webApi.postFaceResults(config ?? {});
794
+ }
795
+ pipelineTypeToWasmEnum(type) {
796
+ switch (type) {
797
+ case WasmPipelineType.IdBlurGlarePipeline: return this.wasmModule.WorkflowType.IdBlurGlareWorkflow;
798
+ case WasmPipelineType.IdBarcodeAndTextQualityPipeline: return this.wasmModule.WorkflowType.IdBarcodeAndTextQualityWorkflow;
799
+ case WasmPipelineType.IdVideoSelfiePipeline: return this.wasmModule.WorkflowType.IdVideoSelfieWorkflow;
800
+ case WasmPipelineType.SelfieWithAggregationMetrics: return this.wasmModule.WorkflowType.SelfieWithAggregationMetrics;
801
+ case WasmPipelineType.SelfieWithQualityMetrics: return this.wasmModule.WorkflowType.SelfieWithQualityMetrics;
802
+ case WasmPipelineType.OnDeviceSelfieWorkflow: return this.wasmModule.WorkflowType.OnDeviceSelfieWorkflow;
803
+ default: throw new Error("Unknown pipeline type");
804
+ }
805
+ }
806
+ pipelineTypeFromWasmEnum(type) {
807
+ switch (type) {
808
+ case this.wasmModule.WorkflowType.IdBlurGlareWorkflow: return WasmPipelineType.IdBlurGlarePipeline;
809
+ case this.wasmModule.WorkflowType.IdBarcodeAndTextQualityWorkflow: return WasmPipelineType.IdBarcodeAndTextQualityPipeline;
810
+ case this.wasmModule.WorkflowType.IdVideoSelfieWorkflow: return WasmPipelineType.IdVideoSelfiePipeline;
811
+ case this.wasmModule.WorkflowType.SelfieWithAggregationMetrics: return WasmPipelineType.SelfieWithAggregationMetrics;
812
+ case this.wasmModule.WorkflowType.SelfieWithQualityMetrics: return WasmPipelineType.SelfieWithQualityMetrics;
813
+ case this.wasmModule.WorkflowType.OnDeviceSelfieWorkflow: return WasmPipelineType.OnDeviceSelfieWorkflow;
814
+ default: throw new Error("Unknown pipeline type");
815
+ }
816
+ }
817
+ IdCaptureModelTypeToWasmEnum(type) {
818
+ switch (type) {
819
+ case IdCaptureModelType.IdCaptureV1x: return this.wasmModule.IdCaptureModelType.IdCaptureV1x;
820
+ case IdCaptureModelType.IdCaptureV2x: return this.wasmModule.IdCaptureModelType.IdCaptureV2x;
821
+ case IdCaptureModelType.IdCaptureV3x: return this.wasmModule.IdCaptureModelType.IdCaptureV3x;
822
+ default: throw new Error("Unknown Id Capture model type");
823
+ }
824
+ }
825
+ IdCaptureModelTypeFromWasmEnum(type) {
826
+ switch (type) {
827
+ case this.wasmModule.IdCaptureModelType.IdCaptureV1x: return IdCaptureModelType.IdCaptureV1x;
828
+ case this.wasmModule.IdCaptureModelType.IdCaptureV2x: return IdCaptureModelType.IdCaptureV2x;
829
+ case this.wasmModule.IdCaptureModelType.IdCaptureV3x: return IdCaptureModelType.IdCaptureV3x;
830
+ default: throw new Error("Unknown Id Capture model type");
831
+ }
832
+ }
833
+ checkWasmInitialization(message) {
834
+ if (!this.isInitialized()) throw new Error(message);
835
+ }
836
+ };
837
+ var mlWasmJSApi_default = MlWasmJSApi.getInstance();
838
+
839
+ //#endregion
840
+ //#region ../infra/src/wasm/warmup.ts
841
+ /**
842
+ * Pipelines preloaded when no explicit `pipelines` array is passed to
843
+ * {@link warmupWasm}. The on-device selfie bundle is opt-in (loaded only when
844
+ * a SELFIE/AUTH module has `onDeviceFaceResultsSubmissionEnabled: true`), so
845
+ * it is intentionally excluded here to keep the default warmup small.
846
+ */
847
+ const WASM_PIPELINES = ["selfie", "idCapture"];
848
+ /**
849
+ * Default model files for each pipeline.
850
+ * These are the ONNX model files required by each ML pipeline.
851
+ */
852
+ const DEFAULT_PIPELINE_MODELS = {
853
+ selfie: [
854
+ "selfie_bf_angles_192x192_opset9_fp16.ortmodelv2",
855
+ "face_attributes_v1_3_fp16.ortmodelv2",
856
+ "mls_regressor_4773007c657b4f05a460321456740d0f_fp16.ortmodelv2",
857
+ "face_occlusion_v0_2_fp16.ortmodelv2"
858
+ ],
859
+ onDeviceSelfie: [
860
+ "selfie_bf_angles_192x192_opset9_fp16.ortmodelv2",
861
+ "face_attributes_v1_3_fp16.ortmodelv2",
862
+ "mls_regressor_4773007c657b4f05a460321456740d0f_fp16.ortmodelv2",
863
+ "face_occlusion_v0_2_fp16.ortmodelv2",
864
+ "ondevice_physical_liveness_v2_1_fp16.ortmodelv2",
865
+ "age_estimation_v2_2_2_fp16.ortmodelv2"
866
+ ],
867
+ idCapture: ["id_capture_2_01_fp16.ortmodelv2", "id_fiqa_19a81a0b9bf6492eb03b4667f6db4c85_fp16.ortmodelv2"]
868
+ };
869
+ let state = "idle";
870
+ let loadingPromise = null;
871
+ let wasmError = null;
872
+ let loadedPipelines = [];
873
+ let lastConfig = null;
874
+ function mapPipelineToWasmType(pipeline) {
875
+ switch (pipeline) {
876
+ case "selfie": return WasmPipelineType.SelfieWithQualityMetrics;
877
+ case "onDeviceSelfie": return WasmPipelineType.OnDeviceSelfieWorkflow;
878
+ case "idCapture": return WasmPipelineType.IdBlurGlarePipeline;
879
+ default: throw new Error(`Unknown pipeline: ${pipeline}`);
880
+ }
881
+ }
882
+ /**
883
+ * Derives the models base path from the WASM path.
884
+ * Assumes models are in a 'models' subdirectory relative to the WASM binary location.
885
+ * e.g., '/wasm/v2/binary.wasm' -> '/wasm/v2/models'
886
+ */
887
+ function deriveModelsBasePath(wasmPath) {
888
+ const lastSlashIndex = wasmPath.lastIndexOf("/");
889
+ if (lastSlashIndex === -1) return "models";
890
+ return `${wasmPath.substring(0, lastSlashIndex)}/models`;
891
+ }
892
+ /**
893
+ * Builds the pipelines map with model paths for WASM initialization.
894
+ * @param pipelines - Array of pipeline types to initialize
895
+ * @param modelsBasePath - Base path where model files are located
896
+ * @param customModels - Optional custom model files per pipeline
897
+ */
898
+ function buildPipelinesMap(pipelines, modelsBasePath, customModels) {
899
+ const pipelinesMap = /* @__PURE__ */ new Map();
900
+ for (const pipeline of pipelines) {
901
+ const wasmType = mapPipelineToWasmType(pipeline);
902
+ if (!pipelinesMap.has(wasmType)) {
903
+ const modelPaths = (customModels?.[pipeline] ?? DEFAULT_PIPELINE_MODELS[pipeline]).map((modelFile) => `${modelsBasePath}/${modelFile}`);
904
+ pipelinesMap.set(wasmType, modelPaths);
905
+ }
906
+ }
907
+ return pipelinesMap;
908
+ }
909
+ /**
910
+ * Preloads WASM binary and ML models at app startup.
911
+ * Runs asynchronously - app can continue while WASM loads in background.
912
+ *
913
+ * Model files are automatically loaded based on the pipeline type.
914
+ * By default, models are expected in a 'models' subdirectory relative to the WASM binary.
915
+ *
916
+ * @param config - Configuration for WASM warmup
917
+ * @returns Promise that resolves when WASM is ready
918
+ *
919
+ * @example
920
+ * ```ts
921
+ * // Basic usage - models loaded from /wasm/v2/models/
922
+ * warmupWasm({
923
+ * wasmPath: '/wasm/v2/ml-wasm.wasm',
924
+ * glueCodePath: '/wasm/v2/ml-wasm.js',
925
+ * pipelines: ['selfie', 'idCapture'],
926
+ * });
927
+ *
928
+ * // With explicit models path
929
+ * warmupWasm({
930
+ * wasmPath: '/wasm/v2/ml-wasm.wasm',
931
+ * glueCodePath: '/wasm/v2/ml-wasm.js',
932
+ * modelsBasePath: 'https://cdn.example.com/wasm/v2/models',
933
+ * pipelines: ['selfie'],
934
+ * });
935
+ * ```
936
+ */
937
+ async function warmupWasm(config) {
938
+ const pipelines = config.pipelines ?? [...WASM_PIPELINES];
939
+ const modelsBasePath = config.modelsBasePath ?? deriveModelsBasePath(config.wasmPath);
940
+ if (state === "loading" && loadingPromise) return loadingPromise;
941
+ if (state === "ready") {
942
+ if (pipelines.filter((p) => !loadedPipelines.includes(p)).length === 0) return;
943
+ if (!lastConfig) throw new Error("Cannot add pipelines: original warmup config not available");
944
+ if (lastConfig.wasmPath !== config.wasmPath || lastConfig.glueCodePath !== config.glueCodePath || (lastConfig.wasmSimdPath ?? lastConfig.wasmPath) !== (config.wasmSimdPath ?? config.wasmPath) || (lastConfig.glueCodeSimdPath ?? "") !== (config.glueCodeSimdPath ?? "") || (lastConfig.useSimd ?? true) !== (config.useSimd ?? true)) throw new Error("Cannot add pipelines: WASM config mismatch. Use same wasmPath, glueCodePath, and useSimd settings.");
945
+ const combinedPipelines = [...new Set([...loadedPipelines, ...pipelines])];
946
+ state = "loading";
947
+ wasmError = null;
948
+ loadingPromise = (async () => {
949
+ try {
950
+ const pipelinesMap = buildPipelinesMap(combinedPipelines, lastConfig.modelsBasePath ?? deriveModelsBasePath(lastConfig.wasmPath), lastConfig.pipelineModels);
951
+ await mlWasmJSApi_default.initialize(lastConfig.wasmPath, lastConfig.wasmSimdPath ?? lastConfig.wasmPath, lastConfig.glueCodePath, lastConfig.glueCodeSimdPath ?? "", lastConfig.useSimd ?? true, "", pipelinesMap);
952
+ await mlWasmJSApi_default.loadModels();
953
+ await mlWasmJSApi_default.initializePipelines();
954
+ state = "ready";
955
+ loadedPipelines = combinedPipelines;
956
+ lastConfig = {
957
+ ...lastConfig,
958
+ pipelines: combinedPipelines
959
+ };
960
+ loadingPromise = null;
961
+ } catch (error) {
962
+ state = "error";
963
+ wasmError = error instanceof Error ? error : new Error(String(error));
964
+ loadingPromise = null;
965
+ throw wasmError;
966
+ }
967
+ })();
968
+ return loadingPromise;
969
+ }
970
+ state = "loading";
971
+ wasmError = null;
972
+ loadingPromise = (async () => {
973
+ try {
974
+ const pipelinesMap = buildPipelinesMap(pipelines, modelsBasePath, config.pipelineModels);
975
+ await mlWasmJSApi_default.initialize(config.wasmPath, config.wasmSimdPath ?? config.wasmPath, config.glueCodePath, config.glueCodeSimdPath ?? "", config.useSimd ?? true, "", pipelinesMap);
976
+ await mlWasmJSApi_default.loadModels();
977
+ await mlWasmJSApi_default.initializePipelines();
978
+ state = "ready";
979
+ loadedPipelines = [...pipelines];
980
+ lastConfig = {
981
+ ...config,
982
+ pipelines
983
+ };
984
+ loadingPromise = null;
985
+ } catch (error) {
986
+ state = "error";
987
+ wasmError = error instanceof Error ? error : new Error(String(error));
988
+ loadingPromise = null;
989
+ throw wasmError;
990
+ }
991
+ })();
992
+ return loadingPromise;
993
+ }
994
+ /**
995
+ * Returns the current warmup status.
996
+ * Useful for showing loading indicators.
997
+ *
998
+ * @returns Current warmup status
999
+ */
1000
+ function getWasmStatus() {
1001
+ return {
1002
+ isReady: state === "ready",
1003
+ isLoading: state === "loading",
1004
+ error: wasmError ?? void 0,
1005
+ loadedPipelines: [...loadedPipelines]
1006
+ };
1007
+ }
1008
+ /**
1009
+ * Returns true if WASM is fully initialized and ready.
1010
+ *
1011
+ * @returns True if WASM is ready
1012
+ */
1013
+ function isWasmReady() {
1014
+ return state === "ready";
1015
+ }
1016
+ /**
1017
+ * Returns a promise that resolves when WASM is ready.
1018
+ * - If ready: resolves immediately
1019
+ * - If loading: waits for completion, then resolves
1020
+ * - If not started: rejects with error
1021
+ *
1022
+ * @returns Promise that resolves when WASM is ready
1023
+ * @throws Error if WASM is in error state or was never started
1024
+ */
1025
+ function waitForWasm() {
1026
+ if (state === "ready") return Promise.resolve();
1027
+ if (state === "loading" && loadingPromise) return loadingPromise;
1028
+ if (state === "error") return Promise.reject(wasmError ?? /* @__PURE__ */ new Error("WASM initialization failed"));
1029
+ return Promise.reject(/* @__PURE__ */ new Error("WASM warmup was not started. Call warmupWasm() first."));
1030
+ }
1031
+
1032
+ //#endregion
1033
+ //#region ../infra/src/providers/wasm/BaseWasmProvider.ts
1034
+ /**
1035
+ * Base provider class that abstracts common WASM functionality.
1036
+ * This serves as a foundation for specific ML capability providers
1037
+ * like FaceDetectionProvider and IdCaptureProvider.
1038
+ */
1039
+ var BaseWasmProvider = class {
1040
+ /**
1041
+ * Creates a new BaseWasmProvider
1042
+ * @param pipelineType - The WASM pipeline type this provider uses
1043
+ */
1044
+ constructor(pipelineType) {
1045
+ this._isInitialized = false;
1046
+ this.pipelineType = pipelineType;
1047
+ }
1048
+ /**
1049
+ * Returns whether this provider has been initialized.
1050
+ */
1051
+ get initialized() {
1052
+ return this._isInitialized;
1053
+ }
1054
+ getPipelineType() {
1055
+ if (this.pipelineType === void 0) throw new Error(`${this.constructor.name} has no pipeline type configured.`);
1056
+ return this.pipelineType;
1057
+ }
1058
+ /**
1059
+ * Initializes the provider by ensuring WASM is loaded
1060
+ * @param config - Provider configuration
1061
+ * @param pipeline - The pipeline type to warm up ('selfie', 'idCapture', etc.)
1062
+ */
1063
+ async initializeBase(config, pipeline) {
1064
+ if (this._isInitialized) return;
1065
+ const status = getWasmStatus();
1066
+ if (status.isLoading || isWasmReady() || status.error) await waitForWasm();
1067
+ else {
1068
+ if (!config.wasmPath || !config.glueCodePath) throw new Error("WASM path and glue code path are required. Call warmupWasm() first.");
1069
+ await warmupWasm({
1070
+ wasmPath: config.wasmPath,
1071
+ wasmSimdPath: config.wasmSimdPath,
1072
+ glueCodePath: config.glueCodePath,
1073
+ glueCodeSimdPath: config.glueCodeSimdPath,
1074
+ useSimd: config.useSimd,
1075
+ modelsBasePath: config.modelsBasePath,
1076
+ pipelines: [pipeline]
1077
+ });
1078
+ }
1079
+ this._isInitialized = true;
1080
+ }
1081
+ /**
1082
+ * Ensures the provider is initialized before performing operations.
1083
+ * @throws Error if not initialized
1084
+ */
1085
+ ensureInitialized() {
1086
+ if (!this._isInitialized) throw new Error(`${this.constructor.name} not initialized. Call initialize() first.`);
1087
+ }
1088
+ /**
1089
+ * Processes a frame through the WASM pipeline
1090
+ * @param image - Image data to process
1091
+ * @returns The pipeline result (type depends on pipeline - WASM returns any)
1092
+ */
1093
+ async processFrameWasm(image) {
1094
+ this.ensureInitialized();
1095
+ const pipelineType = this.getPipelineType();
1096
+ await mlWasmJSApi_default.allocateImageBuffers(image.width, image.height);
1097
+ await mlWasmJSApi_default.handleDetectionCallAndUpdateState(pipelineType);
1098
+ return await mlWasmJSApi_default.process(image, pipelineType);
1099
+ }
1100
+ /**
1101
+ * Resets the pipeline to its initial state.
1102
+ * Safe to call even if not initialized (no-op in that case).
1103
+ */
1104
+ reset() {
1105
+ if (this._isInitialized && this.pipelineType !== void 0) mlWasmJSApi_default.resetPipeline(this.pipelineType);
1106
+ }
1107
+ /**
1108
+ * Disposes of resources and resets initialization state.
1109
+ * Safe to call even if not initialized.
1110
+ */
1111
+ async dispose() {
1112
+ this.reset();
1113
+ this._isInitialized = false;
1114
+ }
1115
+ };
1116
+
1117
+ //#endregion
1118
+ export { executeWasmRequest as a, setupWasmConnection as c, WasmWebClientError as i, WasmPipelineType as l, warmupWasm as n, initializeWasmWebClient as o, mlWasmJSApi_default as r, setWebApiHttpTransport as s, BaseWasmProvider as t, IdCaptureModelType as u };