@ezetgalaxy/titan 25.12.7 → 25.12.9
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 +103 -126
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { execSync, spawn } from "child_process";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/* Resolve __dirname for ES modules */
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
/* Colors */
|
|
12
12
|
const cyan = (t) => `\x1b[36m${t}\x1b[0m`;
|
|
13
13
|
const green = (t) => `\x1b[32m${t}\x1b[0m`;
|
|
14
14
|
const yellow = (t) => `\x1b[33m${t}\x1b[0m`;
|
|
@@ -18,7 +18,13 @@ const bold = (t) => `\x1b[1m${t}\x1b[0m`;
|
|
|
18
18
|
const args = process.argv.slice(2);
|
|
19
19
|
const cmd = args[0];
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
/* Titan version (read from package.json) */
|
|
22
|
+
const pkg = JSON.parse(
|
|
23
|
+
fs.readFileSync(path.join(__dirname, "package.json"), "utf8")
|
|
24
|
+
);
|
|
25
|
+
const TITAN_VERSION = pkg.version;
|
|
26
|
+
|
|
27
|
+
/* Safe copy directory */
|
|
22
28
|
function copyDir(src, dest) {
|
|
23
29
|
fs.mkdirSync(dest, { recursive: true });
|
|
24
30
|
|
|
@@ -34,20 +40,21 @@ function copyDir(src, dest) {
|
|
|
34
40
|
}
|
|
35
41
|
}
|
|
36
42
|
|
|
37
|
-
|
|
43
|
+
/* HELP */
|
|
38
44
|
function help() {
|
|
39
45
|
console.log(`
|
|
40
|
-
${bold(cyan("Titan CLI"))}
|
|
46
|
+
${bold(cyan("Titan CLI"))} v${TITAN_VERSION}
|
|
41
47
|
|
|
42
48
|
${green("tit init <project>")} Create new Titan project
|
|
43
49
|
${green("tit dev")} Dev mode (hot reload)
|
|
44
50
|
${green("tit build")} Build production Rust server
|
|
45
51
|
${green("tit start")} Start production binary
|
|
46
|
-
${green("tit update")} Update
|
|
52
|
+
${green("tit update")} Update Titan engine
|
|
53
|
+
${green("tit --version")} Show Titan CLI version
|
|
47
54
|
`);
|
|
48
55
|
}
|
|
49
56
|
|
|
50
|
-
|
|
57
|
+
/* INIT PROJECT */
|
|
51
58
|
function initProject(name) {
|
|
52
59
|
if (!name) return console.log(red("Usage: tit init <project>"));
|
|
53
60
|
|
|
@@ -61,7 +68,6 @@ function initProject(name) {
|
|
|
61
68
|
|
|
62
69
|
console.log(cyan(`Creating Titan project → ${target}`));
|
|
63
70
|
|
|
64
|
-
copyDir(templateDir, target);
|
|
65
71
|
copyDir(templateDir, target);
|
|
66
72
|
|
|
67
73
|
[".gitignore", ".dockerignore", "Dockerfile"].forEach((file) => {
|
|
@@ -70,13 +76,12 @@ function initProject(name) {
|
|
|
70
76
|
if (fs.existsSync(src)) fs.copyFileSync(src, dest);
|
|
71
77
|
});
|
|
72
78
|
|
|
73
|
-
|
|
74
79
|
console.log(green("✔ Titan project created!"));
|
|
75
80
|
console.log(cyan("Installing dependencies..."));
|
|
76
81
|
|
|
77
82
|
execSync(`npm install esbuild --silent`, {
|
|
78
83
|
cwd: target,
|
|
79
|
-
stdio: "inherit"
|
|
84
|
+
stdio: "inherit",
|
|
80
85
|
});
|
|
81
86
|
|
|
82
87
|
console.log(green("✔ Dependencies installed"));
|
|
@@ -87,31 +92,44 @@ Next steps:
|
|
|
87
92
|
`);
|
|
88
93
|
}
|
|
89
94
|
|
|
90
|
-
|
|
91
|
-
function runBundler() {
|
|
92
|
-
const bundler = path.join(
|
|
95
|
+
/* BUNDLER (absolute path, Railway-safe) */
|
|
96
|
+
function runBundler(root) {
|
|
97
|
+
const bundler = path.join(root, "titan", "bundle.js");
|
|
93
98
|
|
|
94
|
-
if (fs.existsSync(bundler)) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
console.log(yellow("Warning: titan/bundle.js missing."));
|
|
99
|
+
if (!fs.existsSync(bundler)) {
|
|
100
|
+
console.log(red("ERROR: titan/bundle.js missing."));
|
|
101
|
+
process.exit(1);
|
|
98
102
|
}
|
|
99
|
-
}
|
|
100
103
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// ------------------------------------------
|
|
104
|
+
execSync(`node "${bundler}"`, { stdio: "inherit" });
|
|
105
|
+
}
|
|
104
106
|
|
|
107
|
+
/* DEV SERVER — HOT RELOAD */
|
|
105
108
|
async function devServer() {
|
|
109
|
+
const root = process.cwd();
|
|
106
110
|
console.log(cyan("Titan Dev Mode — Hot Reload Enabled"));
|
|
107
111
|
|
|
108
112
|
let rustProcess = null;
|
|
109
113
|
|
|
114
|
+
function launchRust(done) {
|
|
115
|
+
const processHandle = spawn("cargo", ["run"], {
|
|
116
|
+
cwd: path.join(root, "server"),
|
|
117
|
+
stdio: "inherit",
|
|
118
|
+
shell: true,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
processHandle.on("spawn", () => setTimeout(done, 200));
|
|
122
|
+
processHandle.on("close", (code) =>
|
|
123
|
+
console.log(`[Titan] Rust server exited: ${code}`)
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
return processHandle;
|
|
127
|
+
}
|
|
128
|
+
|
|
110
129
|
function startRust() {
|
|
111
130
|
return new Promise((resolve) => {
|
|
112
|
-
// if server already running → kill it
|
|
113
131
|
if (rustProcess) {
|
|
114
|
-
console.log("[Titan]
|
|
132
|
+
console.log("[Titan] Restarting Rust server...");
|
|
115
133
|
|
|
116
134
|
if (process.platform === "win32") {
|
|
117
135
|
const killer = spawn("taskkill", ["/PID", rustProcess.pid, "/T", "/F"], {
|
|
@@ -134,40 +152,19 @@ async function devServer() {
|
|
|
134
152
|
});
|
|
135
153
|
}
|
|
136
154
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
155
|
+
/* Build logic */
|
|
156
|
+
function rebuild() {
|
|
157
|
+
execSync(`node "${path.join(root, "app", "app.js")}"`, {
|
|
140
158
|
stdio: "inherit",
|
|
141
|
-
shell: true,
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
processHandle.on("spawn", () => {
|
|
145
|
-
setTimeout(done, 200); // wait for OS to release port
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
processHandle.on("close", (code) => {
|
|
149
|
-
console.log(`[Titan] Rust server exited: ${code}`);
|
|
150
159
|
});
|
|
151
160
|
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
function rebuild() {
|
|
157
|
-
console.log(cyan("Titan: Regenerating routes..."));
|
|
158
|
-
execSync("node app/app.js", { stdio: "inherit" });
|
|
159
|
-
|
|
160
|
-
console.log(cyan("Titan: Bundling actions..."));
|
|
161
|
-
runBundler();
|
|
161
|
+
runBundler(root);
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
// First build
|
|
165
164
|
rebuild();
|
|
166
165
|
startRust();
|
|
167
166
|
|
|
168
|
-
// WATCHER
|
|
169
167
|
const chokidar = (await import("chokidar")).default;
|
|
170
|
-
|
|
171
168
|
const watcher = chokidar.watch("app", { ignoreInitial: true });
|
|
172
169
|
|
|
173
170
|
let timer = null;
|
|
@@ -176,113 +173,88 @@ async function devServer() {
|
|
|
176
173
|
if (timer) clearTimeout(timer);
|
|
177
174
|
|
|
178
175
|
timer = setTimeout(() => {
|
|
179
|
-
console.log(yellow(`Change
|
|
180
|
-
|
|
176
|
+
console.log(yellow(`Change → ${file}`));
|
|
181
177
|
rebuild();
|
|
182
178
|
startRust();
|
|
183
|
-
|
|
184
179
|
}, 250);
|
|
185
180
|
});
|
|
186
181
|
}
|
|
187
182
|
|
|
188
|
-
|
|
189
|
-
// BUILD RELEASE
|
|
183
|
+
/* PRODUCTION BUILD */
|
|
190
184
|
function buildProd() {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
185
|
+
const root = process.cwd();
|
|
186
|
+
const appJs = path.join(root, "app", "app.js");
|
|
187
|
+
|
|
188
|
+
console.log(cyan("Titan: Building production output..."));
|
|
189
|
+
|
|
190
|
+
if (!fs.existsSync(appJs)) {
|
|
191
|
+
console.log(red("ERROR: app/app.js missing."));
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* Generate routes */
|
|
196
|
+
execSync(`node "${appJs}"`, { stdio: "inherit" });
|
|
194
197
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
+
/* Bundle actions */
|
|
199
|
+
runBundler(root);
|
|
200
|
+
|
|
201
|
+
/* Copy bundles → server/actions */
|
|
202
|
+
const outDir = path.join(root, "server", "actions");
|
|
203
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
204
|
+
|
|
205
|
+
const builtActions = path.join(root, "titan", "actions");
|
|
206
|
+
|
|
207
|
+
if (fs.existsSync(builtActions)) {
|
|
208
|
+
for (const file of fs.readdirSync(builtActions)) {
|
|
209
|
+
if (file.endsWith(".jsbundle")) {
|
|
210
|
+
fs.copyFileSync(
|
|
211
|
+
path.join(builtActions, file),
|
|
212
|
+
path.join(outDir, file)
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
console.log(green("✔ Actions copied to server/actions"));
|
|
219
|
+
|
|
220
|
+
/* Rust release build */
|
|
221
|
+
execSync(`cargo build --release`, {
|
|
222
|
+
cwd: path.join(root, "server"),
|
|
198
223
|
stdio: "inherit",
|
|
199
224
|
});
|
|
225
|
+
|
|
226
|
+
console.log(green("✔ Rust binary built successfully."));
|
|
200
227
|
}
|
|
201
228
|
|
|
202
|
-
|
|
229
|
+
/* START PRODUCTION BINARY */
|
|
203
230
|
function startProd() {
|
|
204
|
-
const
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
const exe = path.join(
|
|
208
|
-
process.cwd(),
|
|
209
|
-
"server",
|
|
210
|
-
"target",
|
|
211
|
-
"release",
|
|
212
|
-
binaryName
|
|
213
|
-
);
|
|
231
|
+
const isWin = process.platform === "win32";
|
|
232
|
+
const bin = isWin ? "titan-server.exe" : "titan-server";
|
|
214
233
|
|
|
234
|
+
const exe = path.join(process.cwd(), "server", "target", "release", bin);
|
|
215
235
|
execSync(`"${exe}"`, { stdio: "inherit" });
|
|
216
236
|
}
|
|
217
237
|
|
|
218
|
-
|
|
219
|
-
// TITAN UPDATE — Upgrade titan/ runtime
|
|
220
|
-
// ------------------------------------------
|
|
238
|
+
/* UPDATE TITAN */
|
|
221
239
|
function updateTitan() {
|
|
222
|
-
const
|
|
223
|
-
const projectTitan = path.join(
|
|
240
|
+
const root = process.cwd();
|
|
241
|
+
const projectTitan = path.join(root, "titan");
|
|
224
242
|
|
|
225
243
|
const cliTemplatesRoot = path.join(__dirname, "templates");
|
|
226
244
|
const cliTitan = path.join(cliTemplatesRoot, "titan");
|
|
227
245
|
|
|
228
246
|
if (!fs.existsSync(projectTitan)) {
|
|
229
|
-
console.log(red("
|
|
230
|
-
console.log(yellow("Make sure you are inside a Titan project."));
|
|
247
|
+
console.log(red("Not a Titan project (titan/ missing)."));
|
|
231
248
|
return;
|
|
232
249
|
}
|
|
233
250
|
|
|
234
|
-
|
|
235
|
-
//
|
|
236
|
-
// 2. Replace titan/ runtime folder
|
|
237
|
-
//
|
|
238
251
|
fs.rmSync(projectTitan, { recursive: true, force: true });
|
|
239
|
-
console.log(green("✔ Old titan/ runtime removed"));
|
|
240
|
-
|
|
241
252
|
copyDir(cliTitan, projectTitan);
|
|
242
|
-
console.log(green("✔ titan/ runtime updated"));
|
|
243
|
-
|
|
244
|
-
//
|
|
245
|
-
// 3. Update server/Cargo.toml
|
|
246
|
-
//
|
|
247
|
-
const srcToml = path.join(cliTemplatesRoot, "server", "Cargo.toml");
|
|
248
|
-
const destToml = path.join(projectRoot, "server", "Cargo.toml");
|
|
249
|
-
if (fs.existsSync(srcToml)) {
|
|
250
|
-
fs.copyFileSync(srcToml, destToml);
|
|
251
|
-
console.log(green("✔ Updated server/Cargo.toml"));
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
//
|
|
255
|
-
// 4. Update ONLY server/src/main.rs
|
|
256
|
-
//
|
|
257
|
-
const srcMain = path.join(cliTemplatesRoot, "server", "src", "main.rs");
|
|
258
|
-
const destMain = path.join(projectRoot, "server", "src", "main.rs");
|
|
259
|
-
if (fs.existsSync(srcMain)) {
|
|
260
|
-
fs.copyFileSync(srcMain, destMain);
|
|
261
|
-
console.log(green("✔ Updated server/src/main.rs"));
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
//
|
|
265
|
-
// 5. Update root-level config files
|
|
266
|
-
//
|
|
267
|
-
[".gitignore", ".dockerignore", "Dockerfile"].forEach((file) => {
|
|
268
|
-
const src = path.join(cliTemplatesRoot, file);
|
|
269
|
-
const dest = path.join(projectRoot, file);
|
|
270
|
-
|
|
271
|
-
if (fs.existsSync(src)) {
|
|
272
|
-
fs.copyFileSync(src, dest);
|
|
273
|
-
console.log(green(`✔ Updated ${file}`));
|
|
274
|
-
}
|
|
275
|
-
});
|
|
276
253
|
|
|
277
|
-
console.log(
|
|
254
|
+
console.log(green("✔ Titan runtime updated"));
|
|
278
255
|
}
|
|
279
256
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
// ROUTER
|
|
257
|
+
/* ROUTER */
|
|
286
258
|
switch (cmd) {
|
|
287
259
|
case "init":
|
|
288
260
|
initProject(args[1]);
|
|
@@ -304,7 +276,12 @@ switch (cmd) {
|
|
|
304
276
|
updateTitan();
|
|
305
277
|
break;
|
|
306
278
|
|
|
279
|
+
case "--version":
|
|
280
|
+
case "-v":
|
|
281
|
+
case "version":
|
|
282
|
+
console.log(green(`Titan v${TITAN_VERSION}`));
|
|
283
|
+
break;
|
|
284
|
+
|
|
307
285
|
default:
|
|
308
286
|
help();
|
|
309
287
|
}
|
|
310
|
-
|