@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 +6 -6
- package/index.js +91 -44
- package/package.json +3 -2
- package/templates/Dockerfile +1 -1
- package/templates/titan/bundle.js +0 -62
- package/templates/titan/dev.js +0 -67
- package/templates/titan/titan.js +0 -82
package/README.md
CHANGED
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
# Notice
|
|
12
12
|
|
|
13
13
|
✅ **Production mode is ready**
|
|
14
|
-
💙 **Enjoy development mode `
|
|
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
|
-
|
|
97
|
+
titan init my-app
|
|
98
98
|
cd my-app
|
|
99
|
-
|
|
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
|
-
|
|
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 (`
|
|
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
|
-
/*
|
|
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
|
-
/*
|
|
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
|
-
/*
|
|
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
|
-
/*
|
|
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("
|
|
49
|
-
${green("
|
|
50
|
-
${green("
|
|
51
|
-
${green("
|
|
52
|
-
${green("
|
|
53
|
-
${green("
|
|
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
|
-
/*
|
|
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
|
-
/*
|
|
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
|
-
/*
|
|
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
|
-
/*
|
|
184
|
-
|
|
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
|
-
|
|
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
|
-
/*
|
|
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
|
-
|
|
371
|
+
/* -------------------------------------------------------
|
|
372
|
+
* ROUTER
|
|
373
|
+
* ----------------------------------------------------- */
|
|
311
374
|
switch (cmd) {
|
|
312
|
-
case "init":
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
case "
|
|
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(
|
|
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.
|
|
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",
|
package/templates/Dockerfile
CHANGED
|
@@ -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
|
-
}
|
package/templates/titan/dev.js
DELETED
|
@@ -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();
|
package/templates/titan/titan.js
DELETED
|
@@ -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;
|