@ezetgalaxy/titan 26.15.1 → 26.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 +65 -38
- package/package.json +1 -1
- package/templates/js/server/src/extensions/mod.rs +5 -6
- package/templates/js/server/src/extensions/titan_core.js +30 -9
- package/templates/ts/server/src/extensions/mod.rs +5 -6
- package/templates/ts/server/src/extensions/titan_core.js +30 -9
- package/titanpl-sdk/package.json +1 -1
- package/titanpl-sdk/templates/server/src/extensions/mod.rs +5 -6
- package/titanpl-sdk/templates/server/src/extensions/titan_core.js +30 -9
package/README.md
CHANGED
|
@@ -1,56 +1,84 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://titan-docs-ez.vercel.app/" target="_blank">
|
|
3
|
+
<img src="https://i.ibb.co/VpBsTg6m/tpl-Logo.png" width="120" alt="TitanPl Logo" />
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
1
6
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
██║ ██║ ██║ ███████║██╔██╗ ██║ █████╔╝██║██╔██║ █████╔╝███████╗
|
|
6
|
-
██║ ██║ ██║ ██╔══██║██║╚██╗██║ ██╔═══╝ ████╔╝██║██╔═══╝ ██═══██║
|
|
7
|
-
██║ ██║ ██║ ██║ ██║██║ ╚████║ ███████╗╚██████╔╝███████╗███████║
|
|
8
|
-
╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚══════╝ ╚═════╝ ╚══════╝╚══════╝
|
|
9
|
-
```
|
|
7
|
+
<p align="center">
|
|
8
|
+
You write zero Rust. TitanPl handles routing, bundling, runtime execution, hot reload, and deployment — <br> all powered by <a href="https://rust-lang.org/">Rust</a> under the hood.
|
|
9
|
+
</p>
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/@ezetgalaxy/titan">
|
|
13
|
+
<img src="https://img.shields.io/npm/v/@ezetgalaxy/titan?style=for-the-badge&logo=npm&logoColor=white" />
|
|
14
|
+
</a>
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
💟 **Titan Planet docs:** https://titan-docs-ez.vercel.app/docs
|
|
15
|
-
🚀 **CLI: `titan` is now the canonical command. `tit` remains supported as an alias.**
|
|
16
|
-
🛡️ **Strict Mode:** Titan now enforces zero type errors before running.
|
|
17
|
-
✅ **For text response from a action file use t.response.text("Hii TitanPl")
|
|
16
|
+
<img src="https://img.shields.io/badge/Runtime-Gravity(V8)%20%26%20Rust%20Tokio-1f2937?style=for-the-badge" />
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
<img src="https://img.shields.io/badge/Powered%20By%20Rust%20Axum-DEA584?style=for-the-badge&logo=rust&logoColor=black" />
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
<a href="https://discord.gg/mPDaTRtP">
|
|
21
|
+
<img src="https://img.shields.io/badge/Join-5865F2?style=for-the-badge&logo=discord&logoColor=white" />
|
|
22
|
+
</a>
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
<a href="https://x.com/TitanPl">
|
|
25
|
+
<img src="https://img.shields.io/badge/Follow-000000?style=for-the-badge&logo=x&logoColor=white" />
|
|
26
|
+
</a>
|
|
24
27
|
|
|
28
|
+
</p>
|
|
25
29
|
|
|
26
|
-
**TypeScript Precision. JavaScript Simplicity. Native Rust Power. Zero Configuration.**
|
|
27
|
-
|
|
28
|
-
Titan Planet is a **JavaScript/TypeScript-first Backend Framework** that compiles your application into a single, high-performance native binary. It embeds a V8 JavaScript runtime directly into a specialized Rust + Axum server.
|
|
29
30
|
|
|
30
|
-
**Start with pure TypeScript/JavaScript.**
|
|
31
|
-
**Need raw power? Add Rust actions seamlessly.**
|
|
32
|
-
Titan handles the compilation, bundling, and routing automatically for both.
|
|
33
31
|
|
|
34
|
-
Titan = **TS/JS productivity × Rust performance × Zero DevOps**
|
|
35
32
|
|
|
36
|
-
|
|
33
|
+
<h1> Description
|
|
34
|
+
</h1>
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
Titan Planet is a JavaScript/TypeScript-first Backend Framework that compiles your application into a single, high-performance native binary. It embeds it's own Gravity (V8) JavaScript runtime directly into a specialized Rust + Axum server.
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
| ------------------------------------ | ----- | ------------ | ------- | --------- |
|
|
42
|
-
| Native binary output | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
43
|
-
| Hybrid Rust + JS/TS Actions | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
44
|
-
| Strict TypeScript Enforcement | ✅ Yes | ❌ Setup Req. | ❌ No | ❌ Partial |
|
|
45
|
-
| Zero-config Docker deploy | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
46
|
-
| Action-based architecture | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
47
|
-
| Hot reload dev server | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
48
|
-
| Modular, Isolated Templates | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
38
|
+
**TypeScript Precision. JavaScript Simplicity. Native Rust Power. Zero Configuration.**
|
|
49
39
|
|
|
50
|
-
|
|
40
|
+
<p>
|
|
41
|
+
|
|
42
|
+
<img src="https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white" />
|
|
43
|
+
<img src="https://img.shields.io/badge/JavaScript-F7DF1E?style=for-the-badge&logo=javascript&logoColor=black" />
|
|
44
|
+
<img src="https://img.shields.io/badge/Rust-DEA584?style=for-the-badge&logo=rust&logoColor=black" />
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
## Why Titan?
|
|
49
|
+
|
|
50
|
+
Titan Planet compiles your JavaScript or TypeScript application into a **single native Rust binary**.
|
|
51
|
+
|
|
52
|
+
It embeds a V8 runtime inside a Rust + Axum server — giving you:
|
|
53
|
+
|
|
54
|
+
- ⚡ Native-level performance
|
|
55
|
+
- 📦 Single binary deployment
|
|
56
|
+
- 🧠 Strict TypeScript enforcement
|
|
57
|
+
- 🛡 Zero type errors before runtime
|
|
58
|
+
- 🚀 No DevOps configuration required
|
|
59
|
+
|
|
60
|
+
Start with pure TypeScript.
|
|
61
|
+
Drop into Rust when you need extreme performance.
|
|
62
|
+
Titan handles the integration automatically.
|
|
63
|
+
|
|
64
|
+
<p>
|
|
65
|
+
<a href="https://titan-docs-ez.vercel.app/docs" target="_blank">
|
|
66
|
+
<img src="https://i.ibb.co/VpBsTg6m/tpl-Logo.png" width="28" style="vertical-align:middle;" />
|
|
67
|
+
<strong style="vertical-align:middle;"> Documentation</strong>
|
|
68
|
+
</p>
|
|
69
|
+
<p>
|
|
70
|
+
<a href="https://titan-docs-ez.vercel.app/docs/runtime-architecture" target="_blank">
|
|
71
|
+
<strong style="vertical-align:middle;">Gravity Runtime</strong>
|
|
72
|
+
</a>
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
<p>
|
|
76
|
+
<a href="https://titan-docs-ez.vercel.app/docs/14-drift" target="_blank">
|
|
77
|
+
<strong style="vertical-align:middle;">Drift</strong>
|
|
78
|
+
</a>
|
|
79
|
+
</p>
|
|
51
80
|
|
|
52
81
|
# 🚀 Quick Start
|
|
53
|
-
|
|
54
82
|
### 1. Prerequisites
|
|
55
83
|
* **Rust** (latest stable): [Install Rust](https://rust-lang.org/tools/install/)
|
|
56
84
|
* **Node.js** (v18+): Required for CLI and JS tooling.
|
|
@@ -100,7 +128,6 @@ You'll see the Titan Dev Server spin up:
|
|
|
100
128
|
• Your app is now orbiting Titan Planet
|
|
101
129
|
```
|
|
102
130
|
|
|
103
|
-
---
|
|
104
131
|
|
|
105
132
|
# ⚡ Hybrid Action System
|
|
106
133
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ezetgalaxy/titan",
|
|
3
|
-
"version": "26.15.
|
|
3
|
+
"version": "26.15.3",
|
|
4
4
|
"description": "Titan Planet is a JavaScript-first backend framework that embeds JS actions into a Rust + Axum server and ships as a single native binary. Routes are compiled to static metadata; only actions run in the embedded JS runtime. No Node.js. No event loop in production.",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "ezetgalaxy",
|
|
@@ -470,16 +470,15 @@ pub fn execute_action_optimized(
|
|
|
470
470
|
let p_val = v8_str(scope, req_path);
|
|
471
471
|
req_obj.set(scope, p_key.into(), p_val.into());
|
|
472
472
|
|
|
473
|
-
//
|
|
473
|
+
// body — attach raw bytes as ArrayBuffer under "rawBody" key
|
|
474
|
+
let rb_key = v8::Local::new(scope, &gk_raw_body);
|
|
474
475
|
let body_val: v8::Local<v8::Value> = if let Some(bytes) = req_body {
|
|
475
|
-
let
|
|
476
|
-
let
|
|
477
|
-
let ab = v8::ArrayBuffer::with_backing_store(scope, &store.make_shared());
|
|
476
|
+
let backing = v8::ArrayBuffer::new_backing_store_from_vec(bytes.to_vec());
|
|
477
|
+
let ab = v8::ArrayBuffer::with_backing_store(scope, &backing.make_shared());
|
|
478
478
|
ab.into()
|
|
479
479
|
} else {
|
|
480
480
|
v8::null(scope).into()
|
|
481
481
|
};
|
|
482
|
-
let rb_key = v8::Local::new(scope, &gk_raw_body);
|
|
483
482
|
req_obj.set(scope, rb_key.into(), body_val);
|
|
484
483
|
|
|
485
484
|
// headers
|
|
@@ -577,4 +576,4 @@ pub fn throw(scope: &mut v8::HandleScope, msg: &str) {
|
|
|
577
576
|
let message = v8_str(scope, msg);
|
|
578
577
|
let exception = v8::Exception::error(scope, message);
|
|
579
578
|
scope.throw_exception(exception);
|
|
580
|
-
}
|
|
579
|
+
}
|
|
@@ -15,6 +15,32 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
15
15
|
const wrapped = function (req) {
|
|
16
16
|
const requestId = req.__titan_request_id;
|
|
17
17
|
|
|
18
|
+
if (req.rawBody && req.rawBody.byteLength !== undefined) {
|
|
19
|
+
try {
|
|
20
|
+
const decoder = new TextDecoder();
|
|
21
|
+
const text = decoder.decode(req.rawBody);
|
|
22
|
+
|
|
23
|
+
const contentType =
|
|
24
|
+
(req.headers && req.headers["content-type"]) ||
|
|
25
|
+
(req.headers && req.headers["Content-Type"]) ||
|
|
26
|
+
"";
|
|
27
|
+
|
|
28
|
+
if (contentType.includes("application/json")) {
|
|
29
|
+
req.body = text ? JSON.parse(text) : {};
|
|
30
|
+
} else if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
31
|
+
req.body = Object.fromEntries(new URLSearchParams(text));
|
|
32
|
+
} else {
|
|
33
|
+
req.body = text;
|
|
34
|
+
}
|
|
35
|
+
} catch (e) {
|
|
36
|
+
req.body = {};
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
req.body = {};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ===============================
|
|
43
|
+
|
|
18
44
|
const isSuspend = (err) => {
|
|
19
45
|
const msg = err && (err.message || String(err));
|
|
20
46
|
return msg && (msg.includes("__SUSPEND__") || msg.includes("SUSPEND"));
|
|
@@ -25,9 +51,7 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
25
51
|
|
|
26
52
|
if (result && typeof result.then === 'function') {
|
|
27
53
|
result.then(
|
|
28
|
-
(data) =>
|
|
29
|
-
t._finish_request(requestId, data);
|
|
30
|
-
},
|
|
54
|
+
(data) => t._finish_request(requestId, data),
|
|
31
55
|
(err) => {
|
|
32
56
|
if (isSuspend(err)) return;
|
|
33
57
|
t._finish_request(requestId, { error: err.message || String(err) });
|
|
@@ -54,10 +78,8 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
54
78
|
}
|
|
55
79
|
};
|
|
56
80
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
env: t.loadEnv ? t.loadEnv() : {}
|
|
60
|
-
};
|
|
81
|
+
// Titan Environment API
|
|
82
|
+
t.env = t.loadEnv ? t.loadEnv() : {};
|
|
61
83
|
|
|
62
84
|
// Async Proxy Creator
|
|
63
85
|
function createAsyncOp(op) {
|
|
@@ -73,8 +95,7 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
73
95
|
}
|
|
74
96
|
|
|
75
97
|
throw new Error(
|
|
76
|
-
`[Titan Error] Accessed '${String(prop)}' without drift(). `
|
|
77
|
-
`Fix: const res = drift(t.fetch(...));`
|
|
98
|
+
`[Titan Error] Accessed '${String(prop)}' without drift(). `
|
|
78
99
|
);
|
|
79
100
|
}
|
|
80
101
|
});
|
|
@@ -470,16 +470,15 @@ pub fn execute_action_optimized(
|
|
|
470
470
|
let p_val = v8_str(scope, req_path);
|
|
471
471
|
req_obj.set(scope, p_key.into(), p_val.into());
|
|
472
472
|
|
|
473
|
-
//
|
|
473
|
+
// body — attach raw bytes as ArrayBuffer under "rawBody" key
|
|
474
|
+
let rb_key = v8::Local::new(scope, &gk_raw_body);
|
|
474
475
|
let body_val: v8::Local<v8::Value> = if let Some(bytes) = req_body {
|
|
475
|
-
let
|
|
476
|
-
let
|
|
477
|
-
let ab = v8::ArrayBuffer::with_backing_store(scope, &store.make_shared());
|
|
476
|
+
let backing = v8::ArrayBuffer::new_backing_store_from_vec(bytes.to_vec());
|
|
477
|
+
let ab = v8::ArrayBuffer::with_backing_store(scope, &backing.make_shared());
|
|
478
478
|
ab.into()
|
|
479
479
|
} else {
|
|
480
480
|
v8::null(scope).into()
|
|
481
481
|
};
|
|
482
|
-
let rb_key = v8::Local::new(scope, &gk_raw_body);
|
|
483
482
|
req_obj.set(scope, rb_key.into(), body_val);
|
|
484
483
|
|
|
485
484
|
// headers
|
|
@@ -577,4 +576,4 @@ pub fn throw(scope: &mut v8::HandleScope, msg: &str) {
|
|
|
577
576
|
let message = v8_str(scope, msg);
|
|
578
577
|
let exception = v8::Exception::error(scope, message);
|
|
579
578
|
scope.throw_exception(exception);
|
|
580
|
-
}
|
|
579
|
+
}
|
|
@@ -15,6 +15,32 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
15
15
|
const wrapped = function (req) {
|
|
16
16
|
const requestId = req.__titan_request_id;
|
|
17
17
|
|
|
18
|
+
if (req.rawBody && req.rawBody.byteLength !== undefined) {
|
|
19
|
+
try {
|
|
20
|
+
const decoder = new TextDecoder();
|
|
21
|
+
const text = decoder.decode(req.rawBody);
|
|
22
|
+
|
|
23
|
+
const contentType =
|
|
24
|
+
(req.headers && req.headers["content-type"]) ||
|
|
25
|
+
(req.headers && req.headers["Content-Type"]) ||
|
|
26
|
+
"";
|
|
27
|
+
|
|
28
|
+
if (contentType.includes("application/json")) {
|
|
29
|
+
req.body = text ? JSON.parse(text) : {};
|
|
30
|
+
} else if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
31
|
+
req.body = Object.fromEntries(new URLSearchParams(text));
|
|
32
|
+
} else {
|
|
33
|
+
req.body = text;
|
|
34
|
+
}
|
|
35
|
+
} catch (e) {
|
|
36
|
+
req.body = {};
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
req.body = {};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ===============================
|
|
43
|
+
|
|
18
44
|
const isSuspend = (err) => {
|
|
19
45
|
const msg = err && (err.message || String(err));
|
|
20
46
|
return msg && (msg.includes("__SUSPEND__") || msg.includes("SUSPEND"));
|
|
@@ -25,9 +51,7 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
25
51
|
|
|
26
52
|
if (result && typeof result.then === 'function') {
|
|
27
53
|
result.then(
|
|
28
|
-
(data) =>
|
|
29
|
-
t._finish_request(requestId, data);
|
|
30
|
-
},
|
|
54
|
+
(data) => t._finish_request(requestId, data),
|
|
31
55
|
(err) => {
|
|
32
56
|
if (isSuspend(err)) return;
|
|
33
57
|
t._finish_request(requestId, { error: err.message || String(err) });
|
|
@@ -54,10 +78,8 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
54
78
|
}
|
|
55
79
|
};
|
|
56
80
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
env: t.loadEnv ? t.loadEnv() : {}
|
|
60
|
-
};
|
|
81
|
+
// Titan Environment API
|
|
82
|
+
t.env = t.loadEnv ? t.loadEnv() : {};
|
|
61
83
|
|
|
62
84
|
// Async Proxy Creator
|
|
63
85
|
function createAsyncOp(op) {
|
|
@@ -73,8 +95,7 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
73
95
|
}
|
|
74
96
|
|
|
75
97
|
throw new Error(
|
|
76
|
-
`[Titan Error] Accessed '${String(prop)}' without drift(). `
|
|
77
|
-
`Fix: const res = drift(t.fetch(...));`
|
|
98
|
+
`[Titan Error] Accessed '${String(prop)}' without drift(). `
|
|
78
99
|
);
|
|
79
100
|
}
|
|
80
101
|
});
|
package/titanpl-sdk/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "titanpl-sdk",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Development SDK for Titan Planet. Provides TypeScript type definitions for the global 't' runtime object and a 'lite' test-harness runtime for building and verifying extensions.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -470,16 +470,15 @@ pub fn execute_action_optimized(
|
|
|
470
470
|
let p_val = v8_str(scope, req_path);
|
|
471
471
|
req_obj.set(scope, p_key.into(), p_val.into());
|
|
472
472
|
|
|
473
|
-
//
|
|
473
|
+
// body — attach raw bytes as ArrayBuffer under "rawBody" key
|
|
474
|
+
let rb_key = v8::Local::new(scope, &gk_raw_body);
|
|
474
475
|
let body_val: v8::Local<v8::Value> = if let Some(bytes) = req_body {
|
|
475
|
-
let
|
|
476
|
-
let
|
|
477
|
-
let ab = v8::ArrayBuffer::with_backing_store(scope, &store.make_shared());
|
|
476
|
+
let backing = v8::ArrayBuffer::new_backing_store_from_vec(bytes.to_vec());
|
|
477
|
+
let ab = v8::ArrayBuffer::with_backing_store(scope, &backing.make_shared());
|
|
478
478
|
ab.into()
|
|
479
479
|
} else {
|
|
480
480
|
v8::null(scope).into()
|
|
481
481
|
};
|
|
482
|
-
let rb_key = v8::Local::new(scope, &gk_raw_body);
|
|
483
482
|
req_obj.set(scope, rb_key.into(), body_val);
|
|
484
483
|
|
|
485
484
|
// headers
|
|
@@ -577,4 +576,4 @@ pub fn throw(scope: &mut v8::HandleScope, msg: &str) {
|
|
|
577
576
|
let message = v8_str(scope, msg);
|
|
578
577
|
let exception = v8::Exception::error(scope, message);
|
|
579
578
|
scope.throw_exception(exception);
|
|
580
|
-
}
|
|
579
|
+
}
|
|
@@ -15,6 +15,32 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
15
15
|
const wrapped = function (req) {
|
|
16
16
|
const requestId = req.__titan_request_id;
|
|
17
17
|
|
|
18
|
+
if (req.rawBody && req.rawBody.byteLength !== undefined) {
|
|
19
|
+
try {
|
|
20
|
+
const decoder = new TextDecoder();
|
|
21
|
+
const text = decoder.decode(req.rawBody);
|
|
22
|
+
|
|
23
|
+
const contentType =
|
|
24
|
+
(req.headers && req.headers["content-type"]) ||
|
|
25
|
+
(req.headers && req.headers["Content-Type"]) ||
|
|
26
|
+
"";
|
|
27
|
+
|
|
28
|
+
if (contentType.includes("application/json")) {
|
|
29
|
+
req.body = text ? JSON.parse(text) : {};
|
|
30
|
+
} else if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
31
|
+
req.body = Object.fromEntries(new URLSearchParams(text));
|
|
32
|
+
} else {
|
|
33
|
+
req.body = text;
|
|
34
|
+
}
|
|
35
|
+
} catch (e) {
|
|
36
|
+
req.body = {};
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
req.body = {};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ===============================
|
|
43
|
+
|
|
18
44
|
const isSuspend = (err) => {
|
|
19
45
|
const msg = err && (err.message || String(err));
|
|
20
46
|
return msg && (msg.includes("__SUSPEND__") || msg.includes("SUSPEND"));
|
|
@@ -25,9 +51,7 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
25
51
|
|
|
26
52
|
if (result && typeof result.then === 'function') {
|
|
27
53
|
result.then(
|
|
28
|
-
(data) =>
|
|
29
|
-
t._finish_request(requestId, data);
|
|
30
|
-
},
|
|
54
|
+
(data) => t._finish_request(requestId, data),
|
|
31
55
|
(err) => {
|
|
32
56
|
if (isSuspend(err)) return;
|
|
33
57
|
t._finish_request(requestId, { error: err.message || String(err) });
|
|
@@ -54,10 +78,8 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
54
78
|
}
|
|
55
79
|
};
|
|
56
80
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
env: t.loadEnv ? t.loadEnv() : {}
|
|
60
|
-
};
|
|
81
|
+
// Titan Environment API
|
|
82
|
+
t.env = t.loadEnv ? t.loadEnv() : {};
|
|
61
83
|
|
|
62
84
|
// Async Proxy Creator
|
|
63
85
|
function createAsyncOp(op) {
|
|
@@ -73,8 +95,7 @@ if (!globalThis.__TITAN_CORE_LOADED__) {
|
|
|
73
95
|
}
|
|
74
96
|
|
|
75
97
|
throw new Error(
|
|
76
|
-
`[Titan Error] Accessed '${String(prop)}' without drift(). `
|
|
77
|
-
`Fix: const res = drift(t.fetch(...));`
|
|
98
|
+
`[Titan Error] Accessed '${String(prop)}' without drift(). `
|
|
78
99
|
);
|
|
79
100
|
}
|
|
80
101
|
});
|