ziex 0.1.0-dev.966 → 0.1.0-dev.987

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.
@@ -0,0 +1,13 @@
1
+ import type { KVNamespace, SyncKVNamespace } from "../kv";
2
+ export type IndexedDbKVOptions = {
3
+ databaseName?: string;
4
+ storeName?: string;
5
+ namespace?: string;
6
+ };
7
+ export type BrowserKVOptions = IndexedDbKVOptions & {
8
+ storagePrefix?: string;
9
+ };
10
+ export declare function createIndexedDbKV(options?: IndexedDbKVOptions): KVNamespace;
11
+ export declare function createLocalStorageKV(options?: BrowserKVOptions): SyncKVNamespace;
12
+ export declare function hasJSPI(): boolean;
13
+ export declare function createBrowserKVBindings(options?: BrowserKVOptions): Record<string, KVNamespace>;
@@ -232,6 +232,24 @@ function readString(ptr, len) {
232
232
  function writeBytes(ptr, data) {
233
233
  getMemoryView().set(data, ptr);
234
234
  }
235
+ function wrapPromisingExport(fn) {
236
+ if (!fn)
237
+ return;
238
+ const promising = WebAssembly.promising;
239
+ if (typeof promising !== "function")
240
+ return fn;
241
+ return promising(fn);
242
+ }
243
+ function invokeWasmExport(fn, ...args) {
244
+ if (!fn)
245
+ return;
246
+ const result = fn(...args);
247
+ if (result && typeof result.then === "function") {
248
+ result.then(undefined, (error) => {
249
+ console.error(error);
250
+ });
251
+ }
252
+ }
235
253
 
236
254
  class ZxBridgeCore {
237
255
  #intervals = new Map;
@@ -240,8 +258,12 @@ class ZxBridgeCore {
240
258
  #fetchCompleteHandler;
241
259
  constructor(exports) {
242
260
  this._alloc = exports.__zx_alloc;
243
- this.#handler = exports.__zx_cb;
244
- this.#fetchCompleteHandler = exports.__zx_fetch_complete;
261
+ this.#handler = wrapPromisingExport(exports.__zx_cb);
262
+ const fetchCompleteHandler = wrapPromisingExport(exports.__zx_fetch_complete);
263
+ if (!fetchCompleteHandler) {
264
+ throw new Error("__zx_fetch_complete not exported from WASM");
265
+ }
266
+ this.#fetchCompleteHandler = fetchCompleteHandler;
245
267
  if (exports.memory)
246
268
  jsz.memory = exports.memory;
247
269
  }
@@ -252,7 +274,7 @@ class ZxBridgeCore {
252
274
  return;
253
275
  }
254
276
  const dataRef = storeValueGetRef(data);
255
- handler(type, id, dataRef);
277
+ invokeWasmExport(handler, type, id, dataRef);
256
278
  }
257
279
  fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
258
280
  const url = readString(urlPtr, urlLen);
@@ -297,7 +319,7 @@ class ZxBridgeCore {
297
319
  const encoded = textEncoder.encode(body);
298
320
  const ptr = this._alloc(encoded.length);
299
321
  writeBytes(ptr, encoded);
300
- handler(fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
322
+ invokeWasmExport(handler, fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
301
323
  }
302
324
  setTimeout(callbackId, delayMs) {
303
325
  setTimeout(() => {
@@ -369,6 +391,253 @@ class ZxBridgeCore {
369
391
  };
370
392
  }
371
393
  }
394
+ // src/kv.ts
395
+ var exports_kv = {};
396
+ __export(exports_kv, {
397
+ createMemoryKV: () => createMemoryKV,
398
+ createKVImports: () => createKVImports
399
+ });
400
+ function createMemoryKV() {
401
+ const store = new Map;
402
+ return {
403
+ async get(key) {
404
+ return store.get(key) ?? null;
405
+ },
406
+ async put(key, value) {
407
+ store.set(key, value);
408
+ },
409
+ async delete(key) {
410
+ store.delete(key);
411
+ },
412
+ async list(options) {
413
+ const keys = [...store.keys()].filter((k) => !options?.prefix || k.startsWith(options.prefix)).map((name) => ({ name }));
414
+ return { keys };
415
+ }
416
+ };
417
+ }
418
+ function isSyncKVNamespace(binding) {
419
+ const candidate = binding;
420
+ return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
421
+ }
422
+ function createKVImports(bindings, getMemory) {
423
+ const encoder2 = new TextEncoder;
424
+ const decoder2 = new TextDecoder;
425
+ function readStr(ptr, len) {
426
+ return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
427
+ }
428
+ function writeBytes2(buf_ptr, buf_max, data) {
429
+ if (data.length > buf_max)
430
+ return -2;
431
+ new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
432
+ return data.length;
433
+ }
434
+ function binding(ns) {
435
+ return bindings[ns] ?? bindings["default"] ?? null;
436
+ }
437
+ const Suspending = WebAssembly.Suspending;
438
+ if (typeof Suspending !== "function") {
439
+ let syncBinding = function(ns) {
440
+ const candidate = binding(ns);
441
+ return candidate && isSyncKVNamespace(candidate) ? candidate : null;
442
+ };
443
+ return {
444
+ kv_get: (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
445
+ const b = syncBinding(readStr(ns_ptr, ns_len));
446
+ if (!b)
447
+ return -1;
448
+ const value = b.getSync(readStr(key_ptr, key_len));
449
+ if (value === null)
450
+ return -1;
451
+ return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
452
+ },
453
+ kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len) => {
454
+ const b = syncBinding(readStr(ns_ptr, ns_len));
455
+ if (!b)
456
+ return 0;
457
+ b.putSync(readStr(key_ptr, key_len), readStr(val_ptr, val_len));
458
+ return 0;
459
+ },
460
+ kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
461
+ const b = syncBinding(readStr(ns_ptr, ns_len));
462
+ if (!b)
463
+ return 0;
464
+ b.deleteSync(readStr(key_ptr, key_len));
465
+ return 0;
466
+ },
467
+ kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, buf_ptr, buf_max) => {
468
+ const b = syncBinding(readStr(ns_ptr, ns_len));
469
+ if (!b)
470
+ return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
471
+ const prefix = readStr(pfx_ptr, pfx_len);
472
+ const result = b.listSync(prefix.length > 0 ? { prefix } : undefined);
473
+ return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
474
+ }
475
+ };
476
+ }
477
+ return {
478
+ kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
479
+ const b = binding(readStr(ns_ptr, ns_len));
480
+ if (!b)
481
+ return -1;
482
+ const value = await b.get(readStr(key_ptr, key_len));
483
+ if (value === null)
484
+ return -1;
485
+ return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
486
+ }),
487
+ kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len) => {
488
+ const b = binding(readStr(ns_ptr, ns_len));
489
+ if (!b)
490
+ return -1;
491
+ await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len));
492
+ return 0;
493
+ }),
494
+ kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
495
+ const b = binding(readStr(ns_ptr, ns_len));
496
+ if (!b)
497
+ return -1;
498
+ await b.delete(readStr(key_ptr, key_len));
499
+ return 0;
500
+ }),
501
+ kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
502
+ const b = binding(readStr(ns_ptr, ns_len));
503
+ if (!b)
504
+ return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
505
+ const prefix = readStr(prefix_ptr, prefix_len);
506
+ const result = await b.list(prefix.length > 0 ? { prefix } : undefined);
507
+ return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
508
+ })
509
+ };
510
+ }
511
+
512
+ // src/browser/kv.ts
513
+ function getIndexedDb() {
514
+ if (typeof indexedDB === "undefined") {
515
+ throw new Error("IndexedDB is not available in this environment");
516
+ }
517
+ return indexedDB;
518
+ }
519
+ function requestToPromise(request) {
520
+ return new Promise((resolve, reject) => {
521
+ request.onsuccess = () => resolve(request.result);
522
+ request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed"));
523
+ });
524
+ }
525
+ function transactionToPromise(transaction) {
526
+ return new Promise((resolve, reject) => {
527
+ transaction.oncomplete = () => resolve();
528
+ transaction.onabort = () => reject(transaction.error ?? new Error("IndexedDB transaction aborted"));
529
+ transaction.onerror = () => reject(transaction.error ?? new Error("IndexedDB transaction failed"));
530
+ });
531
+ }
532
+ function createIndexedDbKV(options = {}) {
533
+ const databaseName = options.databaseName ?? "ziex-kv";
534
+ const storeName = options.storeName ?? "kv";
535
+ const namespace = options.namespace ?? "default";
536
+ const dbPromise = new Promise((resolve, reject) => {
537
+ const request = getIndexedDb().open(databaseName, 1);
538
+ request.onupgradeneeded = () => {
539
+ const db = request.result;
540
+ if (!db.objectStoreNames.contains(storeName)) {
541
+ db.createObjectStore(storeName);
542
+ }
543
+ };
544
+ request.onsuccess = () => resolve(request.result);
545
+ request.onerror = () => reject(request.error ?? new Error("Failed to open IndexedDB"));
546
+ });
547
+ const scopedKey = (key) => `${namespace}:${key}`;
548
+ return {
549
+ async get(key) {
550
+ const db = await dbPromise;
551
+ const tx = db.transaction(storeName, "readonly");
552
+ const store = tx.objectStore(storeName);
553
+ const value = await requestToPromise(store.get(scopedKey(key)));
554
+ await transactionToPromise(tx);
555
+ console.debug(`KV GET - Key: ${key}, Value: ${value}`);
556
+ return typeof value === "string" ? value : null;
557
+ },
558
+ async put(key, value) {
559
+ const db = await dbPromise;
560
+ const tx = db.transaction(storeName, "readwrite");
561
+ tx.objectStore(storeName).put(value, scopedKey(key));
562
+ await transactionToPromise(tx);
563
+ console.debug(`KV PUT - Key: ${key}, Value: ${value}`);
564
+ },
565
+ async delete(key) {
566
+ const db = await dbPromise;
567
+ const tx = db.transaction(storeName, "readwrite");
568
+ tx.objectStore(storeName).delete(scopedKey(key));
569
+ await transactionToPromise(tx);
570
+ },
571
+ async list(options2) {
572
+ const db = await dbPromise;
573
+ const tx = db.transaction(storeName, "readonly");
574
+ const store = tx.objectStore(storeName);
575
+ const keys = await requestToPromise(store.getAllKeys());
576
+ await transactionToPromise(tx);
577
+ const prefix = scopedKey(options2?.prefix ?? "");
578
+ return {
579
+ keys: keys.filter((key) => typeof key === "string" && key.startsWith(prefix)).map((key) => ({ name: key.slice(namespace.length + 1) }))
580
+ };
581
+ }
582
+ };
583
+ }
584
+ function getLocalStorage() {
585
+ if (typeof localStorage === "undefined") {
586
+ throw new Error("localStorage is not available in this environment");
587
+ }
588
+ return localStorage;
589
+ }
590
+ function createLocalStorageKV(options = {}) {
591
+ const storage = getLocalStorage();
592
+ const namespace = options.namespace ?? "default";
593
+ const storagePrefix = options.storagePrefix ?? "ziex-kv";
594
+ const scopedKey = (key) => `${storagePrefix}:${namespace}:${key}`;
595
+ const namespacePrefix = scopedKey("");
596
+ return {
597
+ getSync(key) {
598
+ return storage.getItem(scopedKey(key));
599
+ },
600
+ async get(key) {
601
+ return this.getSync(key);
602
+ },
603
+ putSync(key, value) {
604
+ storage.setItem(scopedKey(key), value);
605
+ },
606
+ async put(key, value) {
607
+ this.putSync(key, value);
608
+ },
609
+ deleteSync(key) {
610
+ storage.removeItem(scopedKey(key));
611
+ },
612
+ async delete(key) {
613
+ this.deleteSync(key);
614
+ },
615
+ listSync(options2) {
616
+ const prefix = namespacePrefix + (options2?.prefix ?? "");
617
+ const keys = [];
618
+ for (let i = 0;i < storage.length; i += 1) {
619
+ const key = storage.key(i);
620
+ if (!key || !key.startsWith(prefix))
621
+ continue;
622
+ keys.push({ name: key.slice(namespacePrefix.length) });
623
+ }
624
+ return { keys };
625
+ },
626
+ async list(options2) {
627
+ return this.listSync(options2);
628
+ }
629
+ };
630
+ }
631
+ function hasJSPI() {
632
+ return typeof WebAssembly.Suspending === "function" && typeof WebAssembly.promising === "function";
633
+ }
634
+ function createBrowserKVBindings(options = {}) {
635
+ const namespace = options.namespace ?? "default";
636
+ return {
637
+ [namespace]: hasJSPI() ? createIndexedDbKV(options) : createLocalStorageKV(options)
638
+ };
639
+ }
640
+
372
641
  // src/wasm/index.ts
373
642
  class ZxBridge extends ZxBridgeCore {
374
643
  #websockets = new Map;
@@ -377,13 +646,30 @@ class ZxBridge extends ZxBridgeCore {
377
646
  #wsOnErrorHandler;
378
647
  #wsOnCloseHandler;
379
648
  #eventbridge;
649
+ #eventbridgeAsync;
380
650
  constructor(exports) {
381
651
  super(exports);
382
- this.#wsOnOpenHandler = exports.__zx_ws_onopen;
383
- this.#wsOnMessageHandler = exports.__zx_ws_onmessage;
384
- this.#wsOnErrorHandler = exports.__zx_ws_onerror;
385
- this.#wsOnCloseHandler = exports.__zx_ws_onclose;
652
+ this.#wsOnOpenHandler = wrapPromisingExport(exports.__zx_ws_onopen);
653
+ this.#wsOnMessageHandler = wrapPromisingExport(exports.__zx_ws_onmessage);
654
+ this.#wsOnErrorHandler = wrapPromisingExport(exports.__zx_ws_onerror);
655
+ this.#wsOnCloseHandler = wrapPromisingExport(exports.__zx_ws_onclose);
386
656
  this.#eventbridge = exports.__zx_eventbridge;
657
+ this.#eventbridgeAsync = wrapPromisingExport(exports.__zx_eventbridge_async ?? exports.__zx_eventbridge);
658
+ }
659
+ eventMaySuspend(velementId, eventTypeId) {
660
+ return !!((eventHandlerModes.get(velementId) ?? 0) & 1 << eventTypeId);
661
+ }
662
+ setEventHandlerMode(velementId, eventTypeId, maySuspend) {
663
+ const bit = 1 << eventTypeId;
664
+ const current = eventHandlerModes.get(velementId) ?? 0;
665
+ const next = maySuspend ? current | bit : current & ~bit;
666
+ if (next === 0)
667
+ eventHandlerModes.delete(velementId);
668
+ else
669
+ eventHandlerModes.set(velementId, next);
670
+ }
671
+ clearEventHandlerModes(velementId) {
672
+ eventHandlerModes.delete(velementId);
387
673
  }
388
674
  submitFormActionAsync(form, statesJson, fetchId) {
389
675
  const formData = new FormData(form);
@@ -413,7 +699,7 @@ class ZxBridge extends ZxBridgeCore {
413
699
  return;
414
700
  const protocol = ws.protocol || "";
415
701
  const { ptr, len } = this._writeStringToWasm(protocol);
416
- handler(wsId, ptr, len);
702
+ invokeWasmExport(handler, wsId, ptr, len);
417
703
  };
418
704
  ws.onmessage = (event) => {
419
705
  const handler = this.#wsOnMessageHandler;
@@ -422,14 +708,14 @@ class ZxBridge extends ZxBridgeCore {
422
708
  const isBinary = event.data instanceof ArrayBuffer;
423
709
  const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
424
710
  const { ptr, len } = this._writeBytesToWasm(data);
425
- handler(wsId, ptr, len, isBinary ? 1 : 0);
711
+ invokeWasmExport(handler, wsId, ptr, len, isBinary ? 1 : 0);
426
712
  };
427
713
  ws.onerror = (_event) => {
428
714
  const handler = this.#wsOnErrorHandler;
429
715
  if (!handler)
430
716
  return;
431
717
  const { ptr, len } = this._writeStringToWasm("WebSocket error");
432
- handler(wsId, ptr, len);
718
+ invokeWasmExport(handler, wsId, ptr, len);
433
719
  };
434
720
  ws.onclose = (event) => {
435
721
  const handler = this.#wsOnCloseHandler;
@@ -437,7 +723,7 @@ class ZxBridge extends ZxBridgeCore {
437
723
  return;
438
724
  const reason = event.reason || "";
439
725
  const { ptr, len } = this._writeStringToWasm(reason);
440
- handler(wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
726
+ invokeWasmExport(handler, wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
441
727
  this.#websockets.delete(wsId);
442
728
  };
443
729
  this.#websockets.set(wsId, ws);
@@ -446,7 +732,7 @@ class ZxBridge extends ZxBridgeCore {
446
732
  if (handler) {
447
733
  const msg = error instanceof Error ? error.message : "WebSocket connection failed";
448
734
  const { ptr, len } = this._writeStringToWasm(msg);
449
- handler(wsId, ptr, len);
735
+ invokeWasmExport(handler, wsId, ptr, len);
450
736
  }
451
737
  }
452
738
  }
@@ -477,6 +763,7 @@ class ZxBridge extends ZxBridgeCore {
477
763
  }
478
764
  dispose() {
479
765
  super.dispose();
766
+ eventHandlerModes.clear();
480
767
  for (const ws of this.#websockets.values()) {
481
768
  try {
482
769
  ws.close();
@@ -485,16 +772,24 @@ class ZxBridge extends ZxBridgeCore {
485
772
  this.#websockets.clear();
486
773
  }
487
774
  eventbridge(velementId, eventTypeId, event) {
488
- if (!this.#eventbridge)
489
- return;
490
775
  const eventRef = storeValueGetRef(event);
491
- this.#eventbridge(velementId, eventTypeId, eventRef);
776
+ if (this.eventMaySuspend(velementId, eventTypeId)) {
777
+ invokeWasmExport(this.#eventbridgeAsync, velementId, eventTypeId, eventRef);
778
+ return;
779
+ }
780
+ invokeWasmExport(this.#eventbridge, velementId, eventTypeId, eventRef);
492
781
  }
493
782
  static createImportObject(bridgeRef) {
494
783
  return {
495
784
  ...jsz.importObject(),
496
785
  __zx: {
497
786
  _log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
787
+ _setEventHandlerMode: (vnodeId, eventTypeId, maySuspend) => {
788
+ bridgeRef.current?.setEventHandlerMode(vnodeId, eventTypeId, maySuspend !== 0);
789
+ },
790
+ _clearEventHandlerModes: (vnodeId) => {
791
+ bridgeRef.current?.clearEventHandlerModes(vnodeId);
792
+ },
498
793
  _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
499
794
  bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
500
795
  },
@@ -863,6 +1158,7 @@ var EVENT_TYPE_MAP = {
863
1158
  touchmove: 17,
864
1159
  scroll: 18
865
1160
  };
1161
+ var eventHandlerModes = new Map;
866
1162
  function initEventDelegation(bridge, rootSelector = "body") {
867
1163
  const root = document.querySelector(rootSelector);
868
1164
  if (!root)
@@ -892,17 +1188,31 @@ function initEventDelegation(bridge, rootSelector = "body") {
892
1188
  }
893
1189
  var DEFAULT_URL = "/assets/_/main.wasm";
894
1190
  var activeRuntime = null;
1191
+ function buildDevtoolsLocation() {
1192
+ return {
1193
+ href: window.location.href,
1194
+ origin: window.location.origin,
1195
+ host: window.location.host,
1196
+ pathname: window.location.pathname
1197
+ };
1198
+ }
895
1199
  function normalizeOptions(options = {}) {
896
1200
  return {
897
1201
  url: options.url,
898
1202
  eventDelegationRoot: options.eventDelegationRoot,
899
- importObject: options.importObject
1203
+ importObject: options.importObject,
1204
+ kv: options.kv
900
1205
  };
901
1206
  }
902
1207
  function registerDevReinit(options) {
903
1208
  if (typeof window === "undefined")
904
1209
  return;
905
- window.__zx_dev_reinit = () => init(options);
1210
+ const reinit = () => init(options);
1211
+ window.__zx_dev_reinit = reinit;
1212
+ window.__ZIEX_DEVTOOLS_GLOBAL_HOOK__ = {
1213
+ location: buildDevtoolsLocation(),
1214
+ reinit
1215
+ };
906
1216
  }
907
1217
  async function init(options = {}) {
908
1218
  const normalizedOptions = normalizeOptions(options);
@@ -912,17 +1222,28 @@ async function init(options = {}) {
912
1222
  }
913
1223
  const url = options.url ?? document.getElementById("__$wasmlink")?.href ?? DEFAULT_URL;
914
1224
  const bridgeRef = { current: null };
915
- const importObject = Object.assign({}, ZxBridge.createImportObject(bridgeRef), options.importObject);
1225
+ let wasmMemory = null;
1226
+ const kvBindings = options.kv ?? createBrowserKVBindings();
1227
+ const kvImportObject = {
1228
+ __zx_kv: createKVImports(kvBindings, () => {
1229
+ if (wasmMemory)
1230
+ return wasmMemory;
1231
+ if (jsz.memory)
1232
+ return jsz.memory;
1233
+ throw new Error("WASM memory is not ready");
1234
+ })
1235
+ };
1236
+ const importObject = Object.assign({}, ZxBridge.createImportObject(bridgeRef), kvImportObject, options.importObject);
916
1237
  const source = await WebAssembly.instantiateStreaming(fetch(url), importObject);
917
1238
  const { instance } = source;
918
- jsz.memory = instance.exports.memory;
1239
+ wasmMemory = instance.exports.memory;
1240
+ jsz.memory = wasmMemory;
919
1241
  const bridge = new ZxBridge(instance.exports);
920
1242
  bridgeRef.current = bridge;
921
1243
  domNodes.clear();
922
1244
  const disposeDelegation = initEventDelegation(bridge, options.eventDelegationRoot ?? "body");
923
- const main = instance.exports.mainClient;
924
- if (typeof main === "function")
925
- main();
1245
+ const main = wrapPromisingExport(instance.exports.mainClient);
1246
+ invokeWasmExport(main);
926
1247
  activeRuntime = {
927
1248
  options: normalizedOptions,
928
1249
  dispose: () => {
@@ -1069,89 +1390,6 @@ class ZxWasiBridge {
1069
1390
  }
1070
1391
  }
1071
1392
 
1072
- // src/kv.ts
1073
- var exports_kv = {};
1074
- __export(exports_kv, {
1075
- createMemoryKV: () => createMemoryKV,
1076
- createKVImports: () => createKVImports
1077
- });
1078
- function createMemoryKV() {
1079
- const store = new Map;
1080
- return {
1081
- async get(key) {
1082
- return store.get(key) ?? null;
1083
- },
1084
- async put(key, value) {
1085
- store.set(key, value);
1086
- },
1087
- async delete(key) {
1088
- store.delete(key);
1089
- },
1090
- async list(options) {
1091
- const keys = [...store.keys()].filter((k) => !options?.prefix || k.startsWith(options.prefix)).map((name) => ({ name }));
1092
- return { keys };
1093
- }
1094
- };
1095
- }
1096
- function createKVImports(bindings, getMemory) {
1097
- const encoder3 = new TextEncoder;
1098
- const decoder3 = new TextDecoder;
1099
- function readStr(ptr, len) {
1100
- return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
1101
- }
1102
- function writeBytes2(buf_ptr, buf_max, data) {
1103
- if (data.length > buf_max)
1104
- return -2;
1105
- new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
1106
- return data.length;
1107
- }
1108
- function binding(ns) {
1109
- return bindings[ns] ?? bindings["default"] ?? null;
1110
- }
1111
- const Suspending = WebAssembly.Suspending;
1112
- if (typeof Suspending !== "function") {
1113
- return {
1114
- kv_get: (_ns, _nsLen, _key, _keyLen, _buf, _max) => -1,
1115
- kv_put: (_ns, _nsLen, _key, _keyLen, _val, _valLen) => 0,
1116
- kv_delete: (_ns, _nsLen, _key, _keyLen) => 0,
1117
- kv_list: (_ns, _nsLen, _pfx, _pfxLen, buf_ptr, buf_max) => writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"))
1118
- };
1119
- }
1120
- return {
1121
- kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
1122
- const b = binding(readStr(ns_ptr, ns_len));
1123
- if (!b)
1124
- return -1;
1125
- const value = await b.get(readStr(key_ptr, key_len));
1126
- if (value === null)
1127
- return -1;
1128
- return writeBytes2(buf_ptr, buf_max, encoder3.encode(value));
1129
- }),
1130
- kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len) => {
1131
- const b = binding(readStr(ns_ptr, ns_len));
1132
- if (!b)
1133
- return -1;
1134
- await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len));
1135
- return 0;
1136
- }),
1137
- kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
1138
- const b = binding(readStr(ns_ptr, ns_len));
1139
- if (!b)
1140
- return -1;
1141
- await b.delete(readStr(key_ptr, key_len));
1142
- return 0;
1143
- }),
1144
- kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
1145
- const b = binding(readStr(ns_ptr, ns_len));
1146
- if (!b)
1147
- return writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"));
1148
- const prefix = readStr(prefix_ptr, prefix_len);
1149
- const result = await b.list(prefix.length > 0 ? { prefix } : undefined);
1150
- return writeBytes2(buf_ptr, buf_max, encoder3.encode(JSON.stringify(result.keys.map((k) => k.name))));
1151
- })
1152
- };
1153
- }
1154
-
1155
1393
  // src/db.ts
1156
1394
  function decodeBlob(base64) {
1157
1395
  const binary = atob(base64);
@@ -1723,18 +1961,20 @@ async function run({
1723
1961
  ctx?.waitUntil(wasmPromise);
1724
1962
  return new Response(null, { status: 101, webSocket: server.client });
1725
1963
  }
1726
- const { stderrText } = collectOutput();
1727
- const meta = parseEdgeMeta(stderrText);
1728
- if (meta.streaming) {
1964
+ const { stderrText: earlyStderrText } = collectOutput();
1965
+ const earlyMeta = parseEdgeMeta(earlyStderrText);
1966
+ if (earlyMeta.streaming) {
1729
1967
  const { readable, writable } = new TransformStream;
1730
1968
  streamWriter = writable.getWriter();
1731
1969
  for (const chunk of stdoutChunks)
1732
1970
  streamWriter.write(chunk);
1733
1971
  stdoutChunks.length = 0;
1734
1972
  wasmPromise.finally(() => streamWriter?.close());
1735
- return new Response(readable, { status: meta.status, headers: meta.headers });
1973
+ return new Response(readable, { status: earlyMeta.status, headers: earlyMeta.headers });
1736
1974
  }
1737
1975
  await wasmPromise;
1976
+ const { stderrText } = collectOutput();
1977
+ const meta = parseEdgeMeta(stderrText);
1738
1978
  const body = mergeUint8Arrays(stdoutChunks);
1739
1979
  meta.headers.delete("transfer-encoding");
1740
1980
  if (!meta.headers.has("content-length"))