@ezetgalaxy/titan 25.11.5 → 25.11.6
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 +166 -117
- package/index.js +70 -44
- package/package.json +2 -1
- package/templates/app/actions/hello.js +6 -0
- package/templates/app/app.js +2 -2
- package/templates/titan/bundle.js +17 -8
- package/templates/titan/dev.js +67 -0
- package/templates/app/actions/getname.js +0 -6
package/README.md
CHANGED
|
@@ -1,44 +1,65 @@
|
|
|
1
|
-
|
|
2
1
|
***
|
|
3
2
|
|
|
4
|
-
## TITAN 🚀
|
|
3
|
+
## TITAN PLANET 🚀
|
|
5
4
|
JavaScript Simplicity. Rust Power.
|
|
6
5
|
|
|
7
|
-
Titan is a JavaScript-first backend framework that compiles your JS routes and actions into a production-grade Rust + Axum server
|
|
6
|
+
Titan is a JavaScript-first backend framework that compiles your JS routes and actions into a production-grade **Rust + Axum native server**.
|
|
7
|
+
|
|
8
|
+
Developers write **zero Rust**, yet deploy a high-performance, safe, fully native backend with excellent DX (developer experience).
|
|
9
|
+
|
|
10
|
+
Titan = Next.js DX × Rust performance × JavaScript simplicity
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
---
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
## ⚙ Requirements
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
- A JS action execution runtime (via Boa)
|
|
15
|
-
- A standalone binary ready for Railway, Fly.io, VPS, Docker
|
|
16
|
-
- A fully portable server with no Node.js required in production
|
|
16
|
+
Before using Titan, ensure your system has:
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
### **1. Rust (latest stable)**
|
|
19
|
+
Install from:
|
|
20
|
+
https://rust-lang.org/tools/install/
|
|
19
21
|
|
|
20
|
-
###
|
|
22
|
+
### **2. Node.js (v18+)**
|
|
23
|
+
Required for:
|
|
24
|
+
- Titan CLI
|
|
25
|
+
- esbuild
|
|
26
|
+
- JS → Rust compilation process
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
Check version:
|
|
29
|
+
```bash
|
|
30
|
+
node -v
|
|
31
|
+
npm -v
|
|
32
|
+
rustc -V
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## ✨ Features
|
|
38
|
+
|
|
39
|
+
- Write your backend in **pure JavaScript**
|
|
40
|
+
- Compile into a **native Rust HTTP server**
|
|
41
|
+
- Titan DSL: `t.get()`, `t.post()`, `t.start()`
|
|
42
|
+
- Automatic **route generation**
|
|
43
|
+
- Automatic **JS action bundling**
|
|
44
|
+
- Fast **Rust Axum runtime**
|
|
45
|
+
- JavaScript execution via **Boa engine**
|
|
46
|
+
- **Hot Reload Dev Server** (edit → rebuild → restart automatically)
|
|
47
|
+
- Production output: **single binary**
|
|
31
48
|
- Zero-config deployment
|
|
32
49
|
|
|
33
|
-
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 📦 Installation
|
|
34
53
|
|
|
35
54
|
Install the Titan CLI globally:
|
|
36
55
|
|
|
37
56
|
```bash
|
|
38
|
-
npm install -g titan
|
|
57
|
+
npm install -g @ezetgalaxy/titan
|
|
39
58
|
```
|
|
40
59
|
|
|
41
|
-
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 🚀 Create a New Titan Project
|
|
42
63
|
|
|
43
64
|
```bash
|
|
44
65
|
tit init my-app
|
|
@@ -46,191 +67,219 @@ cd my-app
|
|
|
46
67
|
tit dev
|
|
47
68
|
```
|
|
48
69
|
|
|
49
|
-
|
|
70
|
+
Titan will automatically:
|
|
71
|
+
|
|
72
|
+
- Create project structure
|
|
73
|
+
- Generate routes from `/app/app.js`
|
|
74
|
+
- Bundle JS actions into `.jsbundle` files
|
|
75
|
+
- Start the **Rust Axum dev server with Hot Reload**
|
|
50
76
|
|
|
51
|
-
|
|
52
|
-
- Build routes from /app/app.js
|
|
53
|
-
- Bundle JS actions into [.jsbundle] files
|
|
54
|
-
- Start the Rust Axum development server with hot reload
|
|
77
|
+
---
|
|
55
78
|
|
|
56
|
-
|
|
79
|
+
# 📁 Project Structure
|
|
57
80
|
|
|
58
81
|
```
|
|
59
82
|
my-app/
|
|
60
83
|
├── app/
|
|
61
|
-
│
|
|
62
|
-
│
|
|
63
|
-
│
|
|
84
|
+
│ ├── app.js # Titan routes (DSL)
|
|
85
|
+
│ └── actions/
|
|
86
|
+
│ └── hello.js # Titan action
|
|
64
87
|
│
|
|
65
88
|
├── titan/
|
|
66
|
-
│
|
|
67
|
-
|
|
68
|
-
│
|
|
69
|
-
├── cli/
|
|
70
|
-
│ └── bundle.js
|
|
89
|
+
│ ├── titan.js # Titan DSL
|
|
90
|
+
│ ├── bundle.js # Bundler (esbuild)
|
|
91
|
+
│ └── dev.js # Hot reload engine
|
|
71
92
|
│
|
|
72
|
-
├── server/
|
|
73
|
-
│
|
|
74
|
-
│
|
|
75
|
-
│
|
|
76
|
-
│
|
|
77
|
-
│
|
|
78
|
-
│
|
|
79
|
-
│
|
|
93
|
+
├── server/ # Rust backend (auto generated)
|
|
94
|
+
│ ├── src/
|
|
95
|
+
│ ├── actions/ # JS → .jsbundle compiled actions
|
|
96
|
+
│ ├── titan/ # internal runtime files
|
|
97
|
+
│ ├── target/ # Cargo build output
|
|
98
|
+
│ ├── routes.json
|
|
99
|
+
│ ├── action_map.json
|
|
100
|
+
│ └── titan-server # Final Rust binary
|
|
80
101
|
│
|
|
81
102
|
└── package.json
|
|
82
103
|
```
|
|
83
104
|
|
|
84
|
-
|
|
105
|
+
This is the complete Titan architecture:
|
|
106
|
+
**JS input → Rust server output → Native production binary.**
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
# 🧩 Example: Titan Action
|
|
85
111
|
|
|
86
112
|
**app/actions/hello.js**
|
|
87
113
|
|
|
88
114
|
```js
|
|
89
115
|
function hello(req) {
|
|
90
|
-
|
|
116
|
+
return { message: "Hello from Titan!" };
|
|
91
117
|
}
|
|
92
118
|
|
|
93
|
-
globalThis.hello = hello
|
|
119
|
+
globalThis.hello = hello;
|
|
94
120
|
```
|
|
95
121
|
|
|
96
|
-
|
|
122
|
+
---
|
|
97
123
|
|
|
98
|
-
|
|
124
|
+
# 🛣 Example: Titan Routes (DSL)
|
|
99
125
|
|
|
100
126
|
**app/app.js**
|
|
101
127
|
|
|
102
128
|
```js
|
|
103
129
|
import t from "../titan/titan.js";
|
|
104
130
|
|
|
105
|
-
|
|
106
131
|
// POST /hello → hello action
|
|
107
132
|
t.post("/hello").action("hello");
|
|
108
133
|
|
|
109
134
|
// GET / → reply text
|
|
110
135
|
t.get("/").reply("Welcome to Titan");
|
|
111
136
|
|
|
112
|
-
t.start(3000, "Titan
|
|
137
|
+
t.start(3000, "Ready to land on Titan Planet 🚀");
|
|
113
138
|
```
|
|
114
139
|
|
|
115
|
-
Titan generates
|
|
140
|
+
Titan generates:
|
|
141
|
+
|
|
142
|
+
- `server/routes.json`
|
|
143
|
+
- `server/action_map.json`
|
|
116
144
|
|
|
117
|
-
|
|
118
|
-
- server/action_map.json
|
|
145
|
+
Used by the Rust runtime to dispatch requests.
|
|
119
146
|
|
|
120
|
-
|
|
147
|
+
---
|
|
121
148
|
|
|
122
|
-
|
|
149
|
+
# 🔥 Hot Reload Dev Mode
|
|
150
|
+
|
|
151
|
+
Start development mode:
|
|
123
152
|
|
|
124
153
|
```bash
|
|
125
154
|
tit dev
|
|
126
155
|
```
|
|
127
156
|
|
|
128
|
-
Titan will:
|
|
157
|
+
Titan Dev Mode will:
|
|
158
|
+
|
|
159
|
+
- Regenerate routes on every save
|
|
160
|
+
- Rebundle actions automatically
|
|
161
|
+
- **Kill and restart the Rust server safely**
|
|
162
|
+
- Give full hot reload like modern JS frameworks
|
|
163
|
+
|
|
164
|
+
Full DX flow:
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
Save file → auto rebuild → auto restart → updated API
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Supports:
|
|
129
171
|
|
|
130
|
-
-
|
|
131
|
-
-
|
|
132
|
-
-
|
|
172
|
+
- Editing `app/app.js`
|
|
173
|
+
- Editing `app/actions/*.js`
|
|
174
|
+
- Fast rebuilds via esbuild
|
|
133
175
|
|
|
134
|
-
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
# 🏭 Production Build
|
|
135
179
|
|
|
136
180
|
```bash
|
|
137
181
|
tit build
|
|
138
182
|
```
|
|
139
183
|
|
|
140
|
-
|
|
184
|
+
Production output goes into:
|
|
141
185
|
|
|
142
186
|
```
|
|
143
187
|
server/
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
titan/titan.jsbundle
|
|
188
|
+
titan-server
|
|
189
|
+
routes.json
|
|
190
|
+
action_map.json
|
|
191
|
+
actions/*.jsbundle
|
|
149
192
|
```
|
|
150
193
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
### Deploying Titan
|
|
194
|
+
You deploy **only the server folder**.
|
|
154
195
|
|
|
155
|
-
|
|
196
|
+
---
|
|
156
197
|
|
|
157
|
-
|
|
198
|
+
# ☁ Deploying Titan
|
|
158
199
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
tit build
|
|
163
|
-
```
|
|
200
|
+
After `tit build`, deploy the `server/` folder anywhere:
|
|
164
201
|
|
|
165
|
-
|
|
202
|
+
- Railway
|
|
203
|
+
- Fly.io
|
|
204
|
+
- Docker
|
|
205
|
+
- VPS
|
|
206
|
+
- Render
|
|
207
|
+
- Bare metal
|
|
166
208
|
|
|
167
|
-
|
|
209
|
+
Start command:
|
|
168
210
|
|
|
169
211
|
```bash
|
|
170
212
|
./titan-server
|
|
171
213
|
```
|
|
172
214
|
|
|
173
|
-
No Node.js needed in production
|
|
174
|
-
|
|
175
|
-
### How Titan Works Internally
|
|
215
|
+
No Node.js needed in production — Titan runs as a pure Rust binary.
|
|
176
216
|
|
|
177
|
-
|
|
217
|
+
---
|
|
178
218
|
|
|
179
|
-
|
|
219
|
+
# 🧠 How Titan Works (Internals)
|
|
180
220
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
- t.start()
|
|
221
|
+
### 1. JavaScript DSL
|
|
222
|
+
You write backend logic using Titan’s intuitive DSL.
|
|
184
223
|
|
|
185
|
-
2. Bundler
|
|
224
|
+
### 2. Bundler
|
|
225
|
+
Titan uses esbuild to compile JS actions into `.jsbundle`.
|
|
186
226
|
|
|
187
|
-
|
|
227
|
+
### 3. Metadata
|
|
228
|
+
`t.start()` writes:
|
|
188
229
|
|
|
230
|
+
- `routes.json`
|
|
231
|
+
- `action_map.json`
|
|
189
232
|
|
|
190
|
-
4. Rust Server
|
|
233
|
+
### 4. Rust Server
|
|
234
|
+
Axum server:
|
|
191
235
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
- Loads .jsbundle files
|
|
236
|
+
- Loads `.jsbundle` actions
|
|
195
237
|
- Injects request data
|
|
196
|
-
- Executes JS
|
|
197
|
-
- Returns
|
|
198
|
-
|
|
199
|
-
5. Production Output
|
|
238
|
+
- Executes JS via Boa
|
|
239
|
+
- Returns JSON response to user
|
|
200
240
|
|
|
201
|
-
|
|
241
|
+
### 5. Production Output
|
|
242
|
+
Titan produces:
|
|
202
243
|
|
|
203
|
-
-
|
|
244
|
+
- A **native binary**
|
|
204
245
|
- JS bundles
|
|
205
|
-
- Route maps
|
|
246
|
+
- Route maps
|
|
247
|
+
- Entire backend in one folder
|
|
206
248
|
|
|
207
|
-
|
|
249
|
+
---
|
|
208
250
|
|
|
209
|
-
|
|
251
|
+
# 🎯 Why Titan Exists
|
|
210
252
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
-
|
|
214
|
-
-
|
|
253
|
+
Titan exists for developers who want:
|
|
254
|
+
|
|
255
|
+
- Rust performance
|
|
256
|
+
- JavaScript simplicity
|
|
257
|
+
- Zero Rust learning curve
|
|
258
|
+
- Zero config deployment
|
|
259
|
+
- Modern DX + native speed
|
|
215
260
|
|
|
216
261
|
Titan bridges two worlds:
|
|
217
262
|
|
|
218
|
-
JavaScript
|
|
263
|
+
**JavaScript Productivity × Rust Performance**
|
|
264
|
+
|
|
265
|
+
---
|
|
219
266
|
|
|
220
|
-
|
|
267
|
+
# 📌 Version
|
|
221
268
|
|
|
222
|
-
Titan v1
|
|
269
|
+
**Titan v1 — Stable**
|
|
223
270
|
|
|
224
271
|
- JS → Rust server compiler
|
|
225
|
-
-
|
|
226
|
-
- Axum
|
|
272
|
+
- Action Engine
|
|
273
|
+
- Axum Runtime
|
|
227
274
|
- Titan DSL
|
|
228
|
-
- Hot
|
|
229
|
-
- Railway
|
|
275
|
+
- Hot Reload Dev Mode
|
|
276
|
+
- Railway/Fly.io Deployment
|
|
230
277
|
|
|
278
|
+
---
|
|
231
279
|
|
|
232
|
-
|
|
280
|
+
# 🤝 Contributing
|
|
233
281
|
|
|
234
|
-
PRs, issues, and discussions are welcome.
|
|
282
|
+
PRs, issues, suggestions, and feature discussions are welcome.
|
|
283
|
+
|
|
284
|
+
***
|
|
235
285
|
|
|
236
|
-
***
|
package/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import path from "path";
|
|
|
4
4
|
import { execSync, spawn } from "child_process";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
|
|
7
|
+
// __dirname in ES modules
|
|
7
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
9
|
const __dirname = path.dirname(__filename);
|
|
9
10
|
|
|
@@ -17,9 +18,7 @@ const bold = (t) => `\x1b[1m${t}\x1b[0m`;
|
|
|
17
18
|
const args = process.argv.slice(2);
|
|
18
19
|
const cmd = args[0];
|
|
19
20
|
|
|
20
|
-
// ------------------------------------------
|
|
21
21
|
// COPY TEMPLATES
|
|
22
|
-
// ------------------------------------------
|
|
23
22
|
function copyDir(src, dest) {
|
|
24
23
|
fs.mkdirSync(dest, { recursive: true });
|
|
25
24
|
|
|
@@ -35,23 +34,19 @@ function copyDir(src, dest) {
|
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
// ------------------------------------------
|
|
39
37
|
// HELP
|
|
40
|
-
// ------------------------------------------
|
|
41
38
|
function help() {
|
|
42
39
|
console.log(`
|
|
43
40
|
${bold(cyan("Titan CLI"))}
|
|
44
41
|
|
|
45
42
|
${green("tit init <project>")} Create new Titan project
|
|
46
|
-
${green("tit dev")}
|
|
47
|
-
${green("tit build")} Build Rust
|
|
43
|
+
${green("tit dev")} Dev mode (hot reload)
|
|
44
|
+
${green("tit build")} Build production Rust server
|
|
48
45
|
${green("tit start")} Start production binary
|
|
49
46
|
`);
|
|
50
47
|
}
|
|
51
48
|
|
|
52
|
-
// ------------------------------------------
|
|
53
49
|
// INIT PROJECT
|
|
54
|
-
// ------------------------------------------
|
|
55
50
|
function initProject(name) {
|
|
56
51
|
if (!name) return console.log(red("Usage: tit init <project>"));
|
|
57
52
|
|
|
@@ -68,21 +63,14 @@ function initProject(name) {
|
|
|
68
63
|
copyDir(templateDir, target);
|
|
69
64
|
|
|
70
65
|
console.log(green("✔ Titan project created!"));
|
|
71
|
-
console.log(cyan("Installing
|
|
66
|
+
console.log(cyan("Installing dependencies..."));
|
|
72
67
|
|
|
73
|
-
|
|
74
|
-
"esbuild",
|
|
75
|
-
];
|
|
76
|
-
|
|
77
|
-
execSync(`npm install ${deps.join(" ")} --silent`, {
|
|
68
|
+
execSync(`npm install esbuild --silent`, {
|
|
78
69
|
cwd: target,
|
|
79
70
|
stdio: "inherit"
|
|
80
71
|
});
|
|
81
72
|
|
|
82
|
-
console.log(green("✔ Dependencies installed
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
console.log(green("✔ Titan project created"));
|
|
73
|
+
console.log(green("✔ Dependencies installed"));
|
|
86
74
|
console.log(`
|
|
87
75
|
Next steps:
|
|
88
76
|
cd ${name}
|
|
@@ -90,14 +78,11 @@ Next steps:
|
|
|
90
78
|
`);
|
|
91
79
|
}
|
|
92
80
|
|
|
93
|
-
//
|
|
94
|
-
// RUN BUNDLER
|
|
95
|
-
// ------------------------------------------
|
|
81
|
+
// BUNDLE
|
|
96
82
|
function runBundler() {
|
|
97
83
|
const bundler = path.join(process.cwd(), "titan", "bundle.js");
|
|
98
84
|
|
|
99
85
|
if (fs.existsSync(bundler)) {
|
|
100
|
-
console.log(cyan("Titan: bundling actions..."));
|
|
101
86
|
execSync(`node ${bundler}`, { stdio: "inherit" });
|
|
102
87
|
} else {
|
|
103
88
|
console.log(yellow("Warning: titan/bundle.js missing."));
|
|
@@ -105,29 +90,77 @@ function runBundler() {
|
|
|
105
90
|
}
|
|
106
91
|
|
|
107
92
|
// ------------------------------------------
|
|
108
|
-
// DEV SERVER
|
|
93
|
+
// FULL HOT RELOAD DEV SERVER
|
|
109
94
|
// ------------------------------------------
|
|
110
|
-
function devServer() {
|
|
111
|
-
console.log(cyan("Titan: generating routes.json & action_map.json..."));
|
|
112
|
-
execSync("node app/app.js", { stdio: "inherit" });
|
|
113
95
|
|
|
114
|
-
|
|
115
|
-
|
|
96
|
+
async function devServer() {
|
|
97
|
+
console.log(cyan("Titan Dev Mode — Hot Reload Enabled"));
|
|
116
98
|
|
|
117
|
-
|
|
99
|
+
let rustProcess = null;
|
|
118
100
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
101
|
+
function startRust() {
|
|
102
|
+
// ---- FIX: Proper kill for Windows ----
|
|
103
|
+
if (rustProcess) {
|
|
104
|
+
console.log(yellow("[Titan] Killing old Rust server..."));
|
|
105
|
+
|
|
106
|
+
if (process.platform === "win32") {
|
|
107
|
+
spawn("taskkill", ["/PID", rustProcess.pid, "/T", "/F"], {
|
|
108
|
+
stdio: "inherit",
|
|
109
|
+
shell: true
|
|
110
|
+
});
|
|
111
|
+
} else {
|
|
112
|
+
rustProcess.kill();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ---- START NEW PROCESS ----
|
|
117
|
+
rustProcess = spawn("cargo", ["run"], {
|
|
118
|
+
cwd: path.join(process.cwd(), "server"),
|
|
119
|
+
stdio: "inherit",
|
|
120
|
+
shell: true,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
rustProcess.on("close", (code) => {
|
|
124
|
+
console.log(red(`[Titan] Rust server exited: ${code}`));
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function rebuild() {
|
|
129
|
+
console.log(cyan("Titan: Regenerating routes..."));
|
|
130
|
+
execSync("node app/app.js", { stdio: "inherit" });
|
|
131
|
+
|
|
132
|
+
console.log(cyan("Titan: Bundling actions..."));
|
|
133
|
+
runBundler();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// First build
|
|
137
|
+
rebuild();
|
|
138
|
+
startRust();
|
|
139
|
+
|
|
140
|
+
// WATCHER
|
|
141
|
+
const chokidar = (await import("chokidar")).default;
|
|
142
|
+
|
|
143
|
+
const watcher = chokidar.watch("app", { ignoreInitial: true });
|
|
144
|
+
|
|
145
|
+
let timer = null;
|
|
146
|
+
|
|
147
|
+
watcher.on("all", (event, file) => {
|
|
148
|
+
if (timer) clearTimeout(timer);
|
|
149
|
+
|
|
150
|
+
timer = setTimeout(() => {
|
|
151
|
+
console.log(yellow(`Change detected → ${file}`));
|
|
152
|
+
|
|
153
|
+
rebuild();
|
|
154
|
+
startRust();
|
|
155
|
+
|
|
156
|
+
}, 250);
|
|
123
157
|
});
|
|
124
158
|
}
|
|
125
159
|
|
|
126
|
-
|
|
160
|
+
|
|
127
161
|
// BUILD RELEASE
|
|
128
|
-
// ------------------------------------------
|
|
129
162
|
function buildProd() {
|
|
130
|
-
console.log(cyan("Titan:
|
|
163
|
+
console.log(cyan("Titan: generate routes + bundle..."));
|
|
131
164
|
execSync("node app/app.js", { stdio: "inherit" });
|
|
132
165
|
runBundler();
|
|
133
166
|
|
|
@@ -138,13 +171,10 @@ function buildProd() {
|
|
|
138
171
|
});
|
|
139
172
|
}
|
|
140
173
|
|
|
141
|
-
// ------------------------------------------
|
|
142
174
|
// START PRODUCTION
|
|
143
|
-
// ------------------------------------------
|
|
144
175
|
function startProd() {
|
|
145
176
|
const isWindows = process.platform === "win32";
|
|
146
|
-
|
|
147
|
-
const binaryName = isWindows ? "titan-server.exe" : "titan-server"; // Linux / macOS
|
|
177
|
+
const binaryName = isWindows ? "titan-server.exe" : "titan-server";
|
|
148
178
|
|
|
149
179
|
const exe = path.join(
|
|
150
180
|
process.cwd(),
|
|
@@ -157,11 +187,7 @@ function startProd() {
|
|
|
157
187
|
execSync(`"${exe}"`, { stdio: "inherit" });
|
|
158
188
|
}
|
|
159
189
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// ------------------------------------------
|
|
163
190
|
// ROUTER
|
|
164
|
-
// ------------------------------------------
|
|
165
191
|
switch (cmd) {
|
|
166
192
|
case "init":
|
|
167
193
|
initProject(args[1]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ezetgalaxy/titan",
|
|
3
|
-
"version": "25.11.
|
|
3
|
+
"version": "25.11.6",
|
|
4
4
|
"description": "JavaScript backend framework that compiles your JS into a Rust + Axum server.",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "ezetgalaxy",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"test": "echo \"No tests specified\""
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
+
"chokidar": "^5.0.0",
|
|
49
50
|
"esbuild": "^0.27.1"
|
|
50
51
|
}
|
|
51
52
|
}
|
package/templates/app/app.js
CHANGED
|
@@ -3,8 +3,8 @@ import t from "../titan/titan.js";
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
t.post("/
|
|
6
|
+
t.post("/hello").action("hello") // pass a json payload { "name": "titan" }
|
|
7
7
|
|
|
8
|
-
t.get("/").reply("Ready to land on Titan 🚀");
|
|
8
|
+
t.get("/").reply("Ready to land on Titan Planet 🚀");
|
|
9
9
|
|
|
10
10
|
t.start(3000, "Titan Running!");
|
|
@@ -6,20 +6,29 @@ const root = process.cwd();
|
|
|
6
6
|
const actionsDir = path.join(root, "app", "actions");
|
|
7
7
|
const outDir = path.join(root, "server", "actions");
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
export async function bundle() {
|
|
10
|
+
console.log("[Titan] Bundling actions...");
|
|
10
11
|
|
|
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"));
|
|
12
20
|
|
|
13
|
-
(async () => {
|
|
14
21
|
for (const file of files) {
|
|
15
22
|
const entry = path.join(actionsDir, file);
|
|
16
|
-
const outfile = path.join(outDir, file + "bundle");
|
|
17
23
|
|
|
18
|
-
|
|
24
|
+
// Rust runtime expects `.jsbundle` extension — consistent with previous design
|
|
25
|
+
const outfile = path.join(outDir, file.replace(".js", ".jsbundle"));
|
|
26
|
+
|
|
27
|
+
console.log(`[Titan] Bundling ${entry} → ${outfile}`);
|
|
19
28
|
|
|
20
29
|
await esbuild.build({
|
|
21
30
|
entryPoints: [entry],
|
|
22
|
-
bundle:
|
|
31
|
+
bundle: true,
|
|
23
32
|
format: "cjs",
|
|
24
33
|
platform: "neutral",
|
|
25
34
|
outfile,
|
|
@@ -27,5 +36,5 @@ const files = fs.readdirSync(actionsDir).filter(f => f.endsWith(".js"));
|
|
|
27
36
|
});
|
|
28
37
|
}
|
|
29
38
|
|
|
30
|
-
console.log("Bundling
|
|
31
|
-
}
|
|
39
|
+
console.log("[Titan] Bundling finished.");
|
|
40
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
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();
|