@ezetgalaxy/titan 26.3.3 → 26.4.1
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 +1 -1
- package/index.js +16 -93
- package/package.json +1 -1
- package/templates/Dockerfile +1 -2
- package/templates/app/actions/hello.js +3 -3
- package/templates/app/titan.d.ts +72 -81
- package/templates/jsconfig.json +19 -0
- package/templates/server/Cargo.lock +286 -712
- package/templates/server/Cargo.toml +2 -2
- package/templates/server/src/errors.rs +1 -1
- package/templates/server/src/extensions.rs +335 -514
- package/templates/server/src/main.rs +100 -142
- package/templates/server/src/utils.rs +2 -0
- package/templates/titan/bundle.js +6 -3
- package/templates/titan/dev.js +44 -8
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
# Notice
|
|
12
12
|
|
|
13
13
|
💙 **Enjoy development mode `titan dev`**
|
|
14
|
-
💟 **Titan Planet docs
|
|
14
|
+
💟 **Titan Planet docs:** https://titan-docs-ez.vercel.app/docs
|
|
15
15
|
🚀 **CLI: `titan` is now the canonical command. `tit` remains supported as an alias.**
|
|
16
16
|
|
|
17
17
|
---
|
package/index.js
CHANGED
|
@@ -175,106 +175,29 @@ Next steps:
|
|
|
175
175
|
`);
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
|
|
179
|
-
/* -------------------------------------------------------
|
|
180
|
-
* BUNDLER
|
|
181
|
-
* ----------------------------------------------------- */
|
|
182
|
-
function runBundler(root) {
|
|
183
|
-
const bundler = path.join(root, "titan", "bundle.js");
|
|
184
|
-
|
|
185
|
-
if (!fs.existsSync(bundler)) {
|
|
186
|
-
console.log(red("ERROR: titan/bundle.js missing."));
|
|
187
|
-
process.exit(1);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
execSync(`node "${bundler}"`, { stdio: "inherit" });
|
|
191
|
-
}
|
|
192
|
-
|
|
193
178
|
/* -------------------------------------------------------
|
|
194
179
|
* DEV SERVER
|
|
195
180
|
* ----------------------------------------------------- */
|
|
196
181
|
async function devServer() {
|
|
197
182
|
const root = process.cwd();
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
let rustProcess = null;
|
|
201
|
-
|
|
202
|
-
function launchRust(done) {
|
|
203
|
-
const processHandle = spawn("cargo", ["run"], {
|
|
204
|
-
cwd: path.join(root, "server"),
|
|
205
|
-
stdio: "inherit",
|
|
206
|
-
shell: true,
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
processHandle.on("spawn", () => setTimeout(done, 200));
|
|
210
|
-
processHandle.on("close", (code) =>
|
|
211
|
-
console.log(`[Titan] Rust server exited: ${code}`)
|
|
212
|
-
);
|
|
213
|
-
|
|
214
|
-
return processHandle;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function startRust() {
|
|
218
|
-
return new Promise((resolve) => {
|
|
219
|
-
if (rustProcess) {
|
|
220
|
-
console.log("[Titan] Restarting Rust server...");
|
|
221
|
-
|
|
222
|
-
if (process.platform === "win32") {
|
|
223
|
-
const killer = spawn("taskkill", ["/PID", rustProcess.pid, "/T", "/F"], {
|
|
224
|
-
stdio: "ignore",
|
|
225
|
-
shell: true,
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
killer.on("exit", () => {
|
|
229
|
-
rustProcess = launchRust(resolve);
|
|
230
|
-
});
|
|
231
|
-
} else {
|
|
232
|
-
rustProcess.kill();
|
|
233
|
-
rustProcess.on("close", () => {
|
|
234
|
-
rustProcess = launchRust(resolve);
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
} else {
|
|
238
|
-
rustProcess = launchRust(resolve);
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/* Build logic */
|
|
244
|
-
function rebuild() {
|
|
245
|
-
execSync(`node "${path.join(root, "app", "app.js")}"`, {
|
|
246
|
-
stdio: "inherit",
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
runBundler(root);
|
|
250
|
-
}
|
|
183
|
+
const devScript = path.join(root, "titan", "dev.js");
|
|
251
184
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
console.log(red("Initial build failed:"));
|
|
257
|
-
console.log(e.message);
|
|
258
|
-
// Do not die even on initial fail, user might fix it.
|
|
185
|
+
if (!fs.existsSync(devScript)) {
|
|
186
|
+
console.log(red("Error: titan/dev.js not found."));
|
|
187
|
+
console.log("Try running `titan update` to fix missing files.");
|
|
188
|
+
return;
|
|
259
189
|
}
|
|
260
190
|
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
watcher.on("all", (event, file) => {
|
|
267
|
-
if (timer) clearTimeout(timer);
|
|
191
|
+
const child = spawn("node", [devScript], {
|
|
192
|
+
stdio: "inherit",
|
|
193
|
+
cwd: root
|
|
194
|
+
});
|
|
268
195
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
} catch (err) {
|
|
275
|
-
console.log(red("Build failed — waiting for changes..."));
|
|
276
|
-
}
|
|
277
|
-
}, 250);
|
|
196
|
+
child.on("close", (code) => {
|
|
197
|
+
// Exit strictly if the dev script failed
|
|
198
|
+
if (code !== 0) {
|
|
199
|
+
process.exit(code);
|
|
200
|
+
}
|
|
278
201
|
});
|
|
279
202
|
}
|
|
280
203
|
|
|
@@ -413,7 +336,7 @@ function updateTitan() {
|
|
|
413
336
|
console.log(green("✔ Updated server/src/"));
|
|
414
337
|
|
|
415
338
|
// Root-level config files
|
|
416
|
-
[".gitignore", ".dockerignore", "Dockerfile"].forEach((file) => {
|
|
339
|
+
[".gitignore", ".dockerignore", "Dockerfile", "jsconfig.json"].forEach((file) => {
|
|
417
340
|
const src = path.join(templatesRoot, file);
|
|
418
341
|
const dest = path.join(root, file);
|
|
419
342
|
|
|
@@ -425,7 +348,7 @@ function updateTitan() {
|
|
|
425
348
|
|
|
426
349
|
// app/titan.d.ts (JS typing contract)
|
|
427
350
|
const appDir = path.join(root, "app");
|
|
428
|
-
const srcDts = path.join(
|
|
351
|
+
const srcDts = path.join(templateServer, "../app/titan.d.ts"); // templates/app/titan.d.ts
|
|
429
352
|
const destDts = path.join(appDir, "titan.d.ts");
|
|
430
353
|
|
|
431
354
|
if (fs.existsSync(srcDts)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ezetgalaxy/titan",
|
|
3
|
-
"version": "26.
|
|
3
|
+
"version": "26.4.1",
|
|
4
4
|
"description": "Titan Planet is a JavaScript-first backend framework that embeds JS actions into a Rust + Axum server and ships as a single native binary. Routes are compiled to static metadata; only actions run in the embedded JS runtime. No Node.js. No event loop in production.",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "ezetgalaxy",
|
package/templates/Dockerfile
CHANGED
|
@@ -44,8 +44,7 @@ COPY --from=builder /app/server/action_map.json ./action_map.json
|
|
|
44
44
|
RUN mkdir -p /app/actions
|
|
45
45
|
COPY --from=builder /app/server/actions /app/actions
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
COPY app/db /app/assets/db
|
|
47
|
+
COPY --from=builder /app/db /app/assets
|
|
49
48
|
|
|
50
49
|
# Expose Titan port
|
|
51
50
|
EXPOSE 3000
|
package/templates/app/titan.d.ts
CHANGED
|
@@ -1,96 +1,87 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* TITAN TYPE DEFINITIONS
|
|
3
|
+
* ----------------------
|
|
4
|
+
* These types are globally available in your Titan project.
|
|
3
5
|
*/
|
|
4
|
-
declare global {
|
|
5
|
-
/**
|
|
6
|
-
* Titan Request Object passed to actions
|
|
7
|
-
*/
|
|
8
|
-
interface TitanRequest {
|
|
9
|
-
body: any;
|
|
10
|
-
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
11
|
-
path: string;
|
|
12
|
-
headers: Record<string, string>;
|
|
13
|
-
params: Record<string, string>;
|
|
14
|
-
query: Record<string, string>;
|
|
15
|
-
}
|
|
16
6
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
7
|
+
/**
|
|
8
|
+
* The Titan Request Object passed to actions.
|
|
9
|
+
*/
|
|
10
|
+
interface TitanRequest {
|
|
11
|
+
body: any;
|
|
12
|
+
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
13
|
+
path: string;
|
|
14
|
+
headers: {
|
|
15
|
+
host?: string;
|
|
16
|
+
"content-type"?: string;
|
|
17
|
+
"user-agent"?: string;
|
|
18
|
+
authorization?: string;
|
|
19
|
+
[key: string]: string | undefined;
|
|
20
|
+
};
|
|
21
|
+
params: Record<string, string>;
|
|
22
|
+
query: Record<string, string>;
|
|
23
|
+
}
|
|
25
24
|
|
|
25
|
+
interface DbConnection {
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Execute a SQL query.
|
|
28
|
+
* @param sql The SQL query string.
|
|
29
|
+
* @param params (Optional) Parameters for the query ($1, $2, etc).
|
|
28
30
|
*/
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* Log messages to the server console with Titan formatting.
|
|
32
|
-
*/
|
|
33
|
-
log(...args: any[]): void;
|
|
31
|
+
query(sql: string, params?: any[]): any[];
|
|
32
|
+
}
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Define a Titan Action with type inference.
|
|
36
|
+
* @example
|
|
37
|
+
* export const hello = defineAction((req) => {
|
|
38
|
+
* return req.headers;
|
|
39
|
+
* });
|
|
40
|
+
*/
|
|
41
|
+
declare function defineAction<T>(actionFn: (req: TitanRequest) => T): (req: TitanRequest) => T;
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
error?: string;
|
|
50
|
-
};
|
|
43
|
+
/**
|
|
44
|
+
* Titan Runtime Utilities
|
|
45
|
+
*/
|
|
46
|
+
declare const t: {
|
|
47
|
+
/**
|
|
48
|
+
* Log messages to the server console with Titan formatting.
|
|
49
|
+
*/
|
|
50
|
+
log(...args: any[]): void;
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
* @param options Configuration options.
|
|
58
|
-
*/
|
|
59
|
-
sign(
|
|
60
|
-
payload: object,
|
|
61
|
-
secret: string,
|
|
62
|
-
options?: { expiresIn?: string | number }
|
|
63
|
-
): string;
|
|
52
|
+
/**
|
|
53
|
+
* Read a file contents as string.
|
|
54
|
+
* @param path Relative path to the file from project root.
|
|
55
|
+
*/
|
|
56
|
+
read(path: string): string;
|
|
64
57
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
58
|
+
fetch(url: string, options?: {
|
|
59
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
60
|
+
headers?: Record<string, string>;
|
|
61
|
+
body?: string | object;
|
|
62
|
+
}): {
|
|
63
|
+
ok: boolean;
|
|
64
|
+
status?: number;
|
|
65
|
+
body?: string;
|
|
66
|
+
error?: string;
|
|
67
|
+
};
|
|
73
68
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
69
|
+
jwt: {
|
|
70
|
+
sign(
|
|
71
|
+
payload: object,
|
|
72
|
+
secret: string,
|
|
73
|
+
options?: { expiresIn?: string | number }
|
|
74
|
+
): string;
|
|
75
|
+
verify(token: string, secret: string): any;
|
|
76
|
+
};
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
};
|
|
78
|
+
password: {
|
|
79
|
+
hash(password: string): string;
|
|
80
|
+
verify(password: string, hash: string): boolean;
|
|
81
|
+
};
|
|
85
82
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
* Connect to a PostgreSQL database.
|
|
89
|
-
* @param url Connection string (e.g. postgres://user:pass@localhost:5432/db)
|
|
90
|
-
*/
|
|
91
|
-
connect(url: string): DbConnection;
|
|
92
|
-
};
|
|
83
|
+
db: {
|
|
84
|
+
connect(url: string): DbConnection;
|
|
93
85
|
};
|
|
94
|
-
}
|
|
86
|
+
};
|
|
95
87
|
|
|
96
|
-
export { };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "esnext",
|
|
4
|
+
"target": "esnext",
|
|
5
|
+
"checkJs": false,
|
|
6
|
+
"noImplicitAny": false,
|
|
7
|
+
"allowJs": true,
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"baseUrl": ".",
|
|
10
|
+
"paths": {
|
|
11
|
+
"*": [
|
|
12
|
+
"./app/*"
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"include": [
|
|
17
|
+
"app/**/*"
|
|
18
|
+
]
|
|
19
|
+
}
|