@ezetgalaxy/titan 25.14.6 → 25.14.7

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,339 +1,344 @@
1
-
2
- ```
3
- ████████╗██╗████████╗ █████╗ ███╗ ██╗
4
- ╚══██╔══╝██║╚══██╔══╝██╔══██╗████╗ ██║
5
- ██║ ██║ ██║ ███████║██╔██╗ ██║
6
- ██║ ██║ ██║ ██╔══██║██║╚██╗██║
7
- ██║ ██║ ██║ ██║ ██║██║ ╚████║
8
- ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝
9
- ```
10
-
11
- # TITAN PLANET 🚀
12
-
13
- **JavaScript Simplicity. Rust Power. Zero Configuration.**
14
-
15
- Titan Planet is a JavaScript-first backend framework that compiles your JavaScript routes and actions into a **native Rust + Axum server**.
16
-
17
- You write **zero Rust**.
18
- Titan ships a full backend engine, dev server, bundler, router, action runtime, and Docker deploy pipeline all powered by Rust under the hood.
19
-
20
- Titan = JavaScript productivity × Rust performance × Zero DevOps.
21
-
22
- ---
23
-
24
- # 🌌 Why Titan?
25
-
26
- | Feature | Titan | Express/Nest | FastAPI | Bun |
27
- | ------------------------------------ | ----- | ------------ | ------- | --------- |
28
- | Native binary output | ✅ Yes | ❌ No | ❌ No | ❌ No |
29
- | Rust-level performance | Yes | No | No | ❌ No |
30
- | Pure JavaScript developer experience | Yes | Yes | No | Partial |
31
- | Zero-config Docker deploy | ✅ Yes | ❌ No | ❌ No | ❌ No |
32
- | Action-based architecture | ✅ Yes | ❌ No | ❌ No | ❌ No |
33
- | Hot reload dev server | ✅ Yes | No | ❌ No | ❌ No |
34
-
35
- Titan gives you:
36
-
37
- * Native speed
38
- * JS comfort
39
- * Cloud-first deployment
40
- * Full environment variable support
41
- * Built-in HTTP client (`t.fetch`)
42
- * Lightweight serverless-like actions
43
- * Instant hot reload
44
- * Zero configuration
45
- * Single deployable binary
46
-
47
- ---
48
-
49
- # 🚀 Quick Start
50
-
51
-
52
- # Requirements
53
-
54
- Install before using Titan:
55
-
56
- ### 1. Rust (latest stable)
57
-
58
- [https://rust-lang.org/tools/install/](https://rust-lang.org/tools/install/)
59
-
60
- ### 2. Node.js (v18+)
61
-
62
- Required for:
63
-
64
- * Titan CLI
65
- * esbuild
66
- * JS → Rust compilation pipeline
67
-
68
- Verify:
69
-
70
- ```bash
71
- node -v
72
- npm -v
73
- rustc -V
74
- ```
75
-
76
- ---
77
-
78
- ### Install Titan CLI
79
-
80
- ```bash
81
- npm install -g @ezetgalaxy/titan
82
- ```
83
-
84
- ### Create a new project
85
-
86
- ```bash
87
- tit init my-app
88
- cd my-app
89
- tit dev
90
- ```
91
-
92
- Titan will:
93
-
94
- * Build routes
95
- * Bundle actions
96
- * Start Rust dev server
97
- * Watch file changes
98
- * Trigger instant reload
99
-
100
- ---
101
-
102
- # 📁 Project Layout
103
-
104
- ```
105
- my-app/
106
- ├── app/ # You develop ONLY this folder
107
- │ ├── app.js # Titan routes (DSL)
108
- │ └── actions/ # Your custom JS actions
109
- │ └── hello.js # Example Titan action
110
-
111
- ───────────────────────────────────────────────────────────────
112
- Everything below is auto-generated by `tit init`
113
- You never modify these folders manually
114
- ───────────────────────────────────────────────────────────────
115
-
116
- ├── titan/ # Titan's internal JS engine
117
- │ ├── titan.js # Titan DSL runtime
118
- │ ├── bundle.js # JS → .jsbundle bundler
119
- │ └── dev.js # Hot Reload system
120
-
121
- ├── server/ # Auto-generated Rust backend
122
- ├── Cargo.toml # Rust project config
123
- ├── src/ # Rust source code
124
- ├── actions/ # Compiled .jsbundle actions
125
- │ ├── titan/ # Internal Rust runtime files
126
- │ ├── routes.json # Generated route metadata
127
- │ ├── action_map.json # Maps actions to bundles
128
- └── titan-server # Final production Rust binary
129
-
130
- ├── Dockerfile # Auto-generated production Dockerfile
131
- ├── .dockerignore # Auto-generated Docker ignore rules
132
- ├── package.json # JS project config (auto)
133
- └── .gitignore # Auto-generated by `tit init`
134
-
135
- ```
136
-
137
- ---
138
-
139
- # 🛣 Example Route
140
-
141
- **app/app.js**
142
-
143
- ```js
144
- import t from "../titan/titan.js";
145
-
146
- t.post("/hello").action("hello");
147
- t.get("/").reply("Welcome to Titan Planet");
148
-
149
- t.start(3000, "Ready to land on Titan 🚀");
150
- ```
151
-
152
- ---
153
-
154
- # 🧩 Example Action
155
-
156
- **app/actions/hello.js**
157
-
158
- ```js
159
- export function hello(req) {
160
- return { message: "Hello from Titan!" };
161
- }
162
-
163
- globalThis.hello = hello;
164
- ```
165
-
166
- ---
167
-
168
- # ⚡ New: Built-In HTTP Fetch (`t.fetch`)
169
-
170
- Titan now includes a built-in server-side `fetch` bridge powered by Rust.
171
-
172
- Use it to call any external API:
173
-
174
- ```js
175
- function hello(req) {
176
- const body = JSON.stringify({
177
- model: "gpt-4.1-mini",
178
- messages: [{ role: "user", content: "hii" }]
179
- });
180
-
181
- const r = t.fetch("https://api.openai.com/v1/chat/completions", {
182
- method: "POST",
183
- headers: {
184
- "Content-Type": "application/json",
185
- "Authorization": `Bearer ${process.env.OPENAI_API_KEY}`
186
- },
187
- body
188
- });
189
-
190
- const json = JSON.parse(r.body);
191
-
192
- return {
193
- ok: true,
194
- message: json.choices[0].message.content
195
- };
196
- }
197
-
198
- globalThis.hello = hello;
199
- ```
200
-
201
- ### `t.fetch` supports:
202
-
203
- * GET, POST, PUT, DELETE
204
- * Custom headers
205
- * JSON bodies
206
- * Authorization tokens
207
- * External / internal APIs
208
-
209
- ---
210
-
211
- # 🔥 Hot Reload Dev Server
212
-
213
- ```bash
214
- tit dev
215
- ```
216
-
217
- Titan’s dev engine:
218
-
219
- * Rebuilds routes
220
- * Rebundil actions
221
- * Restarts Rust server
222
- * Updates instantly
223
-
224
-
225
- ---
226
-
227
- # 🧱 Production Build
228
-
229
- ```bash
230
- tit build
231
- ```
232
-
233
- Output includes:
234
-
235
- * `titan-server` native binary
236
- * JS bundles
237
- * routing metadata
238
-
239
- ---
240
-
241
- # 🐳 Docker Deployment (Zero Config)
242
-
243
- Titan generates an optimized **multi-stage Dockerfile**:
244
-
245
- Works on:
246
-
247
- * Railway
248
- * Fly.io
249
- * Render
250
- * VPS / Dedicated servers
251
- * Docker Hub
252
- * Kubernetes
253
-
254
- ---
255
-
256
- # Uploading Titan to GitHub
257
-
258
- Titan projects are designed for **direct repository upload**.
259
-
260
- Include everything generated by `tit init`:
261
-
262
- ```
263
- app/
264
- titan/
265
- server/
266
- Cargo.toml
267
- Dockerfile
268
- .gitignore
269
- package.json
270
- ```
271
-
272
- Push to GitHub:
273
-
274
- ```bash
275
- git init
276
- git add .
277
- git commit -m "Initial Titan project"
278
- git branch -M main
279
- git remote add origin <your_repo_url>
280
- git push -u origin main
281
- ```
282
-
283
- Your repo is now fully deployable with Docker.
284
-
285
- ---
286
-
287
- # ☁ Zero-Config Deployment with Docker
288
-
289
- Once pushed to GitHub, you can deploy anywhere.
290
-
291
- ## Deploy to Railway
292
-
293
- 1. Go to Railway
294
- 2. Create New Project Deploy from GitHub
295
- 3. Select your Titan repo
296
- 4. Railway auto-detects the Dockerfile
297
- 5. It builds + deploys automatically
298
-
299
- Railway will:
300
-
301
- * Build your Rust server
302
- * Copy JS bundles
303
- * Start the `titan-server` binary
304
- * Expose the correct port
305
-
306
- No configuration required.
307
-
308
- ---
309
-
310
- # ✨ Updating Titan
311
-
312
- ```bash
313
- tit update
314
- ```
315
-
316
- Updates:
317
-
318
- * Titan CLI
319
- * DSL
320
- * Bundler
321
- * Dev server
322
- * Rust runtime templates
323
- * Dockerfile
324
-
325
- ---
326
-
327
- # 📦 Version
328
-
329
- **Titan v25 — Stable**
330
- Optimized for production, cloud deployment, and AI workloads.
331
-
332
- ---
333
-
334
- # 🤝 Contributing
335
-
336
- Pull requests welcome
337
- https://github.com/ezet-galaxy/-ezetgalaxy-titan
338
-
339
- ---
1
+
2
+ ```
3
+ ████████╗██╗████████╗ █████╗ ███╗ ██╗
4
+ ╚══██╔══╝██║╚══██╔══╝██╔══██╗████╗ ██║
5
+ ██║ ██║ ██║ ███████║██╔██╗ ██║
6
+ ██║ ██║ ██║ ██╔══██║██║╚██╗██║
7
+ ██║ ██║ ██║ ██║ ██║██║ ╚████║
8
+ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝
9
+ ```
10
+ # Notice
11
+ **Production mode is under development 😞**
12
+ **Enjoy development mode `tit dev` 💙**
13
+
14
+ # TITAN PLANET 🚀
15
+
16
+ **JavaScript Simplicity. Rust Power. Zero Configuration.**
17
+
18
+ Titan Planet is a JavaScript-first backend framework that compiles your JavaScript routes and actions into a **native Rust + Axum server**.
19
+
20
+ You write **zero Rust**.
21
+ Titan ships a full backend engine, dev server, bundler, router, action runtime, and Docker deploy pipeline — all powered by Rust under the hood.
22
+
23
+ Titan = JavaScript productivity × Rust performance × Zero DevOps.
24
+
25
+ ---
26
+
27
+ # 🌌 Why Titan?
28
+
29
+ | Feature | Titan | Express/Nest | FastAPI | Bun |
30
+ | ------------------------------------ | ----- | ------------ | ------- | --------- |
31
+ | Native binary output | ✅ Yes | ❌ No | ❌ No | ❌ No |
32
+ | Rust-level performance | ✅ Yes | ❌ No | ❌ No | ❌ No |
33
+ | Pure JavaScript developer experience | ✅ Yes | Yes | ❌ No | ❌ Partial |
34
+ | Zero-config Docker deploy | ✅ Yes | ❌ No | ❌ No | ❌ No |
35
+ | Action-based architecture | ✅ Yes | ❌ No | ❌ No | ❌ No |
36
+ | Hot reload dev server | ✅ Yes | ❌ No | ❌ No | ❌ No |
37
+
38
+ Titan gives you:
39
+
40
+ * Native speed
41
+ * JS comfort
42
+ * Cloud-first deployment
43
+ * Full environment variable support
44
+ * Built-in HTTP client (`t.fetch`)
45
+ * Lightweight serverless-like actions
46
+ * Instant hot reload
47
+ * Zero configuration
48
+ * Single deployable binary
49
+
50
+ ---
51
+
52
+ # 🚀 Quick Start
53
+
54
+
55
+ # ⚙ Requirements
56
+
57
+ Install before using Titan:
58
+
59
+ ### 1. Rust (latest stable)
60
+
61
+ [https://rust-lang.org/tools/install/](https://rust-lang.org/tools/install/)
62
+
63
+ ### 2. Node.js (v18+)
64
+
65
+ Required for:
66
+
67
+ * Titan CLI
68
+ * esbuild
69
+ * JS → Rust compilation pipeline
70
+
71
+ Verify:
72
+
73
+ ```bash
74
+ node -v
75
+ npm -v
76
+ rustc -V
77
+ ```
78
+
79
+ ---
80
+
81
+ ### Install Titan CLI
82
+
83
+ ```bash
84
+ npm install -g @ezetgalaxy/titan
85
+ ```
86
+
87
+ ### Create a new project
88
+
89
+ ```bash
90
+ tit init my-app
91
+ cd my-app
92
+ tit dev
93
+ ```
94
+
95
+ Titan will:
96
+
97
+ * Build routes
98
+ * Bundle actions
99
+ * Start Rust dev server
100
+ * Watch file changes
101
+ * Trigger instant reload
102
+
103
+ ---
104
+
105
+ # 📁 Project Layout
106
+
107
+ ```
108
+ my-app/
109
+ ├── app/ # You develop ONLY this folder
110
+ │ ├── app.js # Titan routes (DSL)
111
+ │ └── actions/ # Your custom JS actions
112
+ │ └── hello.js # Example Titan action
113
+
114
+ ───────────────────────────────────────────────────────────────
115
+ Everything below is auto-generated by `tit init`
116
+ You never modify these folders manually
117
+ ───────────────────────────────────────────────────────────────
118
+
119
+ ├── titan/ # Titan's internal JS engine
120
+ ├── titan.js # Titan DSL runtime
121
+ ├── bundle.js # JS .jsbundle bundler
122
+ └── dev.js # Hot Reload system
123
+
124
+ ├── server/ # Auto-generated Rust backend
125
+ │ ├── Cargo.toml # Rust project config
126
+ │ ├── src/ # Rust source code
127
+ │ ├── actions/ # Compiled .jsbundle actions
128
+ ├── titan/ # Internal Rust runtime files
129
+ ├── routes.json # Generated route metadata
130
+ ├── action_map.json # Maps actions to bundles
131
+ │ └── titan-server # Final production Rust binary
132
+
133
+ ├── Dockerfile # Auto-generated production Dockerfile
134
+ ├── .dockerignore # Auto-generated Docker ignore rules
135
+ ├── package.json # JS project config (auto)
136
+ └── .gitignore # Auto-generated by `tit init`
137
+
138
+ ```
139
+
140
+ ---
141
+
142
+ # 🛣 Example Route
143
+
144
+ **app/app.js**
145
+
146
+ ```js
147
+ import t from "../titan/titan.js";
148
+
149
+ t.post("/hello").action("hello");
150
+ t.get("/").reply("Welcome to Titan Planet");
151
+
152
+ t.start(3000, "Ready to land on Titan 🚀");
153
+ ```
154
+
155
+ ---
156
+
157
+ # 🧩 Example Action
158
+
159
+ **app/actions/hello.js**
160
+
161
+ ```js
162
+ export function hello(req) {
163
+ return { message: "Hello from Titan!" };
164
+ }
165
+
166
+ globalThis.hello = hello;
167
+ ```
168
+
169
+ ---
170
+
171
+ # ⚡ New: Built-In HTTP Fetch (`t.fetch`)
172
+
173
+ Titan now includes a built-in server-side `fetch` bridge powered by Rust.
174
+
175
+ Use it to call any external API:
176
+
177
+ ```js
178
+ function hello(req) {
179
+ const API_KEY = process.env.API_KEY || __titan_env.API_KEY;
180
+
181
+ const body = JSON.stringify({
182
+ model: "gpt-4.1-mini",
183
+ messages: [{ role: "user", content: "hii" }]
184
+ });
185
+
186
+ const r = t.fetch("https://api.openai.com/v1/chat/completions", {
187
+ method: "POST",
188
+ headers: {
189
+ "Content-Type": "application/json",
190
+ "Authorization": `Bearer ${API_KEY}`
191
+ },
192
+ body
193
+ });
194
+
195
+ const json = JSON.parse(r.body);
196
+
197
+ return {
198
+ ok: true,
199
+ message: json.choices[0].message.content
200
+ };
201
+ }
202
+
203
+ globalThis.hello = hello;
204
+ ```
205
+
206
+ ### `t.fetch` supports:
207
+
208
+ * GET, POST, PUT, DELETE
209
+ * Custom headers
210
+ * JSON bodies
211
+ * Authorization tokens
212
+ * External / internal APIs
213
+
214
+ ---
215
+
216
+ # 🔥 Hot Reload Dev Server
217
+
218
+ ```bash
219
+ tit dev
220
+ ```
221
+
222
+ Titan’s dev engine:
223
+
224
+ * Rebuilds routes
225
+ * Rebundil actions
226
+ * Restarts Rust server
227
+ * Updates instantly
228
+
229
+
230
+ ---
231
+
232
+ # 🧱 Production Build
233
+
234
+ ```bash
235
+ tit build
236
+ ```
237
+
238
+ Output includes:
239
+
240
+ * `titan-server` native binary
241
+ * JS bundles
242
+ * routing metadata
243
+
244
+ ---
245
+
246
+ # 🐳 Docker Deployment (Zero Config)
247
+
248
+ Titan generates an optimized **multi-stage Dockerfile**:
249
+
250
+ Works on:
251
+
252
+ * Railway
253
+ * Fly.io
254
+ * Render
255
+ * VPS / Dedicated servers
256
+ * Docker Hub
257
+ * Kubernetes
258
+
259
+ ---
260
+
261
+ # ☁ Uploading Titan to GitHub
262
+
263
+ Titan projects are designed for **direct repository upload**.
264
+
265
+ Include everything generated by `tit init`:
266
+
267
+ ```
268
+ app/
269
+ titan/
270
+ server/
271
+ Cargo.toml
272
+ Dockerfile
273
+ .gitignore
274
+ package.json
275
+ ```
276
+
277
+ Push to GitHub:
278
+
279
+ ```bash
280
+ git init
281
+ git add .
282
+ git commit -m "Initial Titan project"
283
+ git branch -M main
284
+ git remote add origin <your_repo_url>
285
+ git push -u origin main
286
+ ```
287
+
288
+ Your repo is now fully deployable with Docker.
289
+
290
+ ---
291
+
292
+ # ☁ Zero-Config Deployment with Docker
293
+
294
+ Once pushed to GitHub, you can deploy anywhere.
295
+
296
+ ## Deploy to Railway
297
+
298
+ 1. Go to Railway
299
+ 2. Create New Project → Deploy from GitHub
300
+ 3. Select your Titan repo
301
+ 4. Railway auto-detects the Dockerfile
302
+ 5. It builds + deploys automatically
303
+
304
+ Railway will:
305
+
306
+ * Build your Rust server
307
+ * Copy JS bundles
308
+ * Start the `titan-server` binary
309
+ * Expose the correct port
310
+
311
+ No configuration required.
312
+
313
+ ---
314
+
315
+ # ✨ Updating Titan
316
+
317
+ ```bash
318
+ tit update
319
+ ```
320
+
321
+ Updates:
322
+
323
+ * Titan CLI
324
+ * DSL
325
+ * Bundler
326
+ * Dev server
327
+ * Rust runtime templates
328
+ * Dockerfile
329
+
330
+ ---
331
+
332
+ # 📦 Version
333
+
334
+ **Titan v25 — Stable**
335
+ Optimized for production, cloud deployment, and AI workloads.
336
+
337
+ ---
338
+
339
+ # 🤝 Contributing
340
+
341
+ Pull requests welcome
342
+ https://github.com/ezet-galaxy/-ezetgalaxy-titan
343
+
344
+ ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ezetgalaxy/titan",
3
- "version": "25.14.6",
3
+ "version": "25.14.7",
4
4
  "description": "JavaScript backend framework that compiles your JS into a Rust + Axum server.",
5
5
  "license": "ISC",
6
6
  "author": "ezetgalaxy",
@@ -1,21 +1,21 @@
1
1
  // server/src/main.rs
2
- use std::{collections::HashMap, env, fs, path::PathBuf, sync::Arc, path::Path};
2
+ use std::{collections::HashMap, env, fs, path::Path, path::PathBuf, sync::Arc};
3
3
 
4
4
  use anyhow::Result;
5
5
  use axum::{
6
- body::{to_bytes, Body},
6
+ Router,
7
+ body::{Body, to_bytes},
7
8
  extract::State,
8
9
  http::{Request, StatusCode},
9
10
  response::{IntoResponse, Json},
10
11
  routing::any,
11
- Router,
12
12
  };
13
13
 
14
- use boa_engine::{object::ObjectInitializer, Context, JsValue, Source};
14
+ use boa_engine::{Context, JsValue, Source, object::ObjectInitializer};
15
15
  use boa_engine::{js_string, native_function::NativeFunction, property::Attribute};
16
16
 
17
- use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
18
17
  use reqwest::blocking::Client;
18
+ use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
19
19
 
20
20
  use serde::Deserialize;
21
21
  use serde_json::Value;
@@ -152,9 +152,10 @@ fn inject_t_fetch(ctx: &mut Context) {
152
152
  if !header_pairs.is_empty() {
153
153
  let mut headers = HeaderMap::new();
154
154
  for (k, v) in header_pairs.into_iter() {
155
- if let (Ok(name), Ok(val)) =
156
- (HeaderName::from_bytes(k.as_bytes()), HeaderValue::from_str(&v))
157
- {
155
+ if let (Ok(name), Ok(val)) = (
156
+ HeaderName::from_bytes(k.as_bytes()),
157
+ HeaderValue::from_str(&v),
158
+ ) {
158
159
  headers.insert(name, val);
159
160
  }
160
161
  }
@@ -230,7 +231,8 @@ async fn dynamic_handler_inner(
230
231
  "action" => {
231
232
  let action_name = route.value.as_str().unwrap_or("").trim();
232
233
  if action_name.is_empty() {
233
- return (StatusCode::INTERNAL_SERVER_ERROR, "Invalid action name").into_response();
234
+ return (StatusCode::INTERNAL_SERVER_ERROR, "Invalid action name")
235
+ .into_response();
234
236
  }
235
237
 
236
238
  // Resolve actions directory: prefer resolve_actions_dir(), fall back to heuristic find_actions_dir
@@ -272,30 +274,56 @@ async fn dynamic_handler_inner(
272
274
  };
273
275
 
274
276
  // Build env object
275
- let mut env_map = serde_json::Map::new();
277
+ let mut env_map: serde_json::Map<String, Value> = serde_json::Map::new();
276
278
  for (k, v) in std::env::vars() {
277
279
  env_map.insert(k, Value::String(v));
278
280
  }
279
- let env_json = Value::Object(env_map);
281
+ let env_json: Value = Value::Object(env_map);
282
+
283
+ // Ensure body_str is valid JS: we will embed it as a JS expression.
284
+ // If body_str is a JSON object string, embedding it directly is fine.
285
+ // But to be safe, we create a quoted JS string and parse it in JS if necessary.
286
+ let safe_body_literal: String =
287
+ serde_json::to_string(&body_str).unwrap_or_else(|_| "null".to_string());
280
288
 
281
- // Injected script: sets process.env and __titan_req and invokes action function.
282
- let injected = format!(
289
+ // Injected script: sets process.env, __titan_env, __titan_req and invokes action function.
290
+ let injected: String = format!(
283
291
  r#"
284
- globalThis.process = {{ env: {} }};
285
- const __titan_req = {};
286
- {};
287
- {}(__titan_req);
288
- "#,
289
- env_json.to_string(),
290
- body_str,
291
- js_code,
292
- action_name
292
+ // Runtime env injected by Titan
293
+ globalThis.process = {{ env: {} }};
294
+ globalThis.__titan_env = {};
295
+ // quick debug so prod logs show whether API key is present
296
+ try {{
297
+ console.log('TITAN: runtime API_KEY =', (process && process.env && process.env.API_KEY) || (typeof __titan_env !== 'undefined' && __titan_env.API_KEY) || null);
298
+ }} catch(e) {{ /* ignore */ }}
299
+
300
+ // Parse the incoming request body. If it's a JSON string we parse it into an object.
301
+ const __titan_req_body_literal = {};
302
+ let __titan_req;
303
+ try {{
304
+ // it's a quoted JSON string in Rust, so first unquote via JSON.parse
305
+ __titan_req = JSON.parse(__titan_req_body_literal);
306
+ }} catch (e) {{
307
+ // if parse fails, fall back to empty object
308
+ __titan_req = {{}};
309
+ }}
310
+
311
+ // Action code (bundled JS)
312
+ {};
313
+ // call exported action function
314
+ {}(__titan_req);
315
+ "#,
316
+ env_json.to_string(), // inserted JSON object for process.env
317
+ env_json.to_string(), // inserted also as __titan_env
318
+ safe_body_literal, // quoted JSON string literal of request body
319
+ js_code, // code from the .jsbundle
320
+ action_name // call function
293
321
  );
294
322
 
295
- let mut ctx = Context::default();
323
+ let mut ctx: Context = Context::default();
296
324
  inject_t_fetch(&mut ctx);
297
325
 
298
- let result = match ctx.eval(Source::from_bytes(&injected)) {
326
+ let result: JsValue = match ctx.eval(Source::from_bytes(&injected)) {
299
327
  Ok(v) => v,
300
328
  Err(e) => return Json(json_error(e.to_string())).into_response(),
301
329
  };
@@ -361,7 +389,10 @@ async fn main() -> Result<()> {
361
389
  println!(" ██║ ██║ ██║ ██╔══██║██║╚██╗██║");
362
390
  println!(" ██║ ██║ ██║ ██║ ██║██║ ╚████║");
363
391
  println!(" ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝\x1b[0m\n");
364
- println!("\x1b[38;5;39mTitan server running at:\x1b[0m http://localhost:{}", port);
392
+ println!(
393
+ "\x1b[38;5;39mTitan server running at:\x1b[0m http://localhost:{}",
394
+ port
395
+ );
365
396
 
366
397
  axum::serve(listener, app).await?;
367
398
  Ok(())