ziex 0.1.0-dev.1466 → 0.1.0-dev.1568

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -158,7 +158,7 @@ var ZxWasiBridge = class {
158
158
  function createFetchImports(getMemory) {
159
159
  const encoder3 = new TextEncoder();
160
160
  const decoder3 = new TextDecoder();
161
- function readStr(ptr, len) {
161
+ function readStr2(ptr, len) {
162
162
  return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
163
163
  }
164
164
  function writeBytes(buf_ptr, buf_max, data) {
@@ -184,9 +184,9 @@ function createFetchImports(getMemory) {
184
184
  return headers;
185
185
  }
186
186
  async function doFetch(url_ptr, url_len, method_ptr, method_len, headers_ptr, headers_len, body_ptr, body_len, timeout_ms, status_out, buf_ptr, buf_max) {
187
- const url = readStr(url_ptr, url_len);
188
- const method = method_len > 0 ? readStr(method_ptr, method_len) : "GET";
189
- const headersJson = headers_len > 0 ? readStr(headers_ptr, headers_len) : "{}";
187
+ const url = readStr2(url_ptr, url_len);
188
+ const method = method_len > 0 ? readStr2(method_ptr, method_len) : "GET";
189
+ const headersJson = headers_len > 0 ? readStr2(headers_ptr, headers_len) : "{}";
190
190
  const body = body_len > 0 ? readBytes(body_ptr, body_len) : void 0;
191
191
  const headers = parseHeaders(headersJson);
192
192
  const controller = new AbortController();
@@ -209,14 +209,14 @@ function createFetchImports(getMemory) {
209
209
  return -1;
210
210
  }
211
211
  }
212
- const Suspending = WebAssembly.Suspending;
213
- if (typeof Suspending !== "function") {
212
+ const Suspending2 = WebAssembly.Suspending;
213
+ if (typeof Suspending2 !== "function") {
214
214
  return {
215
215
  fetch: (_url_ptr, _url_len, _method_ptr, _method_len, _headers_ptr, _headers_len, _body_ptr, _body_len, _timeout_ms, _status_out, _buf_ptr, _buf_max) => -1
216
216
  };
217
217
  }
218
218
  return {
219
- fetch: new Suspending(doFetch)
219
+ fetch: new Suspending2(doFetch)
220
220
  };
221
221
  }
222
222
 
@@ -498,90 +498,96 @@ function bindWasmAlloc(allocRef, exports) {
498
498
  }
499
499
 
500
500
  // src/runtime/kv/extern.ts
501
+ var Suspending = WebAssembly.Suspending;
502
+ var jspi = typeof Suspending === "function";
503
+ var miss = jspi ? -1 : 0;
501
504
  function putOptions(ttlSeconds) {
502
505
  if (ttlSeconds < 60) return void 0;
503
506
  return { expirationTtl: ttlSeconds };
504
507
  }
508
+ function kvDel(binding, key) {
509
+ const b = binding;
510
+ return (b.del ?? b.delete).call(b, key);
511
+ }
505
512
  function isSyncKVNamespace(binding) {
506
- const candidate = binding;
507
- return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
513
+ return typeof binding.get === "function" && binding.get.constructor.name !== "AsyncFunction";
508
514
  }
509
- function createKVImports(bindings, getMemory, allocRef) {
510
- const encoder3 = new TextEncoder();
511
- const decoder3 = new TextDecoder();
512
- function readStr(ptr, len) {
513
- return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
514
- }
515
- function binding(ns) {
516
- return bindings[ns] ?? bindings["default"] ?? null;
515
+ function listOpts(prefix) {
516
+ return prefix.length > 0 ? { prefix } : void 0;
517
+ }
518
+ function maybeThen(r, f) {
519
+ return r instanceof Promise ? r.then(f) : f(r);
520
+ }
521
+ function readStr(getMemory, ptr, len) {
522
+ return textDecoder.decode(new Uint8Array(getMemory().buffer, ptr, len));
523
+ }
524
+ function resolve(bindings, ns) {
525
+ const b = bindings[ns] ?? bindings["default"] ?? null;
526
+ if (!b || jspi) return b;
527
+ return isSyncKVNamespace(b) ? b : null;
528
+ }
529
+ function encodeGet(getMemory, allocRef, value, out_ptr) {
530
+ if (value === null) return -1;
531
+ return writeBytesOut(getMemory, allocRef, out_ptr, textEncoder.encode(value));
532
+ }
533
+ function encodeList(getMemory, allocRef, names, out_ptr) {
534
+ if (names.length === 0) {
535
+ new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
536
+ return 0;
517
537
  }
518
- const Suspending = WebAssembly.Suspending;
519
- if (typeof Suspending !== "function") {
520
- let syncBinding2 = function(ns) {
521
- const candidate = binding(ns);
522
- return candidate && isSyncKVNamespace(candidate) ? candidate : null;
523
- };
524
- var syncBinding = syncBinding2;
525
- return {
526
- kv_get: (ns_ptr, ns_len, key_ptr, key_len, out_ptr) => {
527
- const b = syncBinding2(readStr(ns_ptr, ns_len));
528
- if (!b) return -1;
529
- const value = b.getSync(readStr(key_ptr, key_len));
530
- if (value === null) return -1;
531
- return writeBytesOut(getMemory, allocRef, out_ptr, encoder3.encode(value));
532
- },
533
- kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
534
- const b = syncBinding2(readStr(ns_ptr, ns_len));
535
- if (!b) return 0;
536
- b.putSync(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
537
- return 0;
538
- },
539
- kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
540
- const b = syncBinding2(readStr(ns_ptr, ns_len));
541
- if (!b) return 0;
542
- b.deleteSync(readStr(key_ptr, key_len));
543
- return 0;
544
- },
545
- kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, out_ptr) => {
546
- const b = syncBinding2(readStr(ns_ptr, ns_len));
547
- if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
548
- const prefix = readStr(pfx_ptr, pfx_len);
549
- const result = b.listSync(prefix.length > 0 ? { prefix } : void 0);
550
- return writeJsonOut(getMemory, allocRef, out_ptr, result.keys.map((k) => k.name));
551
- }
552
- };
538
+ return writeJsonOut(getMemory, allocRef, out_ptr, names);
539
+ }
540
+ function get(b, key, out_ptr, getMemory, allocRef) {
541
+ return maybeThen(b.get(key), (v) => encodeGet(getMemory, allocRef, v, out_ptr));
542
+ }
543
+ function put(b, key, val, ttl) {
544
+ return maybeThen(b.put(key, val, putOptions(ttl)), () => 0);
545
+ }
546
+ function del(b, key) {
547
+ return maybeThen(kvDel(b, key), () => 0);
548
+ }
549
+ function list(b, prefix, out_ptr, getMemory, allocRef) {
550
+ return maybeThen(
551
+ b.list(listOpts(prefix)),
552
+ (result) => encodeList(getMemory, allocRef, result.keys.map((k) => k.name), out_ptr)
553
+ );
554
+ }
555
+ function wrapImport(impl) {
556
+ if (!jspi) {
557
+ return ((...args) => {
558
+ const r = impl(...args);
559
+ if (r instanceof Promise) throw new Error("async kv binding requires JSPI");
560
+ return r;
561
+ });
553
562
  }
563
+ return new Suspending(impl);
564
+ }
565
+ function createKVImports(bindings, getMemory, allocRef) {
554
566
  return {
555
- kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, out_ptr) => {
556
- const b = binding(readStr(ns_ptr, ns_len));
567
+ kv_get: wrapImport((ns_ptr, ns_len, key_ptr, key_len, out_ptr) => {
568
+ const b = resolve(bindings, readStr(getMemory, ns_ptr, ns_len));
557
569
  if (!b) return -1;
558
- const value = await b.get(readStr(key_ptr, key_len));
559
- if (value === null) return -1;
560
- return writeBytesOut(getMemory, allocRef, out_ptr, encoder3.encode(value));
570
+ return get(b, readStr(getMemory, key_ptr, key_len), out_ptr, getMemory, allocRef);
561
571
  }),
562
- kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
563
- const b = binding(readStr(ns_ptr, ns_len));
564
- if (!b) return -1;
565
- await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
566
- return 0;
572
+ kv_put: wrapImport((ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
573
+ const b = resolve(bindings, readStr(getMemory, ns_ptr, ns_len));
574
+ if (!b) return miss;
575
+ return put(
576
+ b,
577
+ readStr(getMemory, key_ptr, key_len),
578
+ readStr(getMemory, val_ptr, val_len),
579
+ ttl_seconds
580
+ );
567
581
  }),
568
- kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
569
- const b = binding(readStr(ns_ptr, ns_len));
570
- if (!b) return -1;
571
- await b.delete(readStr(key_ptr, key_len));
572
- return 0;
582
+ kv_delete: wrapImport((ns_ptr, ns_len, key_ptr, key_len) => {
583
+ const b = resolve(bindings, readStr(getMemory, ns_ptr, ns_len));
584
+ if (!b) return miss;
585
+ return del(b, readStr(getMemory, key_ptr, key_len));
573
586
  }),
574
- kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, out_ptr) => {
575
- const b = binding(readStr(ns_ptr, ns_len));
587
+ kv_list: wrapImport((ns_ptr, ns_len, pfx_ptr, pfx_len, out_ptr) => {
588
+ const b = resolve(bindings, readStr(getMemory, ns_ptr, ns_len));
576
589
  if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
577
- const prefix = readStr(prefix_ptr, prefix_len);
578
- const result = await b.list(prefix.length > 0 ? { prefix } : void 0);
579
- const names = result.keys.map((k) => k.name);
580
- if (names.length === 0) {
581
- new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
582
- return 0;
583
- }
584
- return writeJsonOut(getMemory, allocRef, out_ptr, names);
590
+ return list(b, readStr(getMemory, pfx_ptr, pfx_len), out_ptr, getMemory, allocRef);
585
591
  })
586
592
  };
587
593
  }
@@ -653,21 +659,21 @@ function valuesToWireRows(rows) {
653
659
  }
654
660
  function createDbImports(bindings, getMemory, allocRef) {
655
661
  const decoder3 = new TextDecoder();
656
- function readStr(ptr, len) {
662
+ function readStr2(ptr, len) {
657
663
  return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
658
664
  }
659
665
  function binding(ns) {
660
666
  return bindings[ns] ?? bindings["default"] ?? null;
661
667
  }
662
668
  async function statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len) {
663
- const database = binding(readStr(ns_ptr, ns_len));
669
+ const database = binding(readStr2(ns_ptr, ns_len));
664
670
  if (!database) return null;
665
- const sql = readStr(sql_ptr, sql_len);
666
- const bindingsJson = JSON.parse(readStr(bindings_ptr, bindings_len));
671
+ const sql = readStr2(sql_ptr, sql_len);
672
+ const bindingsJson = JSON.parse(readStr2(bindings_ptr, bindings_len));
667
673
  return database.prepare(sql).bind(...toPositionalBindings(bindingsJson));
668
674
  }
669
- const Suspending = WebAssembly.Suspending;
670
- if (typeof Suspending !== "function") {
675
+ const Suspending2 = WebAssembly.Suspending;
676
+ if (typeof Suspending2 !== "function") {
671
677
  return {
672
678
  db_open: (_ns, _ns_len) => -1,
673
679
  db_run: (_a, _b, _c, _d, _e, _f, _g) => -1,
@@ -677,8 +683,8 @@ function createDbImports(bindings, getMemory, allocRef) {
677
683
  };
678
684
  }
679
685
  return {
680
- db_open: (ns_ptr, ns_len) => binding(readStr(ns_ptr, ns_len)) ? 0 : -1,
681
- db_run: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
686
+ db_open: (ns_ptr, ns_len) => binding(readStr2(ns_ptr, ns_len)) ? 0 : -1,
687
+ db_run: new Suspending2(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
682
688
  const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
683
689
  if (!stmt) return -1;
684
690
  const result = await stmt.run();
@@ -687,7 +693,7 @@ function createDbImports(bindings, getMemory, allocRef) {
687
693
  changes: result.meta?.changes ?? 0
688
694
  });
689
695
  }),
690
- db_get: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
696
+ db_get: new Suspending2(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
691
697
  const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
692
698
  if (!stmt) return -1;
693
699
  const row = await stmt.first();
@@ -697,7 +703,7 @@ function createDbImports(bindings, getMemory, allocRef) {
697
703
  }
698
704
  return writeJsonOut(getMemory, allocRef, out_ptr, [objectToWireRow(row)]);
699
705
  }),
700
- db_all: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
706
+ db_all: new Suspending2(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
701
707
  const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
702
708
  if (!stmt) return -1;
703
709
  const result = await stmt.all();
@@ -708,7 +714,7 @@ function createDbImports(bindings, getMemory, allocRef) {
708
714
  }
709
715
  return writeJsonOut(getMemory, allocRef, out_ptr, rows);
710
716
  }),
711
- db_values: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
717
+ db_values: new Suspending2(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
712
718
  const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
713
719
  if (!stmt) return -1;
714
720
  const rows = await stmt.raw();
@@ -730,8 +736,7 @@ var ProcExit = class extends Error {
730
736
  };
731
737
  function createWasiImports({
732
738
  request,
733
- stdinData,
734
- onStdout
739
+ stdinData
735
740
  }) {
736
741
  const encoder3 = new TextEncoder();
737
742
  const url = new URL(request.url);
@@ -755,8 +760,6 @@ function createWasiImports({
755
760
  const setMemory = (m2) => {
756
761
  wasmMemory = m2;
757
762
  };
758
- const stdoutChunks = [];
759
- let stderrMeta = "";
760
763
  let stderrPartial = "";
761
764
  const stderrDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
762
765
  function processStderrChunk(chunk) {
@@ -764,9 +767,7 @@ function createWasiImports({
764
767
  const lines = (stderrPartial + text).split("\n");
765
768
  stderrPartial = lines.pop() ?? "";
766
769
  for (const line of lines) {
767
- if (line.startsWith("__ZIEX_META__:")) {
768
- stderrMeta += line + "\n";
769
- } else if (line.length > 0) {
770
+ if (line.length > 0) {
770
771
  console.error("[ziex]", line);
771
772
  }
772
773
  }
@@ -812,10 +813,7 @@ function createWasiImports({
812
813
  const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
813
814
  const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
814
815
  const chunk = mem.slice(buf_ptr, buf_ptr + buf_len);
815
- if (fd === 1) {
816
- if (onStdout) onStdout(chunk);
817
- else stdoutChunks.push(chunk);
818
- } else if (fd === 2) processStderrChunk(chunk);
816
+ if (fd === 2) processStderrChunk(chunk);
819
817
  written += buf_len;
820
818
  }
821
819
  dv.setUint32(nwritten_ptr, written, true);
@@ -983,26 +981,12 @@ function createWasiImports({
983
981
  v().setUint32(bufused_ptr, 0, true);
984
982
  return 76;
985
983
  },
986
- // Stub for poll_oneoff - no blocking I/O in edge runtimes.
987
984
  poll_oneoff(_in, _out, _nsubscriptions, nevents_ptr) {
988
985
  v().setUint32(nevents_ptr, 0, true);
989
986
  return 0;
990
987
  }
991
988
  };
992
- function collectOutput() {
993
- const remaining = stderrDecoder.decode(void 0, { stream: false });
994
- const tail = stderrPartial + remaining;
995
- if (tail.length > 0) {
996
- if (tail.startsWith("__ZIEX_META__:")) stderrMeta += tail;
997
- else console.error("[ziex]", tail);
998
- stderrPartial = "";
999
- }
1000
- return {
1001
- stdout: mergeUint8Arrays(stdoutChunks),
1002
- stderrText: stderrMeta
1003
- };
1004
- }
1005
- return { wasiImport, setMemory, collectOutput };
989
+ return { wasiImport, setMemory };
1006
990
  }
1007
991
  function mergeUint8Arrays(arrays) {
1008
992
  const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
@@ -1016,50 +1000,78 @@ function mergeUint8Arrays(arrays) {
1016
1000
  }
1017
1001
 
1018
1002
  // src/runtime/kv/memory.ts
1019
- function createMemoryKV() {
1020
- const store = /* @__PURE__ */ new Map();
1021
- function read(key) {
1022
- const entry = store.get(key);
1023
- if (!entry) return null;
1024
- const expiresAt = entry[1];
1025
- if (expiresAt !== void 0 && Date.now() >= expiresAt) {
1026
- store.delete(key);
1027
- return null;
1028
- }
1029
- return entry[0];
1030
- }
1031
- function write(key, value, options) {
1032
- let expiresAt;
1033
- if (options?.expiration !== void 0) {
1034
- expiresAt = options.expiration * 1e3;
1035
- } else if (options?.expirationTtl !== void 0) {
1036
- expiresAt = Date.now() + options.expirationTtl * 1e3;
1037
- }
1038
- store.set(key, [value, expiresAt]);
1003
+ var store = /* @__PURE__ */ new Map();
1004
+ async function get2(key) {
1005
+ const entry = store.get(key);
1006
+ if (!entry) return null;
1007
+ const expiresAt = entry[1];
1008
+ if (expiresAt !== void 0 && Date.now() >= expiresAt) {
1009
+ store.delete(key);
1010
+ return null;
1011
+ }
1012
+ return entry[0];
1013
+ }
1014
+ async function put2(key, value, options) {
1015
+ let expiresAt;
1016
+ if (options?.expiration !== void 0) {
1017
+ expiresAt = options.expiration * 1e3;
1018
+ } else if (options?.expirationTtl !== void 0) {
1019
+ expiresAt = Date.now() + options.expirationTtl * 1e3;
1020
+ }
1021
+ store.set(key, [value, expiresAt]);
1022
+ }
1023
+ async function del2(key) {
1024
+ store.delete(key);
1025
+ }
1026
+ async function list2(options) {
1027
+ const keys = [];
1028
+ for (const name of [...store.keys()]) {
1029
+ if (options?.prefix && !name.startsWith(options.prefix)) continue;
1030
+ if (await get2(name) !== null) keys.push({ name });
1039
1031
  }
1032
+ return { keys };
1033
+ }
1034
+
1035
+ // src/runtime/index.ts
1036
+ function buildHttpImports(mem, http) {
1037
+ const decoder3 = new TextDecoder();
1040
1038
  return {
1041
- async get(key) {
1042
- return read(key);
1043
- },
1044
- async put(key, value, options) {
1045
- write(key, value, options);
1039
+ commit: (status, meta_ptr, meta_len) => {
1040
+ http.status = status >>> 0;
1041
+ http.committed = true;
1042
+ http.headers = new Headers();
1043
+ http.streaming = false;
1044
+ if (meta_len > 0) {
1045
+ try {
1046
+ const raw = decoder3.decode(new Uint8Array(mem().buffer, meta_ptr >>> 0, meta_len >>> 0));
1047
+ const parsed = JSON.parse(raw);
1048
+ if (parsed.streaming === true) http.streaming = true;
1049
+ if (Array.isArray(parsed.headers)) {
1050
+ for (const [name, value] of parsed.headers) {
1051
+ http.headers.append(name, value);
1052
+ }
1053
+ }
1054
+ } catch {
1055
+ }
1056
+ }
1046
1057
  },
1047
- async delete(key) {
1048
- store.delete(key);
1058
+ write: (ptr, len) => {
1059
+ if (len <= 0) return;
1060
+ const chunk = new Uint8Array(mem().buffer, ptr >>> 0, len >>> 0).slice();
1061
+ if (http.streamWriter) void http.streamWriter.write(chunk);
1062
+ else http.bodyChunks.push(chunk);
1049
1063
  },
1050
- async list(options) {
1051
- const keys = [...store.keys()].filter((k) => {
1052
- if (options?.prefix && !k.startsWith(options.prefix)) return false;
1053
- return read(k) !== null;
1054
- }).map((name) => ({ name }));
1055
- return { keys };
1064
+ end: () => {
1065
+ http.ended = true;
1066
+ if (http.streamWriter) {
1067
+ void http.streamWriter.close();
1068
+ http.streamWriter = null;
1069
+ }
1056
1070
  }
1057
1071
  };
1058
1072
  }
1059
-
1060
- // src/runtime/index.ts
1061
- function buildWsImports(Suspending, mem, decoder3, ws) {
1062
- const readStr = (ptr, len) => decoder3.decode(new Uint8Array(mem().buffer, ptr, len));
1073
+ function buildWsImports(Suspending2, mem, decoder3, ws) {
1074
+ const readStr2 = (ptr, len) => decoder3.decode(new Uint8Array(mem().buffer, ptr, len));
1063
1075
  return {
1064
1076
  ws_upgrade: () => {
1065
1077
  ws.upgraded = true;
@@ -1075,7 +1087,7 @@ function buildWsImports(Suspending, mem, decoder3, ws) {
1075
1087
  ws_close: (code, reason_ptr, reason_len) => {
1076
1088
  ws.server?.close(code, decoder3.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
1077
1089
  },
1078
- ws_recv: Suspending ? new Suspending(async (buf_ptr, buf_max) => {
1090
+ ws_recv: Suspending2 ? new Suspending2(async (buf_ptr, buf_max) => {
1079
1091
  if (ws._resolveFirstSuspend) {
1080
1092
  const fn = ws._resolveFirstSuspend;
1081
1093
  ws._resolveFirstSuspend = void 0;
@@ -1088,23 +1100,23 @@ function buildWsImports(Suspending, mem, decoder3, ws) {
1088
1100
  return n;
1089
1101
  };
1090
1102
  if (ws.messageQueue.length > 0) return deliver(ws.messageQueue.shift());
1091
- return new Promise((resolve) => {
1092
- ws.recvResolve = (bytes) => resolve(deliver(bytes));
1103
+ return new Promise((resolve2) => {
1104
+ ws.recvResolve = (bytes) => resolve2(deliver(bytes));
1093
1105
  });
1094
1106
  }) : (_buf_ptr, _buf_max) => -1,
1095
1107
  // Pub/sub - delegates to optional callbacks (real in DO, no-ops otherwise)
1096
1108
  ws_subscribe: (ptr, len) => {
1097
- ws.subscribe?.(readStr(ptr, len));
1109
+ ws.subscribe?.(readStr2(ptr, len));
1098
1110
  },
1099
1111
  ws_unsubscribe: (ptr, len) => {
1100
- ws.unsubscribe?.(readStr(ptr, len));
1112
+ ws.unsubscribe?.(readStr2(ptr, len));
1101
1113
  },
1102
1114
  ws_publish: (topic_ptr, topic_len, data_ptr, data_len) => {
1103
- const topic = readStr(topic_ptr, topic_len);
1115
+ const topic = readStr2(topic_ptr, topic_len);
1104
1116
  const data = new Uint8Array(mem().buffer, data_ptr, data_len).slice();
1105
1117
  return ws.publish?.(topic, data) ?? 0;
1106
1118
  },
1107
- ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr(ptr, len)) ? 1 : 0
1119
+ ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr2(ptr, len)) ? 1 : 0
1108
1120
  };
1109
1121
  }
1110
1122
  function attachWebSocket(ws) {
@@ -1135,14 +1147,14 @@ function attachWebSocket(ws) {
1135
1147
  });
1136
1148
  return { client };
1137
1149
  }
1138
- function buildSysImports(jspi, Suspending) {
1150
+ function buildSysImports(jspi2, Suspending2) {
1139
1151
  return {
1140
- sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {
1152
+ sleep_ms: jspi2 ? new Suspending2(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {
1141
1153
  }
1142
1154
  };
1143
1155
  }
1144
- function executeWasm(instance, jspi, Suspending, wsState) {
1145
- if (!jspi) {
1156
+ function executeWasm(instance, jspi2, Suspending2, wsState) {
1157
+ if (!jspi2) {
1146
1158
  try {
1147
1159
  instance.exports._start();
1148
1160
  } catch (e) {
@@ -1162,25 +1174,6 @@ function executeWasm(instance, jspi, Suspending, wsState) {
1162
1174
  }
1163
1175
  });
1164
1176
  }
1165
- function parseZiexMeta(stderrText) {
1166
- const meta = { status: 200, headers: new Headers(), streaming: false };
1167
- const metaPrefix = "__ZIEX_META__:";
1168
- const metaLine = stderrText.split("\n").find((line) => line.startsWith(metaPrefix));
1169
- if (metaLine) {
1170
- try {
1171
- const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
1172
- if (parsed.status) meta.status = parsed.status;
1173
- if (parsed.streaming === true) meta.streaming = true;
1174
- if (Array.isArray(parsed.headers)) {
1175
- for (const [name, value] of parsed.headers) {
1176
- meta.headers.append(name, value);
1177
- }
1178
- }
1179
- } catch {
1180
- }
1181
- }
1182
- return meta;
1183
- }
1184
1177
  async function run({
1185
1178
  request,
1186
1179
  env,
@@ -1190,29 +1183,32 @@ async function run({
1190
1183
  db: dbBindings,
1191
1184
  imports,
1192
1185
  wasi,
1193
- websocket: doNamespace
1186
+ sticky
1194
1187
  }) {
1195
- if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
1196
- const id = doNamespace.idFromName(new URL(request.url).pathname);
1197
- return doNamespace.get(id).fetch(request);
1188
+ if (sticky && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
1189
+ const id = sticky.idFromName(new URL(request.url).pathname);
1190
+ return sticky.get(id).fetch(request);
1198
1191
  }
1199
1192
  const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : void 0;
1200
- const stdoutChunks = [];
1201
- let streamWriter = null;
1202
- const { wasiImport, setMemory, collectOutput } = createWasiImports({
1193
+ const httpState = {
1194
+ committed: false,
1195
+ ended: false,
1196
+ status: 200,
1197
+ streaming: false,
1198
+ headers: new Headers(),
1199
+ bodyChunks: [],
1200
+ streamWriter: null
1201
+ };
1202
+ const { wasiImport, setMemory } = createWasiImports({
1203
1203
  request,
1204
- stdinData,
1205
- onStdout: (chunk) => {
1206
- if (streamWriter) void streamWriter.write(chunk);
1207
- else stdoutChunks.push(chunk);
1208
- }
1204
+ stdinData
1209
1205
  });
1210
1206
  let wasmMemory = null;
1211
1207
  const mem = () => wasmMemory;
1212
1208
  const bridgeRef = [null];
1213
1209
  const allocRef = [null];
1214
- const Suspending = WebAssembly.Suspending;
1215
- const jspi = typeof Suspending === "function";
1210
+ const Suspending2 = WebAssembly.Suspending;
1211
+ const jspi2 = typeof Suspending2 === "function";
1216
1212
  const wsState = {
1217
1213
  upgraded: false,
1218
1214
  server: null,
@@ -1222,15 +1218,16 @@ async function run({
1222
1218
  };
1223
1219
  const importObject = {
1224
1220
  wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
1225
- __zx_sys: buildSysImports(jspi, Suspending),
1226
- __zx_ws: buildWsImports(jspi ? Suspending : null, mem, new TextDecoder(), wsState),
1221
+ __zx_sys: buildSysImports(jspi2, Suspending2),
1222
+ __zx_ws: buildWsImports(jspi2 ? Suspending2 : null, mem, new TextDecoder(), wsState),
1223
+ __zx_http: buildHttpImports(mem, httpState),
1227
1224
  __zx_net: createFetchImports(mem),
1228
1225
  ...imports ? imports(mem) : {},
1229
1226
  ...ZxWasiBridge.createImportObject(bridgeRef)
1230
1227
  };
1231
1228
  if (true) {
1232
1229
  importObject.__zx_kv = createKVImports(
1233
- kvBindings ?? { default: createMemoryKV() },
1230
+ kvBindings ?? { default: { get: get2, put: put2, del: del2, list: list2 } },
1234
1231
  mem,
1235
1232
  allocRef
1236
1233
  );
@@ -1247,34 +1244,37 @@ async function run({
1247
1244
  setMemory(wasmMemory);
1248
1245
  bridgeRef[0] = new ZxWasiBridge(instance.exports);
1249
1246
  bindWasmAlloc(allocRef, instance.exports);
1250
- const wasmPromise = executeWasm(instance, jspi, Suspending, wsState);
1247
+ const wasmPromise = executeWasm(instance, jspi2, Suspending2, wsState);
1251
1248
  if (wsState.upgraded) {
1252
1249
  const server = attachWebSocket(wsState);
1253
1250
  ctx?.waitUntil(wasmPromise);
1254
1251
  return new Response(null, { status: 101, webSocket: server.client });
1255
1252
  }
1256
- const { stderrText: earlyStderrText } = collectOutput();
1257
- const earlyMeta = parseZiexMeta(earlyStderrText);
1258
- if (earlyMeta.streaming) {
1253
+ if (httpState.committed && httpState.streaming) {
1259
1254
  const { readable, writable } = new TransformStream();
1260
- streamWriter = writable.getWriter();
1261
- for (const chunk of stdoutChunks) void streamWriter.write(chunk);
1262
- stdoutChunks.length = 0;
1263
- void wasmPromise.finally(() => streamWriter?.close());
1264
- return new Response(readable, { status: earlyMeta.status, headers: earlyMeta.headers });
1255
+ httpState.streamWriter = writable.getWriter();
1256
+ for (const chunk of httpState.bodyChunks) void httpState.streamWriter.write(chunk);
1257
+ httpState.bodyChunks.length = 0;
1258
+ void wasmPromise.finally(() => {
1259
+ if (httpState.streamWriter) {
1260
+ void httpState.streamWriter.close();
1261
+ httpState.streamWriter = null;
1262
+ }
1263
+ });
1264
+ return new Response(readable, { status: httpState.status, headers: httpState.headers });
1265
1265
  }
1266
1266
  await wasmPromise;
1267
- const { stderrText } = collectOutput();
1268
- const meta = parseZiexMeta(stderrText);
1269
- const body = mergeUint8Arrays(stdoutChunks);
1270
- meta.headers.delete("transfer-encoding");
1271
- const nullBody = meta.status === 101 || meta.status === 204 || meta.status === 205 || meta.status === 304;
1267
+ const status = httpState.status;
1268
+ const headers = httpState.headers;
1269
+ headers.delete("transfer-encoding");
1270
+ const nullBody = status === 101 || status === 204 || status === 205 || status === 304;
1272
1271
  if (nullBody) {
1273
- meta.headers.delete("content-length");
1274
- return new Response(null, { status: meta.status, headers: meta.headers });
1272
+ headers.delete("content-length");
1273
+ return new Response(null, { status, headers });
1275
1274
  }
1276
- if (!meta.headers.has("content-length")) meta.headers.set("content-length", String(body.byteLength));
1277
- return new Response(body.buffer, { status: meta.status, headers: meta.headers });
1275
+ const body = mergeUint8Arrays(httpState.bodyChunks);
1276
+ if (!headers.has("content-length")) headers.set("content-length", String(body.byteLength));
1277
+ return new Response(body.buffer, { status, headers });
1278
1278
  }
1279
1279
 
1280
1280
  // src/app.ts
@@ -1311,7 +1311,7 @@ var Ziex = class {
1311
1311
  */
1312
1312
  this.fetch = async (request, env, ctx) => {
1313
1313
  const module = await this.getModule();
1314
- const { wasi, imports, websocket } = this.options;
1314
+ const { wasi, imports, sticky } = this.options;
1315
1315
  return run({
1316
1316
  request,
1317
1317
  env,
@@ -1321,7 +1321,7 @@ var Ziex = class {
1321
1321
  imports,
1322
1322
  kv: this.resolveKV(env),
1323
1323
  db: this.resolveDB(env),
1324
- websocket: websocket !== void 0 ? env[websocket] : void 0
1324
+ sticky: sticky !== void 0 ? env[sticky] : void 0
1325
1325
  });
1326
1326
  };
1327
1327
  this.options = options;
@@ -1330,6 +1330,27 @@ var Ziex = class {
1330
1330
  if (!this.resolved) this.resolved = await resolveModule(this.options.module);
1331
1331
  return this.resolved;
1332
1332
  }
1333
+ /**
1334
+ * Enable sticky upgrade forwarding and return host config for platform adapters
1335
+ * (e.g. Cloudflare {@linkcode stateful}).
1336
+ *
1337
+ * Requires `options.module` to already be a compiled `WebAssembly.Module`.
1338
+ */
1339
+ stickyHost(binding) {
1340
+ this.options.sticky = binding;
1341
+ const mod = this.options.module;
1342
+ if (mod instanceof ArrayBuffer || ArrayBuffer.isView(mod) || mod instanceof Response || mod instanceof URL || typeof mod === "string") {
1343
+ throw new Error(
1344
+ 'sticky handlers require a compiled WebAssembly.Module (e.g. `import module from "./app.wasm"` under wrangler)'
1345
+ );
1346
+ }
1347
+ return {
1348
+ module: mod,
1349
+ imports: this.options.imports,
1350
+ kv: (env) => this.resolveKV(env),
1351
+ db: (env) => this.resolveDB(env)
1352
+ };
1353
+ }
1333
1354
  resolveKV(env) {
1334
1355
  const { kv } = this.options;
1335
1356
  if (kv === void 0) return void 0;