ziex 0.1.0-dev.628 → 0.1.0-dev.765

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/README.md CHANGED
@@ -1,11 +1,16 @@
1
- # ZX
1
+ # Ziex
2
2
 
3
3
  A full-stack web framework for Zig. Write declarative UI components using familiar JSX patterns, transpiled to efficient Zig code.
4
4
 
5
- ZX combines the power and performance of Zig with the expressiveness of JSX, enabling you to build fast, type-safe web applications.
5
+ Ziex combines the power and performance of Zig with the expressiveness of JSX, enabling you to build fast, type-safe web applications.
6
6
 
7
7
  **[Documentation →](https://ziex.dev/learn)**
8
8
 
9
+
10
+
11
+ > **Note:** Most of the API and syntax are finalized and stable, and server-side rendering (SSR) features are production-ready, Ziex continues to evolve with ongoing improvements to client-side rendering and state management. You can start using the documented features today, as they are stable and unlikely to change. Areas still under development are not yet documented and will be added as they mature.
12
+
13
+
9
14
  ## Installation
10
15
 
11
16
  ##### Linux/macOS
@@ -25,51 +30,45 @@ winget install -e --id zig.zig # Windows
25
30
  ```
26
31
  [_See for other platforms →_](https://ziglang.org/learn/getting-started/)
27
32
 
28
- ## Quick Example
29
33
 
30
- ```tsx site/pages/examples/overview.zx
31
- pub fn QuickExample(allocator: zx.Allocator) zx.Component {
34
+ ## At a Glance
35
+
36
+ ```tsx site/pages/examples/playground.zx
37
+ pub fn Playground(allocator: zx.Allocator) zx.Component {
32
38
  const is_loading = true;
33
- const chars = "Hello, ZX Dev!";
34
39
  var i: usize = 0;
40
+
35
41
  return (
36
42
  <main @allocator={allocator}>
37
- <section>
38
- {if (is_loading) (<h1>Loading...</h1>) else (<h1>Loaded</h1>)}
39
- </section>
40
-
41
- <section>
42
- {for (chars) |char| (<span>{char}</span>)}
43
- </section>
44
-
45
- <section>
46
- {for (users) |user| (
47
- <Profile name={user.name} age={user.age} role={user.role} />
48
- )}
49
- </section>
50
-
51
- <section>
52
- {while (i < 10) : (i += 1) (<p>{i}</p>)}
53
- </section>
43
+ <h1>Hello, Ziex!</h1>
44
+
45
+ {for (users) |user| (
46
+ <Profile name={user.name} age={user.age} role={user.role} />
47
+ )}
48
+
49
+ {if (is_loading) (<p>Loading...</p>) else (<p>Loaded</p>)}
50
+
51
+ {while (i < 5) : (i += 1) (<i>{i}</i>)}
54
52
  </main>
55
53
  );
56
54
  }
57
55
 
58
- fn Profile(allocator: zx.Allocator, user: User) zx.Component {
56
+ fn Profile(ctx: *zx.ComponentCtx(User)) zx.Component {
59
57
  return (
60
- <div @allocator={allocator}>
61
- <h1>{user.name}</h1>
62
- <p>{user.age}</p>
63
- {switch (user.role) {
64
- .admin => (<p>Admin</p>),
65
- .member => (<p>Member</p>),
66
- }}
58
+ <div @allocator={ctx.allocator}>
59
+ <h3>{ctx.props.name}</h3>
60
+ <div>{ctx.props.age}</div>
61
+ <strong>
62
+ {switch (ctx.props.role) {
63
+ .admin => "Admin",
64
+ .member => "Member",
65
+ }}
66
+ </strong>
67
67
  </div>
68
68
  );
69
69
  }
70
70
 
71
- const UserRole = enum { admin, member };
72
- const User = struct { name: []const u8, age: u32, role: UserRole };
71
+ const User = struct { name: []const u8, age: u32, role: enum { admin, member } };
73
72
 
74
73
  const users = [_]User{
75
74
  .{ .name = "John", .age = 20, .role = .admin },
@@ -78,123 +77,116 @@ const users = [_]User{
78
77
 
79
78
  const zx = @import("zx");
80
79
  ```
81
- ## Feature Checklist
82
-
83
- - [x] Server Side Rendering (SSR)
84
- - [x] Streaming
85
- - [x] Static Site Generation (SSG)
86
- - [x] `options.static.params`, `options.static.getParams`
87
- - [ ] Client Side Rendering (CSR) via WebAssembly (_Alpha_)
88
- - [x] Virtual DOM and diffing
89
- - [x] Rendering only changed nodes
90
- - [x] `on`event handler
91
- - [x] State managment
92
- - [x] Hydration
93
- - [ ] Lifecycle hook
94
- - [ ] Server Actions
95
- - [ ] Rendering performance
96
- - [x] Client Side Rendering (CSR) via React
97
- - [x] Routing
98
- - [x] File-system Routing
99
- - [x] Search Parameters
100
- - [x] Path Segments
101
- - [x] Components
102
- - [x] Control Flow
103
- - [x] `if`
104
- - [x] `if/else`
105
- - [x] `for`
106
- - [x] `switch`
107
- - [x] `while`
108
- - [x] nesting control flows
109
- - [x] error/optional captures in `while` and `if`
110
- - [x] Assets
111
- - [x] Copying
112
- - [x] Serving
113
- - [ ] Assets Optimization
114
- - [ ] Image
115
- - [x] CSS (via plugins such as Tailwind)
116
- - [x] JS/TS (via esbuild)
117
- - [x] HTML (optimized by default)
118
- - [x] Proxy/Middleware
119
- - [ ] Caching (configurable)
120
- - [x] Component
121
- - [ ] Layout
122
- - [x] Page
123
- - [ ] Assets
124
- - [x] API Route
125
- - [x] Websocket Route
126
- - [ ] Plugin (_Alpha_)
127
- - [x] Builtin TailwindCSS and Esbuild
128
- - [x] Command based plugin system
129
- - [ ] Source based plugin system
130
- - [x] Context (configurable)
131
- - [x] App
132
- - [x] Layout
133
- - [x] Page
134
- - [x] Component
135
- - [x] `error.zx` for default and per-route error page
136
- - [x] `notfound.zx` for default and per-route error page
137
- - [x] CLI
138
- - [x] `init` Project Template
139
- - [x] `transpile` Transpile .zx files to Zig source code
140
- - [x] `serve` Serve the project
141
- - [x] `dev` HMR or Rebuild on Change
142
- - [x] `fmt` Format the ZX source code
143
- - [x] `export` Generate static site assets
144
- - [x] `bundle` Bundle the ZX executable with public/assets and exe
145
- - [x] `version` Show the version of the ZX CLI
146
- - [x] `update` Update the version of ZX dependency
147
- - [x] `upgrade` Upgrade the version of ZX CLI
148
- - [ ] Platform
149
- - [x] Server
150
- - [x] Browser
151
- - [ ] Edge Runtime (Cloudflare Workers, Vercel Function, etc)
152
- - [ ] iOS
153
- - [ ] Android
154
- - [ ] macOS
155
- - [ ] Windows
156
-
157
- #### Editor Support
158
-
159
- - ##### [VSCode](https://marketplace.visualstudio.com/items?itemName=nurulhudaapon.zx)/[VSCode Forks](https://marketplace.visualstudio.com/items?itemName=nurulhudaapon.zx) Extension
160
- - ##### [Neovim](/editors/neovim/)
161
- - ##### [Zed](/editors/zed/)
162
-
163
- ## Similar Projects
164
-
165
- ### Rust
166
-
167
- * [Leptos](https://github.com/leptos-rs/leptos) - Full-stack, isomorphic Rust web framework with fine-grained reactivity and JSX-like syntax
168
- * [Dioxus](https://github.com/DioxusLabs/dioxus) - Cross-platform GUI framework with React-like API, supporting web, desktop, mobile, and SSR
169
- * [Yew](https://github.com/yewstack/yew) - Rust / Wasm framework for creating reliable and efficient web applications with component-based architecture
170
- * [Sycamore](https://github.com/sycamore-rs/sycamore) - Reactive web framework with fine-grained reactivity and minimal bundle sizes
171
- * [Perseus](https://github.com/framesurge/perseus) - Full-stack framework built on Sycamore with SSR, SSG, and incremental regeneration
172
-
173
- ### Zig
174
-
175
- * [Jetzig](https://github.com/jetzig-framework/jetzig) - Zig web framework with MVC architecture, built-in ORM, and powerful templating
176
- * [ZTS](https://github.com/zigster64/zts) - Zig Templates made Simple, a templating system for Zig
177
- * [zmpl](https://github.com/jetzig-framework/zmpl) - Mode-based templating language that compiles to Zig functions at build time, used in Jetzig
178
- * [mustache-zig](https://github.com/batiati/mustache-zig) - Mustache template engine implementation in Zig
179
- * [etch](https://github.com/haze/etch) - Compile-time tuned templating engine focusing on speed and simplicity
180
- * [Zap](https://github.com/zigzap/zap) - High-performance backend framework in Zig
181
- * [http.zig](https://github.com/karlseguin/http.zig) - Low-level HTTP/1.1 server written entirely in Zig (_ZX_'s backend)
182
- * [tokamak](https://github.com/cztomsik/tokamak) - Server-side framework for Zig
183
- * [zig-router](https://github.com/Cloudef/zig-router) - Straightforward HTTP-like request routing library for Zig
184
- * [zig-webui](https://github.com/webui-dev/zig-webui/) - Zig library that allows using any web browser as a GUI
185
- * [Zine](https://github.com/kristoff-it/zine) - Fast, scalable, flexible static site generator (SSG) written in Zig
186
- * [Zinc](https://github.com/zon-dev/zinc/) - Web framework written in pure Zig with focus on high performance, usability, security, and extensibility
187
- * [zUI](https://github.com/thienpow/zui) - UI kit for Jetzig framework with reusable components and styles
188
- * [zig-pek](https://github.com/nektro/zig-pek) - Comptime HTML/XML parser and renderer in Zig
189
- * [zigomponent](https://zigomp.prjct.dev/) - HTML compoenents in pure zig
190
-
191
- ## Related Projects
192
-
193
- * [Codeberg Mirror](https://codeberg.org/nurulhudaapon/zx) - ZX repository mirror on Codeberg
194
- * [ziex.dev](https://github.com/nurulhudaapon/zx/tree/main/site) - Official documentation site of ZX made using ZX.
195
- * [zx-example-portfolio](https://github.com/nurulhudaapon/zx-example-portfolio) - Demo portfolio web application built with ZX
196
- * [thegates.dev](https://github.com/nurulhudaapon/thegates.dev) - Example clone demonstrating ZX capabilities
80
+
81
+ Try this in [Playground →](https://ziex.dev/playground#data=eF59U01vnDAQ_StTTtAiyGZVqSKAEuVSVa2USy8NUUTAu2sJbGQgoUv83ztjlo-y2_rCfLx5zMyze-uhSH_vlWxF7h07K7Cq9gV2AuawnRaFzNJGqgCOnXc3eg5597KspGCigT4RgCeTom6A18-FTHMu9hBBo1p2M2RfUwU8gLbmR4aZKwwPCcWaVgmwB49OWKZcwO3086ifTB3PMAM9bOKvDLMu_OKs-xD6GBiZx9PvpAK7rZmqHXin7_vydxPXg5I7XjAQacminnAemRrS_eijpUHJYvTJ1OCvunL0WQt8B_a8GgfssIq_D47neaFfxQ6womZTguUmeM70dqAebQ4hfHYgIOtTBBui5HHPdehzUzYWhD6t89Shg2s3lKTzMK6dNV0AH5eK3jed_RPHcy4LfUGxnL_-JRhyev8RbRsbRKVkVQ87RuG2axiSLnG0-9Cn4ApXN0qK_SpKp6_feJMdwJ5JSDBnHGR9vDQv8eZFMSTWHZmJ5f4DWbLyhakB-sPYF7Far3r1z5pdjjTJM7wl0gDfCpa0GW7fXMwAHp-GbPvFpZuJb2p77ZpLGQATbYlAM4cLpyY16JuZ1LwDZH18fiL-0yq8HowQmEisb_JAowOtHAPXV2gSP9qnFWn3Ulkq2LJssygbW8G6ZTPHDpO3HC-YauzEOnaJRTuw9B927V4U)
82
+
83
+ <details>
84
+ <summary>Explanation of this</summary>
85
+
86
+ ```tsx site/pages/examples/playground.zx
87
+ // A Zig function that returns a `zx.Component`.
88
+ pub fn Playground(allocator: zx.Allocator) zx.Component {
89
+ const is_loading = true;
90
+ var i: usize = 0;
91
+
92
+ // HTML Block is always surrounded by parentheses and can contain HTML elements and control flow statements.
93
+ return (
94
+ // @allocator or any other attribute starting with `@` is called builtin attribute
95
+ // `@allocator` is used to specify the allocator for the component and its children for mem allocation.
96
+ <main @allocator={allocator}>
97
+ <h1>Hello, Ziex!</h1>
98
+
99
+ // `for` loop to iterate over `users` array and render a `Profile` component for each user.
100
+ // Since this is an expression the HTMLs are inside parenteses not curly braces.
101
+ {for (users) |user| (
102
+ // `Profile` component is called with props: name, age, and role.
103
+ // Optional props can be omitted, and the component will receive default values for them.
104
+ <Profile name={user.name} age={user.age} role={user.role} />
105
+ )}
106
+
107
+ // `if` statement works just like other control flow statements.
108
+ {if (is_loading) (<p>Loading...</p>) else (<p>Loaded</p>)}
109
+
110
+ // `while` loop with an optional increment statement.
111
+ {while (i < 5) : (i += 1) (<i>{i}</i>)}
112
+ </main>
113
+ );
114
+ }
115
+
116
+ // A Ziex Component is a Zig function that returns a `zx.Component`.
117
+ // It can have signatures like:
118
+ // - `pub fn ComponentName(allocator: zx.Allocator) zx.Component`
119
+ // - `pub fn ComponentName(ctx: *zx.ComponentCtx<PropsType>) zx.Component`
120
+ // - `pub fn ComponentName(allocator: zx.Allocator, props: PropsType) zx.Component`
121
+ fn Profile(ctx: *zx.ComponentCtx(User)) zx.Component {
122
+ return (
123
+ <div @allocator={ctx.allocator}>
124
+ // Exrepssion starts with `{` and ends with `}`. You can use it to access props, call functions, any valid Zig expression
125
+ <h3>{ctx.props.name}</h3>
126
+ <div>{ctx.props.age}</div>
127
+ <strong>
128
+ {switch (ctx.props.role) {
129
+ .admin => "Admin",
130
+ .member => "Member",
131
+ }}
132
+ </strong>
133
+ </div>
134
+ );
135
+ }
136
+
137
+ const User = struct { name: []const u8, age: u32, role: enum { admin, member } };
138
+
139
+ const users = [_]User{
140
+ .{ .name = "John", .age = 20, .role = .admin },
141
+ .{ .name = "Jane", .age = 21, .role = .member },
142
+ };
143
+
144
+ const zx = @import("zx");
145
+ ```
146
+
147
+ </details>
148
+
149
+ ## Features
150
+ - **JSX-like Syntax**: Write declarative UI components using familiar JSX patterns, transpiled to efficient Zig code.
151
+ - **Full-Stack Capabilities**: Build both frontend and backend of your web application using
152
+ - **It's Fast**: Significantly faster at SSR than many other frameworks.
153
+ - **Compile-time Safety**: Zig's type system catches bugs at compile time. No runtime surprises, no GC.
154
+ - **Familiar Syntax**: Familiar JSX-like syntax, or plain HTML-style markup, with full access to Zig's control flow.
155
+ - **Server-side Rendering**: Render per request on the server for dynamic data, auth, and personalized pages for best performance and SEO.
156
+ - **Static Site Generation**: Pre-render pages at build/export time into static HTML for fast CDN delivery.
157
+ - **File System Routing**: Folder structure defines routes. No configs, no magic strings, just files in folders.
158
+ - **Client-side Rendering**: Optional client-side rendering for interactive experiences when you need it.
159
+ - **Control Flow in Zig's Syntax**: if/else, for/while, and switch all work as expected. It's just Zig.
160
+ - **Developer Tooling**: CLI, hot reload, and editor extensions for the best DX.
161
+
162
+ ## Roadmap
163
+
164
+ We track our feature roadmap and bugs using GitHub Issues.
165
+ You can view our current progress and planned features here:
166
+
167
+ **[Check out the Ziex Issue Tracker →](https://github.com/ziex-dev/ziex/issues)**
168
+
169
+ ## Editor Support
170
+
171
+ * [VSCode](https://marketplace.visualstudio.com/items?itemName=ziex.ziex)/[VSCode Forks](https://open-vsx.org/extension/ziex/ziex) Extension
172
+ * [Neovim](/ide/neovim/)
173
+ * [Helix](/ide/helix/)
174
+ * [Zed](/ide/zed/)
175
+
176
+ ## Community
177
+
178
+ - [Discord](https://ziex.dev/r/discord)
179
+ - [Topic on Ziggit](https://ziex.dev/r/ziggit)
180
+ - [Project on Zig Discord Community](https://ziex.dev/r/zig-discord) (Join Zig Discord first: https://discord.gg/zig)
181
+
182
+
183
+ ## Links
184
+
185
+ * [Codeberg Mirror](https://codeberg.org/ziex-dev/ziex) - ZX repository mirror on Codeberg
186
+ * [ziex.dev](https://github.com/ziex-dev/ziex/tree/main/site) - Official documentation site of ZX made using ZX.
187
+ * [example-blog](https://github.com/ziex-dev/example-blog) - Demo blog web application built with ZX
197
188
  * [zx-numbers-game](https://github.com/Andrew-Velox/zx-numbers-game) - ZX numbers game
189
+ * [Comparision with other frameworks](https://ziex.dev/vs)
198
190
 
199
191
  ## Contributing
200
192
 
@@ -0,0 +1,2 @@
1
+ export * as worker from "./worker";
2
+ export * as kv from "./kv";
@@ -0,0 +1,383 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
9
+ });
10
+ };
11
+
12
+ // src/cloudflare/worker.ts
13
+ var exports_worker = {};
14
+ __export(exports_worker, {
15
+ run: () => run,
16
+ respond: () => respond,
17
+ prepare: () => prepare
18
+ });
19
+
20
+ // src/cloudflare/kv.ts
21
+ var exports_kv = {};
22
+ __export(exports_kv, {
23
+ createKVImports: () => createKVImports
24
+ });
25
+ function createKVImports(bindings, getMemory) {
26
+ const encoder = new TextEncoder;
27
+ const decoder = new TextDecoder;
28
+ function readStr(ptr, len) {
29
+ return decoder.decode(new Uint8Array(getMemory().buffer, ptr, len));
30
+ }
31
+ function writeBytes(buf_ptr, buf_max, data) {
32
+ if (data.length > buf_max)
33
+ return -2;
34
+ new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
35
+ return data.length;
36
+ }
37
+ function binding(ns) {
38
+ return bindings[ns] ?? bindings["default"] ?? null;
39
+ }
40
+ const Suspending = WebAssembly.Suspending;
41
+ return {
42
+ kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
43
+ const b = binding(readStr(ns_ptr, ns_len));
44
+ if (!b)
45
+ return -1;
46
+ const value = await b.get(readStr(key_ptr, key_len));
47
+ if (value === null)
48
+ return -1;
49
+ return writeBytes(buf_ptr, buf_max, encoder.encode(value));
50
+ }),
51
+ kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len) => {
52
+ const b = binding(readStr(ns_ptr, ns_len));
53
+ if (!b)
54
+ return -1;
55
+ await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len));
56
+ return 0;
57
+ }),
58
+ kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
59
+ const b = binding(readStr(ns_ptr, ns_len));
60
+ if (!b)
61
+ return -1;
62
+ await b.delete(readStr(key_ptr, key_len));
63
+ return 0;
64
+ }),
65
+ kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
66
+ const b = binding(readStr(ns_ptr, ns_len));
67
+ if (!b)
68
+ return writeBytes(buf_ptr, buf_max, encoder.encode("[]"));
69
+ const prefix = readStr(prefix_ptr, prefix_len);
70
+ const result = await b.list(prefix.length > 0 ? { prefix } : undefined);
71
+ return writeBytes(buf_ptr, buf_max, encoder.encode(JSON.stringify(result.keys.map((k) => k.name))));
72
+ })
73
+ };
74
+ }
75
+
76
+ // src/cloudflare/worker.ts
77
+ class ProcExit extends Error {
78
+ code;
79
+ constructor(code) {
80
+ super(`proc_exit(${code})`);
81
+ this.code = code;
82
+ }
83
+ }
84
+ function createWasiImports({
85
+ request,
86
+ stdinData
87
+ }) {
88
+ const encoder = new TextEncoder;
89
+ const decoder = new TextDecoder;
90
+ const url = new URL(request.url);
91
+ const argStrings = [
92
+ "wasm",
93
+ "--pathname",
94
+ url.pathname,
95
+ "--method",
96
+ request.method,
97
+ "--search",
98
+ url.search
99
+ ];
100
+ for (const name of FORWARDED_HEADERS) {
101
+ const value = request.headers.get(name);
102
+ if (value)
103
+ argStrings.push("--header", `${name}:${value}`);
104
+ }
105
+ const encodedArgs = argStrings.map((a) => encoder.encode(a + "\x00"));
106
+ const argBufSize = encodedArgs.reduce((s, a) => s + a.length, 0);
107
+ let wasmMemory = null;
108
+ const setMemory = (m2) => {
109
+ wasmMemory = m2;
110
+ };
111
+ const stdoutChunks = [];
112
+ const stderrChunks = [];
113
+ let stdinOffset = 0;
114
+ function v() {
115
+ return new DataView(wasmMemory.buffer);
116
+ }
117
+ function m() {
118
+ return new Uint8Array(wasmMemory.buffer);
119
+ }
120
+ const wasiImport = {
121
+ args_sizes_get(argc_ptr, argv_buf_size_ptr) {
122
+ v().setUint32(argc_ptr, encodedArgs.length, true);
123
+ v().setUint32(argv_buf_size_ptr, argBufSize, true);
124
+ return 0;
125
+ },
126
+ args_get(argv_ptr, argv_buf_ptr) {
127
+ const dv = v();
128
+ const mem = m();
129
+ let offset = argv_buf_ptr;
130
+ for (const arg of encodedArgs) {
131
+ dv.setUint32(argv_ptr, offset, true);
132
+ mem.set(arg, offset);
133
+ argv_ptr += 4;
134
+ offset += arg.length;
135
+ }
136
+ return 0;
137
+ },
138
+ environ_sizes_get(count_ptr, buf_size_ptr) {
139
+ v().setUint32(count_ptr, 0, true);
140
+ v().setUint32(buf_size_ptr, 0, true);
141
+ return 0;
142
+ },
143
+ environ_get(_environ_ptr, _environ_buf_ptr) {
144
+ return 0;
145
+ },
146
+ fd_write(fd, iovs_ptr, iovs_len, nwritten_ptr) {
147
+ const dv = v();
148
+ const mem = m();
149
+ let written = 0;
150
+ for (let i = 0;i < iovs_len; i++) {
151
+ const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
152
+ const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
153
+ const chunk = mem.slice(buf_ptr, buf_ptr + buf_len);
154
+ if (fd === 1)
155
+ stdoutChunks.push(chunk);
156
+ else if (fd === 2)
157
+ stderrChunks.push(chunk);
158
+ written += buf_len;
159
+ }
160
+ dv.setUint32(nwritten_ptr, written, true);
161
+ return 0;
162
+ },
163
+ fd_read(fd, iovs_ptr, iovs_len, nread_ptr) {
164
+ const dv = v();
165
+ const mem = m();
166
+ const stdin = stdinData ?? new Uint8Array(0);
167
+ let totalRead = 0;
168
+ for (let i = 0;i < iovs_len; i++) {
169
+ const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
170
+ const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
171
+ if (fd === 0 && stdinOffset < stdin.length) {
172
+ const toRead = Math.min(buf_len, stdin.length - stdinOffset);
173
+ mem.set(stdin.subarray(stdinOffset, stdinOffset + toRead), buf_ptr);
174
+ stdinOffset += toRead;
175
+ totalRead += toRead;
176
+ }
177
+ }
178
+ dv.setUint32(nread_ptr, totalRead, true);
179
+ return 0;
180
+ },
181
+ fd_fdstat_get(_fd, fdstat_ptr) {
182
+ const dv = v();
183
+ dv.setUint8(fdstat_ptr, 2);
184
+ dv.setUint8(fdstat_ptr + 1, 0);
185
+ dv.setUint16(fdstat_ptr + 2, 0, true);
186
+ dv.setUint32(fdstat_ptr + 4, 0, true);
187
+ dv.setBigUint64(fdstat_ptr + 8, 0n, true);
188
+ dv.setBigUint64(fdstat_ptr + 16, 0n, true);
189
+ return 0;
190
+ },
191
+ fd_prestat_get(_fd, _bufptr) {
192
+ return 8;
193
+ },
194
+ fd_prestat_dir_name(_fd, _path, _path_len) {
195
+ return 8;
196
+ },
197
+ fd_close(_fd) {
198
+ return 0;
199
+ },
200
+ fd_pread(_fd, _iovs, _iovs_len, _offset, nread_ptr) {
201
+ v().setUint32(nread_ptr, 0, true);
202
+ return 0;
203
+ },
204
+ fd_pwrite(_fd, _iovs, _iovs_len, _offset, nwritten_ptr) {
205
+ v().setUint32(nwritten_ptr, 0, true);
206
+ return 0;
207
+ },
208
+ fd_filestat_get(_fd, filestat_ptr) {
209
+ const dv = v();
210
+ dv.setBigUint64(filestat_ptr, 0n, true);
211
+ dv.setBigUint64(filestat_ptr + 8, 0n, true);
212
+ dv.setUint8(filestat_ptr + 16, 2);
213
+ dv.setBigUint64(filestat_ptr + 24, 1n, true);
214
+ dv.setBigUint64(filestat_ptr + 32, 0n, true);
215
+ dv.setBigUint64(filestat_ptr + 40, 0n, true);
216
+ dv.setBigUint64(filestat_ptr + 48, 0n, true);
217
+ dv.setBigUint64(filestat_ptr + 56, 0n, true);
218
+ return 0;
219
+ },
220
+ fd_seek(_fd, _offset, _whence, newoffset_ptr) {
221
+ v().setBigInt64(newoffset_ptr, 0n, true);
222
+ return 0;
223
+ },
224
+ proc_exit(code) {
225
+ throw new ProcExit(code);
226
+ },
227
+ sched_yield() {
228
+ return 0;
229
+ },
230
+ clock_time_get(_id, _precision, time_ptr) {
231
+ v().setBigUint64(time_ptr, BigInt(Date.now()) * 1000000n, true);
232
+ return 0;
233
+ },
234
+ random_get(buf_ptr, buf_len) {
235
+ crypto.getRandomValues(new Uint8Array(wasmMemory.buffer, buf_ptr, buf_len));
236
+ return 0;
237
+ }
238
+ };
239
+ function collectOutput() {
240
+ return {
241
+ stdout: mergeUint8Arrays(stdoutChunks),
242
+ stderrText: decoder.decode(mergeUint8Arrays(stderrChunks))
243
+ };
244
+ }
245
+ return { wasiImport, setMemory, collectOutput };
246
+ }
247
+ function buildResponse({
248
+ stdout,
249
+ stderrText
250
+ }) {
251
+ const meta = parseEdgeMeta(stderrText);
252
+ return new Response(stdout.buffer, {
253
+ status: meta.status,
254
+ headers: meta.headers
255
+ });
256
+ }
257
+ async function run({
258
+ request,
259
+ env,
260
+ ctx,
261
+ module,
262
+ kv: kvBindings,
263
+ imports
264
+ }) {
265
+ const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : undefined;
266
+ const { wasiImport, setMemory, collectOutput } = createWasiImports({ request, stdinData });
267
+ let wasmMemory = null;
268
+ const mem = () => wasmMemory;
269
+ const instance = new WebAssembly.Instance(module, {
270
+ wasi_snapshot_preview1: wasiImport,
271
+ ...kvBindings ? { __zx_kv: createKVImports(kvBindings, mem) } : {},
272
+ ...imports ? imports(mem) : {}
273
+ });
274
+ wasmMemory = instance.exports.memory;
275
+ setMemory(wasmMemory);
276
+ const start = WebAssembly.promising(instance.exports._start);
277
+ try {
278
+ await start();
279
+ } catch (e) {
280
+ if (!(e instanceof Error) || !e.message.startsWith("proc_exit"))
281
+ throw e;
282
+ }
283
+ return buildResponse(collectOutput());
284
+ }
285
+ var FORWARDED_HEADERS = [
286
+ "content-type",
287
+ "accept",
288
+ "authorization",
289
+ "cookie",
290
+ "user-agent",
291
+ "referer",
292
+ "x-forwarded-for",
293
+ "x-forwarded-proto",
294
+ "x-real-ip"
295
+ ];
296
+ function parseEdgeMeta(stderrText) {
297
+ const meta = { status: 200, headers: new Headers };
298
+ const metaPrefix = "__EDGE_META__:";
299
+ const metaLine = stderrText.split(`
300
+ `).find((line) => line.startsWith(metaPrefix));
301
+ if (metaLine) {
302
+ try {
303
+ const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
304
+ if (parsed.status)
305
+ meta.status = parsed.status;
306
+ if (Array.isArray(parsed.headers)) {
307
+ for (const [name, value] of parsed.headers) {
308
+ meta.headers.append(name, value);
309
+ }
310
+ }
311
+ } catch {}
312
+ }
313
+ return meta;
314
+ }
315
+ function mergeUint8Arrays(arrays) {
316
+ const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
317
+ const result = new Uint8Array(totalLen);
318
+ let offset = 0;
319
+ for (const arr of arrays) {
320
+ result.set(arr, offset);
321
+ offset += arr.length;
322
+ }
323
+ return result;
324
+ }
325
+ async function collectStream(readable, chunks) {
326
+ const reader = readable.getReader();
327
+ while (true) {
328
+ const { done, value } = await reader.read();
329
+ if (done)
330
+ break;
331
+ if (value)
332
+ chunks.push(value);
333
+ }
334
+ }
335
+ function prepare({
336
+ request,
337
+ env,
338
+ ctx
339
+ }) {
340
+ const stdout = new TransformStream;
341
+ const stderr = new TransformStream;
342
+ const url = new URL(request.url);
343
+ const args = [
344
+ "--pathname",
345
+ url.pathname,
346
+ "--method",
347
+ request.method,
348
+ "--search",
349
+ url.search
350
+ ];
351
+ for (const name of FORWARDED_HEADERS) {
352
+ const value = request.headers.get(name);
353
+ if (value) {
354
+ args.push("--header", `${name}:${value}`);
355
+ }
356
+ }
357
+ const stdin = request.body ?? undefined;
358
+ return { args, stdout, stderr, stdin };
359
+ }
360
+ async function respond({
361
+ exec,
362
+ stdout,
363
+ stderr
364
+ }) {
365
+ const stdoutChunks = [];
366
+ const stderrChunks = [];
367
+ const stderrReadable = stderr instanceof ReadableStream ? stderr : stderr.readable;
368
+ await Promise.all([
369
+ exec,
370
+ collectStream(stdout.readable, stdoutChunks),
371
+ collectStream(stderrReadable, stderrChunks)
372
+ ]);
373
+ const stderrText = new TextDecoder().decode(mergeUint8Arrays(stderrChunks));
374
+ const meta = parseEdgeMeta(stderrText);
375
+ return new Response(mergeUint8Arrays(stdoutChunks).buffer, {
376
+ status: meta.status,
377
+ headers: meta.headers
378
+ });
379
+ }
380
+ export {
381
+ exports_worker as worker,
382
+ exports_kv as kv
383
+ };
@@ -0,0 +1,19 @@
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
+ * Create a `__zx_kv` import object for use with `worker.run({ kv: ... })`.
18
+ */
19
+ export declare function createKVImports(bindings: Record<string, KVNamespace>, getMemory: () => WebAssembly.Memory): Record<string, unknown>;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Run a WASM module for a single request using JSPI.
3
+ *
4
+ * Pass `kv` as a map of binding names → KV namespaces. The Zig side selects
5
+ * a binding via `zx.kv.scope("name")`; the top-level `zx.kv.*` functions use
6
+ * `"default"`.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * return worker.run({
11
+ * request, env, ctx, wasmModule,
12
+ * kv: { default: env.KV, users: env.USERS_KV },
13
+ * });
14
+ * ```
15
+ */
16
+ export declare function run({ request, env, ctx, module, kv: kvBindings, imports, }: {
17
+ request: Request;
18
+ env?: unknown;
19
+ ctx?: unknown;
20
+ module: WebAssembly.Module;
21
+ /** KV namespace bindings — `{ default: env.KV, otherName: env.OTHER_KV }` */
22
+ kv?: Record<string, import("./kv").KVNamespace>;
23
+ imports?: (mem: () => WebAssembly.Memory) => Record<string, Record<string, unknown>>;
24
+ }): Promise<Response>;
25
+ export declare function prepare({ request, env, ctx, }: {
26
+ request: Request;
27
+ env: unknown;
28
+ ctx: unknown;
29
+ }): {
30
+ args: string[];
31
+ stdout: TransformStream<any, any>;
32
+ stderr: TransformStream<any, any>;
33
+ stdin: ReadableStream<Uint8Array<ArrayBufferLike>> | undefined;
34
+ };
35
+ export declare function respond({ exec, stdout, stderr, }: {
36
+ exec: Promise<number | undefined>;
37
+ stdout: TransformStream;
38
+ stderr: TransformStream | ReadableStream<Uint8Array>;
39
+ }): Promise<Response>;
package/index.js CHANGED
@@ -1,9 +1,22 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
9
+ });
10
+ };
11
+
1
12
  // src/index.ts
2
13
  var zx = {
3
14
  name: "zx",
4
- version: "0.1.0-dev.628",
15
+ version: "0.1.0-dev.765",
16
+ jsglue_version: "0.1.0-dev.727",
5
17
  description: "ZX is a framework for building web applications with Zig.",
6
- repository: "https://github.com/nurulhudaapon/zx",
18
+ repository: "https://github.com/ziex-dev/ziex",
19
+ homepage: "https://ziex.dev",
7
20
  fingerprint: 14616285862371232000,
8
21
  minimum_zig_version: "0.15.2",
9
22
  dependencies: {
@@ -21,7 +34,10 @@ var zx = {
21
34
  path: "vendor/zig-tree-sitter"
22
35
  },
23
36
  tree_sitter_zx: {
24
- path: "packages/tree-sitter-zx"
37
+ path: "pkg/tree-sitter-zx"
38
+ },
39
+ tree_sitter_mdzx: {
40
+ path: "pkg/tree-sitter-mdzx"
25
41
  },
26
42
  cachez: {
27
43
  path: "vendor/cachez"
@@ -31,7 +47,8 @@ var zx = {
31
47
  "build.zig",
32
48
  "build.zig.zon",
33
49
  "src",
34
- "packages/tree-sitter-zx",
50
+ "pkg/tree-sitter-zx",
51
+ "pkg/tree-sitter-mdzx",
35
52
  "vendor/cachez",
36
53
  "vendor/cliz",
37
54
  "vendor/jsz",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ziex",
3
- "version": "0.1.0-dev.628",
3
+ "version": "0.1.0-dev.765",
4
4
  "description": "ZX is a framework for building web applications with Zig.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -8,12 +8,13 @@
8
8
  ".": "./index.js",
9
9
  "./react": "./react/index.js",
10
10
  "./wasm": "./wasm/index.js",
11
- "./wasm/init": "./wasm/init.js"
11
+ "./wasm/init": "./wasm/init.js",
12
+ "./cloudflare": "./cloudflare/index.js"
12
13
  },
13
- "homepage": "https://github.com/nurulhudaapon/zx",
14
+ "homepage": "https://ziex.dev",
14
15
  "repository": {
15
16
  "type": "git",
16
- "url": "git+https://github.com/nurulhudaapon/zx.git"
17
+ "url": "git+https://github.com/ziex-dev/ziex.git"
17
18
  },
18
19
  "keywords": [
19
20
  "zx",
package/react/index.js CHANGED
@@ -1,3 +1,14 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
9
+ });
10
+ };
11
+
1
12
  // src/react/dom.ts
2
13
  function findCommentMarker(id) {
3
14
  const startPrefix = `$${id} `;
package/wasm/index.js CHANGED
@@ -1,3 +1,14 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
9
+ });
10
+ };
11
+
1
12
  // ../../vendor/jsz/js/src/zigjs.ts
2
13
  var NAN_PREFIX = 2146959360;
3
14
  var predefined = {
@@ -205,6 +216,9 @@ class ZxBridge {
205
216
  constructor(exports) {
206
217
  this.#exports = exports;
207
218
  }
219
+ get #alloc() {
220
+ return this.#exports.__zx_alloc;
221
+ }
208
222
  get #handler() {
209
223
  return this.#exports.__zx_cb;
210
224
  }
@@ -272,19 +286,8 @@ class ZxBridge {
272
286
  }
273
287
  #notifyFetchComplete(fetchId, statusCode, body, isError) {
274
288
  const handler = this.#fetchCompleteHandler;
275
- if (!handler) {
276
- console.warn("__zx_fetch_complete not exported from WASM");
277
- return;
278
- }
279
289
  const encoded = new TextEncoder().encode(body);
280
- const allocFn = this.#exports.__zx_alloc;
281
- let ptr = 0;
282
- if (allocFn) {
283
- ptr = allocFn(encoded.length);
284
- } else {
285
- const heapBase = this.#exports.__heap_base?.value ?? 65536;
286
- ptr = heapBase + Number(fetchId % BigInt(256)) * 65536;
287
- }
290
+ const ptr = this.#alloc(encoded.length);
288
291
  writeBytes(ptr, encoded);
289
292
  handler(fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
290
293
  }
@@ -394,14 +397,7 @@ class ZxBridge {
394
397
  return this.#writeBytesToWasm(encoded);
395
398
  }
396
399
  #writeBytesToWasm(data) {
397
- const allocFn = this.#exports.__zx_alloc;
398
- let ptr = 0;
399
- if (allocFn) {
400
- ptr = allocFn(data.length);
401
- } else {
402
- const heapBase = this.#exports.__heap_base?.value ?? 65536;
403
- ptr = heapBase + Date.now() % 256 * 4096;
404
- }
400
+ const ptr = this.#alloc(data.length);
405
401
  writeBytes(ptr, data);
406
402
  return { ptr, len: data.length };
407
403
  }
package/wasm/init.js CHANGED
@@ -205,6 +205,9 @@ class ZxBridge {
205
205
  constructor(exports) {
206
206
  this.#exports = exports;
207
207
  }
208
+ get #alloc() {
209
+ return this.#exports.__zx_alloc;
210
+ }
208
211
  get #handler() {
209
212
  return this.#exports.__zx_cb;
210
213
  }
@@ -272,19 +275,8 @@ class ZxBridge {
272
275
  }
273
276
  #notifyFetchComplete(fetchId, statusCode, body, isError) {
274
277
  const handler = this.#fetchCompleteHandler;
275
- if (!handler) {
276
- console.warn("__zx_fetch_complete not exported from WASM");
277
- return;
278
- }
279
278
  const encoded = new TextEncoder().encode(body);
280
- const allocFn = this.#exports.__zx_alloc;
281
- let ptr = 0;
282
- if (allocFn) {
283
- ptr = allocFn(encoded.length);
284
- } else {
285
- const heapBase = this.#exports.__heap_base?.value ?? 65536;
286
- ptr = heapBase + Number(fetchId % BigInt(256)) * 65536;
287
- }
279
+ const ptr = this.#alloc(encoded.length);
288
280
  writeBytes(ptr, encoded);
289
281
  handler(fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
290
282
  }
@@ -394,14 +386,7 @@ class ZxBridge {
394
386
  return this.#writeBytesToWasm(encoded);
395
387
  }
396
388
  #writeBytesToWasm(data) {
397
- const allocFn = this.#exports.__zx_alloc;
398
- let ptr = 0;
399
- if (allocFn) {
400
- ptr = allocFn(data.length);
401
- } else {
402
- const heapBase = this.#exports.__heap_base?.value ?? 65536;
403
- ptr = heapBase + Date.now() % 256 * 4096;
404
- }
389
+ const ptr = this.#alloc(data.length);
405
390
  writeBytes(ptr, data);
406
391
  return { ptr, len: data.length };
407
392
  }