@ezetgalaxy/titan 25.15.4 → 25.15.5

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
@@ -11,10 +11,10 @@
11
11
  # Notice
12
12
 
13
13
  ✅ **Production mode is ready**
14
- 💙 **Enjoy development mode `tit dev`**
14
+ 💙 **Enjoy development mode `titan dev`**
15
15
  ✅ **No more `globalThis` required**
16
16
  💟 **Website for titan docs: https://titan-docs-ez.vercel.app/docs**
17
-
17
+ 🚀 **CLI: `titan` is now the canonical command. `tit` remains supported as an alias.**
18
18
 
19
19
  ---
20
20
 
@@ -94,9 +94,9 @@ npm install -g @ezetgalaxy/titan
94
94
  ### Create a new project
95
95
 
96
96
  ```bash
97
- tit init my-app
97
+ titan init my-app
98
98
  cd my-app
99
- tit dev
99
+ titan dev
100
100
  ```
101
101
 
102
102
  Titan will:
@@ -119,7 +119,7 @@ npm install -g @ezetgalaxy/titan@latest
119
119
  * Then
120
120
 
121
121
  ```bash
122
- tit update
122
+ titan update
123
123
  ```
124
124
  * ``tit update`` will update and add new features in your Titan project
125
125
 
@@ -179,7 +179,7 @@ This object is:
179
179
 
180
180
  ### 🔥 Developer Experience
181
181
 
182
- * Hot reload dev server (`tit dev`)
182
+ * Hot reload dev server (`titan dev`)
183
183
  * Automatic rebundling of actions
184
184
  * Automatic Rust server restart
185
185
  * Colored request logs
package/index.js CHANGED
@@ -8,23 +8,73 @@ import { fileURLToPath } from "url";
8
8
  const __filename = fileURLToPath(import.meta.url);
9
9
  const __dirname = path.dirname(__filename);
10
10
 
11
- /* Colors */
11
+ /* -------------------------------------------------------
12
+ * Colors (MUST be defined before usage)
13
+ * ----------------------------------------------------- */
12
14
  const cyan = (t) => `\x1b[36m${t}\x1b[0m`;
13
15
  const green = (t) => `\x1b[32m${t}\x1b[0m`;
14
16
  const yellow = (t) => `\x1b[33m${t}\x1b[0m`;
15
17
  const red = (t) => `\x1b[31m${t}\x1b[0m`;
16
18
  const bold = (t) => `\x1b[1m${t}\x1b[0m`;
17
19
 
20
+ /* -------------------------------------------------------
21
+ * Invocation detection (tit vs titan)
22
+ * ----------------------------------------------------- */
23
+ function wasInvokedAsTit() {
24
+ // Case 1: direct binary (global / local)
25
+ const argv = process.argv.map(a => a.toLowerCase());
26
+ const direct =
27
+ argv[1]?.endsWith("tit") ||
28
+ argv[1]?.endsWith("tit.cmd") ||
29
+ argv[1]?.endsWith("tit.ps1");
30
+
31
+ if (direct) return true;
32
+
33
+ // Case 2: npx / npm exec
34
+ const npmArgvRaw = process.env.npm_config_argv;
35
+ if (!npmArgvRaw) return false;
36
+
37
+ try {
38
+ const npmArgv = JSON.parse(npmArgvRaw);
39
+
40
+ // npm stores original command here
41
+ return npmArgv.original?.includes("tit");
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+
47
+ const isTitAlias = wasInvokedAsTit();
48
+
49
+ if (isTitAlias) {
50
+ console.log(
51
+ yellow(
52
+ "[Notice] `tit` is deprecated. Please use `titan` instead.\n" +
53
+ " `tit` will continue to work for now."
54
+ )
55
+ );
56
+ }
57
+
58
+
59
+
60
+
61
+ /* -------------------------------------------------------
62
+ * Args
63
+ * ----------------------------------------------------- */
18
64
  const args = process.argv.slice(2);
19
65
  const cmd = args[0];
20
66
 
21
- /* Titan version (read from package.json) */
67
+ /* -------------------------------------------------------
68
+ * Titan version
69
+ * ----------------------------------------------------- */
22
70
  const pkg = JSON.parse(
23
71
  fs.readFileSync(path.join(__dirname, "package.json"), "utf8")
24
72
  );
25
73
  const TITAN_VERSION = pkg.version;
26
74
 
27
- /* Safe copy directory */
75
+ /* -------------------------------------------------------
76
+ * Utils
77
+ * ----------------------------------------------------- */
28
78
  function copyDir(src, dest) {
29
79
  fs.mkdirSync(dest, { recursive: true });
30
80
 
@@ -40,21 +90,27 @@ function copyDir(src, dest) {
40
90
  }
41
91
  }
42
92
 
43
- /* HELP */
93
+ /* -------------------------------------------------------
94
+ * HELP
95
+ * ----------------------------------------------------- */
44
96
  function help() {
45
97
  console.log(`
46
98
  ${bold(cyan("Titan Planet"))} v${TITAN_VERSION}
47
99
 
48
- ${green("tit init <project>")} Create new Titan project
49
- ${green("tit dev")} Dev mode (hot reload)
50
- ${green("tit build")} Build production Rust server
51
- ${green("tit start")} Start production binary
52
- ${green("tit update")} Update Titan engine
53
- ${green("tit --version")} Show Titan CLI version
100
+ ${green("titan init <project>")} Create new Titan project
101
+ ${green("titan dev")} Dev mode (hot reload)
102
+ ${green("titan build")} Build production Rust server
103
+ ${green("titan start")} Start production binary
104
+ ${green("titan update")} Update Titan engine
105
+ ${green("titan --version")} Show Titan CLI version
106
+
107
+ ${yellow("Note: `tit` is supported as a legacy alias.")}
54
108
  `);
55
109
  }
56
110
 
57
- /* INIT PROJECT */
111
+ /* -------------------------------------------------------
112
+ * INIT
113
+ * ----------------------------------------------------- */
58
114
  function initProject(name) {
59
115
  if (!name) return console.log(red("Usage: tit init <project>"));
60
116
 
@@ -92,7 +148,9 @@ Next steps:
92
148
  `);
93
149
  }
94
150
 
95
- /* BUNDLER (absolute path, Railway-safe) */
151
+ /* -------------------------------------------------------
152
+ * BUNDLER
153
+ * ----------------------------------------------------- */
96
154
  function runBundler(root) {
97
155
  const bundler = path.join(root, "titan", "bundle.js");
98
156
 
@@ -104,7 +162,9 @@ function runBundler(root) {
104
162
  execSync(`node "${bundler}"`, { stdio: "inherit" });
105
163
  }
106
164
 
107
- /* DEV SERVER — HOT RELOAD */
165
+ /* -------------------------------------------------------
166
+ * DEV SERVER
167
+ * ----------------------------------------------------- */
108
168
  async function devServer() {
109
169
  const root = process.cwd();
110
170
  console.log(cyan("Titan Dev Mode — Hot Reload Enabled"));
@@ -180,8 +240,9 @@ async function devServer() {
180
240
  });
181
241
  }
182
242
 
183
- /* PRODUCTION BUILD */
184
- // BUILD RELEASE — PRODUCTION READY
243
+ /* -------------------------------------------------------
244
+ * BUILD
245
+ * ----------------------------------------------------- */
185
246
  function buildProd() {
186
247
  console.log(cyan("Titan: Building production output..."));
187
248
 
@@ -231,9 +292,9 @@ function buildProd() {
231
292
  console.log(green("✔ Titan production build complete!"));
232
293
  }
233
294
 
234
-
235
-
236
- /* START PRODUCTION BINARY */
295
+ /* -------------------------------------------------------
296
+ * START
297
+ * ----------------------------------------------------- */
237
298
  function startProd() {
238
299
  const isWin = process.platform === "win32";
239
300
  const bin = isWin ? "titan-server.exe" : "titan-server";
@@ -242,7 +303,9 @@ function startProd() {
242
303
  execSync(`"${exe}"`, { stdio: "inherit" });
243
304
  }
244
305
 
245
- /* UPDATE TITAN */
306
+ /* -------------------------------------------------------
307
+ * UPDATE
308
+ * ----------------------------------------------------- */
246
309
  function updateTitan() {
247
310
  const root = process.cwd();
248
311
  const projectTitan = path.join(root, "titan");
@@ -305,36 +368,20 @@ function updateTitan() {
305
368
 
306
369
  console.log(bold(green("✔ Titan update complete")));
307
370
  }
308
-
309
-
310
- /* ROUTER */
371
+ /* -------------------------------------------------------
372
+ * ROUTER
373
+ * ----------------------------------------------------- */
311
374
  switch (cmd) {
312
- case "init":
313
- initProject(args[1]);
314
- break;
315
-
316
- case "dev":
317
- devServer();
318
- break;
319
-
320
- case "build":
321
- buildProd();
322
- break;
323
-
324
- case "start":
325
- startProd();
326
- break;
327
-
328
- case "update":
329
- updateTitan();
330
- break;
331
-
375
+ case "init": initProject(args[1]); break;
376
+ case "dev": devServer(); break;
377
+ case "build": buildProd(); break;
378
+ case "start": startProd(); break;
379
+ case "update": updateTitan(); break;
332
380
  case "--version":
333
381
  case "-v":
334
382
  case "version":
335
- console.log(green(`Titan v${TITAN_VERSION}`));
383
+ console.log(cyan(`Titan v${TITAN_VERSION}`));
336
384
  break;
337
-
338
385
  default:
339
386
  help();
340
387
  }
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@ezetgalaxy/titan",
3
- "version": "25.15.4",
3
+ "version": "25.15.5",
4
4
  "description": "JavaScript backend framework that compiles your JS into a Rust + Axum server.",
5
5
  "license": "ISC",
6
6
  "author": "ezetgalaxy",
7
7
  "type": "module",
8
8
  "main": "index.js",
9
9
  "bin": {
10
- "tit": "./index.js"
10
+ "tit": "./index.js",
11
+ "titan": "./index.js"
11
12
  },
12
13
  "files": [
13
14
  "index.js",
@@ -19,7 +19,7 @@ COPY . .
19
19
  RUN npm install
20
20
 
21
21
  # Build Titan metadata + bundle JS actions
22
- RUN tit build
22
+ RUN titan build
23
23
 
24
24
  # Build Rust binary
25
25
  RUN cd server && cargo build --release
@@ -1,62 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import esbuild from "esbuild";
4
-
5
- const root = process.cwd();
6
- const actionsDir = path.join(root, "app", "actions");
7
- const outDir = path.join(root, "server", "actions");
8
-
9
- export async function bundle() {
10
- console.log("[Titan] Bundling actions...");
11
-
12
- fs.mkdirSync(outDir, { recursive: true });
13
-
14
- // Clean old bundles
15
- for (const file of fs.readdirSync(outDir)) {
16
- fs.unlinkSync(path.join(outDir, file));
17
- }
18
-
19
- const files = fs.readdirSync(actionsDir).filter(f => f.endsWith(".js"));
20
-
21
- for (const file of files) {
22
- const actionName = path.basename(file, ".js");
23
-
24
- const entry = path.join(actionsDir, file);
25
-
26
- // Rust runtime expects `.jsbundle` extension — consistent with previous design
27
- const outfile = path.join(outDir, file.replace(".js", ".jsbundle"));
28
-
29
- console.log(`[Titan] Bundling ${entry} → ${outfile}`);
30
-
31
- await esbuild.build({
32
- entryPoints: [entry],
33
- outfile,
34
- bundle: true,
35
- format: "iife",
36
- globalName: "__titan_exports",
37
- platform: "neutral",
38
- target: "es2020",
39
-
40
- footer: {
41
- js: `
42
- (function () {
43
- const fn =
44
- __titan_exports["${actionName}"] ||
45
- __titan_exports.default;
46
-
47
- if (typeof fn !== "function") {
48
- throw new Error("[Titan] Action '${actionName}' not found or not a function");
49
- }
50
-
51
- globalThis["${actionName}"] = fn;
52
- })();
53
- `
54
- }
55
- });
56
-
57
-
58
-
59
- }
60
-
61
- console.log("[Titan] Bundling finished.");
62
- }
@@ -1,67 +0,0 @@
1
- import chokidar from "chokidar";
2
- import { spawn, execSync } from "child_process";
3
- import path from "path";
4
- import { fileURLToPath } from "url";
5
- import { bundle } from "./bundle.js";
6
-
7
- // Required for __dirname in ES modules
8
- const __filename = fileURLToPath(import.meta.url);
9
- const __dirname = path.dirname(__filename);
10
-
11
- let serverProcess = null;
12
-
13
- function startRustServer() {
14
- if (serverProcess) {
15
- serverProcess.kill();
16
- }
17
-
18
- const serverPath = path.join(process.cwd(), "server");
19
-
20
- serverProcess = spawn("cargo", ["run"], {
21
- cwd: serverPath,
22
- stdio: "inherit",
23
- shell: true
24
- });
25
-
26
- serverProcess.on("close", (code) => {
27
- console.log(`[Titan] Rust server exited: ${code}`);
28
- });
29
- }
30
-
31
- async function rebuild() {
32
- console.log("[Titan] Regenerating routes.json & action_map.json...");
33
- execSync("node app/app.js", { stdio: "inherit" });
34
-
35
- console.log("[Titan] Bundling JS actions...");
36
- await bundle();
37
- }
38
-
39
- async function startDev() {
40
- console.log("[Titan] Dev mode starting...");
41
-
42
- // FIRST BUILD
43
- await rebuild();
44
- startRustServer();
45
-
46
- const watcher = chokidar.watch("app", {
47
- ignoreInitial: true
48
- });
49
-
50
- let timer = null;
51
-
52
- watcher.on("all", async (event, file) => {
53
- if (timer) clearTimeout(timer);
54
-
55
- timer = setTimeout(async () => {
56
- console.log(`[Titan] Change detected: ${file}`);
57
-
58
- await rebuild();
59
-
60
- console.log("[Titan] Restarting Rust server...");
61
- startRustServer();
62
-
63
- }, 200);
64
- });
65
- }
66
-
67
- startDev();
@@ -1,82 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { bundle } from "./bundle.js";
4
-
5
- const cyan = (t) => `\x1b[36m${t}\x1b[0m`;
6
- const green = (t) => `\x1b[32m${t}\x1b[0m`;
7
-
8
- const routes = {};
9
- const dynamicRoutes = {};
10
- const actionMap = {};
11
-
12
- function addRoute(method, route) {
13
- const key = `${method.toUpperCase()}:${route}`;
14
-
15
-
16
- return {
17
- reply(value) {
18
- routes[key] = {
19
- type: typeof value === "object" ? "json" : "text",
20
- value
21
- };
22
- },
23
-
24
- action(name) {
25
- if (route.includes(":")) {
26
- if (!dynamicRoutes[method]) dynamicRoutes[method] = [];
27
- dynamicRoutes[method].push({
28
- method: method.toUpperCase(),
29
- pattern: route,
30
- action: name
31
- });
32
- } else {
33
- routes[key] = {
34
- type: "action",
35
- value: name
36
- };
37
- actionMap[key] = name;
38
- }
39
- }
40
- };
41
- }
42
-
43
- const t = {
44
- get(route) {
45
- return addRoute("GET", route);
46
- },
47
-
48
- post(route) {
49
- return addRoute("POST", route);
50
- },
51
-
52
- async start(port = 3000, msg = "") {
53
- console.log(cyan("[Titan] Bundling actions..."));
54
- await bundle();
55
-
56
- const base = path.join(process.cwd(), "server");
57
- fs.mkdirSync(base, { recursive: true });
58
-
59
- fs.writeFileSync(
60
- path.join(base, "routes.json"),
61
- JSON.stringify(
62
- {
63
- __config: { port },
64
- routes,
65
- __dynamic_routes: Object.values(dynamicRoutes).flat()
66
- },
67
- null,
68
- 2
69
- )
70
- );
71
-
72
- fs.writeFileSync(
73
- path.join(base, "action_map.json"),
74
- JSON.stringify(actionMap, null, 2)
75
- );
76
-
77
- console.log(green(`Titan: routes.json + action_map.json written -> ${base}`));
78
- if (msg) console.log(cyan(msg));
79
- }
80
- };
81
-
82
- export default t;