@ezetgalaxy/titan 25.15.1 → 25.15.3

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
@@ -13,7 +13,7 @@
13
13
  ✅ **Production mode is ready**
14
14
  💙 **Enjoy development mode `tit dev`**
15
15
  ✅ **No more `globalThis` required**
16
- 💟 **Website for titan docs coming soon**
16
+ 💟 **Website for titan docs: https://titan-docs-ez.vercel.app/docs**
17
17
 
18
18
 
19
19
  ---
@@ -261,14 +261,3 @@ No exports wiring. No globals. No boilerplate.
261
261
  * Designed for cloud & AI workloads
262
262
 
263
263
  ---
264
-
265
- # 🧠 Final Note
266
-
267
- What you built today is **not a wrapper**, **not a toy**, and **not a clone**.
268
-
269
- You now have:
270
-
271
- * A real JS runtime
272
- * A real routing engine
273
- * A real compiler pipeline
274
- * A real production server
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ezetgalaxy/titan",
3
- "version": "25.15.1",
3
+ "version": "25.15.3",
4
4
  "description": "JavaScript backend framework that compiles your JS into a Rust + Axum server.",
5
5
  "license": "ISC",
6
6
  "author": "ezetgalaxy",
@@ -183,16 +183,28 @@ fn inject_t_runtime(ctx: &mut Context, action_name: &str) {
183
183
  // t.fetch(...) — no capture, safe fn pointer
184
184
  // =========================================================
185
185
  let t_fetch_native = NativeFunction::from_fn_ptr(|_this, args, ctx| {
186
- let url = args
187
- .get(0)
188
- .and_then(|v| v.to_string(ctx).ok())
189
- .map(|s| s.to_std_string_escaped())
190
- .unwrap_or_default();
186
+ // -----------------------------
187
+ // 1. URL (required)
188
+ // -----------------------------
189
+ let url = match args.get(0) {
190
+ Some(v) => v.to_string(ctx)?.to_std_string_escaped(),
191
+ None => {
192
+ return Err(JsError::from_native(
193
+ boa_engine::JsNativeError::typ()
194
+ .with_message("t.fetch(url[, options]): url is required"),
195
+ ));
196
+ }
197
+ };
198
+
199
+ // -----------------------------
200
+ // 2. Options (optional, JSON-only)
201
+ // -----------------------------
202
+ let opts_js = args.get(1).cloned().unwrap_or(JsValue::Null);
191
203
 
192
- let opts_js = args.get(1).cloned().unwrap_or(JsValue::undefined());
193
- let opts_json: Value = opts_js
194
- .to_json(ctx)
195
- .unwrap_or(Value::Object(serde_json::Map::new()));
204
+ let opts_json = match opts_js.to_json(ctx) {
205
+ Ok(v) => v,
206
+ Err(_) => Value::Object(serde_json::Map::new()),
207
+ };
196
208
 
197
209
  let method = opts_json
198
210
  .get("method")
@@ -200,28 +212,35 @@ fn inject_t_runtime(ctx: &mut Context, action_name: &str) {
200
212
  .unwrap_or("GET")
201
213
  .to_string();
202
214
 
203
- let body_opt = opts_json.get("body").map(|v| v.to_string());
215
+ let body_opt = opts_json
216
+ .get("body")
217
+ .and_then(|v| v.as_str())
218
+ .map(|s| s.to_string());
204
219
 
205
220
  let mut header_pairs = Vec::new();
206
221
  if let Some(Value::Object(map)) = opts_json.get("headers") {
207
222
  for (k, v) in map {
208
- header_pairs.push((k.clone(), v.to_string()));
223
+ if let Some(val) = v.as_str() {
224
+ header_pairs.push((k.clone(), val.to_string()));
225
+ }
209
226
  }
210
227
  }
211
228
 
229
+ // -----------------------------
230
+ // 3. Blocking HTTP (safe fallback)
231
+ // -----------------------------
212
232
  let out_json = task::block_in_place(move || {
213
233
  let client = Client::new();
214
- let mut req = client.request(
215
- method.parse().unwrap_or(reqwest::Method::GET),
216
- &url,
217
- );
234
+
235
+ let mut req = client.request(method.parse().unwrap_or(reqwest::Method::GET), &url);
218
236
 
219
237
  if !header_pairs.is_empty() {
220
238
  let mut headers = HeaderMap::new();
221
239
  for (k, v) in header_pairs {
222
- if let (Ok(name), Ok(val)) =
223
- (HeaderName::from_bytes(k.as_bytes()), HeaderValue::from_str(&v))
224
- {
240
+ if let (Ok(name), Ok(val)) = (
241
+ HeaderName::from_bytes(k.as_bytes()),
242
+ HeaderValue::from_str(&v),
243
+ ) {
225
244
  headers.insert(name, val);
226
245
  }
227
246
  }
@@ -245,7 +264,15 @@ fn inject_t_runtime(ctx: &mut Context, action_name: &str) {
245
264
  }
246
265
  });
247
266
 
248
- Ok(JsValue::from_json(&out_json, ctx).unwrap_or(JsValue::undefined()))
267
+ // -----------------------------
268
+ // 4. JSON → JsValue (NO undefined fallback)
269
+ // -----------------------------
270
+ match JsValue::from_json(&out_json, ctx) {
271
+ Ok(v) => Ok(v),
272
+ Err(e) => Err(boa_engine::JsNativeError::error()
273
+ .with_message(format!("t.fetch: JSON conversion failed: {}", e))
274
+ .into()),
275
+ }
249
276
  });
250
277
 
251
278
  // =========================================================