@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.
Files changed (44) hide show
  1. package/index.js +7 -12
  2. package/package.json +1 -1
  3. package/templates/js/server/Cargo.toml +19 -1
  4. package/templates/js/server/src/action_management.rs +159 -177
  5. package/templates/js/server/src/errors.rs +10 -10
  6. package/templates/js/server/src/extensions/builtin.rs +66 -165
  7. package/templates/js/server/src/extensions/external.rs +1 -6
  8. package/templates/js/server/src/extensions/mod.rs +136 -62
  9. package/templates/js/server/src/extensions/titan_core.js +200 -186
  10. package/templates/js/server/src/fast_path.rs +654 -0
  11. package/templates/js/server/src/main.rs +555 -406
  12. package/templates/js/server/src/runtime.rs +97 -80
  13. package/templates/js/server/src/utils.rs +32 -33
  14. package/templates/js/titan/dev.js +2 -2
  15. package/templates/js/titan/error-box.js +10 -1
  16. package/templates/ts/server/Cargo.toml +19 -1
  17. package/templates/ts/server/src/action_management.rs +159 -177
  18. package/templates/ts/server/src/errors.rs +10 -10
  19. package/templates/ts/server/src/extensions/builtin.rs +66 -165
  20. package/templates/ts/server/src/extensions/external.rs +1 -6
  21. package/templates/ts/server/src/extensions/mod.rs +136 -62
  22. package/templates/ts/server/src/extensions/titan_core.js +200 -186
  23. package/templates/ts/server/src/fast_path.rs +654 -0
  24. package/templates/ts/server/src/main.rs +555 -406
  25. package/templates/ts/server/src/runtime.rs +97 -80
  26. package/templates/ts/server/src/utils.rs +32 -33
  27. package/titanpl-sdk/package.json +1 -1
  28. package/titanpl-sdk/templates/app/t.native.d.ts +1983 -0
  29. package/titanpl-sdk/templates/app/t.native.js +39 -0
  30. package/titanpl-sdk/templates/server/Cargo.toml +19 -1
  31. package/titanpl-sdk/templates/server/src/action_management.rs +159 -177
  32. package/titanpl-sdk/templates/server/src/errors.rs +10 -10
  33. package/titanpl-sdk/templates/server/src/extensions/builtin.rs +66 -165
  34. package/titanpl-sdk/templates/server/src/extensions/external.rs +11 -86
  35. package/titanpl-sdk/templates/server/src/extensions/mod.rs +136 -62
  36. package/titanpl-sdk/templates/server/src/extensions/titan_core.js +200 -186
  37. package/titanpl-sdk/templates/server/src/fast_path.rs +654 -0
  38. package/titanpl-sdk/templates/server/src/main.rs +555 -406
  39. package/titanpl-sdk/templates/server/src/runtime.rs +97 -80
  40. package/titanpl-sdk/templates/server/src/utils.rs +32 -33
  41. package/templates/rust-js/server/Cargo.lock +0 -2869
  42. package/templates/rust-ts/server/Cargo.lock +0 -2869
  43. package/titanpl-sdk/templates/app/titan.d.ts +0 -87
  44. 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
- // app/titan.d.ts (JS typing contract)
577
+ // ----------------------------------------------------------
578
+ // 3. Update app/ with common files (t.native.js, definitions)
579
+ // ----------------------------------------------------------
578
580
  const appDir = path.join(root, "app");
579
- const templatesDts = path.join(templatesRoot, "app", "titan.d.ts");
580
- const commonDts = path.join(commonRoot, "app", "titan.d.ts");
581
+ const commonApp = path.join(commonRoot, "app");
581
582
 
582
- const finalDtsSrc = fs.existsSync(templatesDts) ? templatesDts : (fs.existsSync(commonDts) ? commonDts : null);
583
- const destDts = path.join(appDir, "titan.d.ts");
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.0",
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
- use std::collections::HashMap;
2
- use std::env;
3
- use std::path::{Path, PathBuf};
4
- use serde::Deserialize;
5
- use serde_json::Value;
6
-
7
- /// Route configuration (loaded from routes.json)
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
- // ACTION DIRECTORY RESOLUTION
24
- // -------------------------
25
-
26
- pub fn resolve_actions_dir() -> PathBuf {
27
- // Respect explicit override first
28
- if let Ok(override_dir) = env::var("TITAN_ACTIONS_DIR") {
29
- return PathBuf::from(override_dir);
30
- }
31
-
32
- // Production container layout
33
- if Path::new("/app/actions").exists() {
34
- return PathBuf::from("/app/actions");
35
- }
36
-
37
- // Try to walk up from the executing binary to discover `<...>/server/src/actions`
38
- if let Ok(exe) = std::env::current_exe() {
39
- if let Some(parent) = exe.parent() {
40
- if let Some(target_dir) = parent.parent() {
41
- if let Some(server_dir) = target_dir.parent() {
42
- let candidate = server_dir.join("src").join("actions");
43
- if candidate.exists() {
44
- return candidate;
45
- }
46
- let candidate2 = server_dir.join("actions");
47
- if candidate2.exists() {
48
- return candidate2;
49
- }
50
- }
51
- }
52
- }
53
- }
54
-
55
- // Fall back to local ./src/actions
56
- PathBuf::from("./src/actions")
57
- }
58
-
59
- /// Try to find the directory that contains compiled action bundles.
60
- pub fn find_actions_dir(project_root: &PathBuf) -> Option<PathBuf> {
61
- let candidates = [
62
- project_root.join("server").join("src").join("actions"),
63
- project_root.join("server").join("actions"),
64
- project_root.join("app").join("actions"),
65
- project_root.join("actions"),
66
-
67
- project_root.join("..").join("server").join("actions"),
68
- PathBuf::from("/app").join("actions"),
69
- PathBuf::from("actions"),
70
- ];
71
-
72
- for p in &candidates {
73
- if p.exists() && p.is_dir() {
74
- return Some(p.clone());
75
- }
76
- }
77
-
78
- None
79
- }
80
-
81
- // Dynamic Matcher (Core Logic)
82
-
83
- pub fn match_dynamic_route(
84
- method: &str,
85
- path: &str,
86
- routes: &[DynamicRoute],
87
- ) -> Option<(String, HashMap<String, String>)> {
88
- let path_segments: Vec<&str> =
89
- path.trim_matches('/').split('/').collect();
90
-
91
- for route in routes {
92
- if route.method != method {
93
- continue;
94
- }
95
-
96
- let pattern_segments: Vec<&str> =
97
- route.pattern.trim_matches('/').split('/').collect();
98
-
99
- if pattern_segments.len() != path_segments.len() {
100
- continue;
101
- }
102
-
103
- let mut params = HashMap::new();
104
- let mut matched = true;
105
-
106
- for (pat, val) in pattern_segments.iter().zip(path_segments.iter()) {
107
- if pat.starts_with(':') {
108
- let inner = &pat[1..];
109
-
110
- let (name, ty) = inner
111
- .split_once('<')
112
- .map(|(n, t)| (n, t.trim_end_matches('>')))
113
- .unwrap_or((inner, "string"));
114
-
115
- let valid = match ty {
116
- "number" => val.parse::<i64>().is_ok(),
117
- "string" => true,
118
- _ => false,
119
- };
120
-
121
- if !valid {
122
- matched = false;
123
- break;
124
- }
125
-
126
- params.insert(name.to_string(), (*val).to_string());
127
- } else if pat != val {
128
- matched = false;
129
- break;
130
- }
131
- }
132
-
133
- if matched {
134
- return Some((route.action.clone(), params));
135
- }
136
- }
137
-
138
- None
139
- }
140
-
141
- // -------------------------
142
- // ACTION SCANNING
143
- // -------------------------
144
-
145
- pub fn scan_actions(root: &PathBuf) -> HashMap<String, PathBuf> {
146
- let mut map = HashMap::new();
147
-
148
- // Locate actions dir - Priority: project root relative paths
149
- let dir = match find_actions_dir(root) {
150
- Some(d) => d,
151
- None => {
152
- let ad = resolve_actions_dir();
153
- if ad.exists() { ad } else { return map; }
154
- }
155
- };
156
-
157
- // Scanning actions
158
- if let Ok(entries) = std::fs::read_dir(dir) {
159
- for entry in entries.flatten() {
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
- use v8::JsError;
2
-
3
- // A helper to Format v8 Errors
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
+ }