@jupitermetalabs/face-zk-sdk 0.1.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 (83) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +181 -0
  3. package/assets/README.md +22 -0
  4. package/assets/face-guidance/face-logic.js.txt +77 -0
  5. package/assets/face-guidance/index.html +173 -0
  6. package/assets/face-guidance/pose-guidance.js.txt +403 -0
  7. package/assets/liveness/antispoof.js.txt +143 -0
  8. package/assets/liveness/index.html +451 -0
  9. package/assets/liveness/liveness.js.txt +1003 -0
  10. package/assets/mediapipe/face_mesh.js.txt +131 -0
  11. package/assets/mediapipe/face_mesh_solution_packed_assets.data +0 -0
  12. package/assets/mediapipe/face_mesh_solution_simd_wasm_bin.wasm +0 -0
  13. package/assets/mediapipe/face_mesh_solution_wasm_bin.wasm +0 -0
  14. package/assets/onnx/ort-wasm-simd.wasm +0 -0
  15. package/assets/onnx/ort-wasm.wasm +0 -0
  16. package/assets/onnx/ort.min.js.txt +7 -0
  17. package/assets/wasm/zk_face_wasm_bg.wasm +0 -0
  18. package/assets/zk-worker.html +472 -0
  19. package/cli/copy-ort-assets.js +65 -0
  20. package/cli/setup.js +266 -0
  21. package/dist/FaceZkSdk.d.ts +69 -0
  22. package/dist/FaceZkSdk.js +132 -0
  23. package/dist/assets/onnx/ort-min.d.ts +1 -0
  24. package/dist/assets/onnx/ort-min.js +8 -0
  25. package/dist/config/defaults.d.ts +49 -0
  26. package/dist/config/defaults.js +55 -0
  27. package/dist/config/types.d.ts +123 -0
  28. package/dist/config/types.js +16 -0
  29. package/dist/core/enrollment-core.d.ts +68 -0
  30. package/dist/core/enrollment-core.js +202 -0
  31. package/dist/core/matching.d.ts +69 -0
  32. package/dist/core/matching.js +96 -0
  33. package/dist/core/types.d.ts +365 -0
  34. package/dist/core/types.js +34 -0
  35. package/dist/core/verification-core.d.ts +120 -0
  36. package/dist/core/verification-core.js +434 -0
  37. package/dist/core/zk-core.d.ts +69 -0
  38. package/dist/core/zk-core.js +240 -0
  39. package/dist/index.d.ts +29 -0
  40. package/dist/index.js +39 -0
  41. package/dist/react-native/adapters/faceEmbeddingProvider.d.ts +38 -0
  42. package/dist/react-native/adapters/faceEmbeddingProvider.js +41 -0
  43. package/dist/react-native/adapters/imageDataProvider.d.ts +53 -0
  44. package/dist/react-native/adapters/imageDataProvider.js +97 -0
  45. package/dist/react-native/adapters/livenessProvider.d.ts +133 -0
  46. package/dist/react-native/adapters/livenessProvider.js +144 -0
  47. package/dist/react-native/adapters/zkProofEngine-webview.d.ts +73 -0
  48. package/dist/react-native/adapters/zkProofEngine-webview.js +129 -0
  49. package/dist/react-native/components/FacePoseGuidanceWebView.d.ts +30 -0
  50. package/dist/react-native/components/FacePoseGuidanceWebView.js +474 -0
  51. package/dist/react-native/components/LivenessWebView.d.ts +39 -0
  52. package/dist/react-native/components/LivenessWebView.js +348 -0
  53. package/dist/react-native/components/OnnxRuntimeWebView.d.ts +54 -0
  54. package/dist/react-native/components/OnnxRuntimeWebView.js +394 -0
  55. package/dist/react-native/components/ZkProofWebView.d.ts +59 -0
  56. package/dist/react-native/components/ZkProofWebView.js +259 -0
  57. package/dist/react-native/dependencies.d.ts +144 -0
  58. package/dist/react-native/dependencies.js +123 -0
  59. package/dist/react-native/hooks/useOnnxLoader.d.ts +38 -0
  60. package/dist/react-native/hooks/useOnnxLoader.js +81 -0
  61. package/dist/react-native/hooks/useWasmLoader.d.ts +30 -0
  62. package/dist/react-native/hooks/useWasmLoader.js +122 -0
  63. package/dist/react-native/index.d.ts +59 -0
  64. package/dist/react-native/index.js +96 -0
  65. package/dist/react-native/services/FaceRecognition.d.ts +70 -0
  66. package/dist/react-native/services/FaceRecognition.js +517 -0
  67. package/dist/react-native/ui/FaceZkVerificationFlow.d.ts +97 -0
  68. package/dist/react-native/ui/FaceZkVerificationFlow.js +433 -0
  69. package/dist/react-native/ui/ReferenceEnrollmentFlow.d.ts +72 -0
  70. package/dist/react-native/ui/ReferenceEnrollmentFlow.js +321 -0
  71. package/dist/react-native/utils/faceAlignment.d.ts +37 -0
  72. package/dist/react-native/utils/faceAlignment.js +182 -0
  73. package/dist/react-native/utils/modelInitialisationChecks.d.ts +36 -0
  74. package/dist/react-native/utils/modelInitialisationChecks.js +92 -0
  75. package/dist/react-native/utils/resolveModelUri.d.ts +55 -0
  76. package/dist/react-native/utils/resolveModelUri.js +172 -0
  77. package/dist/react-native/utils/resolveUiConfig.d.ts +41 -0
  78. package/dist/react-native/utils/resolveUiConfig.js +76 -0
  79. package/dist/storage/defaultStorageAdapter.d.ts +44 -0
  80. package/dist/storage/defaultStorageAdapter.js +299 -0
  81. package/dist/tsconfig.tsbuildinfo +1 -0
  82. package/face-zk.config.example.js +88 -0
  83. package/package.json +76 -0
Binary file
@@ -0,0 +1,472 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <title>ZK Worker</title>
7
+ </head>
8
+
9
+ <body>
10
+ <div id="status">Initializing...</div>
11
+ <script>
12
+ // ==========================================
13
+ // WASM Bindings (Full set from pkg-web/zk_face_wasm.js)
14
+ // BUILD TIMESTAMP: 2025-12-22T17:00:00 [CACHE_BUST]
15
+ // ==========================================
16
+ const BUILD_TIMESTAMP = "2025-12-22T17:00:00";
17
+ let wasm;
18
+
19
+ const heap = new Array(128).fill(undefined);
20
+ heap.push(undefined, null, true, false);
21
+
22
+ function getObject(idx) { return heap[idx]; }
23
+
24
+ let heap_next = heap.length;
25
+
26
+ function dropObject(idx) {
27
+ if (idx < 132) return;
28
+ heap[idx] = heap_next;
29
+ heap_next = idx;
30
+ }
31
+
32
+ function takeObject(idx) {
33
+ const ret = getObject(idx);
34
+ dropObject(idx);
35
+ return ret;
36
+ }
37
+
38
+
39
+
40
+ function isLikeNone(x) {
41
+ return x === undefined || x === null;
42
+ }
43
+
44
+ // --- Memory Views ---
45
+ let cachedDataViewMemory0 = null;
46
+ function getDataViewMemory0() {
47
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
48
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
49
+ }
50
+ return cachedDataViewMemory0;
51
+ }
52
+
53
+ let cachedUint8ArrayMemory0 = null;
54
+ function getUint8ArrayMemory0() {
55
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
56
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
57
+ }
58
+ return cachedUint8ArrayMemory0;
59
+ }
60
+
61
+ function getArrayU8FromWasm0(ptr, len) {
62
+ ptr = ptr >>> 0;
63
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
64
+ }
65
+
66
+ // --- String Handling ---
67
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
68
+ cachedTextDecoder.decode();
69
+
70
+ function getStringFromWasm0(ptr, len) {
71
+ ptr = ptr >>> 0;
72
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
73
+ }
74
+
75
+ let WASM_VECTOR_LEN = 0;
76
+ let cachedTextEncoder = new TextEncoder('utf-8');
77
+
78
+ const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
79
+ ? function (arg, view) {
80
+ return cachedTextEncoder.encodeInto(arg, view);
81
+ }
82
+ : function (arg, view) {
83
+ const buf = cachedTextEncoder.encode(arg);
84
+ view.set(buf);
85
+ return {
86
+ read: arg.length,
87
+ written: buf.length
88
+ };
89
+ });
90
+
91
+ function passStringToWasm0(arg, malloc, realloc) {
92
+ if (realloc === undefined) {
93
+ const buf = cachedTextEncoder.encode(arg);
94
+ const ptr = malloc(buf.length, 1) >>> 0;
95
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
96
+ WASM_VECTOR_LEN = buf.length;
97
+ return ptr;
98
+ }
99
+
100
+ let len = arg.length;
101
+ let ptr = malloc(len, 1) >>> 0;
102
+ const mem = getUint8ArrayMemory0();
103
+ let offset = 0;
104
+
105
+ for (; offset < len; offset++) {
106
+ const code = arg.charCodeAt(offset);
107
+ if (code > 0x7F) break;
108
+ mem[ptr + offset] = code;
109
+ }
110
+ if (offset !== len) {
111
+ if (offset !== 0) {
112
+ arg = arg.slice(offset);
113
+ }
114
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
115
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
116
+ const ret = encodeString(arg, view);
117
+ offset += ret.written;
118
+ }
119
+ WASM_VECTOR_LEN = offset;
120
+ return ptr;
121
+ }
122
+
123
+
124
+
125
+ function takeFromExternrefTable0(idx) {
126
+ const value = wasm.__wbindgen_externrefs.get(idx);
127
+ wasm.__externref_table_dealloc(idx);
128
+ return value;
129
+ }
130
+
131
+ // --- THE FULL IMPORTS OBJECT ---
132
+ function getImports() {
133
+ const wbg = {};
134
+
135
+ wbg.__wbg_error_7534b8e9a36f1ab4 = function (arg0, arg1) {
136
+ let deferred0_0;
137
+ let deferred0_1;
138
+ try {
139
+ deferred0_0 = arg0;
140
+ deferred0_1 = arg1;
141
+ console.error(getStringFromWasm0(arg0, arg1));
142
+ } finally {
143
+ wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
144
+ }
145
+ };
146
+ wbg.__wbg_new_8a6f238a6ece86ea = function () {
147
+ const ret = new Error();
148
+ return ret;
149
+ };
150
+ wbg.__wbg_stack_0ed75d68575b0f3c = function (arg0, arg1) {
151
+ const ret = arg1.stack;
152
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
153
+ const len1 = WASM_VECTOR_LEN;
154
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
155
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
156
+ };
157
+ wbg.__wbindgen_cast_2241b6af4c4b2941 = function (arg0, arg1) {
158
+ const ret = getStringFromWasm0(arg0, arg1);
159
+ return ret;
160
+ };
161
+ wbg.__wbindgen_init_externref_table = function () {
162
+ const table = wasm.__wbindgen_externrefs;
163
+ const offset = table.grow(4);
164
+ table.set(0, undefined);
165
+ table.set(offset + 0, undefined);
166
+ table.set(offset + 1, null);
167
+ table.set(offset + 2, true);
168
+ table.set(offset + 3, false);
169
+ };
170
+
171
+ // DUAL-MODE RETURN
172
+ return {
173
+ wbg: wbg,
174
+ './zk_face_wasm_bg.js': wbg
175
+ };
176
+ }
177
+
178
+ function finalizeInit(instance, module) {
179
+ wasm = instance.exports;
180
+ cachedUint8ArrayMemory0 = null;
181
+ cachedDataViewMemory0 = null;
182
+
183
+ // Critical: Initialize the externref table
184
+ wasm.__wbindgen_start();
185
+ return wasm;
186
+ }
187
+
188
+ // ==========================================
189
+ // Main Application Logic
190
+ // ==========================================
191
+
192
+ function log(msg) {
193
+ console.log(msg);
194
+ if (window.ReactNativeWebView) {
195
+ window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'log', message: msg }));
196
+ }
197
+ }
198
+
199
+ function base64ToUint8Array(base64) {
200
+ // Basic Base64 decoding - ensure whitespace is removed
201
+ const cleanBase64 = base64.replace(/\s/g, '');
202
+ const binary_string = window.atob(cleanBase64);
203
+ const len = binary_string.length;
204
+ const bytes = new Uint8Array(len);
205
+ for (let i = 0; i < len; i++) {
206
+ bytes[i] = binary_string.charCodeAt(i);
207
+ }
208
+ return bytes;
209
+ }
210
+
211
+ // Initialize WASM (Plonky3 - No Proving Key Needed!)
212
+ async function initWasm(base64Data) {
213
+ try {
214
+ log('[ZK Worker] Instantiating Plonky3 WASM... Build: ' + (typeof BUILD_TIMESTAMP !== 'undefined' ? BUILD_TIMESTAMP : 'UNKNOWN'));
215
+ const bytes = base64ToUint8Array(base64Data);
216
+
217
+ // Use the imports from our inlined glue code
218
+ const imports = getImports();
219
+ log('[ZK Worker] Imports prepared. Keys: ' + Object.keys(imports).join(', '));
220
+
221
+ const { instance, module } = await WebAssembly.instantiate(bytes, imports);
222
+ finalizeInit(instance, module);
223
+
224
+ // No proving key needed with Plonky3 STARKs!
225
+ log('[ZK Worker] ✅ Plonky3 WASM Loaded (no keys needed!)');
226
+ document.getElementById('status').innerText = 'Ready - Plonky3';
227
+
228
+ window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'wasm_initialized' }));
229
+
230
+ } catch (err) {
231
+ log('[ZK Worker] FATAL: ' + err.message);
232
+ if (err.stack) log(err.stack);
233
+ document.getElementById('status').innerText = 'Error: ' + err.message;
234
+ }
235
+ }
236
+
237
+ async function generateProof(payload) {
238
+ if (!wasm) throw new Error("WASM not initialized");
239
+
240
+ const { alloc, dealloc, generate_face_proof_from_ptrs } = wasm;
241
+
242
+ // 1. Prepare Data
243
+ const storedFloats = new Float64Array(payload.storedEmbedding);
244
+ const capturedFloats = new Float64Array(payload.capturedEmbedding);
245
+
246
+ const storedSize = storedFloats.length * 8;
247
+ const capturedSize = capturedFloats.length * 8;
248
+
249
+ // 2. Alloc
250
+ const storedPtr = alloc(storedSize);
251
+ const capturedPtr = alloc(capturedSize);
252
+
253
+ try {
254
+ // 3. Write embeddings to WASM memory
255
+ // Use Uint8Array to copy bytes directly, avoiding "Byte offset is not aligned" errors
256
+ // if the allocator returns an address that isn't 8-byte aligned.
257
+ new Uint8Array(wasm.memory.buffer).set(new Uint8Array(storedFloats.buffer), storedPtr);
258
+ new Uint8Array(wasm.memory.buffer).set(new Uint8Array(capturedFloats.buffer), capturedPtr);
259
+
260
+ log('[ZK Worker] === Diagnostic Info ===');
261
+
262
+ // Prepare all parameters
263
+ const thresholdValue = payload.threshold || 0.6;
264
+ const nonceValue = BigInt(Date.now());
265
+
266
+ // Log parameter values
267
+ log(`Stored: ptr=${storedPtr}, count=${storedFloats.length}, first value=${storedFloats[0]}`);
268
+ log(`Captured: ptr=${capturedPtr}, count=${capturedFloats.length}, first value=${capturedFloats[0]}`);
269
+ log(`Threshold: ${thresholdValue}`);
270
+ log(`Nonce: ${nonceValue}`);
271
+
272
+ // Log parameter TYPES for debugging
273
+ log('[ZK Worker] === Parameter Types ===');
274
+ log(`storedPtr type: ${typeof storedPtr}, value: ${storedPtr}`);
275
+ log(`storedFloats.length type: ${typeof storedFloats.length}, value: ${storedFloats.length}`);
276
+ log(`capturedPtr type: ${typeof capturedPtr}, value: ${capturedPtr}`);
277
+ log(`capturedFloats.length type: ${typeof capturedFloats.length}, value: ${capturedFloats.length}`);
278
+ log(`threshold type: ${typeof thresholdValue}, value: ${thresholdValue}`);
279
+ log(`nonce type: ${typeof nonceValue}, value: ${nonceValue}`);
280
+
281
+ log('[ZK Worker] Calling Rust (Plonky3 - no PK needed)...');
282
+
283
+ const start = performance.now();
284
+
285
+ let ret;
286
+ try {
287
+ // 4. Call Rust (no PK parameters!)
288
+ // Plonky3 STARKs don't need proving keys
289
+ // Convert nonce to BigInt to match Rust u64 type
290
+ ret = generate_face_proof_from_ptrs(
291
+ storedPtr, storedFloats.length,
292
+ capturedPtr, capturedFloats.length,
293
+ thresholdValue,
294
+ nonceValue
295
+ );
296
+ log('[ZK Worker] Rust call returned successfully');
297
+ log(`[ZK Worker] Return value type: ${typeof ret}, isArray: ${Array.isArray(ret)}`);
298
+ if (Array.isArray(ret)) {
299
+ log(`[ZK Worker] Return array length: ${ret.length}`);
300
+ ret.forEach((val, idx) => {
301
+ log(`[ZK Worker] ret[${idx}] type: ${typeof val}, value: ${val}`);
302
+ });
303
+ }
304
+ } catch (wasmErr) {
305
+ log('[ZK Worker] WASM threw during call: ' + wasmErr.message);
306
+ log('[ZK Worker] Error stack: ' + (wasmErr.stack || 'No stack available'));
307
+ throw wasmErr;
308
+ }
309
+
310
+ var ptr = ret[0];
311
+ var len = ret[1];
312
+ var errPtr = ret[2];
313
+ var isErr = ret[3] !== 0;
314
+
315
+ if (isErr) {
316
+ // Extract error from externref table
317
+ const errorObj = takeFromExternrefTable0(errPtr);
318
+ throw new Error(errorObj);
319
+ }
320
+
321
+ // If success, read string from memory
322
+ const resultJson = getStringFromWasm0(ptr, len);
323
+
324
+ // Free the result string memory
325
+ if (wasm.__wbindgen_free) {
326
+ wasm.__wbindgen_free(ptr, len, 1);
327
+ }
328
+
329
+ const end = performance.now();
330
+ log(`[ZK Worker] ✅ Plonky3 proof generated in ${(end - start).toFixed(2)}ms`);
331
+
332
+ return resultJson;
333
+
334
+ } finally {
335
+ dealloc(storedPtr, storedSize);
336
+ dealloc(capturedPtr, capturedSize);
337
+ }
338
+ }
339
+
340
+ function handleMessage(event) {
341
+ try {
342
+ const msg = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
343
+
344
+ if (msg.type === 'init_wasm') {
345
+ initWasm(msg.payload.wasmBase64); // Access via payload
346
+ }
347
+ else if (msg.type === 'generate_proof') {
348
+ generateProof(msg.payload)
349
+ .then(result => {
350
+ log('[ZK Worker] Raw Result Type: ' + typeof result);
351
+ log('[ZK Worker] Raw Result Length: ' + result.length);
352
+ log('[ZK Worker] Raw Result Start: ' + result.substring(0, 50));
353
+ log('[ZK Worker] Raw Result End: ' + result.substring(result.length - 50));
354
+
355
+ let parsed;
356
+ try {
357
+ parsed = JSON.parse(result);
358
+ log('[ZK Worker] Parse Success. Keys: ' + Object.keys(parsed).join(', '));
359
+ if (parsed.proof) log('[ZK Worker] parsed.proof length: ' + parsed.proof.length);
360
+ } catch (e) {
361
+ log('[ZK Worker] JSON Parse Error: ' + e.message);
362
+ }
363
+
364
+ window.ReactNativeWebView.postMessage(JSON.stringify({
365
+ type: 'proof_result',
366
+ data: parsed
367
+ }));
368
+ })
369
+ .catch(err => {
370
+ // Handle WASM panics properly
371
+ let errorMsg = err.toString();
372
+ if (err.message) errorMsg = err.message;
373
+
374
+ window.ReactNativeWebView.postMessage(JSON.stringify({
375
+ type: 'error',
376
+ error: errorMsg
377
+ }));
378
+ });
379
+ }
380
+ else if (msg.type === 'verify_proof') {
381
+ if (!wasm) throw new Error("WASM not initialized");
382
+ try {
383
+ const { verify_face_proof, __wbindgen_free } = wasm;
384
+ const payload = msg.payload;
385
+
386
+ // LOG THE RAW PAYLOAD GOING TO RUST
387
+ log('[ZK Worker] Verify Payload Keys: ' + Object.keys(payload).join(', '));
388
+ if(payload.public_inputs) {
389
+ log('[ZK Worker] Verify Public Inputs: ' + JSON.stringify(payload.public_inputs));
390
+ }
391
+
392
+ const proofJson = JSON.stringify(payload);
393
+
394
+ log('[ZK Worker] Verifying proof... Input JSON len: ' + proofJson.length);
395
+ const sPtr = passStringToWasm0(proofJson, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
396
+ const sLen = WASM_VECTOR_LEN;
397
+
398
+ const ret = verify_face_proof(sPtr, sLen);
399
+
400
+ var ptr = ret[0];
401
+ var len = ret[1];
402
+ var errPtr = ret[2];
403
+ var isErr = ret[3] !== 0;
404
+
405
+ if (isErr) {
406
+ const errorObj = takeFromExternrefTable0(errPtr);
407
+ throw new Error(errorObj);
408
+ }
409
+
410
+ const resultJson = getStringFromWasm0(ptr, len);
411
+ log('[ZK Worker] Verify Result raw JSON: ' + resultJson);
412
+
413
+ if (__wbindgen_free) __wbindgen_free(ptr, len, 1);
414
+
415
+ window.ReactNativeWebView.postMessage(JSON.stringify({
416
+ type: 'verify_result',
417
+ data: JSON.parse(resultJson)
418
+ }));
419
+ } catch (e) {
420
+ log('[ZK Worker] Verify Error: ' + e.message);
421
+ window.ReactNativeWebView.postMessage(JSON.stringify({
422
+ type: 'error',
423
+ error: e.message
424
+ }));
425
+ }
426
+ }
427
+ else if (msg.type === 'get_proof_hash') {
428
+ if (!wasm) throw new Error("WASM not initialized");
429
+ try {
430
+ const { get_proof_hash, __wbindgen_free } = wasm;
431
+ const proofJson = JSON.stringify(msg.payload);
432
+
433
+ const sPtr = passStringToWasm0(proofJson, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
434
+ const sLen = WASM_VECTOR_LEN;
435
+
436
+ const ret = get_proof_hash(sPtr, sLen);
437
+
438
+ var ptr = ret[0];
439
+ var len = ret[1];
440
+
441
+ const hashStr = getStringFromWasm0(ptr, len);
442
+ if (__wbindgen_free) __wbindgen_free(ptr, len, 1);
443
+
444
+ window.ReactNativeWebView.postMessage(JSON.stringify({
445
+ type: 'hash_result',
446
+ hash: hashStr
447
+ }));
448
+ } catch (e) {
449
+ window.ReactNativeWebView.postMessage(JSON.stringify({
450
+ type: 'error',
451
+ error: e.message
452
+ }));
453
+ }
454
+ }
455
+ } catch (e) {
456
+ log('Worker JSON Error: ' + e.message);
457
+ }
458
+ }
459
+
460
+ window.addEventListener('message', handleMessage);
461
+ document.addEventListener('message', handleMessage);
462
+
463
+ if (window.ReactNativeWebView) {
464
+ setTimeout(() => {
465
+ window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'ready' }));
466
+ }, 100);
467
+ }
468
+ </script>
469
+ </body>
470
+
471
+ </html>
472
+
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Copyright 2026 JupiterMeta Labs
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ "use strict";
18
+
19
+ /**
20
+ * Copies onnxruntime-web assets from node_modules into assets/onnx/ so they
21
+ * can be bundled with the SDK and loaded offline (no CDN dependency at runtime).
22
+ *
23
+ * Runs automatically via the "postinstall" npm script.
24
+ * Safe to run multiple times (idempotent).
25
+ *
26
+ * Files copied:
27
+ * ort.min.js → assets/onnx/ort.min.js.txt (.txt so Metro treats it as a static asset)
28
+ * ort-wasm-simd.wasm → assets/onnx/ort-wasm-simd.wasm
29
+ */
30
+
31
+ const fs = require("fs");
32
+ const path = require("path");
33
+
34
+ const DIST = path.resolve(__dirname, "../node_modules/onnxruntime-web/dist");
35
+ const DEST = path.resolve(__dirname, "../assets/onnx");
36
+
37
+ const COPIES = [
38
+ { src: "ort.min.js", dst: "ort.min.js.txt" },
39
+ { src: "ort-wasm-simd.wasm", dst: "ort-wasm-simd.wasm" },
40
+ ];
41
+
42
+ if (!fs.existsSync(DIST)) {
43
+ // onnxruntime-web not installed yet — happens when the SDK itself is installed
44
+ // as a package (consumers get pre-bundled files from assets/onnx/ in the npm tarball).
45
+ process.exit(0);
46
+ }
47
+
48
+ fs.mkdirSync(DEST, { recursive: true });
49
+
50
+ for (const { src, dst } of COPIES) {
51
+ const srcPath = path.join(DIST, src);
52
+ const dstPath = path.join(DEST, dst);
53
+
54
+ if (!fs.existsSync(srcPath)) {
55
+ process.stderr.write(
56
+ `[copy-ort-assets] WARNING: ${src} not found in ${DIST}\n` +
57
+ ` Is onnxruntime-web@1.16.x installed? Check devDependencies.\n`
58
+ );
59
+ continue;
60
+ }
61
+
62
+ fs.copyFileSync(srcPath, dstPath);
63
+ const size = Math.round(fs.statSync(dstPath).size / 1024);
64
+ process.stdout.write(`[copy-ort-assets] copied ${src} → assets/onnx/${dst} (${size} KB)\n`);
65
+ }