@ezetgalaxy/titan 26.13.9 → 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 (50) hide show
  1. package/index.js +7 -12
  2. package/package.json +1 -1
  3. package/templates/common/app/t.native.d.ts +0 -82
  4. package/templates/extension/jsconfig.json +2 -1
  5. package/templates/js/jsconfig.json +2 -1
  6. package/templates/js/server/Cargo.toml +19 -1
  7. package/templates/js/server/src/action_management.rs +159 -177
  8. package/templates/js/server/src/errors.rs +10 -10
  9. package/templates/js/server/src/extensions/builtin.rs +66 -165
  10. package/templates/js/server/src/extensions/external.rs +11 -86
  11. package/templates/js/server/src/extensions/mod.rs +136 -62
  12. package/templates/js/server/src/extensions/titan_core.js +200 -186
  13. package/templates/js/server/src/fast_path.rs +654 -0
  14. package/templates/js/server/src/main.rs +555 -406
  15. package/templates/js/server/src/runtime.rs +97 -80
  16. package/templates/js/server/src/utils.rs +32 -33
  17. package/templates/js/titan/dev.js +2 -2
  18. package/templates/js/titan/error-box.js +10 -1
  19. package/templates/rust-js/jsconfig.json +2 -1
  20. package/templates/rust-ts/tsconfig.json +2 -1
  21. package/templates/ts/server/Cargo.toml +19 -1
  22. package/templates/ts/server/src/action_management.rs +159 -177
  23. package/templates/ts/server/src/errors.rs +10 -10
  24. package/templates/ts/server/src/extensions/builtin.rs +66 -165
  25. package/templates/ts/server/src/extensions/external.rs +11 -86
  26. package/templates/ts/server/src/extensions/mod.rs +136 -62
  27. package/templates/ts/server/src/extensions/titan_core.js +200 -186
  28. package/templates/ts/server/src/fast_path.rs +654 -0
  29. package/templates/ts/server/src/main.rs +555 -406
  30. package/templates/ts/server/src/runtime.rs +97 -80
  31. package/templates/ts/server/src/utils.rs +32 -33
  32. package/templates/ts/tsconfig.json +2 -1
  33. package/titanpl-sdk/package.json +1 -1
  34. package/titanpl-sdk/templates/app/t.native.d.ts +1983 -0
  35. package/titanpl-sdk/templates/app/t.native.js +39 -0
  36. package/titanpl-sdk/templates/server/Cargo.toml +19 -1
  37. package/titanpl-sdk/templates/server/src/action_management.rs +159 -177
  38. package/titanpl-sdk/templates/server/src/errors.rs +10 -10
  39. package/titanpl-sdk/templates/server/src/extensions/builtin.rs +66 -165
  40. package/titanpl-sdk/templates/server/src/extensions/external.rs +11 -86
  41. package/titanpl-sdk/templates/server/src/extensions/mod.rs +136 -62
  42. package/titanpl-sdk/templates/server/src/extensions/titan_core.js +200 -186
  43. package/titanpl-sdk/templates/server/src/fast_path.rs +654 -0
  44. package/titanpl-sdk/templates/server/src/main.rs +555 -406
  45. package/titanpl-sdk/templates/server/src/runtime.rs +97 -80
  46. package/titanpl-sdk/templates/server/src/utils.rs +32 -33
  47. package/templates/rust-js/server/Cargo.lock +0 -2869
  48. package/templates/rust-ts/server/Cargo.lock +0 -2869
  49. package/titanpl-sdk/templates/app/titan.d.ts +0 -87
  50. 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.13.9",
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",
@@ -325,14 +325,6 @@ export const time: typeof t.time;
325
325
  */
326
326
  export const url: typeof t.url;
327
327
 
328
- /**
329
- * HTTP response builder for controlling status codes, headers, and content types.
330
- *
331
- * Re-exported from the `t` global for module-style imports.
332
- * @see {@link TitanCore.ResponseModule} for full documentation.
333
- */
334
- export const response: typeof t.response;
335
-
336
328
  /**
337
329
  * Runtime validation utilities.
338
330
  *
@@ -1046,15 +1038,6 @@ declare global {
1046
1038
 
1047
1039
  /**
1048
1040
 
1049
-
1050
- /**
1051
- * HTTP response builder utilities.
1052
- * @see https://www.npmjs.com/package/@titanpl/13-titan-core — TitanCore Valid Extension
1053
- */
1054
- response: TitanCore.ResponseModule;
1055
-
1056
-
1057
-
1058
1041
  /**
1059
1042
  * Runtime validation utilities.
1060
1043
  *
@@ -1994,71 +1977,6 @@ declare global {
1994
1977
  SearchParams: any;
1995
1978
  }
1996
1979
 
1997
-
1998
-
1999
- interface ResponseModule {
2000
-
2001
- /**
2002
- * Return a JSON response.
2003
- * Body is automatically JSON.stringify-ed.
2004
- *
2005
- * @example
2006
- * ```js
2007
- * return t.response.json({ ok: true });
2008
- * ```
2009
- */
2010
- json(
2011
- data: any,
2012
- status?: number,
2013
- extraHeaders?: Record<string, string>
2014
- ): TitanResponse;
2015
-
2016
- /**
2017
- * Return a plain-text response.
2018
- * Content-Type: text/plain
2019
- *
2020
- * @example
2021
- * ```js
2022
- * return t.response.text("Hello World");
2023
- * ```
2024
- */
2025
- text(
2026
- content: string,
2027
- status?: number,
2028
- extraHeaders?: Record<string, string>
2029
- ): TitanResponse;
2030
-
2031
- /**
2032
- * Return an HTML response.
2033
- * Content-Type: text/html
2034
- *
2035
- * @example
2036
- * ```js
2037
- * return t.response.html("<h1>Hello</h1>");
2038
- * ```
2039
- */
2040
- html(
2041
- content: string,
2042
- status?: number,
2043
- extraHeaders?: Record<string, string>
2044
- ): TitanResponse;
2045
-
2046
- /**
2047
- * Return a redirect response.
2048
- * Defaults to HTTP 302.
2049
- *
2050
- * @example
2051
- * ```js
2052
- * return t.response.redirect("/login");
2053
- * ```
2054
- */
2055
- redirect(
2056
- url: string,
2057
- status?: number,
2058
- extraHeaders?: Record<string, string>
2059
- ): TitanResponse;
2060
- }
2061
-
2062
1980
  }
2063
1981
  }
2064
1982
 
@@ -8,6 +8,7 @@
8
8
  },
9
9
  "include": [
10
10
  "index.js",
11
- "node_modules/titan-sdk/index.d.ts"
11
+ "node_modules/titan-sdk/index.d.ts",
12
+ "node_modules/**/titan-ext.d.ts"
12
13
  ]
13
14
  }
@@ -21,6 +21,7 @@
21
21
  },
22
22
  "include": [
23
23
  "app/**/*",
24
- "titan/**/*"
24
+ "titan/**/*",
25
+ "node_modules/**/titan-ext.d.ts"
25
26
  ]
26
27
  }
@@ -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
+ }