@ezetgalaxy/titan 26.9.1 → 26.9.3
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 +17 -5
- package/index.js +177 -112
- package/package.json +19 -5
- package/templates/common/app/titan.d.ts +87 -0
- package/templates/extension/node_modules/.bin/esbuild +16 -0
- package/templates/extension/node_modules/.bin/esbuild.cmd +17 -0
- package/templates/extension/node_modules/.bin/esbuild.ps1 +28 -0
- package/templates/extension/node_modules/.bin/titanpl-sdk +16 -0
- package/templates/extension/node_modules/.bin/titanpl-sdk.cmd +17 -0
- package/templates/extension/node_modules/.bin/titanpl-sdk.ps1 +28 -0
- package/templates/extension/node_modules/.package-lock.json +111 -0
- package/templates/extension/node_modules/@esbuild/win32-x64/README.md +3 -0
- package/templates/extension/node_modules/@esbuild/win32-x64/esbuild.exe +0 -0
- package/templates/extension/node_modules/@esbuild/win32-x64/package.json +20 -0
- package/templates/extension/node_modules/@titanpl/core/LICENSE +15 -0
- package/templates/extension/node_modules/@titanpl/core/README.md +127 -0
- package/templates/extension/node_modules/@titanpl/core/globals.d.ts +17 -0
- package/templates/extension/node_modules/@titanpl/core/index.js +250 -0
- package/templates/extension/node_modules/@titanpl/core/native/target/release/titan_core.dll +0 -0
- package/templates/extension/node_modules/@titanpl/core/package.json +41 -0
- package/templates/extension/node_modules/@titanpl/core/titan.json +115 -0
- package/templates/extension/node_modules/chokidar/LICENSE +21 -0
- package/templates/extension/node_modules/chokidar/README.md +305 -0
- package/templates/extension/node_modules/chokidar/handler.d.ts +90 -0
- package/templates/extension/node_modules/chokidar/handler.js +632 -0
- package/templates/extension/node_modules/chokidar/index.d.ts +217 -0
- package/templates/extension/node_modules/chokidar/index.js +822 -0
- package/templates/extension/node_modules/chokidar/package.json +63 -0
- package/templates/extension/node_modules/esbuild/LICENSE.md +21 -0
- package/templates/extension/node_modules/esbuild/README.md +3 -0
- package/templates/extension/node_modules/esbuild/bin/esbuild +223 -0
- package/templates/extension/node_modules/esbuild/install.js +289 -0
- package/templates/extension/node_modules/esbuild/lib/main.d.ts +716 -0
- package/templates/extension/node_modules/esbuild/lib/main.js +2242 -0
- package/templates/extension/node_modules/esbuild/package.json +49 -0
- package/templates/extension/node_modules/readdirp/LICENSE +21 -0
- package/templates/extension/node_modules/readdirp/README.md +120 -0
- package/templates/extension/node_modules/readdirp/index.d.ts +108 -0
- package/templates/extension/node_modules/readdirp/index.js +272 -0
- package/templates/extension/node_modules/readdirp/package.json +66 -0
- package/templates/extension/node_modules/titanpl-sdk/LICENSE +15 -0
- package/templates/extension/node_modules/titanpl-sdk/README.md +109 -0
- package/templates/extension/node_modules/titanpl-sdk/assets/titanpl-sdk.png +0 -0
- package/templates/extension/node_modules/titanpl-sdk/bin/run.js +251 -0
- package/templates/extension/node_modules/titanpl-sdk/index.d.ts +46 -0
- package/templates/extension/node_modules/titanpl-sdk/index.js +5 -0
- package/templates/extension/node_modules/titanpl-sdk/package.json +33 -0
- package/templates/{rust-js → extension/node_modules/titanpl-sdk/templates}/Dockerfile +4 -17
- package/templates/extension/node_modules/titanpl-sdk/templates/app/actions/hello.js +5 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/app/app.js +10 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/jsconfig.json +19 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/server/Cargo.lock +2839 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/server/Cargo.toml +27 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/server/src/action_management.rs +131 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/server/src/errors.rs +10 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/server/src/extensions.rs +640 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/server/src/main.rs +345 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/server/src/utils.rs +33 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/titan/bundle.js +65 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/titan/dev.js +113 -0
- package/templates/extension/node_modules/titanpl-sdk/templates/titan/titan.js +98 -0
- package/templates/extension/package-lock.json +522 -0
- package/templates/extension/package.json +4 -3
- package/templates/rust-ts/app/actions/hello.ts +1 -1
- package/templates/rust-ts/titan/runtime.d.ts +1 -0
- package/templates/rust-ts/titan/runtime.js +1 -0
- package/templates/rust-ts/titan/titan.d.ts +117 -117
- package/templates/rust-ts/titan/titan.js +1 -1
- package/templates/ts/app/actions/hello.ts +1 -1
- package/templates/ts/titan/builder.js +121 -121
- package/templates/ts/titan/runtime.d.ts +1 -0
- package/templates/ts/titan/runtime.js +1 -1
- package/templates/ts/titan/titan.d.ts +117 -117
- package/templates/ts/titan/titan.js +1 -1
- package/titanpl-sdk/node_modules/.package-lock.json +17 -0
- package/titanpl-sdk/node_modules/@titanpl/core/LICENSE +15 -0
- package/titanpl-sdk/node_modules/@titanpl/core/README.md +127 -0
- package/titanpl-sdk/node_modules/@titanpl/core/globals.d.ts +17 -0
- package/titanpl-sdk/node_modules/@titanpl/core/index.js +250 -0
- package/titanpl-sdk/node_modules/@titanpl/core/native/target/release/titan_core.dll +0 -0
- package/titanpl-sdk/node_modules/@titanpl/core/package.json +41 -0
- package/titanpl-sdk/node_modules/@titanpl/core/titan.json +115 -0
- package/titanpl-sdk/package-lock.json +28 -0
- package/titanpl-sdk/package.json +6 -3
- package/templates/rust-js/_gitignore +0 -38
- package/templates/rust-js/app/titan.d.ts +0 -101
- package/templates/rust-ts/Dockerfile +0 -66
- package/templates/rust-ts/_dockerignore +0 -3
- package/templates/rust-ts/_gitignore +0 -38
- package/templates/ts/Dockerfile +0 -40
- package/templates/ts/_dockerignore +0 -3
- package/templates/ts/_gitignore +0 -38
- /package/templates/{js → common}/Dockerfile +0 -0
- /package/templates/{js → common}/_dockerignore +0 -0
- /package/templates/{js → common}/_gitignore +0 -0
- /package/templates/{rust-js/_dockerignore → extension/node_modules/titanpl-sdk/templates/.dockerignore} +0 -0
- /package/templates/{js → extension/node_modules/titanpl-sdk/templates}/app/titan.d.ts +0 -0
package/README.md
CHANGED
|
@@ -44,6 +44,7 @@ Titan = **TS/JS productivity × Rust performance × Zero DevOps**
|
|
|
44
44
|
| Zero-config Docker deploy | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
45
45
|
| Action-based architecture | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
46
46
|
| Hot reload dev server | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
47
|
+
| Modular, Isolated Templates | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
47
48
|
|
|
48
49
|
---
|
|
49
50
|
|
|
@@ -59,15 +60,26 @@ npm install -g @ezetgalaxy/titan
|
|
|
59
60
|
```
|
|
60
61
|
|
|
61
62
|
### 3. Initialize & Run
|
|
63
|
+
Titan guides you through selecting the perfect architecture for your needs.
|
|
64
|
+
|
|
62
65
|
```bash
|
|
63
66
|
titan init my-app
|
|
64
|
-
# Follow the interactive prompt to choose:
|
|
65
|
-
# - JavaScript (Standard)
|
|
66
|
-
# - TypeScript (Strict)
|
|
67
|
-
# - Rust + JavaScript (Beta)
|
|
68
|
-
# - Rust + TypeScript (Beta)
|
|
69
67
|
```
|
|
70
68
|
|
|
69
|
+
**Select your language:**
|
|
70
|
+
1. `JavaScript` (Fast, lightweight)
|
|
71
|
+
2. `TypeScript` (Strict, typed)
|
|
72
|
+
|
|
73
|
+
**Select your architecture:**
|
|
74
|
+
1. `Standard` (Pure JS/TS)
|
|
75
|
+
2. `Rust + JS/TS (Hybrid)` (High-performance native actions)
|
|
76
|
+
|
|
77
|
+
This creates one of four isolated environments:
|
|
78
|
+
* **Standard JS:** Lightweight server, zero Rust overhead.
|
|
79
|
+
* **Standard TS:** Strict server, zero Rust overhead.
|
|
80
|
+
* **Hybrid JS:** Full Rust integration + JS flexibility.
|
|
81
|
+
* **Hybrid TS:** Full Rust integration + TS strictness.
|
|
82
|
+
|
|
71
83
|
Inside your project:
|
|
72
84
|
```bash
|
|
73
85
|
cd my-app
|
package/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import prompts from "prompts";
|
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { execSync, spawn } from "child_process";
|
|
6
|
-
import { fileURLToPath } from "url";
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
7
7
|
|
|
8
8
|
/* Resolve __dirname for ES modules */
|
|
9
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -12,17 +12,17 @@ const __dirname = path.dirname(__filename);
|
|
|
12
12
|
/* -------------------------------------------------------
|
|
13
13
|
* Colors
|
|
14
14
|
* ----------------------------------------------------- */
|
|
15
|
-
const cyan = (t) => `\x1b[36m${t}\x1b[0m`;
|
|
16
|
-
const green = (t) => `\x1b[32m${t}\x1b[0m`;
|
|
17
|
-
const yellow = (t) => `\x1b[33m${t}\x1b[0m`;
|
|
18
|
-
const red = (t) => `\x1b[31m${t}\x1b[0m`;
|
|
19
|
-
const bold = (t) => `\x1b[1m${t}\x1b[0m`;
|
|
20
|
-
const gray = (t) => `\x1b[90m${t}\x1b[0m`;
|
|
15
|
+
export const cyan = (t) => `\x1b[36m${t}\x1b[0m`;
|
|
16
|
+
export const green = (t) => `\x1b[32m${t}\x1b[0m`;
|
|
17
|
+
export const yellow = (t) => `\x1b[33m${t}\x1b[0m`;
|
|
18
|
+
export const red = (t) => `\x1b[31m${t}\x1b[0m`;
|
|
19
|
+
export const bold = (t) => `\x1b[1m${t}\x1b[0m`;
|
|
20
|
+
export const gray = (t) => `\x1b[90m${t}\x1b[0m`;
|
|
21
21
|
|
|
22
22
|
/* -------------------------------------------------------
|
|
23
23
|
* Invocation detection (tit vs titan)
|
|
24
24
|
* ----------------------------------------------------- */
|
|
25
|
-
function wasInvokedAsTit() {
|
|
25
|
+
export function wasInvokedAsTit() {
|
|
26
26
|
const script = process.argv[1];
|
|
27
27
|
if (script) {
|
|
28
28
|
const base = path.basename(script, path.extname(script)).toLowerCase();
|
|
@@ -51,7 +51,6 @@ function wasInvokedAsTit() {
|
|
|
51
51
|
|
|
52
52
|
return false;
|
|
53
53
|
}
|
|
54
|
-
|
|
55
54
|
const isTitAlias = wasInvokedAsTit();
|
|
56
55
|
|
|
57
56
|
if (isTitAlias) {
|
|
@@ -63,24 +62,25 @@ if (isTitAlias) {
|
|
|
63
62
|
);
|
|
64
63
|
}
|
|
65
64
|
|
|
66
|
-
/* -------------------------------------------------------
|
|
67
|
-
* Args
|
|
68
|
-
* ----------------------------------------------------- */
|
|
69
|
-
const args = process.argv.slice(2);
|
|
70
|
-
const cmd = args[0];
|
|
71
|
-
|
|
72
65
|
/* -------------------------------------------------------
|
|
73
66
|
* Titan version
|
|
74
67
|
* ----------------------------------------------------- */
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
68
|
+
let TITAN_VERSION = "0.1.0";
|
|
69
|
+
try {
|
|
70
|
+
const pkg = JSON.parse(
|
|
71
|
+
fs.readFileSync(path.join(__dirname, "package.json"), "utf8")
|
|
72
|
+
);
|
|
73
|
+
TITAN_VERSION = pkg.version;
|
|
74
|
+
} catch (e) {
|
|
75
|
+
// Use default version
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export { TITAN_VERSION };
|
|
79
79
|
|
|
80
80
|
/* -------------------------------------------------------
|
|
81
81
|
* Utils
|
|
82
82
|
* ----------------------------------------------------- */
|
|
83
|
-
function copyDir(src, dest, excludes = []) {
|
|
83
|
+
export function copyDir(src, dest, excludes = []) {
|
|
84
84
|
fs.mkdirSync(dest, { recursive: true });
|
|
85
85
|
|
|
86
86
|
for (const file of fs.readdirSync(src)) {
|
|
@@ -103,26 +103,27 @@ function copyDir(src, dest, excludes = []) {
|
|
|
103
103
|
/* -------------------------------------------------------
|
|
104
104
|
* HELP
|
|
105
105
|
* ----------------------------------------------------- */
|
|
106
|
-
function help() {
|
|
106
|
+
export function help() {
|
|
107
107
|
console.log(`
|
|
108
|
-
${bold(cyan("Titan Planet"))} v${TITAN_VERSION}
|
|
108
|
+
${bold(cyan("Titan Planet"))} v${TITAN_VERSION}
|
|
109
109
|
|
|
110
|
-
${green("titan init <project> [-t <template>]")} Create new Titan project
|
|
111
|
-
${green("titan create ext <name>")} Create new Titan extension
|
|
112
|
-
${green("titan dev")} Dev mode (hot reload)
|
|
113
|
-
${green("titan build")} Build production Rust server
|
|
114
|
-
${green("titan start")} Start production binary
|
|
115
|
-
${green("titan update")} Update Titan engine
|
|
116
|
-
${green("titan --version")} Show Titan CLI version
|
|
110
|
+
${green("titan init <project> [-t <template>]")} Create new Titan project
|
|
111
|
+
${green("titan create ext <name>")} Create new Titan extension
|
|
112
|
+
${green("titan dev")} Dev mode (hot reload)
|
|
113
|
+
${green("titan build")} Build production Rust server
|
|
114
|
+
${green("titan start")} Start production binary
|
|
115
|
+
${green("titan update")} Update Titan engine
|
|
116
|
+
${green("titan --version")} Show Titan CLI version
|
|
117
117
|
|
|
118
|
-
${yellow("Note: `tit` is supported as a legacy alias.")}
|
|
118
|
+
${yellow("Note: `tit` is supported as a legacy alias.")}
|
|
119
119
|
`);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/* -------------------------------------------------------
|
|
123
123
|
* INIT
|
|
124
124
|
* ----------------------------------------------------- */
|
|
125
|
-
async function initProject(name, templateName) {
|
|
125
|
+
export async function initProject(name, templateName) {
|
|
126
|
+
// console.log(`DEBUG: initProject name=${name}, templateName=${templateName}`);
|
|
126
127
|
let projName = name;
|
|
127
128
|
|
|
128
129
|
if (!projName) {
|
|
@@ -150,7 +151,7 @@ async function initProject(name, templateName) {
|
|
|
150
151
|
message: 'Select language:',
|
|
151
152
|
choices: [
|
|
152
153
|
{ title: 'JavaScript', value: 'js' },
|
|
153
|
-
{ title: 'TypeScript', value: 'ts' }
|
|
154
|
+
{ title: 'TypeScript', value: 'ts' },
|
|
154
155
|
],
|
|
155
156
|
initial: 0
|
|
156
157
|
});
|
|
@@ -196,11 +197,16 @@ async function initProject(name, templateName) {
|
|
|
196
197
|
|
|
197
198
|
const target = path.join(process.cwd(), projName);
|
|
198
199
|
const templateDir = path.join(__dirname, "templates", selectedTemplate);
|
|
200
|
+
const commonDir = path.join(__dirname, "templates", "common");
|
|
199
201
|
|
|
200
202
|
if (!fs.existsSync(templateDir)) {
|
|
201
203
|
console.log(red(`Template '${selectedTemplate}' not found.`));
|
|
202
204
|
return;
|
|
203
205
|
}
|
|
206
|
+
if (!fs.existsSync(commonDir)) {
|
|
207
|
+
console.log(red(`Common template folder not found.`));
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
204
210
|
|
|
205
211
|
if (fs.existsSync(target)) {
|
|
206
212
|
console.log(yellow(`Folder already exists: ${target}`));
|
|
@@ -212,12 +218,17 @@ async function initProject(name, templateName) {
|
|
|
212
218
|
console.log(gray(` Template: ${selectedTemplate}`));
|
|
213
219
|
|
|
214
220
|
// ----------------------------------------------------------
|
|
215
|
-
// 1. Copy full
|
|
221
|
+
// 1. Copy full COMMON directory
|
|
222
|
+
// ----------------------------------------------------------
|
|
223
|
+
copyDir(commonDir, target, ["_gitignore", "_dockerignore"]);
|
|
224
|
+
|
|
225
|
+
// ----------------------------------------------------------
|
|
226
|
+
// 2. Copy full SELECTED template directory
|
|
216
227
|
// ----------------------------------------------------------
|
|
217
228
|
copyDir(templateDir, target, ["_gitignore", "_dockerignore"]);
|
|
218
229
|
|
|
219
230
|
// ----------------------------------------------------------
|
|
220
|
-
//
|
|
231
|
+
// 3. Explicitly install dotfiles from COMMON directory
|
|
221
232
|
// ----------------------------------------------------------
|
|
222
233
|
const dotfiles = {
|
|
223
234
|
"_gitignore": ".gitignore",
|
|
@@ -225,7 +236,7 @@ async function initProject(name, templateName) {
|
|
|
225
236
|
};
|
|
226
237
|
|
|
227
238
|
for (const [srcName, destName] of Object.entries(dotfiles)) {
|
|
228
|
-
const src = path.join(
|
|
239
|
+
const src = path.join(commonDir, srcName);
|
|
229
240
|
const dest = path.join(target, destName);
|
|
230
241
|
|
|
231
242
|
if (fs.existsSync(src)) {
|
|
@@ -233,10 +244,18 @@ async function initProject(name, templateName) {
|
|
|
233
244
|
}
|
|
234
245
|
}
|
|
235
246
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (fs.existsSync(
|
|
239
|
-
|
|
247
|
+
const pkgPath = path.join(target, "package.json");
|
|
248
|
+
|
|
249
|
+
if (fs.existsSync(pkgPath)) {
|
|
250
|
+
try {
|
|
251
|
+
const pkgContent = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
252
|
+
if (!pkgContent.titan) pkgContent.titan = {};
|
|
253
|
+
pkgContent.titan.template = selectedTemplate;
|
|
254
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkgContent, null, 2));
|
|
255
|
+
console.log(gray(` Metadata set: ${selectedTemplate}`));
|
|
256
|
+
} catch (e) {
|
|
257
|
+
console.log(yellow("⚠ Could not write template metadata to package.json"));
|
|
258
|
+
}
|
|
240
259
|
}
|
|
241
260
|
|
|
242
261
|
console.log(green("✔ Project structure created"));
|
|
@@ -263,7 +282,7 @@ async function initProject(name, templateName) {
|
|
|
263
282
|
/* -------------------------------------------------------
|
|
264
283
|
* DEV SERVER
|
|
265
284
|
* ----------------------------------------------------- */
|
|
266
|
-
async function devServer() {
|
|
285
|
+
export async function devServer() {
|
|
267
286
|
const root = process.cwd();
|
|
268
287
|
const devScript = path.join(root, "titan", "dev.js");
|
|
269
288
|
|
|
@@ -289,16 +308,17 @@ async function devServer() {
|
|
|
289
308
|
/* -------------------------------------------------------
|
|
290
309
|
* BUILD
|
|
291
310
|
* ----------------------------------------------------- */
|
|
292
|
-
async function buildProd() {
|
|
311
|
+
export async function buildProd() {
|
|
293
312
|
console.log(cyan("Titan: Building production output..."));
|
|
294
313
|
|
|
295
314
|
const root = process.cwd();
|
|
296
315
|
const appJs = path.join(root, "app", "app.js");
|
|
316
|
+
const appTs = path.join(root, "app", "app.ts");
|
|
297
317
|
const serverDir = path.join(root, "server");
|
|
298
318
|
const actionsOut = path.join(serverDir, "actions");
|
|
299
319
|
|
|
300
320
|
// BASIC CHECKS
|
|
301
|
-
if (!fs.existsSync(appJs) && !fs.existsSync(
|
|
321
|
+
if (!fs.existsSync(appJs) && !fs.existsSync(appTs)) {
|
|
302
322
|
console.log(red("ERROR: app/app.js or app/app.ts not found."));
|
|
303
323
|
process.exit(1);
|
|
304
324
|
}
|
|
@@ -327,10 +347,40 @@ async function buildProd() {
|
|
|
327
347
|
}
|
|
328
348
|
|
|
329
349
|
// ----------------------------------------------------
|
|
330
|
-
// 1) BUILD METADATA + BUNDLE ACTIONS
|
|
350
|
+
// 1) BUILD METADATA + BUNDLE ACTIONS
|
|
331
351
|
// ----------------------------------------------------
|
|
332
|
-
console.log(cyan("→ Building Titan metadata
|
|
333
|
-
|
|
352
|
+
console.log(cyan("→ Building Titan metadata..."));
|
|
353
|
+
|
|
354
|
+
// Si es TypeScript, compilar primero
|
|
355
|
+
if (fs.existsSync(appTs)) {
|
|
356
|
+
const dotTitan = path.join(root, ".titan");
|
|
357
|
+
const compiledApp = path.join(dotTitan, "app.js");
|
|
358
|
+
|
|
359
|
+
if (!fs.existsSync(dotTitan)) fs.mkdirSync(dotTitan, { recursive: true });
|
|
360
|
+
|
|
361
|
+
// Importar esbuild dinámicamente
|
|
362
|
+
const esbuild = await import("esbuild");
|
|
363
|
+
await esbuild.build({
|
|
364
|
+
entryPoints: [appTs],
|
|
365
|
+
outfile: compiledApp,
|
|
366
|
+
bundle: true,
|
|
367
|
+
platform: "node",
|
|
368
|
+
format: "esm",
|
|
369
|
+
packages: "external",
|
|
370
|
+
logLevel: "silent"
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
execSync(`node "${compiledApp}" --build`, { stdio: "inherit" });
|
|
374
|
+
} else {
|
|
375
|
+
execSync("node app/app.js --build", { stdio: "inherit" });
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
console.log(cyan("→ Bundling actions..."));
|
|
379
|
+
const bundlePath = path.join(root, "titan", "bundle.js");
|
|
380
|
+
// Convert Windows path to file:// URL for ESM import
|
|
381
|
+
const bundleUrl = pathToFileURL(bundlePath).href;
|
|
382
|
+
const { bundle } = await import(bundleUrl);
|
|
383
|
+
await bundle();
|
|
334
384
|
|
|
335
385
|
// ensure actions directory exists
|
|
336
386
|
fs.mkdirSync(actionsOut, { recursive: true });
|
|
@@ -338,9 +388,13 @@ async function buildProd() {
|
|
|
338
388
|
// verify bundled actions exist
|
|
339
389
|
const bundles = fs.readdirSync(actionsOut).filter(f => f.endsWith(".jsbundle"));
|
|
340
390
|
if (bundles.length === 0) {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
391
|
+
const rustActionsDir = path.join(serverDir, "src", "actions_rust");
|
|
392
|
+
const hasRustActions = fs.existsSync(rustActionsDir) &&
|
|
393
|
+
fs.readdirSync(rustActionsDir).some(f => f.endsWith(".rs") && f !== "mod.rs");
|
|
394
|
+
|
|
395
|
+
if (!hasRustActions) {
|
|
396
|
+
console.log(yellow("⚠ Warning: No JS or Rust actions found."));
|
|
397
|
+
}
|
|
344
398
|
}
|
|
345
399
|
|
|
346
400
|
bundles.forEach(file => {
|
|
@@ -369,7 +423,7 @@ async function buildProd() {
|
|
|
369
423
|
/* -------------------------------------------------------
|
|
370
424
|
* START
|
|
371
425
|
* ----------------------------------------------------- */
|
|
372
|
-
|
|
426
|
+
export function startProd() {
|
|
373
427
|
const isWin = process.platform === "win32";
|
|
374
428
|
const bin = isWin ? "titan-server.exe" : "titan-server";
|
|
375
429
|
const root = process.cwd();
|
|
@@ -388,21 +442,19 @@ async function startProd() {
|
|
|
388
442
|
// Let's check for `.titan/app.js` which is dev artifact? No, use the prod build artifact.
|
|
389
443
|
execSync(`node "${appJs}"`, { stdio: "inherit" });
|
|
390
444
|
}
|
|
391
|
-
|
|
392
445
|
}
|
|
393
446
|
|
|
394
447
|
/* -------------------------------------------------------
|
|
395
448
|
* UPDATE
|
|
396
449
|
* ----------------------------------------------------- */
|
|
397
|
-
|
|
398
|
-
function updateTitan() {
|
|
450
|
+
export function updateTitan() {
|
|
399
451
|
const root = process.cwd();
|
|
400
452
|
|
|
401
453
|
const projectTitan = path.join(root, "titan");
|
|
402
454
|
const projectServer = path.join(root, "server");
|
|
403
455
|
const projectPkg = path.join(root, "package.json");
|
|
404
456
|
|
|
405
|
-
let templateType = "js";
|
|
457
|
+
let templateType = "js";
|
|
406
458
|
if (fs.existsSync(projectPkg)) {
|
|
407
459
|
try {
|
|
408
460
|
const pkg = JSON.parse(fs.readFileSync(projectPkg, "utf-8"));
|
|
@@ -421,10 +473,8 @@ function updateTitan() {
|
|
|
421
473
|
return;
|
|
422
474
|
}
|
|
423
475
|
|
|
424
|
-
if (!fs.existsSync(
|
|
425
|
-
console.log(red(`
|
|
426
|
-
console.log(red(`Expected server template at: ${templateServer}`));
|
|
427
|
-
console.log(yellow(`If you are running from npx, try clearing cache or installing a specific version.`));
|
|
476
|
+
if (!fs.existsSync(templatesRoot)) {
|
|
477
|
+
console.log(red(`Template type '${templateType}' not found in CLI templates.`));
|
|
428
478
|
return;
|
|
429
479
|
}
|
|
430
480
|
|
|
@@ -433,15 +483,18 @@ function updateTitan() {
|
|
|
433
483
|
// ----------------------------------------------------------
|
|
434
484
|
// 1. Update titan/ runtime (authoritative, safe to replace)
|
|
435
485
|
// ----------------------------------------------------------
|
|
436
|
-
fs.
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
486
|
+
if (fs.existsSync(templateTitan)) {
|
|
487
|
+
fs.rmSync(projectTitan, {
|
|
488
|
+
recursive: true,
|
|
489
|
+
force: true,
|
|
490
|
+
maxRetries: 10,
|
|
491
|
+
retryDelay: 500,
|
|
492
|
+
});
|
|
493
|
+
copyDir(templateTitan, projectTitan);
|
|
494
|
+
console.log(green("✔ Updated titan/ runtime"));
|
|
495
|
+
} else {
|
|
496
|
+
console.log(yellow(`⚠ No titan/ folder found in template '${templateType}', skipping.`));
|
|
497
|
+
}
|
|
445
498
|
|
|
446
499
|
// ----------------------------------------------------------
|
|
447
500
|
// 2. Update server/ WITHOUT deleting the folder
|
|
@@ -463,18 +516,19 @@ function updateTitan() {
|
|
|
463
516
|
const projectSrc = path.join(projectServer, "src");
|
|
464
517
|
const templateSrc = path.join(templateServer, "src");
|
|
465
518
|
|
|
466
|
-
if (fs.existsSync(
|
|
467
|
-
fs.
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
519
|
+
if (fs.existsSync(templateSrc)) {
|
|
520
|
+
if (fs.existsSync(projectSrc)) {
|
|
521
|
+
fs.rmSync(projectSrc, {
|
|
522
|
+
recursive: true,
|
|
523
|
+
force: true,
|
|
524
|
+
maxRetries: 10,
|
|
525
|
+
retryDelay: 500,
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
copyDir(templateSrc, projectSrc);
|
|
529
|
+
console.log(green("✔ Updated server/src/"));
|
|
473
530
|
}
|
|
474
531
|
|
|
475
|
-
copyDir(templateSrc, projectSrc);
|
|
476
|
-
console.log(green("✔ Updated server/src/"));
|
|
477
|
-
|
|
478
532
|
// Root-level config files
|
|
479
533
|
const rootFiles = {
|
|
480
534
|
"_gitignore": ".gitignore",
|
|
@@ -495,15 +549,16 @@ function updateTitan() {
|
|
|
495
549
|
|
|
496
550
|
// app/titan.d.ts (JS typing contract)
|
|
497
551
|
const appDir = path.join(root, "app");
|
|
498
|
-
const srcDts = path.join(templateServer, "../app/titan.d.ts");
|
|
552
|
+
const srcDts = path.join(templateServer, "../app/titan.d.ts");
|
|
553
|
+
const fallbackDts = path.join(templatesRoot, "app", "titan.d.ts");
|
|
554
|
+
const finalDtsSrc = fs.existsSync(srcDts) ? srcDts : (fs.existsSync(fallbackDts) ? fallbackDts : null);
|
|
499
555
|
const destDts = path.join(appDir, "titan.d.ts");
|
|
500
556
|
|
|
501
|
-
if (
|
|
557
|
+
if (finalDtsSrc) {
|
|
502
558
|
if (!fs.existsSync(appDir)) {
|
|
503
559
|
fs.mkdirSync(appDir);
|
|
504
560
|
}
|
|
505
|
-
|
|
506
|
-
fs.copyFileSync(srcDts, destDts);
|
|
561
|
+
fs.copyFileSync(finalDtsSrc, destDts);
|
|
507
562
|
console.log(green("✔ Updated app/titan.d.ts"));
|
|
508
563
|
}
|
|
509
564
|
|
|
@@ -516,7 +571,7 @@ function updateTitan() {
|
|
|
516
571
|
/* -------------------------------------------------------
|
|
517
572
|
* CREATE EXTENSION
|
|
518
573
|
* ----------------------------------------------------- */
|
|
519
|
-
function createExtension(name) {
|
|
574
|
+
export function createExtension(name) {
|
|
520
575
|
if (!name) {
|
|
521
576
|
console.log(red("Usage: titan create ext <name>"));
|
|
522
577
|
return;
|
|
@@ -585,7 +640,7 @@ Next steps:
|
|
|
585
640
|
`);
|
|
586
641
|
}
|
|
587
642
|
|
|
588
|
-
function runExtension() {
|
|
643
|
+
export function runExtension() {
|
|
589
644
|
const localSdk = path.join(__dirname, "titanpl-sdk", "bin", "run.js");
|
|
590
645
|
|
|
591
646
|
if (fs.existsSync(localSdk)) {
|
|
@@ -608,35 +663,45 @@ function runExtension() {
|
|
|
608
663
|
/* -------------------------------------------------------
|
|
609
664
|
* ROUTER
|
|
610
665
|
* ----------------------------------------------------- */
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
666
|
+
const isMainModule = process.argv[1] === fileURLToPath(import.meta.url);
|
|
667
|
+
|
|
668
|
+
if (isMainModule) {
|
|
669
|
+
const args = process.argv.slice(2);
|
|
670
|
+
// console.log("DEBUG: args", args);
|
|
671
|
+
const cmd = args[0];
|
|
672
|
+
|
|
673
|
+
(async () => {
|
|
674
|
+
// "titan create ext <name>" -> args = ["create", "ext", "calc_ext"]
|
|
675
|
+
if (cmd === "create" && args[1] === "ext") {
|
|
676
|
+
createExtension(args[2]);
|
|
677
|
+
} else if (cmd === "run" && args[1] === "ext") {
|
|
678
|
+
runExtension();
|
|
679
|
+
} else {
|
|
680
|
+
switch (cmd) {
|
|
681
|
+
case "init": {
|
|
682
|
+
const projName = args[1];
|
|
683
|
+
let tpl = null;
|
|
684
|
+
|
|
685
|
+
const tIndex = args.indexOf("--template") > -1 ? args.indexOf("--template") : args.indexOf("-t");
|
|
686
|
+
if (tIndex > -1 && args[tIndex + 1]) {
|
|
687
|
+
tpl = args[tIndex + 1];
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
await initProject(projName, tpl);
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
case "dev": devServer(); break;
|
|
694
|
+
case "build": await buildProd(); break;
|
|
695
|
+
case "start": startProd(); break;
|
|
696
|
+
case "update": updateTitan(); break;
|
|
697
|
+
case "--version":
|
|
698
|
+
case "-v":
|
|
699
|
+
case "version":
|
|
700
|
+
console.log(cyan(`Titan v${TITAN_VERSION}`));
|
|
701
|
+
break;
|
|
702
|
+
default:
|
|
703
|
+
help();
|
|
625
704
|
}
|
|
626
|
-
|
|
627
|
-
initProject(projName, tpl);
|
|
628
|
-
break;
|
|
629
705
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
case "start": await startProd(); break;
|
|
633
|
-
case "update": updateTitan(); break;
|
|
634
|
-
case "--version":
|
|
635
|
-
case "-v":
|
|
636
|
-
case "version":
|
|
637
|
-
console.log(cyan(`Titan v${TITAN_VERSION}`));
|
|
638
|
-
break;
|
|
639
|
-
default:
|
|
640
|
-
help();
|
|
641
|
-
}
|
|
642
|
-
}
|
|
706
|
+
})();
|
|
707
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ezetgalaxy/titan",
|
|
3
|
-
"version": "26.9.
|
|
3
|
+
"version": "26.9.3",
|
|
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",
|
|
@@ -42,13 +42,27 @@
|
|
|
42
42
|
"super-backend"
|
|
43
43
|
],
|
|
44
44
|
"scripts": {
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
45
|
+
"init": "rm -rf build && node index.js init build",
|
|
46
|
+
"build": "cd build && node ../index.js build",
|
|
47
|
+
"dev": "cd build && node ../index.js dev",
|
|
48
|
+
"start": "cd build && node ../index.js start",
|
|
49
|
+
"help": "cd build && node ../index.js help",
|
|
50
|
+
"update": "cd build && node ../index.js update",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"test:watch": "vitest",
|
|
53
|
+
"test:coverage": "vitest run --coverage",
|
|
54
|
+
"test:cov": "vitest run --coverage",
|
|
55
|
+
"test:ui": "vitest --ui"
|
|
48
56
|
},
|
|
49
57
|
"dependencies": {
|
|
58
|
+
"@titanpl/core": "^1.0.1",
|
|
50
59
|
"chokidar": "^5.0.0",
|
|
51
60
|
"esbuild": "^0.27.2",
|
|
52
61
|
"prompts": "^2.4.2"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@vitest/coverage-v8": "^4.0.17",
|
|
65
|
+
"@vitest/ui": "^4.0.17",
|
|
66
|
+
"vitest": "^4.0.17"
|
|
53
67
|
}
|
|
54
|
-
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TITAN TYPE DEFINITIONS
|
|
3
|
+
* ----------------------
|
|
4
|
+
* These types are globally available in your Titan project.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The Titan Request Object passed to actions.
|
|
9
|
+
*/
|
|
10
|
+
declare 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
|
+
}
|
|
24
|
+
|
|
25
|
+
interface DbConnection {
|
|
26
|
+
/**
|
|
27
|
+
* Execute a SQL query.
|
|
28
|
+
* @param sql The SQL query string.
|
|
29
|
+
* @param params (Optional) Parameters for the query ($1, $2, etc).
|
|
30
|
+
*/
|
|
31
|
+
query(sql: string, params?: any[]): any[];
|
|
32
|
+
}
|
|
33
|
+
|
|
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;
|
|
42
|
+
|
|
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
|
+
|
|
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;
|
|
57
|
+
|
|
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
|
+
};
|
|
68
|
+
|
|
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
|
+
};
|
|
77
|
+
|
|
78
|
+
password: {
|
|
79
|
+
hash(password: string): string;
|
|
80
|
+
verify(password: string, hash: string): boolean;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
db: {
|
|
84
|
+
connect(url: string): DbConnection;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
+
|
|
4
|
+
case `uname` in
|
|
5
|
+
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
+
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
+
basedir=`cygpath -w "$basedir"`
|
|
8
|
+
fi
|
|
9
|
+
;;
|
|
10
|
+
esac
|
|
11
|
+
|
|
12
|
+
if [ -x "$basedir/node" ]; then
|
|
13
|
+
exec "$basedir/node" "$basedir/../esbuild/bin/esbuild" "$@"
|
|
14
|
+
else
|
|
15
|
+
exec node "$basedir/../esbuild/bin/esbuild" "$@"
|
|
16
|
+
fi
|