ziex 0.1.0-dev.787 → 0.1.0-dev.805

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/kv.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ export interface KVNamespace {
2
+ get(key: string): Promise<string | null>;
3
+ put(key: string, value: string, options?: {
4
+ expiration?: number;
5
+ expirationTtl?: number;
6
+ }): Promise<void>;
7
+ delete(key: string): Promise<void>;
8
+ list(options?: {
9
+ prefix?: string;
10
+ }): Promise<{
11
+ keys: {
12
+ name: string;
13
+ }[];
14
+ }>;
15
+ }
16
+ /**
17
+ * In-memory KV namespace. Used as the default shim on platforms that don't
18
+ * provide a real KV binding (e.g. Vercel). Data lives only for the lifetime
19
+ * of the isolate instance.
20
+ */
21
+ export declare function createMemoryKV(): KVNamespace;
22
+ /**
23
+ * Create a `__zx_kv` import object for use with `run({ kv: ... })`.
24
+ * Always returns a valid import object. When JSPI is unavailable all KV
25
+ * operations are stubbed (get → not-found, put/delete → success, list → []).
26
+ */
27
+ export declare function createKVImports(bindings: Record<string, KVNamespace>, getMemory: () => WebAssembly.Memory): Record<string, unknown>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ziex",
3
- "version": "0.1.0-dev.787",
3
+ "version": "0.1.0-dev.805",
4
4
  "description": "ZX is a framework for building web applications with Zig.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -10,7 +10,6 @@
10
10
  "./wasm": "./wasm/index.js",
11
11
  "./wasm/init": "./wasm/init.js",
12
12
  "./cloudflare": "./cloudflare/index.js",
13
- "./hono": "./hono/index.js",
14
13
  "./aws-lambda": "./aws-lambda/index.js",
15
14
  "./vercel": "./vercel/index.js"
16
15
  },
@@ -39,9 +38,6 @@
39
38
  },
40
39
  "react-dom": {
41
40
  "optional": true
42
- },
43
- "hono": {
44
- "optional": true
45
41
  }
46
42
  },
47
43
  "module": "index.js",
package/runtime.d.ts ADDED
@@ -0,0 +1,70 @@
1
+ import type { WASI } from "./wasi";
2
+ import type { KVNamespace } from "./kv";
3
+ /** Minimal Durable Object namespace shape needed for WebSocket routing. */
4
+ export type DurableObjectNamespace = {
5
+ idFromName(name: string): unknown;
6
+ get(id: unknown): {
7
+ fetch(req: Request): Promise<Response>;
8
+ };
9
+ };
10
+ export type WsState = {
11
+ upgraded: boolean;
12
+ server: WebSocket | null;
13
+ pendingWrites: Uint8Array[];
14
+ messageQueue: Uint8Array[];
15
+ recvResolve: ((bytes: Uint8Array | null) => void) | null;
16
+ /** Resolved when ws_recv is called for the first time (WASM has entered the message loop). */
17
+ _resolveFirstSuspend?: () => void;
18
+ subscribe?: (topic: string) => void;
19
+ unsubscribe?: (topic: string) => void;
20
+ publish?: (topic: string, data: Uint8Array) => number;
21
+ isSubscribed?: (topic: string) => boolean;
22
+ };
23
+ /** Build the __zx_ws import object for a given connection state. */
24
+ export declare function buildWsImports(Suspending: any, mem: () => WebAssembly.Memory, decoder: TextDecoder, ws: WsState): {
25
+ ws_upgrade: () => void;
26
+ ws_write: (ptr: number, len: number) => void;
27
+ ws_close: (code: number, reason_ptr: number, reason_len: number) => void;
28
+ ws_recv: any;
29
+ ws_subscribe: (ptr: number, len: number) => void;
30
+ ws_unsubscribe: (ptr: number, len: number) => void;
31
+ ws_publish: (topic_ptr: number, topic_len: number, data_ptr: number, data_len: number) => number;
32
+ ws_is_subscribed: (ptr: number, len: number) => number;
33
+ };
34
+ /** Create WebSocketPair, wire message/close listeners, flush pending writes. */
35
+ export declare function attachWebSocket(ws: WsState): {
36
+ client: WebSocket;
37
+ };
38
+ /**
39
+ * Run a WASM module for a single request using JSPI.
40
+ *
41
+ * Pass `kv` as a map of binding names → KV namespaces. The Zig side selects
42
+ * a binding via `zx.kv.scope("name")`; the top-level `zx.kv.*` functions use
43
+ * `"default"`.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * return run({
48
+ * request, env, ctx, module,
49
+ * kv: { default: env.KV, users: env.USERS_KV },
50
+ * });
51
+ * ```
52
+ */
53
+ export declare function run({ request, env, ctx, module, kv: kvBindings, imports, wasi, websocket: doNamespace, }: {
54
+ request: Request;
55
+ env?: unknown;
56
+ ctx?: {
57
+ waitUntil(promise: Promise<unknown>): void;
58
+ };
59
+ module: WebAssembly.Module;
60
+ /** KV namespace bindings — `{ default: env.KV, otherName: env.OTHER_KV }` */
61
+ kv?: Record<string, KVNamespace>;
62
+ imports?: (mem: () => WebAssembly.Memory) => Record<string, Record<string, unknown>>;
63
+ wasi?: WASI;
64
+ /**
65
+ * Durable Object namespace to use for WebSocket connections.
66
+ * When provided, WebSocket upgrade requests are automatically forwarded to
67
+ * the DO so that pub/sub works across multiple connected clients.
68
+ */
69
+ websocket?: DurableObjectNamespace;
70
+ }): Promise<Response>;
package/wasi.d.ts ADDED
@@ -0,0 +1,61 @@
1
+ export declare class ProcExit extends Error {
2
+ readonly code: number;
3
+ constructor(code: number);
4
+ }
5
+ export type WASI = {
6
+ wasiImport: Record<string, (...args: any[]) => unknown>;
7
+ start(instance: {
8
+ exports: {
9
+ memory: WebAssembly.Memory;
10
+ _start: () => unknown;
11
+ };
12
+ }): number;
13
+ initialize?(instance: {
14
+ exports: {
15
+ memory: WebAssembly.Memory;
16
+ _initialize?: () => unknown;
17
+ };
18
+ }): void;
19
+ };
20
+ export declare function createWasiImports({ request, stdinData, onStdout, }: {
21
+ request: Request;
22
+ stdinData?: Uint8Array;
23
+ /** Called for each stdout chunk. When provided, chunks are NOT buffered internally. */
24
+ onStdout?: (chunk: Uint8Array) => void;
25
+ }): {
26
+ wasiImport: {
27
+ args_sizes_get(argc_ptr: number, argv_buf_size_ptr: number): number;
28
+ args_get(argv_ptr: number, argv_buf_ptr: number): number;
29
+ environ_sizes_get(count_ptr: number, buf_size_ptr: number): number;
30
+ environ_get(_environ_ptr: number, _environ_buf_ptr: number): number;
31
+ fd_write(fd: number, iovs_ptr: number, iovs_len: number, nwritten_ptr: number): number;
32
+ fd_read(fd: number, iovs_ptr: number, iovs_len: number, nread_ptr: number): number;
33
+ fd_fdstat_get(_fd: number, fdstat_ptr: number): number;
34
+ fd_prestat_get(_fd: number, _bufptr: number): number;
35
+ fd_prestat_dir_name(_fd: number, _path: number, _path_len: number): number;
36
+ fd_close(_fd: number): number;
37
+ fd_pread(_fd: number, _iovs: number, _iovs_len: number, _offset: bigint, nread_ptr: number): number;
38
+ fd_pwrite(_fd: number, _iovs: number, _iovs_len: number, _offset: bigint, nwritten_ptr: number): number;
39
+ fd_filestat_get(_fd: number, filestat_ptr: number): number;
40
+ fd_seek(_fd: number, _offset: bigint, _whence: number, newoffset_ptr: number): number;
41
+ proc_exit(code: number): never;
42
+ sched_yield(): number;
43
+ clock_time_get(_id: number, _precision: bigint, time_ptr: number): number;
44
+ random_get(buf_ptr: number, buf_len: number): number;
45
+ path_open(_fd: number, _dirflags: number, _path: number, _path_len: number, _oflags: number, _rights_base: bigint, _rights_inheriting: bigint, _fdflags: number, opened_fd_ptr: number): number;
46
+ path_create_directory(_fd: number, _path: number, _path_len: number): number;
47
+ path_unlink_file(_fd: number, _path: number, _path_len: number): number;
48
+ path_remove_directory(_fd: number, _path: number, _path_len: number): number;
49
+ path_rename(_fd: number, _old_path: number, _old_path_len: number, _new_fd: number, _new_path: number, _new_path_len: number): number;
50
+ path_filestat_get(_fd: number, _flags: number, _path: number, _path_len: number, filestat_ptr: number): number;
51
+ path_readlink(_fd: number, _path: number, _path_len: number, _buf: number, _buf_len: number, nread_ptr: number): number;
52
+ fd_readdir(_fd: number, _buf: number, _buf_len: number, _cookie: bigint, bufused_ptr: number): number;
53
+ poll_oneoff(_in: number, _out: number, _nsubscriptions: number, nevents_ptr: number): number;
54
+ };
55
+ setMemory: (m: WebAssembly.Memory) => void;
56
+ collectOutput: () => {
57
+ stdout: Uint8Array;
58
+ stderrText: string;
59
+ };
60
+ };
61
+ export declare function mergeUint8Arrays(arrays: Uint8Array[]): Uint8Array;
package/wasm/core.d.ts ADDED
@@ -0,0 +1,78 @@
1
+ import { ZigJS } from "../../../../vendor/jsz/js/src";
2
+ /**
3
+ * Core WASM bridge — environment-agnostic (browser + edge).
4
+ * Contains no references to browser globals (document, window, WebSocket, HTMLFormElement).
5
+ */
6
+ export declare const CallbackType: {
7
+ readonly Event: 0;
8
+ readonly FetchSuccess: 1;
9
+ readonly FetchError: 2;
10
+ readonly Timeout: 3;
11
+ readonly Interval: 4;
12
+ readonly WebSocketOpen: 5;
13
+ readonly WebSocketMessage: 6;
14
+ readonly WebSocketError: 7;
15
+ readonly WebSocketClose: 8;
16
+ };
17
+ export type CallbackTypeValue = typeof CallbackType[keyof typeof CallbackType];
18
+ export type CallbackHandler = (callbackType: number, id: bigint, dataRef: bigint) => void;
19
+ export type FetchCompleteHandler = (fetchId: bigint, statusCode: number, bodyPtr: number, bodyLen: number, isError: number) => void;
20
+ export type WsOnOpenHandler = (wsId: bigint, protocolPtr: number, protocolLen: number) => void;
21
+ export type WsOnMessageHandler = (wsId: bigint, dataPtr: number, dataLen: number, isBinary: number) => void;
22
+ export type WsOnErrorHandler = (wsId: bigint, msgPtr: number, msgLen: number) => void;
23
+ export type WsOnCloseHandler = (wsId: bigint, code: number, reasonPtr: number, reasonLen: number, wasClean: number) => void;
24
+ export declare const jsz: ZigJS;
25
+ /** Store a value using jsz.storeValue and get the 64-bit reference. */
26
+ export declare function storeValueGetRef(val: any): bigint;
27
+ /** Shared encoder/decoder — avoids allocating new instances on every call. */
28
+ export declare const textDecoder: TextDecoder;
29
+ export declare const textEncoder: TextEncoder;
30
+ export declare function getMemoryView(): Uint8Array;
31
+ /** Read a string from WASM memory */
32
+ export declare function readString(ptr: number, len: number): string;
33
+ /** Write bytes to WASM memory at a specific location */
34
+ export declare function writeBytes(ptr: number, data: Uint8Array): void;
35
+ /**
36
+ * Core ZX Bridge — works in both browser and edge runtimes.
37
+ * Contains fetch, timers, and logging. No DOM or browser-WebSocket references.
38
+ *
39
+ * Extend this class in browser environments to add DOM and WebSocket support.
40
+ */
41
+ export declare class ZxBridgeCore {
42
+ #private;
43
+ protected readonly _alloc: (size: number) => number;
44
+ constructor(exports: WebAssembly.Exports);
45
+ /**
46
+ * Async fetch with full options support.
47
+ * Calls __zx_fetch_complete when done.
48
+ */
49
+ fetchAsync(urlPtr: number, urlLen: number, methodPtr: number, methodLen: number, headersPtr: number, headersLen: number, bodyPtr: number, bodyLen: number, timeoutMs: number, fetchId: bigint): void;
50
+ /** Notify WASM that a fetch completed */
51
+ protected _notifyFetchComplete(fetchId: bigint, statusCode: number, body: string, isError: boolean): void;
52
+ /** Set a timeout and callback when it fires */
53
+ setTimeout(callbackId: bigint, delayMs: number): void;
54
+ /** Set an interval and callback each time it fires */
55
+ setInterval(callbackId: bigint, intervalMs: number): void;
56
+ /** Clear an interval */
57
+ clearInterval(callbackId: bigint): void;
58
+ /** Write a string to WASM memory, returning pointer and length */
59
+ protected _writeStringToWasm(str: string): {
60
+ ptr: number;
61
+ len: number;
62
+ };
63
+ protected _writeBytesToWasm(data: Uint8Array): {
64
+ ptr: number;
65
+ len: number;
66
+ };
67
+ /** Log a message from WASM at the given level (0=error, 1=warn, 2=info, 3=debug) */
68
+ static log(level: number, ptr: number, len: number): void;
69
+ /**
70
+ * Create the core import object for WASM instantiation.
71
+ * Includes only environment-agnostic bindings: log, fetch, and timers.
72
+ * Use ZxBridge.createImportObject (from wasm/index.ts) in browser contexts
73
+ * to additionally include DOM and WebSocket bindings.
74
+ */
75
+ static createImportObject(bridgeRef: {
76
+ current: ZxBridgeCore | null;
77
+ }): WebAssembly.Imports;
78
+ }
package/wasm/index.d.ts CHANGED
@@ -1,42 +1,16 @@
1
- import { ZigJS } from "../../../../vendor/jsz/js/src";
1
+ export { CallbackType, jsz, storeValueGetRef, textDecoder, textEncoder, getMemoryView, readString, writeBytes, ZxBridgeCore, } from "./core";
2
+ export type { CallbackTypeValue } from "./core";
3
+ import { ZxBridgeCore } from "./core";
2
4
  /**
3
- * ZX Client Bridge - Unified JS↔WASM communication layer
4
- * Handles events, fetch, WebSocket, timers, and other async callbacks using jsz
5
+ * Browser ZX Bridge extends ZxBridgeCore with DOM, WebSocket, and form-action support.
6
+ * Import this from environments that have access to browser globals.
7
+ * For edge runtimes, import ZxBridgeCore from ./core instead.
5
8
  */
6
- export declare const CallbackType: {
7
- readonly Event: 0;
8
- readonly FetchSuccess: 1;
9
- readonly FetchError: 2;
10
- readonly Timeout: 3;
11
- readonly Interval: 4;
12
- readonly WebSocketOpen: 5;
13
- readonly WebSocketMessage: 6;
14
- readonly WebSocketError: 7;
15
- readonly WebSocketClose: 8;
16
- };
17
- export type CallbackTypeValue = typeof CallbackType[keyof typeof CallbackType];
18
- export declare const jsz: ZigJS;
19
- /** Store a value using jsz.storeValue and get the 64-bit reference. */
20
- export declare function storeValueGetRef(val: any): bigint;
21
- /** ZX Bridge - provides JS APIs that callback into WASM */
22
- export declare class ZxBridge {
9
+ export declare class ZxBridge extends ZxBridgeCore {
23
10
  #private;
24
11
  constructor(exports: WebAssembly.Exports);
25
- /**
26
- * Async fetch with full options support.
27
- * Calls __zx_fetch_complete when done.
28
- */
29
- fetchAsync(urlPtr: number, urlLen: number, methodPtr: number, methodLen: number, headersPtr: number, headersLen: number, bodyPtr: number, bodyLen: number, timeoutMs: number, fetchId: bigint): void;
30
- /** Submit a form action with bound-state round-trip.
31
- * Sends the form as multipart/form-data + __zx_states field,
32
- * then calls __zx_fetch_complete so WASM can apply state updates. */
12
+ /** Submit a form action with bound-state round-trip. */
33
13
  submitFormActionAsync(form: HTMLFormElement, statesJson: string, fetchId: bigint): void;
34
- /** Set a timeout and callback when it fires */
35
- setTimeout(callbackId: bigint, delayMs: number): void;
36
- /** Set an interval and callback each time it fires */
37
- setInterval(callbackId: bigint, intervalMs: number): void;
38
- /** Clear an interval */
39
- clearInterval(callbackId: bigint): void;
40
14
  /**
41
15
  * Create and connect a WebSocket.
42
16
  * Calls __zx_ws_onopen, __zx_ws_onmessage, __zx_ws_onerror, __zx_ws_onclose.
@@ -48,7 +22,7 @@ export declare class ZxBridge {
48
22
  wsClose(wsId: bigint, code: number, reasonPtr: number, reasonLen: number): void;
49
23
  /** Handle a DOM event (called by event delegation) */
50
24
  eventbridge(velementId: bigint, eventTypeId: number, event: Event): void;
51
- /** Create the import object for WASM instantiation */
25
+ /** Create the full browser import object for WASM instantiation (includes DOM + WebSocket). */
52
26
  static createImportObject(bridgeRef: {
53
27
  current: ZxBridge | null;
54
28
  }): WebAssembly.Imports;
package/wasm/index.js CHANGED
@@ -178,7 +178,7 @@ class ZigJS {
178
178
  return decoder.decode(data);
179
179
  }
180
180
  }
181
- // src/wasm/index.ts
181
+ // src/wasm/core.ts
182
182
  var CallbackType = {
183
183
  Event: 0,
184
184
  FetchSuccess: 1,
@@ -229,25 +229,17 @@ function writeBytes(ptr, data) {
229
229
  getMemoryView().set(data, ptr);
230
230
  }
231
231
 
232
- class ZxBridge {
232
+ class ZxBridgeCore {
233
233
  #intervals = new Map;
234
- #websockets = new Map;
235
- #alloc;
234
+ _alloc;
236
235
  #handler;
237
236
  #fetchCompleteHandler;
238
- #wsOnOpenHandler;
239
- #wsOnMessageHandler;
240
- #wsOnErrorHandler;
241
- #wsOnCloseHandler;
242
237
  constructor(exports) {
243
- this.#alloc = exports.__zx_alloc;
238
+ this._alloc = exports.__zx_alloc;
244
239
  this.#handler = exports.__zx_cb;
245
240
  this.#fetchCompleteHandler = exports.__zx_fetch_complete;
246
- this.#wsOnOpenHandler = exports.__zx_ws_onopen;
247
- this.#wsOnMessageHandler = exports.__zx_ws_onmessage;
248
- this.#wsOnErrorHandler = exports.__zx_ws_onerror;
249
- this.#wsOnCloseHandler = exports.__zx_ws_onclose;
250
- this.#eventbridge = exports.__zx_eventbridge;
241
+ if (exports.memory)
242
+ jsz.memory = exports.memory;
251
243
  }
252
244
  #invoke(type, id, data) {
253
245
  const handler = this.#handler;
@@ -287,37 +279,22 @@ class ZxBridge {
287
279
  if (timeout)
288
280
  clearTimeout(timeout);
289
281
  const text = await response.text();
290
- this.#notifyFetchComplete(fetchId, response.status, text, false);
282
+ this._notifyFetchComplete(fetchId, response.status, text, false);
291
283
  }).catch((error) => {
292
284
  if (timeout)
293
285
  clearTimeout(timeout);
294
286
  const isAbort = error.name === "AbortError";
295
287
  const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
296
- this.#notifyFetchComplete(fetchId, 0, errorMsg, true);
288
+ this._notifyFetchComplete(fetchId, 0, errorMsg, true);
297
289
  });
298
290
  }
299
- #notifyFetchComplete(fetchId, statusCode, body, isError) {
291
+ _notifyFetchComplete(fetchId, statusCode, body, isError) {
300
292
  const handler = this.#fetchCompleteHandler;
301
293
  const encoded = textEncoder.encode(body);
302
- const ptr = this.#alloc(encoded.length);
294
+ const ptr = this._alloc(encoded.length);
303
295
  writeBytes(ptr, encoded);
304
296
  handler(fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
305
297
  }
306
- submitFormActionAsync(form, statesJson, fetchId) {
307
- const formData = new FormData(form);
308
- formData.append("__zx_states", statesJson);
309
- fetch(window.location.href, {
310
- method: "POST",
311
- headers: { "X-ZX-Action": "1" },
312
- body: formData
313
- }).then(async (response) => {
314
- const text = await response.text();
315
- this.#notifyFetchComplete(fetchId, response.status, text, false);
316
- }).catch((error) => {
317
- const msg = error instanceof Error ? error.message : "Fetch failed";
318
- this.#notifyFetchComplete(fetchId, 0, msg, true);
319
- });
320
- }
321
298
  setTimeout(callbackId, delayMs) {
322
299
  setTimeout(() => {
323
300
  this.#invoke(CallbackType.Timeout, callbackId, null);
@@ -336,6 +313,83 @@ class ZxBridge {
336
313
  this.#intervals.delete(callbackId);
337
314
  }
338
315
  }
316
+ _writeStringToWasm(str) {
317
+ return this._writeBytesToWasm(textEncoder.encode(str));
318
+ }
319
+ _writeBytesToWasm(data) {
320
+ const ptr = this._alloc(data.length);
321
+ writeBytes(ptr, data);
322
+ return { ptr, len: data.length };
323
+ }
324
+ static log(level, ptr, len) {
325
+ const msg = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
326
+ switch (level) {
327
+ case 0:
328
+ console.error(msg);
329
+ break;
330
+ case 1:
331
+ console.warn(msg);
332
+ break;
333
+ case 3:
334
+ console.debug(msg);
335
+ break;
336
+ default:
337
+ console.log(msg);
338
+ break;
339
+ }
340
+ }
341
+ static createImportObject(bridgeRef) {
342
+ return {
343
+ ...jsz.importObject(),
344
+ __zx: {
345
+ _log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
346
+ _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
347
+ bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
348
+ },
349
+ _setTimeout: (callbackId, delayMs) => {
350
+ bridgeRef.current?.setTimeout(callbackId, delayMs);
351
+ },
352
+ _setInterval: (callbackId, intervalMs) => {
353
+ bridgeRef.current?.setInterval(callbackId, intervalMs);
354
+ },
355
+ _clearInterval: (callbackId) => {
356
+ bridgeRef.current?.clearInterval(callbackId);
357
+ }
358
+ }
359
+ };
360
+ }
361
+ }
362
+ // src/wasm/index.ts
363
+ class ZxBridge extends ZxBridgeCore {
364
+ #websockets = new Map;
365
+ #wsOnOpenHandler;
366
+ #wsOnMessageHandler;
367
+ #wsOnErrorHandler;
368
+ #wsOnCloseHandler;
369
+ #eventbridge;
370
+ constructor(exports) {
371
+ super(exports);
372
+ this.#wsOnOpenHandler = exports.__zx_ws_onopen;
373
+ this.#wsOnMessageHandler = exports.__zx_ws_onmessage;
374
+ this.#wsOnErrorHandler = exports.__zx_ws_onerror;
375
+ this.#wsOnCloseHandler = exports.__zx_ws_onclose;
376
+ this.#eventbridge = exports.__zx_eventbridge;
377
+ }
378
+ submitFormActionAsync(form, statesJson, fetchId) {
379
+ const formData = new FormData(form);
380
+ formData.append("__zx_states", statesJson);
381
+ fetch(window.location.href, {
382
+ method: "POST",
383
+ headers: { "X-ZX-Action": "1" },
384
+ body: formData
385
+ }).then(async (response) => {
386
+ const text = await response.text();
387
+ this._notifyFetchComplete(fetchId, response.status, text, false);
388
+ }).catch((error) => {
389
+ const msg = error instanceof Error ? error.message : "Fetch failed";
390
+ this._notifyFetchComplete(fetchId, 0, msg, true);
391
+ });
392
+ }
339
393
  wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
340
394
  const url = readString(urlPtr, urlLen);
341
395
  const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
@@ -348,7 +402,7 @@ class ZxBridge {
348
402
  if (!handler)
349
403
  return;
350
404
  const protocol = ws.protocol || "";
351
- const { ptr, len } = this.#writeStringToWasm(protocol);
405
+ const { ptr, len } = this._writeStringToWasm(protocol);
352
406
  handler(wsId, ptr, len);
353
407
  };
354
408
  ws.onmessage = (event) => {
@@ -356,21 +410,15 @@ class ZxBridge {
356
410
  if (!handler)
357
411
  return;
358
412
  const isBinary = event.data instanceof ArrayBuffer;
359
- let data;
360
- if (isBinary) {
361
- data = new Uint8Array(event.data);
362
- } else {
363
- data = textEncoder.encode(event.data);
364
- }
365
- const { ptr, len } = this.#writeBytesToWasm(data);
413
+ const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
414
+ const { ptr, len } = this._writeBytesToWasm(data);
366
415
  handler(wsId, ptr, len, isBinary ? 1 : 0);
367
416
  };
368
- ws.onerror = (event) => {
417
+ ws.onerror = (_event) => {
369
418
  const handler = this.#wsOnErrorHandler;
370
419
  if (!handler)
371
420
  return;
372
- const msg = "WebSocket error";
373
- const { ptr, len } = this.#writeStringToWasm(msg);
421
+ const { ptr, len } = this._writeStringToWasm("WebSocket error");
374
422
  handler(wsId, ptr, len);
375
423
  };
376
424
  ws.onclose = (event) => {
@@ -378,7 +426,7 @@ class ZxBridge {
378
426
  if (!handler)
379
427
  return;
380
428
  const reason = event.reason || "";
381
- const { ptr, len } = this.#writeStringToWasm(reason);
429
+ const { ptr, len } = this._writeStringToWasm(reason);
382
430
  handler(wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
383
431
  this.#websockets.delete(wsId);
384
432
  };
@@ -387,7 +435,7 @@ class ZxBridge {
387
435
  const handler = this.#wsOnErrorHandler;
388
436
  if (handler) {
389
437
  const msg = error instanceof Error ? error.message : "WebSocket connection failed";
390
- const { ptr, len } = this.#writeStringToWasm(msg);
438
+ const { ptr, len } = this._writeStringToWasm(msg);
391
439
  handler(wsId, ptr, len);
392
440
  }
393
441
  }
@@ -409,25 +457,14 @@ class ZxBridge {
409
457
  return;
410
458
  const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : undefined;
411
459
  try {
412
- if (reason) {
460
+ if (reason)
413
461
  ws.close(code, reason);
414
- } else {
462
+ else
415
463
  ws.close(code);
416
- }
417
464
  } catch {
418
465
  ws.close();
419
466
  }
420
467
  }
421
- #writeStringToWasm(str) {
422
- const encoded = textEncoder.encode(str);
423
- return this.#writeBytesToWasm(encoded);
424
- }
425
- #writeBytesToWasm(data) {
426
- const ptr = this.#alloc(data.length);
427
- writeBytes(ptr, data);
428
- return { ptr, len: data.length };
429
- }
430
- #eventbridge;
431
468
  eventbridge(velementId, eventTypeId, event) {
432
469
  if (!this.#eventbridge)
433
470
  return;
@@ -438,6 +475,7 @@ class ZxBridge {
438
475
  return {
439
476
  ...jsz.importObject(),
440
477
  __zx: {
478
+ _log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
441
479
  _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
442
480
  bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
443
481
  },
@@ -842,10 +880,16 @@ async function init(options = {}) {
842
880
  return { source, bridge };
843
881
  }
844
882
  export {
883
+ writeBytes,
884
+ textEncoder,
885
+ textDecoder,
845
886
  storeValueGetRef,
887
+ readString,
846
888
  jsz,
847
889
  initEventDelegation,
848
890
  init,
891
+ getMemoryView,
892
+ ZxBridgeCore,
849
893
  ZxBridge,
850
894
  CallbackType
851
895
  };