ziex 0.1.0-dev.727 → 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
@@ -6,6 +6,11 @@ Ziex combines the power and performance of Zig with the expressiveness of JSX, e
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,111 @@ 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 {
38
+ const is_loading = true;
39
+ var i: usize = 0;
40
+
41
+ return (
42
+ <main @allocator={allocator}>
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>)}
52
+ </main>
53
+ );
54
+ }
55
+
56
+ fn Profile(ctx: *zx.ComponentCtx(User)) zx.Component {
57
+ return (
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
+ </div>
68
+ );
69
+ }
70
+
71
+ const User = struct { name: []const u8, age: u32, role: enum { admin, member } };
72
+
73
+ const users = [_]User{
74
+ .{ .name = "John", .age = 20, .role = .admin },
75
+ .{ .name = "Jane", .age = 21, .role = .member },
76
+ };
77
+
78
+ const zx = @import("zx");
79
+ ```
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 {
32
89
  const is_loading = true;
33
- const chars = "Hello, ZX Dev!";
34
90
  var i: usize = 0;
91
+
92
+ // HTML Block is always surrounded by parentheses and can contain HTML elements and control flow statements.
35
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.
36
96
  <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>
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>)}
54
112
  </main>
55
113
  );
56
114
  }
57
115
 
58
- fn Profile(allocator: zx.Allocator, user: User) zx.Component {
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 {
59
122
  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
- }}
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>
67
133
  </div>
68
134
  );
69
135
  }
70
136
 
71
- const UserRole = enum { admin, member };
72
- const User = struct { name: []const u8, age: u32, role: UserRole };
137
+ const User = struct { name: []const u8, age: u32, role: enum { admin, member } };
73
138
 
74
139
  const users = [_]User{
75
140
  .{ .name = "John", .age = 20, .role = .admin },
@@ -78,90 +143,35 @@ const users = [_]User{
78
143
 
79
144
  const zx = @import("zx");
80
145
  ```
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
- - [ ] MDZX (Markdown + ZX) (MDX eqiuvalent)
98
- - [ ] Render page as markdown via .md
99
- - [x] Routing
100
- - [x] File-system Routing
101
- - [x] Search Parameters
102
- - [x] Path Segments
103
- - [x] Components
104
- - [x] Control Flow
105
- - [x] `if`
106
- - [x] `if/else`
107
- - [x] `for`
108
- - [x] `switch`
109
- - [x] `while`
110
- - [x] nesting control flows
111
- - [x] error/optional captures in `while` and `if`
112
- - [x] Assets
113
- - [x] Copying
114
- - [x] Serving
115
- - [ ] Assets Optimization
116
- - [ ] Image
117
- - [x] CSS (via plugins such as Tailwind)
118
- - [x] JS/TS (via esbuild)
119
- - [x] HTML (optimized by default)
120
- - [x] Proxy/Middleware
121
- - [ ] Caching (configurable)
122
- - [x] Component
123
- - [ ] Layout
124
- - [x] Page
125
- - [ ] Assets
126
- - [x] API Route
127
- - [x] Websocket Route
128
- - [ ] Plugin (_Alpha_)
129
- - [x] Builtin TailwindCSS and Esbuild
130
- - [x] Command based plugin system
131
- - [ ] Source based plugin system
132
- - [x] Context (configurable)
133
- - [x] App
134
- - [x] Layout
135
- - [x] Page
136
- - [x] Component
137
- - [x] `error.zx` for default and per-route error page
138
- - [x] `notfound.zx` for default and per-route error page
139
- - [x] CLI
140
- - [x] `init` Project Template
141
- - [x] `transpile` Transpile .zx files to Zig source code
142
- - [x] `serve` Serve the project
143
- - [x] `dev` HMR or Rebuild on Change
144
- - [x] `fmt` Format the ZX source code
145
- - [x] `export` Generate static site assets
146
- - [x] `bundle` Bundle the ZX executable with public/assets and exe
147
- - [x] `version` Show the version of the ZX CLI
148
- - [x] `update` Update the version of ZX dependency
149
- - [x] `upgrade` Upgrade the version of ZX CLI
150
- - [ ] Platform
151
- - [x] Server
152
- - [x] Browser
153
- - [ ] Edge Runtime (Cloudflare Workers, Vercel Function, etc)
154
- - [ ] iOS
155
- - [ ] Android
156
- - [ ] macOS
157
- - [ ] Windows
158
-
159
- #### Editor Support
160
-
161
- - ##### [VSCode](https://marketplace.visualstudio.com/items?itemName=ziex.ziex)/[VSCode Forks](https://open-vsx.org/extension/ziex/ziex) Extension
162
- - ##### [Neovim](/ide/neovim/)
163
- - ##### [Helix](/ide/helix/)
164
- - ##### [Zed](/ide/zed/)
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/)
165
175
 
166
176
  ## Community
167
177
 
@@ -169,40 +179,14 @@ const zx = @import("zx");
169
179
  - [Topic on Ziggit](https://ziex.dev/r/ziggit)
170
180
  - [Project on Zig Discord Community](https://ziex.dev/r/zig-discord) (Join Zig Discord first: https://discord.gg/zig)
171
181
 
172
- ## Similar Projects
173
-
174
- ### Rust
175
-
176
- * [Leptos](https://github.com/leptos-rs/leptos) - Full-stack, isomorphic Rust web framework with fine-grained reactivity and JSX-like syntax
177
- * [Dioxus](https://github.com/DioxusLabs/dioxus) - Cross-platform GUI framework with React-like API, supporting web, desktop, mobile, and SSR
178
- * [Yew](https://github.com/yewstack/yew) - Rust / Wasm framework for creating reliable and efficient web applications with component-based architecture
179
- * [Sycamore](https://github.com/sycamore-rs/sycamore) - Reactive web framework with fine-grained reactivity and minimal bundle sizes
180
- * [Perseus](https://github.com/framesurge/perseus) - Full-stack framework built on Sycamore with SSR, SSG, and incremental regeneration
181
-
182
- ### Zig
183
-
184
- * [Jetzig](https://github.com/jetzig-framework/jetzig) - Zig web framework with MVC architecture, built-in ORM, and powerful templating
185
- * [ZTS](https://github.com/zigster64/zts) - Zig Templates made Simple, a templating system for Zig
186
- * [zmpl](https://github.com/jetzig-framework/zmpl) - Mode-based templating language that compiles to Zig functions at build time, used in Jetzig
187
- * [mustache-zig](https://github.com/batiati/mustache-zig) - Mustache template engine implementation in Zig
188
- * [etch](https://github.com/haze/etch) - Compile-time tuned templating engine focusing on speed and simplicity
189
- * [Zap](https://github.com/zigzap/zap) - High-performance backend framework in Zig
190
- * [http.zig](https://github.com/karlseguin/http.zig) - Low-level HTTP/1.1 server written entirely in Zig (_ZX_'s backend)
191
- * [tokamak](https://github.com/cztomsik/tokamak) - Server-side framework for Zig
192
- * [zig-router](https://github.com/Cloudef/zig-router) - Straightforward HTTP-like request routing library for Zig
193
- * [zig-webui](https://github.com/webui-dev/zig-webui/) - Zig library that allows using any web browser as a GUI
194
- * [Zine](https://github.com/kristoff-it/zine) - Fast, scalable, flexible static site generator (SSG) written in Zig
195
- * [Zinc](https://github.com/zon-dev/zinc/) - Web framework written in pure Zig with focus on high performance, usability, security, and extensibility
196
- * [zUI](https://github.com/thienpow/zui) - UI kit for Jetzig framework with reusable components and styles
197
- * [zig-pek](https://github.com/nektro/zig-pek) - Comptime HTML/XML parser and renderer in Zig
198
- * [zigomponent](https://zigomp.prjct.dev/) - HTML compoenents in pure zig
199
-
200
- ## Related Projects
201
-
202
- * [Codeberg Mirror](https://codeberg.org/nurulhudaapon/ziex) - ZX repository mirror on Codeberg
203
- * [ziex.dev](https://github.com/nurulhudaapon/ziex/tree/main/site) - Official documentation site of ZX made using ZX.
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.
204
187
  * [example-blog](https://github.com/ziex-dev/example-blog) - Demo blog web application built with ZX
205
188
  * [zx-numbers-game](https://github.com/Andrew-Velox/zx-numbers-game) - ZX numbers game
189
+ * [Comparision with other frameworks](https://ziex.dev/vs)
206
190
 
207
191
  ## Contributing
208
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,10 +1,21 @@
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.727",
5
- jsglue_version: "0.1.0-dev.628",
15
+ version: "0.1.0-dev.765",
16
+ jsglue_version: "0.1.0-dev.727",
6
17
  description: "ZX is a framework for building web applications with Zig.",
7
- repository: "https://github.com/nurulhudaapon/ziex",
18
+ repository: "https://github.com/ziex-dev/ziex",
8
19
  homepage: "https://ziex.dev",
9
20
  fingerprint: 14616285862371232000,
10
21
  minimum_zig_version: "0.15.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ziex",
3
- "version": "0.1.0-dev.727",
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
14
  "homepage": "https://ziex.dev",
14
15
  "repository": {
15
16
  "type": "git",
16
- "url": "git+https://github.com/nurulhudaapon/ziex.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 = {