@ezetgalaxy/titan 26.14.0 → 26.14.1
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/index.js +7 -12
- package/package.json +1 -1
- package/templates/js/server/Cargo.toml +19 -1
- package/templates/js/server/src/action_management.rs +159 -177
- package/templates/js/server/src/errors.rs +10 -10
- package/templates/js/server/src/extensions/builtin.rs +66 -165
- package/templates/js/server/src/extensions/external.rs +1 -6
- package/templates/js/server/src/extensions/mod.rs +136 -62
- package/templates/js/server/src/extensions/titan_core.js +200 -186
- package/templates/js/server/src/fast_path.rs +654 -0
- package/templates/js/server/src/main.rs +555 -406
- package/templates/js/server/src/runtime.rs +97 -80
- package/templates/js/server/src/utils.rs +32 -33
- package/templates/js/titan/dev.js +2 -2
- package/templates/js/titan/error-box.js +10 -1
- package/templates/ts/server/Cargo.toml +19 -1
- package/templates/ts/server/src/action_management.rs +159 -177
- package/templates/ts/server/src/errors.rs +10 -10
- package/templates/ts/server/src/extensions/builtin.rs +66 -165
- package/templates/ts/server/src/extensions/external.rs +1 -6
- package/templates/ts/server/src/extensions/mod.rs +136 -62
- package/templates/ts/server/src/extensions/titan_core.js +200 -186
- package/templates/ts/server/src/fast_path.rs +654 -0
- package/templates/ts/server/src/main.rs +555 -406
- package/templates/ts/server/src/runtime.rs +97 -80
- package/templates/ts/server/src/utils.rs +32 -33
- package/titanpl-sdk/package.json +1 -1
- package/titanpl-sdk/templates/app/t.native.d.ts +1983 -0
- package/titanpl-sdk/templates/app/t.native.js +39 -0
- package/titanpl-sdk/templates/server/Cargo.toml +19 -1
- package/titanpl-sdk/templates/server/src/action_management.rs +159 -177
- package/titanpl-sdk/templates/server/src/errors.rs +10 -10
- package/titanpl-sdk/templates/server/src/extensions/builtin.rs +66 -165
- package/titanpl-sdk/templates/server/src/extensions/external.rs +11 -86
- package/titanpl-sdk/templates/server/src/extensions/mod.rs +136 -62
- package/titanpl-sdk/templates/server/src/extensions/titan_core.js +200 -186
- package/titanpl-sdk/templates/server/src/fast_path.rs +654 -0
- package/titanpl-sdk/templates/server/src/main.rs +555 -406
- package/titanpl-sdk/templates/server/src/runtime.rs +97 -80
- package/titanpl-sdk/templates/server/src/utils.rs +32 -33
- package/templates/rust-js/server/Cargo.lock +0 -2869
- package/templates/rust-ts/server/Cargo.lock +0 -2869
- package/titanpl-sdk/templates/app/titan.d.ts +0 -87
- package/titanpl-sdk/templates/index.d.ts +0 -249
package/index.js
CHANGED
|
@@ -574,20 +574,15 @@ export function updateTitan() {
|
|
|
574
574
|
}
|
|
575
575
|
}
|
|
576
576
|
|
|
577
|
-
//
|
|
577
|
+
// ----------------------------------------------------------
|
|
578
|
+
// 3. Update app/ with common files (t.native.js, definitions)
|
|
579
|
+
// ----------------------------------------------------------
|
|
578
580
|
const appDir = path.join(root, "app");
|
|
579
|
-
const
|
|
580
|
-
const commonDts = path.join(commonRoot, "app", "titan.d.ts");
|
|
581
|
+
const commonApp = path.join(commonRoot, "app");
|
|
581
582
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
if (finalDtsSrc) {
|
|
586
|
-
if (!fs.existsSync(appDir)) {
|
|
587
|
-
fs.mkdirSync(appDir);
|
|
588
|
-
}
|
|
589
|
-
fs.copyFileSync(finalDtsSrc, destDts);
|
|
590
|
-
console.log(green("✔ Updated app/titan.d.ts"));
|
|
583
|
+
if (fs.existsSync(commonApp)) {
|
|
584
|
+
copyDir(commonApp, appDir);
|
|
585
|
+
console.log(green("✔ Updated app/ common files"));
|
|
591
586
|
}
|
|
592
587
|
|
|
593
588
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ezetgalaxy/titan",
|
|
3
|
-
"version": "26.14.
|
|
3
|
+
"version": "26.14.1",
|
|
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",
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
[package]
|
|
3
2
|
name = "titan-server"
|
|
4
3
|
version = "0.1.0"
|
|
@@ -30,3 +29,22 @@ dashmap = "6.1.0"
|
|
|
30
29
|
bytes = "1.11.0"
|
|
31
30
|
smallvec = "1.15.1"
|
|
32
31
|
num_cpus = "1.17.0"
|
|
32
|
+
|
|
33
|
+
# Performance: Global Allocator
|
|
34
|
+
mimalloc = { version = "0.1", default-features = false }
|
|
35
|
+
|
|
36
|
+
# Static Analysis: OXC (Zero runtime cost, used at startup)
|
|
37
|
+
oxc = { version = "0.108", features = ["semantic"] }
|
|
38
|
+
|
|
39
|
+
# Release Profile
|
|
40
|
+
[profile.release]
|
|
41
|
+
opt-level = 3
|
|
42
|
+
lto = "fat"
|
|
43
|
+
codegen-units = 1
|
|
44
|
+
panic = "abort"
|
|
45
|
+
strip = true
|
|
46
|
+
|
|
47
|
+
# Dev Profile
|
|
48
|
+
[profile.dev]
|
|
49
|
+
opt-level = 0
|
|
50
|
+
debug = 1
|
|
@@ -1,177 +1,159 @@
|
|
|
1
|
-
|
|
2
|
-
use std::
|
|
3
|
-
use std::
|
|
4
|
-
use
|
|
5
|
-
use
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
#[derive(Debug, Deserialize, Clone)]
|
|
9
|
-
pub struct RouteVal {
|
|
10
|
-
pub r#type: String,
|
|
11
|
-
#[serde(alias = "target")]
|
|
12
|
-
pub value: Value,
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
#[derive(Debug, Deserialize, Clone)]
|
|
16
|
-
pub struct DynamicRoute {
|
|
17
|
-
pub method: String,
|
|
18
|
-
pub pattern: String,
|
|
19
|
-
pub action: String,
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
let path = entry.path();
|
|
161
|
-
if !path.is_file() { continue; }
|
|
162
|
-
|
|
163
|
-
let ext = path.extension().and_then(|s| s.to_str()).unwrap_or("");
|
|
164
|
-
if ext != "js" && ext != "jsbundle" {
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
let file_stem = path.file_stem().and_then(|s| s.to_str()).unwrap_or("");
|
|
169
|
-
if file_stem.is_empty() { continue; }
|
|
170
|
-
|
|
171
|
-
// Found action
|
|
172
|
-
map.insert(file_stem.to_string(), path);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
map
|
|
177
|
-
}
|
|
1
|
+
|
|
2
|
+
use std::collections::HashMap;
|
|
3
|
+
use std::env;
|
|
4
|
+
use std::path::{Path, PathBuf};
|
|
5
|
+
use serde::Deserialize;
|
|
6
|
+
use serde_json::Value;
|
|
7
|
+
|
|
8
|
+
#[derive(Debug, Deserialize, Clone)]
|
|
9
|
+
pub struct RouteVal {
|
|
10
|
+
pub r#type: String,
|
|
11
|
+
#[serde(alias = "target")]
|
|
12
|
+
pub value: Value,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
#[derive(Debug, Deserialize, Clone)]
|
|
16
|
+
pub struct DynamicRoute {
|
|
17
|
+
pub method: String,
|
|
18
|
+
pub pattern: String,
|
|
19
|
+
pub action: String,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
pub fn resolve_actions_dir() -> PathBuf {
|
|
23
|
+
if let Ok(override_dir) = env::var("TITAN_ACTIONS_DIR") {
|
|
24
|
+
return PathBuf::from(override_dir);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if Path::new("/app/actions").exists() {
|
|
28
|
+
return PathBuf::from("/app/actions");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if let Ok(exe) = std::env::current_exe() {
|
|
32
|
+
if let Some(parent) = exe.parent() {
|
|
33
|
+
if let Some(target_dir) = parent.parent() {
|
|
34
|
+
if let Some(server_dir) = target_dir.parent() {
|
|
35
|
+
let candidate = server_dir.join("src").join("actions");
|
|
36
|
+
if candidate.exists() {
|
|
37
|
+
return candidate;
|
|
38
|
+
}
|
|
39
|
+
let candidate2 = server_dir.join("actions");
|
|
40
|
+
if candidate2.exists() {
|
|
41
|
+
return candidate2;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
PathBuf::from("./src/actions")
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
pub fn find_actions_dir(project_root: &PathBuf) -> Option<PathBuf> {
|
|
52
|
+
let candidates = [
|
|
53
|
+
project_root.join("server").join("src").join("actions"),
|
|
54
|
+
project_root.join("server").join("actions"),
|
|
55
|
+
project_root.join("app").join("actions"),
|
|
56
|
+
project_root.join("actions"),
|
|
57
|
+
|
|
58
|
+
project_root.join("..").join("server").join("actions"),
|
|
59
|
+
PathBuf::from("/app").join("actions"),
|
|
60
|
+
PathBuf::from("actions"),
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
for p in &candidates {
|
|
64
|
+
if p.exists() && p.is_dir() {
|
|
65
|
+
return Some(p.clone());
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
None
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
pub fn match_dynamic_route(
|
|
73
|
+
method: &str,
|
|
74
|
+
path: &str,
|
|
75
|
+
routes: &[DynamicRoute],
|
|
76
|
+
) -> Option<(String, HashMap<String, String>)> {
|
|
77
|
+
let path_segments: Vec<&str> =
|
|
78
|
+
path.trim_matches('/').split('/').collect();
|
|
79
|
+
|
|
80
|
+
for route in routes {
|
|
81
|
+
if route.method != method {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let pattern_segments: Vec<&str> =
|
|
86
|
+
route.pattern.trim_matches('/').split('/').collect();
|
|
87
|
+
|
|
88
|
+
if pattern_segments.len() != path_segments.len() {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let mut params = HashMap::new();
|
|
93
|
+
let mut matched = true;
|
|
94
|
+
|
|
95
|
+
for (pat, val) in pattern_segments.iter().zip(path_segments.iter()) {
|
|
96
|
+
if pat.starts_with(':') {
|
|
97
|
+
let inner = &pat[1..];
|
|
98
|
+
|
|
99
|
+
let (name, ty) = inner
|
|
100
|
+
.split_once('<')
|
|
101
|
+
.map(|(n, t)| (n, t.trim_end_matches('>')))
|
|
102
|
+
.unwrap_or((inner, "string"));
|
|
103
|
+
|
|
104
|
+
let valid = match ty {
|
|
105
|
+
"number" => val.parse::<i64>().is_ok(),
|
|
106
|
+
"string" => true,
|
|
107
|
+
_ => false,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
if !valid {
|
|
111
|
+
matched = false;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
params.insert(name.to_string(), (*val).to_string());
|
|
116
|
+
} else if pat != val {
|
|
117
|
+
matched = false;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if matched {
|
|
123
|
+
return Some((route.action.clone(), params));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
None
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
pub fn scan_actions(root: &PathBuf) -> HashMap<String, PathBuf> {
|
|
131
|
+
let mut map = HashMap::new();
|
|
132
|
+
|
|
133
|
+
let dir = match find_actions_dir(root) {
|
|
134
|
+
Some(d) => d,
|
|
135
|
+
None => {
|
|
136
|
+
let ad = resolve_actions_dir();
|
|
137
|
+
if ad.exists() { ad } else { return map; }
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
if let Ok(entries) = std::fs::read_dir(dir) {
|
|
142
|
+
for entry in entries.flatten() {
|
|
143
|
+
let path = entry.path();
|
|
144
|
+
if !path.is_file() { continue; }
|
|
145
|
+
|
|
146
|
+
let ext = path.extension().and_then(|s| s.to_str()).unwrap_or("");
|
|
147
|
+
if ext != "js" && ext != "jsbundle" {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let file_stem = path.file_stem().and_then(|s| s.to_str()).unwrap_or("");
|
|
152
|
+
if file_stem.is_empty() { continue; }
|
|
153
|
+
|
|
154
|
+
map.insert(file_stem.to_string(), path);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
map
|
|
159
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
pub fn format_js_error(err: JsError, action: &str) -> String {
|
|
5
|
-
format!(
|
|
6
|
-
"Action: {}\n{}",
|
|
7
|
-
action,
|
|
8
|
-
err.to_string()
|
|
9
|
-
)
|
|
10
|
-
}
|
|
1
|
+
|
|
2
|
+
use v8::JsError;
|
|
3
|
+
|
|
4
|
+
pub fn format_js_error(err: JsError, action: &str) -> String {
|
|
5
|
+
format!(
|
|
6
|
+
"Action: {}\n{}",
|
|
7
|
+
action,
|
|
8
|
+
err.to_string()
|
|
9
|
+
)
|
|
10
|
+
}
|