ziex 0.1.0-dev.787 → 0.1.0-dev.804

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/wasm/init.js CHANGED
@@ -167,7 +167,7 @@ class ZigJS {
167
167
  return decoder.decode(data);
168
168
  }
169
169
  }
170
- // src/wasm/index.ts
170
+ // src/wasm/core.ts
171
171
  var CallbackType = {
172
172
  Event: 0,
173
173
  FetchSuccess: 1,
@@ -218,25 +218,17 @@ function writeBytes(ptr, data) {
218
218
  getMemoryView().set(data, ptr);
219
219
  }
220
220
 
221
- class ZxBridge {
221
+ class ZxBridgeCore {
222
222
  #intervals = new Map;
223
- #websockets = new Map;
224
- #alloc;
223
+ _alloc;
225
224
  #handler;
226
225
  #fetchCompleteHandler;
227
- #wsOnOpenHandler;
228
- #wsOnMessageHandler;
229
- #wsOnErrorHandler;
230
- #wsOnCloseHandler;
231
226
  constructor(exports) {
232
- this.#alloc = exports.__zx_alloc;
227
+ this._alloc = exports.__zx_alloc;
233
228
  this.#handler = exports.__zx_cb;
234
229
  this.#fetchCompleteHandler = exports.__zx_fetch_complete;
235
- this.#wsOnOpenHandler = exports.__zx_ws_onopen;
236
- this.#wsOnMessageHandler = exports.__zx_ws_onmessage;
237
- this.#wsOnErrorHandler = exports.__zx_ws_onerror;
238
- this.#wsOnCloseHandler = exports.__zx_ws_onclose;
239
- this.#eventbridge = exports.__zx_eventbridge;
230
+ if (exports.memory)
231
+ jsz.memory = exports.memory;
240
232
  }
241
233
  #invoke(type, id, data) {
242
234
  const handler = this.#handler;
@@ -276,37 +268,22 @@ class ZxBridge {
276
268
  if (timeout)
277
269
  clearTimeout(timeout);
278
270
  const text = await response.text();
279
- this.#notifyFetchComplete(fetchId, response.status, text, false);
271
+ this._notifyFetchComplete(fetchId, response.status, text, false);
280
272
  }).catch((error) => {
281
273
  if (timeout)
282
274
  clearTimeout(timeout);
283
275
  const isAbort = error.name === "AbortError";
284
276
  const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
285
- this.#notifyFetchComplete(fetchId, 0, errorMsg, true);
277
+ this._notifyFetchComplete(fetchId, 0, errorMsg, true);
286
278
  });
287
279
  }
288
- #notifyFetchComplete(fetchId, statusCode, body, isError) {
280
+ _notifyFetchComplete(fetchId, statusCode, body, isError) {
289
281
  const handler = this.#fetchCompleteHandler;
290
282
  const encoded = textEncoder.encode(body);
291
- const ptr = this.#alloc(encoded.length);
283
+ const ptr = this._alloc(encoded.length);
292
284
  writeBytes(ptr, encoded);
293
285
  handler(fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
294
286
  }
295
- submitFormActionAsync(form, statesJson, fetchId) {
296
- const formData = new FormData(form);
297
- formData.append("__zx_states", statesJson);
298
- fetch(window.location.href, {
299
- method: "POST",
300
- headers: { "X-ZX-Action": "1" },
301
- body: formData
302
- }).then(async (response) => {
303
- const text = await response.text();
304
- this.#notifyFetchComplete(fetchId, response.status, text, false);
305
- }).catch((error) => {
306
- const msg = error instanceof Error ? error.message : "Fetch failed";
307
- this.#notifyFetchComplete(fetchId, 0, msg, true);
308
- });
309
- }
310
287
  setTimeout(callbackId, delayMs) {
311
288
  setTimeout(() => {
312
289
  this.#invoke(CallbackType.Timeout, callbackId, null);
@@ -325,6 +302,83 @@ class ZxBridge {
325
302
  this.#intervals.delete(callbackId);
326
303
  }
327
304
  }
305
+ _writeStringToWasm(str) {
306
+ return this._writeBytesToWasm(textEncoder.encode(str));
307
+ }
308
+ _writeBytesToWasm(data) {
309
+ const ptr = this._alloc(data.length);
310
+ writeBytes(ptr, data);
311
+ return { ptr, len: data.length };
312
+ }
313
+ static log(level, ptr, len) {
314
+ const msg = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
315
+ switch (level) {
316
+ case 0:
317
+ console.error(msg);
318
+ break;
319
+ case 1:
320
+ console.warn(msg);
321
+ break;
322
+ case 3:
323
+ console.debug(msg);
324
+ break;
325
+ default:
326
+ console.log(msg);
327
+ break;
328
+ }
329
+ }
330
+ static createImportObject(bridgeRef) {
331
+ return {
332
+ ...jsz.importObject(),
333
+ __zx: {
334
+ _log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
335
+ _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
336
+ bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
337
+ },
338
+ _setTimeout: (callbackId, delayMs) => {
339
+ bridgeRef.current?.setTimeout(callbackId, delayMs);
340
+ },
341
+ _setInterval: (callbackId, intervalMs) => {
342
+ bridgeRef.current?.setInterval(callbackId, intervalMs);
343
+ },
344
+ _clearInterval: (callbackId) => {
345
+ bridgeRef.current?.clearInterval(callbackId);
346
+ }
347
+ }
348
+ };
349
+ }
350
+ }
351
+ // src/wasm/index.ts
352
+ class ZxBridge extends ZxBridgeCore {
353
+ #websockets = new Map;
354
+ #wsOnOpenHandler;
355
+ #wsOnMessageHandler;
356
+ #wsOnErrorHandler;
357
+ #wsOnCloseHandler;
358
+ #eventbridge;
359
+ constructor(exports) {
360
+ super(exports);
361
+ this.#wsOnOpenHandler = exports.__zx_ws_onopen;
362
+ this.#wsOnMessageHandler = exports.__zx_ws_onmessage;
363
+ this.#wsOnErrorHandler = exports.__zx_ws_onerror;
364
+ this.#wsOnCloseHandler = exports.__zx_ws_onclose;
365
+ this.#eventbridge = exports.__zx_eventbridge;
366
+ }
367
+ submitFormActionAsync(form, statesJson, fetchId) {
368
+ const formData = new FormData(form);
369
+ formData.append("__zx_states", statesJson);
370
+ fetch(window.location.href, {
371
+ method: "POST",
372
+ headers: { "X-ZX-Action": "1" },
373
+ body: formData
374
+ }).then(async (response) => {
375
+ const text = await response.text();
376
+ this._notifyFetchComplete(fetchId, response.status, text, false);
377
+ }).catch((error) => {
378
+ const msg = error instanceof Error ? error.message : "Fetch failed";
379
+ this._notifyFetchComplete(fetchId, 0, msg, true);
380
+ });
381
+ }
328
382
  wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
329
383
  const url = readString(urlPtr, urlLen);
330
384
  const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
@@ -337,7 +391,7 @@ class ZxBridge {
337
391
  if (!handler)
338
392
  return;
339
393
  const protocol = ws.protocol || "";
340
- const { ptr, len } = this.#writeStringToWasm(protocol);
394
+ const { ptr, len } = this._writeStringToWasm(protocol);
341
395
  handler(wsId, ptr, len);
342
396
  };
343
397
  ws.onmessage = (event) => {
@@ -345,21 +399,15 @@ class ZxBridge {
345
399
  if (!handler)
346
400
  return;
347
401
  const isBinary = event.data instanceof ArrayBuffer;
348
- let data;
349
- if (isBinary) {
350
- data = new Uint8Array(event.data);
351
- } else {
352
- data = textEncoder.encode(event.data);
353
- }
354
- const { ptr, len } = this.#writeBytesToWasm(data);
402
+ const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
403
+ const { ptr, len } = this._writeBytesToWasm(data);
355
404
  handler(wsId, ptr, len, isBinary ? 1 : 0);
356
405
  };
357
- ws.onerror = (event) => {
406
+ ws.onerror = (_event) => {
358
407
  const handler = this.#wsOnErrorHandler;
359
408
  if (!handler)
360
409
  return;
361
- const msg = "WebSocket error";
362
- const { ptr, len } = this.#writeStringToWasm(msg);
410
+ const { ptr, len } = this._writeStringToWasm("WebSocket error");
363
411
  handler(wsId, ptr, len);
364
412
  };
365
413
  ws.onclose = (event) => {
@@ -367,7 +415,7 @@ class ZxBridge {
367
415
  if (!handler)
368
416
  return;
369
417
  const reason = event.reason || "";
370
- const { ptr, len } = this.#writeStringToWasm(reason);
418
+ const { ptr, len } = this._writeStringToWasm(reason);
371
419
  handler(wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
372
420
  this.#websockets.delete(wsId);
373
421
  };
@@ -376,7 +424,7 @@ class ZxBridge {
376
424
  const handler = this.#wsOnErrorHandler;
377
425
  if (handler) {
378
426
  const msg = error instanceof Error ? error.message : "WebSocket connection failed";
379
- const { ptr, len } = this.#writeStringToWasm(msg);
427
+ const { ptr, len } = this._writeStringToWasm(msg);
380
428
  handler(wsId, ptr, len);
381
429
  }
382
430
  }
@@ -398,25 +446,14 @@ class ZxBridge {
398
446
  return;
399
447
  const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : undefined;
400
448
  try {
401
- if (reason) {
449
+ if (reason)
402
450
  ws.close(code, reason);
403
- } else {
451
+ else
404
452
  ws.close(code);
405
- }
406
453
  } catch {
407
454
  ws.close();
408
455
  }
409
456
  }
410
- #writeStringToWasm(str) {
411
- const encoded = textEncoder.encode(str);
412
- return this.#writeBytesToWasm(encoded);
413
- }
414
- #writeBytesToWasm(data) {
415
- const ptr = this.#alloc(data.length);
416
- writeBytes(ptr, data);
417
- return { ptr, len: data.length };
418
- }
419
- #eventbridge;
420
457
  eventbridge(velementId, eventTypeId, event) {
421
458
  if (!this.#eventbridge)
422
459
  return;
@@ -427,6 +464,7 @@ class ZxBridge {
427
464
  return {
428
465
  ...jsz.importObject(),
429
466
  __zx: {
467
+ _log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
430
468
  _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
431
469
  bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
432
470
  },
package/wasm/wasi.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * WASI/edge WASM bridge — zero dependencies on ZigJS (jsz) or browser globals.
3
+ *
4
+ * Import this (and only this) from edge/server runtimes. It provides the
5
+ * minimal __zx import namespace needed by server-side WASM: log, fetch, and
6
+ * timers. The jsz importObject is intentionally omitted — the server binary
7
+ * does not use jsz value-passing.
8
+ */
9
+ export declare class ZxWasiBridge {
10
+ #private;
11
+ constructor(exports: WebAssembly.Exports);
12
+ log(level: number, ptr: number, len: number): void;
13
+ fetchAsync(urlPtr: number, urlLen: number, methodPtr: number, methodLen: number, headersPtr: number, headersLen: number, bodyPtr: number, bodyLen: number, timeoutMs: number, fetchId: bigint): void;
14
+ setTimeout(callbackId: bigint, delayMs: number): void;
15
+ setInterval(callbackId: bigint, intervalMs: number): void;
16
+ clearInterval(callbackId: bigint): void;
17
+ /**
18
+ * Create the WASI import object for WASM instantiation.
19
+ *
20
+ * Returns only the `__zx` namespace (log, fetch, timers).
21
+ * Does NOT include jsz.importObject() — the server binary does not use jsz.
22
+ */
23
+ static createImportObject(bridgeRef: {
24
+ current: ZxWasiBridge | null;
25
+ }): {
26
+ __zx: Record<string, unknown>;
27
+ };
28
+ }
package/hono/index.d.ts DELETED
@@ -1,92 +0,0 @@
1
- import { Hono } from "hono";
2
- import type { KVNamespace } from "../cloudflare/kv";
3
- type DurableObjectNamespace = {
4
- idFromName(name: string): unknown;
5
- get(id: unknown): {
6
- fetch(req: Request): Promise<Response>;
7
- };
8
- };
9
- type WASI = {
10
- wasiImport: Record<string, (...args: any[]) => unknown>;
11
- start(instance: {
12
- exports: {
13
- memory: WebAssembly.Memory;
14
- _start: () => unknown;
15
- };
16
- }): number;
17
- initialize?(instance: {
18
- exports: {
19
- memory: WebAssembly.Memory;
20
- _initialize?: () => unknown;
21
- };
22
- }): void;
23
- };
24
- /**
25
- * Create a Hono app that runs a Ziex WASM module.
26
- *
27
- * The returned app handles all routes (`*`) and forwards each request to
28
- * the WASM runtime. Deploy it on any platform Hono supports:
29
- *
30
- * @example Cloudflare Workers
31
- * ```ts
32
- * import { createHonoApp } from "ziex/hono";
33
- * import module from "./app.wasm";
34
- *
35
- * const app = createHonoApp<{ KV: KVNamespace }>({
36
- * module,
37
- * kv: (env) => ({ default: env.KV }),
38
- * });
39
- *
40
- * export default app;
41
- * ```
42
- *
43
- * @example Node / Vercel (requires JSPI support)
44
- * ```ts
45
- * import { createHonoApp } from "ziex/hono";
46
- * import { serve } from "@hono/node-server";
47
- * import module from "./app.wasm";
48
- *
49
- * const app = createHonoApp({ module });
50
- * serve(app);
51
- * ```
52
- *
53
- * **Note:** The WASM async model relies on JSPI (`WebAssembly.Suspending` /
54
- * `WebAssembly.promising`). Verify that your target runtime supports it.
55
- */
56
- export declare function createHonoApp<Bindings extends Record<string, unknown> = Record<string, unknown>>(options: {
57
- /** Compiled WASM module for the Ziex app. */
58
- module: WebAssembly.Module;
59
- /**
60
- * Optional pre-configured WASI instance. When omitted the built-in WASI
61
- * shim (from `ziex/cloudflare`) is used automatically.
62
- */
63
- wasi?: WASI;
64
- /**
65
- * Extra WASM import objects, keyed by module namespace.
66
- * Receives a `mem` accessor so you can read WASM memory lazily.
67
- */
68
- imports?: (mem: () => WebAssembly.Memory) => Record<string, Record<string, unknown>>;
69
- /**
70
- * Factory that maps platform env bindings to Ziex KV namespaces.
71
- * Called once per request so bindings are resolved at runtime.
72
- *
73
- * @example
74
- * ```ts
75
- * kv: (env) => ({ default: env.MY_KV })
76
- * ```
77
- */
78
- kv?: (env: Bindings) => Record<string, KVNamespace>;
79
- /**
80
- * Factory that maps platform env bindings to a Durable Object namespace
81
- * for WebSocket pub/sub support.
82
- *
83
- * @example
84
- * ```ts
85
- * websocket: (env) => env.ZxWS
86
- * ```
87
- */
88
- websocket?: (env: Bindings) => DurableObjectNamespace;
89
- }): Hono<{
90
- Bindings: Bindings;
91
- }>;
92
- export {};