@ezetgalaxy/titan 25.11.4 → 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 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
- Developers write zero Rust, yet deploy a native Rust backend with extreme performance, safety, and scalability.
12
+ ---
10
13
 
11
- Titan turns your JavaScript backend into:
14
+ ## Requirements
12
15
 
13
- - A Rust Axum HTTP server
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
- Titan = Next.js DX × Rust performance × JS developer simplicity
18
+ ### **1. Rust (latest stable)**
19
+ Install from:
20
+ https://rust-lang.org/tools/install/
19
21
 
20
- ### Features
22
+ ### **2. Node.js (v18+)**
23
+ Required for:
24
+ - Titan CLI
25
+ - esbuild
26
+ - JS → Rust compilation process
21
27
 
22
- - Write backend logic in JavaScript
23
- - Compile into native Rust backend
24
- - Titan DSL (t.post(), t.start())
25
- - Automatic route generation
26
- - Automatic JS action bundling
27
- - Rust Axum server runtime
28
- - JavaScript execution via Boa (sandboxed)
29
- - Hot-reload dev server // development in progress
30
- - Production binary output
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
- ### Installation
50
+ ---
51
+
52
+ ## 📦 Installation
34
53
 
35
54
  Install the Titan CLI globally:
36
55
 
37
56
  ```bash
38
- npm install -g titan-cli
57
+ npm install -g @ezetgalaxy/titan
39
58
  ```
40
59
 
41
- ### Create a New Titan Project
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
- This will:
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
- - Generate Titan project structure
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
- ### Project Structure
79
+ # 📁 Project Structure
57
80
 
58
81
  ```
59
82
  my-app/
60
83
  ├── app/
61
-   ├── app.js
62
-   └── actions/
63
-       └── hello.js
84
+ ├── app.js # Titan routes (DSL)
85
+ └── actions/
86
+ └── hello.js # Titan action
64
87
 
65
88
  ├── titan/
66
-   |── titan.js
67
- | |__ bundle.js
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/            ← Rust backend ([translate:auto generated])
73
-   ├── src/
74
-   ├── actions/
75
-   ├── titan/
76
-   ├── target/
77
-   ├── routes.json
78
-   ├── action_map.json
79
-   └── titan-server   ← final binary
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
- ### Example: Titan Action
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
-   return { message: "Hello from Titan!" };
116
+ return { message: "Hello from Titan!" };
91
117
  }
92
118
 
93
- globalThis.hello = hello
119
+ globalThis.hello = hello;
94
120
  ```
95
121
 
96
- This registers a global function _hello_ for the Rust runtime.
122
+ ---
97
123
 
98
- ### Example: Titan Routes
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 is running!");
137
+ t.start(3000, "Ready to land on Titan Planet 🚀");
113
138
  ```
114
139
 
115
- Titan generates routing metadata:
140
+ Titan generates:
141
+
142
+ - `server/routes.json`
143
+ - `server/action_map.json`
116
144
 
117
- - server/routes.json
118
- - server/action_map.json
145
+ Used by the Rust runtime to dispatch requests.
119
146
 
120
- These are then used by the Rust server.
147
+ ---
121
148
 
122
- ### Development Mode
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
- - Generate route definitions
131
- - Bundle JS into .jsbundle files
132
- - Start Axum Rust server with live reload
172
+ - Editing `app/app.js`
173
+ - Editing `app/actions/*.js`
174
+ - Fast rebuilds via esbuild
133
175
 
134
- ### Production Build
176
+ ---
177
+
178
+ # 🏭 Production Build
135
179
 
136
180
  ```bash
137
181
  tit build
138
182
  ```
139
183
 
140
- This produces the final deployment-ready output:
184
+ Production output goes into:
141
185
 
142
186
  ```
143
187
  server/
144
-   titan-server          ← release binary
145
-   routes.json
146
-   action_map.json
147
-   actions/*.jsbundle
148
-   titan/titan.jsbundle
188
+ titan-server
189
+ routes.json
190
+ action_map.json
191
+ actions/*.jsbundle
149
192
  ```
150
193
 
151
- Everything required for production is inside the server/ folder.
152
-
153
- ### Deploying Titan
194
+ You deploy **only the server folder**.
154
195
 
155
- You deploy only the /server folder.
196
+ ---
156
197
 
157
- Example (Railway):
198
+ # ☁ Deploying Titan
158
199
 
159
- Build locally:
160
-
161
- ```bash
162
- tit build
163
- ```
200
+ After `tit build`, deploy the `server/` folder anywhere:
164
201
 
165
- Upload the /server folder
202
+ - Railway
203
+ - Fly.io
204
+ - Docker
205
+ - VPS
206
+ - Render
207
+ - Bare metal
166
208
 
167
- Set start command:
209
+ Start command:
168
210
 
169
211
  ```bash
170
212
  ./titan-server
171
213
  ```
172
214
 
173
- No Node.js needed in production. Titan servers run as pure Rust native binaries.
174
-
175
- ### How Titan Works Internally
215
+ No Node.js needed in production Titan runs as a pure Rust binary.
176
216
 
177
- 1. JavaScript DSL
217
+ ---
178
218
 
179
- You write server logic using the Titan DSL:
219
+ # 🧠 How Titan Works (Internals)
180
220
 
181
- - t.get()
182
- - t.post()
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
- Titan bundles actions using esbuild into .jsbundle.
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
- The Rust Axum server:
193
-
194
- - Loads .jsbundle files
236
+ - Loads `.jsbundle` actions
195
237
  - Injects request data
196
- - Executes JS functions via Boa
197
- - Returns Rust JSON → client
198
-
199
- 5. Production Output
238
+ - Executes JS via Boa
239
+ - Returns JSON response to user
200
240
 
201
- Titan outputs:
241
+ ### 5. Production Output
242
+ Titan produces:
202
243
 
203
- - Native Rust binary
244
+ - A **native binary**
204
245
  - JS bundles
205
- - Route maps
246
+ - Route maps
247
+ - Entire backend in one folder
206
248
 
207
- ### Why Titan Exists
249
+ ---
208
250
 
209
- Titan targets JS developers who want:
251
+ # 🎯 Why Titan Exists
210
252
 
211
- - Rust backend performance
212
- - Without needing Rust knowledge
213
- - With full JS developer experience
214
- - And deployment as easy as Node
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 flexibility + Rust performance
263
+ **JavaScript Productivity × Rust Performance**
264
+
265
+ ---
219
266
 
220
- ### Version
267
+ # 📌 Version
221
268
 
222
- Titan v1 (Current)
269
+ **Titan v1 — Stable**
223
270
 
224
271
  - JS → Rust server compiler
225
- - JavaScript Action Engine
226
- - Axum runtime
272
+ - Action Engine
273
+ - Axum Runtime
227
274
  - Titan DSL
228
- - Hot reload
229
- - Railway deployment
275
+ - Hot Reload Dev Mode
276
+ - Railway/Fly.io Deployment
230
277
 
278
+ ---
231
279
 
232
- ### Contributing
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
@@ -1,9 +1,10 @@
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
+ // __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")} Run dev server (routes + bundle + cargo)
47
- ${green("tit build")} Build Rust release
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 Titan dependencies..."));
66
+ console.log(cyan("Installing dependencies..."));
72
67
 
73
- const deps = [
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 successfully"));
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,44 +78,89 @@ Next steps:
90
78
  `);
91
79
  }
92
80
 
93
- // ------------------------------------------
94
- // RUN BUNDLER
95
- // ------------------------------------------
81
+ // BUNDLE
96
82
  function runBundler() {
97
- const bundler = path.join(process.cwd(), "titan", "bundler.js");
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
- console.log(yellow("Warning: cli/bundle.js missing."));
88
+ console.log(yellow("Warning: titan/bundle.js missing."));
104
89
  }
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
- // RUN BUNDLER HERE
115
- runBundler();
96
+ async function devServer() {
97
+ console.log(cyan("Titan Dev Mode — Hot Reload Enabled"));
116
98
 
117
- console.log(cyan("Titan: starting Rust server..."));
99
+ let rustProcess = null;
118
100
 
119
- spawn("cargo", ["run"], {
120
- cwd: path.join(process.cwd(), "server"),
121
- stdio: "inherit",
122
- shell: true,
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: generating routes + bundling..."));
163
+ console.log(cyan("Titan: generate routes + bundle..."));
131
164
  execSync("node app/app.js", { stdio: "inherit" });
132
165
  runBundler();
133
166
 
@@ -138,15 +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
148
- ? "titan-server.exe"
149
- : "titan-server"; // Linux / macOS
177
+ const binaryName = isWindows ? "titan-server.exe" : "titan-server";
150
178
 
151
179
  const exe = path.join(
152
180
  process.cwd(),
@@ -156,14 +184,10 @@ function startProd() {
156
184
  binaryName
157
185
  );
158
186
 
159
- execSync(`"${exe}"`, { stdio: "inherit", shell: true });
187
+ execSync(`"${exe}"`, { stdio: "inherit" });
160
188
  }
161
189
 
162
-
163
-
164
- // ------------------------------------------
165
190
  // ROUTER
166
- // ------------------------------------------
167
191
  switch (cmd) {
168
192
  case "init":
169
193
  initProject(args[1]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ezetgalaxy/titan",
3
- "version": "25.11.4",
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
  }
@@ -1,39 +1,71 @@
1
1
  #!/usr/bin/env bash
2
2
  set -e
3
- # Create dist folder and copy release binary
4
- ROOT=$(cd "$(dirname "$0")/.." && pwd)
3
+
4
+ echo "Building Titan distribution..."
5
+
6
+ # ---------------------------------------------
7
+ # Resolve directories
8
+ # ---------------------------------------------
9
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
5
10
  SERVER_DIR="$ROOT/server"
6
11
  DIST_DIR="$ROOT/dist"
12
+
13
+ # Clean and recreate dist/
7
14
  rm -rf "$DIST_DIR"
8
15
  mkdir -p "$DIST_DIR"
9
16
 
17
+ # ---------------------------------------------
18
+ # Copy release binary titan-server
19
+ # ---------------------------------------------
20
+ RELEASE_PATH="$SERVER_DIR/target/release"
10
21
 
11
- # copy binary
12
- if [ -f "$SERVER_DIR/target/release/titan-server" ]; then
13
- cp "$SERVER_DIR/target/release/titan-server" "$DIST_DIR/"
22
+ echo "Looking for titan-server binary..."
23
+
24
+ if [ -f "$RELEASE_PATH/titan-server" ]; then
25
+ echo "✓ Found titan-server"
26
+ cp "$RELEASE_PATH/titan-server" "$DIST_DIR/"
14
27
  else
15
- # on mac/linux after build the binary name may differ by package name
16
- BIN=$(ls "$SERVER_DIR/target/release" | grep titan-server || true)
17
- if [ -n "$BIN" ]; then
18
- cp "$SERVER_DIR/target/release/$BIN" "$DIST_DIR/titan-server"
19
- fi
20
- fi
28
+ echo "Binary not found directly, searching..."
29
+ BIN=$(ls "$RELEASE_PATH" | grep 'titan-server' || true)
21
30
 
31
+ if [ -n "$BIN" ]; then
32
+ echo "✓ Found matching binary: $BIN"
33
+ cp "$RELEASE_PATH/$BIN" "$DIST_DIR/titan-server"
34
+ else
35
+ echo "✗ titan-server binary not found in release folder."
36
+ echo "Did you run: cargo build --release ?"
37
+ exit 1
38
+ fi
39
+ fi
22
40
 
23
- # Generate routes.json from project root by inspecting templates (we assume user ran JS bundler to emit routes.build.json)
41
+ # ---------------------------------------------
42
+ # routes.json (JS bundler should generate routes.build.json)
43
+ # ---------------------------------------------
24
44
  if [ -f "$ROOT/routes.build.json" ]; then
25
- cp "$ROOT/routes.build.json" "$DIST_DIR/routes.json"
45
+ echo "✓ Using routes.build.json"
46
+ cp "$ROOT/routes.build.json" "$DIST_DIR/routes.json"
26
47
  else
27
- # try default template
28
- echo "{}" > "$DIST_DIR/routes.json"
48
+ echo "⚠ No routes.build.json found. Creating empty routes.json"
49
+ echo "{}" > "$DIST_DIR/routes.json"
29
50
  fi
30
51
 
31
-
32
- # copy handlers if any
52
+ # ---------------------------------------------
53
+ # Copy handlers if they exist
54
+ # ---------------------------------------------
33
55
  mkdir -p "$DIST_DIR/handlers"
56
+
34
57
  if [ -d "$ROOT/handlers" ]; then
35
- cp -r "$ROOT/handlers"/* "$DIST_DIR/handlers/" || true
58
+ echo " Copying handlers/"
59
+ cp -r "$ROOT/handlers/"* "$DIST_DIR/handlers/" 2>/dev/null || true
60
+ else
61
+ echo "⚠ No handlers/ directory found."
36
62
  fi
37
63
 
38
-
39
- echo "Created dist/ with titan-server and routes.json"
64
+ echo ""
65
+ echo "-------------------------------------------"
66
+ echo " ✔ Titan dist/ build complete"
67
+ echo "-------------------------------------------"
68
+ echo "Binary: dist/titan-server"
69
+ echo "Routes: dist/routes.json"
70
+ echo "Handlers: dist/handlers/"
71
+ echo ""
@@ -0,0 +1,6 @@
1
+ function hello(req) {
2
+ const name = req.name;
3
+ return { name: name, msg: `Hello ${name}` }
4
+ }
5
+
6
+ globalThis.hello = hello;
@@ -3,8 +3,8 @@ import t from "../titan/titan.js";
3
3
 
4
4
 
5
5
 
6
+ t.post("/hello").action("hello") // pass a json payload { "name": "titan" }
6
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
- fs.mkdirSync(outDir, { recursive: true });
9
+ export async function bundle() {
10
+ console.log("[Titan] Bundling actions...");
10
11
 
11
- const files = fs.readdirSync(actionsDir).filter(f => f.endsWith(".js"));
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
- console.log(`Bundling ${entry} ${outfile}`);
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: false,
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 complete.");
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();