@ezetgalaxy/titan 26.9.0 → 26.9.2

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.
Files changed (54) hide show
  1. package/README.md +39 -17
  2. package/index.js +227 -120
  3. package/package.json +17 -5
  4. package/templates/{js → common}/app/titan.d.ts +1 -1
  5. package/templates/{rust → rust-js}/package.json +1 -1
  6. package/templates/rust-ts/app/actions/hello.ts +10 -4
  7. package/templates/rust-ts/app/app.ts +1 -1
  8. package/templates/rust-ts/titan/bundle.js +15 -9
  9. package/templates/rust-ts/titan/dev.js +2 -2
  10. package/templates/rust-ts/titan/runtime.d.ts +1 -0
  11. package/templates/rust-ts/titan/runtime.js +1 -0
  12. package/templates/rust-ts/titan/titan.d.ts +117 -0
  13. package/templates/rust-ts/titan/titan.js +95 -95
  14. package/templates/ts/app/actions/hello.ts +2 -0
  15. package/templates/ts/app/app.ts +1 -1
  16. package/templates/ts/titan/builder.js +121 -0
  17. package/templates/ts/titan/bundle.js +9 -11
  18. package/templates/ts/titan/dev.js +2 -2
  19. package/templates/ts/titan/runtime.d.ts +1 -0
  20. package/templates/ts/titan/runtime.js +1 -0
  21. package/templates/ts/titan/titan.d.ts +117 -0
  22. package/templates/ts/titan/titan.js +95 -95
  23. package/titanpl-sdk/README.md +4 -4
  24. package/titanpl-sdk/bin/run.js +74 -77
  25. package/titanpl-sdk/package.json +1 -1
  26. package/templates/rust/Dockerfile +0 -66
  27. package/templates/rust/_dockerignore +0 -3
  28. package/templates/rust/_gitignore +0 -38
  29. package/templates/rust/app/titan.d.ts +0 -101
  30. package/templates/rust-ts/Dockerfile +0 -66
  31. package/templates/rust-ts/_dockerignore +0 -3
  32. package/templates/rust-ts/_gitignore +0 -38
  33. package/templates/rust-ts/app/titan.d.ts +0 -101
  34. package/templates/ts/Dockerfile +0 -66
  35. package/templates/ts/_dockerignore +0 -3
  36. package/templates/ts/_gitignore +0 -38
  37. package/templates/ts/app/titan.d.ts +0 -102
  38. /package/templates/{js → common}/Dockerfile +0 -0
  39. /package/templates/{js → common}/_dockerignore +0 -0
  40. /package/templates/{js → common}/_gitignore +0 -0
  41. /package/templates/{rust → rust-js}/app/actions/hello.js +0 -0
  42. /package/templates/{rust → rust-js}/app/actions/rust_hello.rs +0 -0
  43. /package/templates/{rust → rust-js}/app/app.js +0 -0
  44. /package/templates/{rust → rust-js}/jsconfig.json +0 -0
  45. /package/templates/{rust → rust-js}/server/Cargo.lock +0 -0
  46. /package/templates/{rust → rust-js}/server/Cargo.toml +0 -0
  47. /package/templates/{rust → rust-js}/server/src/action_management.rs +0 -0
  48. /package/templates/{rust → rust-js}/server/src/errors.rs +0 -0
  49. /package/templates/{rust → rust-js}/server/src/extensions.rs +0 -0
  50. /package/templates/{rust → rust-js}/server/src/main.rs +0 -0
  51. /package/templates/{rust → rust-js}/server/src/utils.rs +0 -0
  52. /package/templates/{rust → rust-js}/titan/bundle.js +0 -0
  53. /package/templates/{rust → rust-js}/titan/dev.js +0 -0
  54. /package/templates/{rust → rust-js}/titan/titan.js +0 -0
@@ -0,0 +1 @@
1
+ export const defineAction = (handler) => handler;
@@ -0,0 +1,117 @@
1
+
2
+ // -- Module Definitions (for imports from "titan") --
3
+
4
+ export interface RouteHandler {
5
+ reply(value: any): void;
6
+ action(name: string): void;
7
+ }
8
+
9
+ export interface TitanBuilder {
10
+ get(route: string): RouteHandler;
11
+ post(route: string): RouteHandler;
12
+ log(module: string, msg: string): void;
13
+ start(port?: number, msg?: string): Promise<void>;
14
+ }
15
+
16
+ // The default export from titan.js is the Builder
17
+ declare const builder: TitanBuilder;
18
+ export default builder;
19
+
20
+ /**
21
+ * Define a Titan Action with type inference.
22
+ */
23
+ export declare function defineAction<T>(actionFn: (req: TitanRequest) => T): (req: TitanRequest) => T;
24
+
25
+
26
+ // -- Global Definitions (Runtime Environment) --
27
+
28
+ declare global {
29
+ /**
30
+ * The Titan Request Object passed to actions.
31
+ */
32
+ interface TitanRequest {
33
+ body: any;
34
+ method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
35
+ path: string;
36
+ headers: {
37
+ host?: string;
38
+ "content-type"?: string;
39
+ "user-agent"?: string;
40
+ authorization?: string;
41
+ [key: string]: string | undefined;
42
+ };
43
+ params: Record<string, string>;
44
+ query: Record<string, string>;
45
+ }
46
+
47
+ interface DbConnection {
48
+ /**
49
+ * Execute a SQL query.
50
+ * @param sql The SQL query string.
51
+ * @param params (Optional) Parameters for the query ($1, $2, etc).
52
+ */
53
+ query(sql: string, params?: any[]): any[];
54
+ }
55
+
56
+ /**
57
+ * Global defineAction (available without import in runtime, though imports are preferred in TS)
58
+ */
59
+ function defineAction<T>(actionFn: (req: TitanRequest) => T): (req: TitanRequest) => T;
60
+
61
+ /**
62
+ * Global Request Object
63
+ * Available automatically in actions.
64
+ */
65
+ var req: TitanRequest;
66
+
67
+ /**
68
+ * Titan Runtime Utilities
69
+ * (Available globally in the runtime, e.g. inside actions)
70
+ */
71
+ const t: {
72
+ /**
73
+ * Log messages to the server console with Titan formatting.
74
+ */
75
+ log(...args: any[]): void;
76
+
77
+ /**
78
+ * Read a file contents as string.
79
+ * @param path Relative path to the file from project root.
80
+ */
81
+ read(path: string): string;
82
+
83
+ fetch(url: string, options?: {
84
+ method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
85
+ headers?: Record<string, string>;
86
+ body?: string | object;
87
+ }): {
88
+ ok: boolean;
89
+ status?: number;
90
+ body?: string;
91
+ error?: string;
92
+ };
93
+
94
+ jwt: {
95
+ sign(
96
+ payload: object,
97
+ secret: string,
98
+ options?: { expiresIn?: string | number }
99
+ ): string;
100
+ verify(token: string, secret: string): any;
101
+ };
102
+
103
+ password: {
104
+ hash(password: string): string;
105
+ verify(password: string, hash: string): boolean;
106
+ };
107
+
108
+ db: {
109
+ connect(url: string): DbConnection;
110
+ };
111
+
112
+ /**
113
+ * Titan Validator (Zod-compatible)
114
+ */
115
+ valid: any;
116
+ };
117
+ }
@@ -1,6 +1,8 @@
1
+ import { bundle } from "./bundle.js";
1
2
  import fs from "fs";
2
3
  import path from "path";
3
- import { bundle } from "./bundle.js";
4
+
5
+ export * from "./runtime.js";
4
6
 
5
7
  const cyan = (t) => `\x1b[36m${t}\x1b[0m`;
6
8
  const green = (t) => `\x1b[32m${t}\x1b[0m`;
@@ -10,34 +12,33 @@ const dynamicRoutes = {};
10
12
  const actionMap = {};
11
13
 
12
14
  function addRoute(method, route) {
13
- const key = `${method.toUpperCase()}:${route}`;
14
-
15
-
16
- return {
17
- reply(value) {
18
- routes[key] = {
19
- type: typeof value === "object" ? "json" : "text",
20
- value
21
- };
22
- },
23
-
24
- action(name) {
25
- if (route.includes(":")) {
26
- if (!dynamicRoutes[method]) dynamicRoutes[method] = [];
27
- dynamicRoutes[method].push({
28
- method: method.toUpperCase(),
29
- pattern: route,
30
- action: name
31
- });
32
- } else {
33
- routes[key] = {
34
- type: "action",
35
- value: name
36
- };
37
- actionMap[key] = name;
38
- }
39
- }
40
- };
15
+ const key = `${method.toUpperCase()}:${route}`;
16
+
17
+ return {
18
+ reply(value) {
19
+ routes[key] = {
20
+ type: typeof value === "object" ? "json" : "text",
21
+ value
22
+ };
23
+ },
24
+
25
+ action(name) {
26
+ if (route.includes(":")) {
27
+ if (!dynamicRoutes[method]) dynamicRoutes[method] = [];
28
+ dynamicRoutes[method].push({
29
+ method: method.toUpperCase(),
30
+ pattern: route,
31
+ action: name
32
+ });
33
+ } else {
34
+ routes[key] = {
35
+ type: "action",
36
+ value: name
37
+ };
38
+ actionMap[key] = name;
39
+ }
40
+ }
41
+ };
41
42
  }
42
43
 
43
44
  /**
@@ -50,73 +51,72 @@ function addRoute(method, route) {
50
51
  * Titan App Builder
51
52
  */
52
53
  const t = {
53
- /**
54
- * Define a GET route
55
- * @param {string} route
56
- * @returns {RouteHandler}
57
- */
58
- get(route) {
59
- return addRoute("GET", route);
60
- },
61
-
62
- /**
63
- * Define a POST route
64
- * @param {string} route
65
- * @returns {RouteHandler}
66
- */
67
- post(route) {
68
- return addRoute("POST", route);
69
- },
70
-
71
- log(module, msg) {
72
- console.log(`[\x1b[35m${module}\x1b[0m] ${msg}`);
73
- },
74
-
75
- /**
76
- * Start the Titan Server
77
- * @param {number} [port=3000]
78
- * @param {string} [msg=""]
79
- */
80
- async start(port = 3000, msg = "") {
81
- try {
82
- console.log(cyan("[Titan] Preparing runtime..."));
83
- await bundle();
84
-
85
- const base = path.join(process.cwd(), "server");
86
- if (!fs.existsSync(base)) {
87
- fs.mkdirSync(base, { recursive: true });
88
- }
89
-
90
- const routesPath = path.join(base, "routes.json");
91
- const actionMapPath = path.join(base, "action_map.json");
92
-
93
- fs.writeFileSync(
94
- routesPath,
95
- JSON.stringify(
96
- {
97
- __config: { port },
98
- routes,
99
- __dynamic_routes: Object.values(dynamicRoutes).flat()
100
- },
101
- null,
102
- 2
103
- )
104
- );
105
-
106
- fs.writeFileSync(
107
- actionMapPath,
108
- JSON.stringify(actionMap, null, 2)
109
- );
110
-
111
- console.log(green("✔ Titan metadata written successfully"));
112
- if (msg) console.log(cyan(msg));
113
-
114
- } catch (e) {
115
- console.error(`\x1b[31m[Titan] Build Error: ${e.message}\x1b[0m`);
116
- process.exit(1);
54
+ /**
55
+ * Define a GET route
56
+ * @param {string} route
57
+ * @returns {RouteHandler}
58
+ */
59
+ get(route) {
60
+ return addRoute("GET", route);
61
+ },
62
+
63
+ /**
64
+ * Define a POST route
65
+ * @param {string} route
66
+ * @returns {RouteHandler}
67
+ */
68
+ post(route) {
69
+ return addRoute("POST", route);
70
+ },
71
+
72
+ log(module, msg) {
73
+ console.log(`[\x1b[35m${module}\x1b[0m] ${msg}`);
74
+ },
75
+
76
+ /**
77
+ * Start the Titan Server
78
+ * @param {number} [port=3000]
79
+ * @param {string} [msg=""]
80
+ */
81
+ async start(port = 3000, msg = "") {
82
+ try {
83
+ console.log(cyan("[Titan] Preparing runtime..."));
84
+ await bundle();
85
+
86
+ const base = path.join(process.cwd(), "server");
87
+ if (!fs.existsSync(base)) {
88
+ fs.mkdirSync(base, { recursive: true });
89
+ }
90
+
91
+ const routesPath = path.join(base, "routes.json");
92
+ const actionMapPath = path.join(base, "action_map.json");
93
+
94
+ fs.writeFileSync(
95
+ routesPath,
96
+ JSON.stringify(
97
+ {
98
+ __config: { port },
99
+ routes,
100
+ __dynamic_routes: Object.values(dynamicRoutes).flat()
101
+ },
102
+ null,
103
+ 2
104
+ )
105
+ );
106
+
107
+ fs.writeFileSync(
108
+ actionMapPath,
109
+ JSON.stringify(actionMap, null, 2)
110
+ );
111
+
112
+ console.log(green("✔ Titan metadata written successfully"));
113
+ if (msg) console.log(cyan(msg));
114
+
115
+ } catch (e) {
116
+ console.error(`\x1b[31m[Titan] Build Error: ${e.message}\x1b[0m`);
117
+ process.exit(1);
118
+ }
117
119
  }
118
- }
119
120
  };
120
121
 
121
-
122
122
  export default t;
@@ -75,11 +75,11 @@ Since the `t` object is injected globally by the Titan engine at runtime, your I
75
75
  ```
76
76
 
77
77
  Now your editor will treat `t` as a first-class citizen:
78
- ```js
79
- export function myAction(req) {
80
- t.log.info("Request received", req.path); // Autocomplete works!
78
+ ```ts
79
+ export const myAction = defineAction((req) => {
80
+ t.log("Request received", req.path); // Autocomplete works!
81
81
  return { status: "ok" };
82
- }
82
+ });
83
83
  ```
84
84
 
85
85
  ---
@@ -53,85 +53,89 @@ function run() {
53
53
  }
54
54
  }
55
55
 
56
- // 3. Create a Test Harness (Mini Titan Project)
56
+ // 3. Setup Test Harness (Mini Titan Project)
57
57
  const runDir = path.join(cwd, ".titan_test_run");
58
- if (fs.existsSync(runDir)) {
59
- try {
60
- fs.rmSync(runDir, {
61
- recursive: true,
62
- force: true,
63
- maxRetries: 10,
64
- retryDelay: 100
65
- });
66
- } catch (e) {
67
- console.log(yellow(`Warning: Could not fully clean ${runDir}. Proceeding anyway...`));
68
- }
69
- }
58
+ const isFirstRun = !fs.existsSync(runDir);
70
59
 
71
- // Ensure runDir exists (sometimes rmSync + mkdirSync fails on Windows due to locks)
72
- if (!fs.existsSync(runDir)) {
60
+ if (isFirstRun) {
61
+ console.log(cyan("Initializing test environment..."));
73
62
  fs.mkdirSync(runDir, { recursive: true });
74
- }
75
63
 
76
- // Create app structure
77
- const appDir = path.join(runDir, "app");
78
- fs.mkdirSync(appDir);
79
-
80
- // Create actions folder (required by Titan build)
81
- const actionsDir = path.join(appDir, "actions");
82
- fs.mkdirSync(actionsDir);
83
-
84
- // Copy titan/ and server/ from templates
85
- const templatesDir = path.join(__dirname, "..", "templates");
86
-
87
- const titanSrc = path.join(templatesDir, "titan");
88
- const titanDest = path.join(runDir, "titan");
89
- if (fs.existsSync(titanSrc)) {
90
- console.log(cyan("→ Setting up Titan runtime..."));
91
- copyDir(titanSrc, titanDest);
92
- // Double check titan.js exists
93
- if (!fs.existsSync(path.join(titanDest, "titan.js"))) {
94
- console.log(red(`Error: Failed to copy titan.js to ${titanDest}`));
64
+ // Create app structure
65
+ const appDir = path.join(runDir, "app");
66
+ fs.mkdirSync(appDir);
67
+
68
+ // Create actions folder (required by Titan build)
69
+ const actionsDir = path.join(appDir, "actions");
70
+ fs.mkdirSync(actionsDir);
71
+
72
+ // Copy titan/ and server/ from templates
73
+ const templatesDir = path.join(__dirname, "..", "templates");
74
+
75
+ const titanSrc = path.join(templatesDir, "titan");
76
+ const titanDest = path.join(runDir, "titan");
77
+ if (fs.existsSync(titanSrc)) {
78
+ copyDir(titanSrc, titanDest);
79
+ // Double check titan.js exists
80
+ if (!fs.existsSync(path.join(titanDest, "titan.js"))) {
81
+ console.log(red(`Error: Failed to copy titan.js to ${titanDest}`));
82
+ process.exit(1);
83
+ }
84
+ } else {
85
+ console.log(red(`Error: Titan templates not found at ${titanSrc}`));
95
86
  process.exit(1);
96
87
  }
97
- } else {
98
- console.log(red(`Error: Titan templates not found at ${titanSrc}`));
99
- process.exit(1);
100
- }
101
88
 
102
- const serverSrc = path.join(templatesDir, "server");
103
- const serverDest = path.join(runDir, "server");
104
- if (fs.existsSync(serverSrc)) {
105
- console.log(cyan("→ Setting up Titan server..."));
106
- copyDir(serverSrc, serverDest);
89
+ const serverSrc = path.join(templatesDir, "server");
90
+ const serverDest = path.join(runDir, "server");
91
+ if (fs.existsSync(serverSrc)) {
92
+ copyDir(serverSrc, serverDest);
93
+ } else {
94
+ console.log(red(`Error: Server templates not found at ${serverSrc}`));
95
+ process.exit(1);
96
+ }
97
+
98
+ // Create package.json for the test harness
99
+ const pkgJson = {
100
+ "type": "module"
101
+ };
102
+ fs.writeFileSync(path.join(runDir, "package.json"), JSON.stringify(pkgJson, null, 2));
103
+
104
+ // Create 'node_modules'
105
+ fs.mkdirSync(path.join(runDir, "node_modules"));
107
106
  } else {
108
- console.log(red(`Error: Server templates not found at ${serverSrc}`));
109
- process.exit(1);
107
+ console.log(cyan("Using existing test environment..."));
110
108
  }
111
109
 
112
- // Create package.json for the test harness
113
- const pkgJson = {
114
- "type": "module"
115
- };
116
- fs.writeFileSync(path.join(runDir, "package.json"), JSON.stringify(pkgJson, null, 2));
117
-
118
- // Create 'node_modules' to link the extension
110
+ // Always Ensure Extension Link is Fresh
119
111
  const nmDir = path.join(runDir, "node_modules");
120
- fs.mkdirSync(nmDir);
112
+ if (!fs.existsSync(nmDir)) fs.mkdirSync(nmDir, { recursive: true });
121
113
 
122
- // Link current extension to node_modules/NAME
123
- // Use junction for Windows compat without admin rights
124
114
  const extDest = path.join(nmDir, name);
115
+
116
+ // Remove old link/folder if exists to ensure freshness
117
+ if (fs.existsSync(extDest)) {
118
+ try {
119
+ fs.rmSync(extDest, { recursive: true, force: true });
120
+ } catch (e) { }
121
+ }
122
+
123
+ // Link current extension to node_modules/NAME
125
124
  try {
125
+ // Use junction for Windows compat without admin rights
126
126
  fs.symlinkSync(cwd, extDest, "junction");
127
127
  } catch (e) {
128
128
  // Fallback to copy if link fails
129
- console.log(yellow("Linking failed, copying extension files..."));
129
+ // console.log(yellow("Linking failed, copying extension files..."));
130
130
  copyDir(cwd, extDest);
131
131
  }
132
132
 
133
- // Create a test action in app/actions/test.js
134
- const testAction = `export const test = (req) => {
133
+ // Create default test files ONLY if they don't exist
134
+ const actionsDir = path.join(runDir, "app", "actions");
135
+ const testActionPath = path.join(actionsDir, "test.js");
136
+
137
+ if (!fs.existsSync(testActionPath)) {
138
+ const testAction = `export const test = (req) => {
135
139
  const ext = t["${name}"];
136
140
 
137
141
  const results = {
@@ -160,12 +164,12 @@ function run() {
160
164
  return results;
161
165
  };
162
166
  `;
167
+ fs.writeFileSync(testActionPath, testAction);
168
+ }
163
169
 
164
- fs.writeFileSync(path.join(actionsDir, "test.js"), testAction);
165
-
166
- // Create a simple test script in app/app.js
167
- // This script will be executed by Titan
168
- const testScript = `import t from "../titan/titan.js";
170
+ const appJsPath = path.join(runDir, "app", "app.js");
171
+ if (!fs.existsSync(appJsPath)) {
172
+ const testScript = `import t from "../titan/titan.js";
169
173
  import "${name}";
170
174
 
171
175
  // Extension test harness for: ${name}
@@ -217,37 +221,30 @@ t.get("/").reply("🚀 Extension Test Harness for ${name}\\n\\nVisit /test to se
217
221
 
218
222
  await t.start(3000, "Titan Extension Test Running!");
219
223
  `;
220
-
221
- fs.writeFileSync(path.join(appDir, "app.js"), testScript);
224
+ fs.writeFileSync(appJsPath, testScript);
225
+ }
222
226
 
223
227
  // Build the app (bundle actions)
224
228
  console.log(cyan("Building test app..."));
225
229
  try {
226
- // Ensure we are in runDir and the file exists
227
- const appJsPath = path.join(runDir, "app", "app.js");
228
- if (!fs.existsSync(appJsPath)) {
229
- throw new Error(`app/app.js missing at ${appJsPath}`);
230
- }
231
-
232
230
  execSync("node app/app.js --build", {
233
231
  cwd: runDir,
234
232
  stdio: "inherit",
235
233
  env: { ...process.env, NODE_OPTIONS: "--no-warnings" }
236
234
  });
237
235
  } catch (e) {
238
- console.log(red("Failed to build test app. This is expected if your extension has errors."));
239
- // Don't exit here, attempt to continue to show runtime errors if possible
236
+ console.log(red("Failed to build test app. checking for runtime errors..."));
240
237
  }
241
238
 
242
- // 4. Run Titan Server using cargo run (like dev mode)
243
- console.log(green("\x1b[1m\n>>> STARTING EXTENSION TEST >>>\n\x1b[0m"));
239
+ // 4. Run Titan Server using cargo run
240
+ console.log(green("\\x1b[1m\\n>>> STARTING EXTENSION TEST >>>\\n\\x1b[0m"));
244
241
 
245
242
  const serverDir = path.join(runDir, "server");
246
243
 
247
244
  try {
248
245
  execSync("cargo run", { cwd: serverDir, stdio: "inherit" });
249
246
  } catch (e) {
250
- console.log(red("Runtime exited."));
247
+ // console.log(red("Runtime exited."));
251
248
  }
252
249
  }
253
250
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "titanpl-sdk",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Development SDK for Titan Planet. Provides TypeScript type definitions for the global 't' runtime object and a 'lite' test-harness runtime for building and verifying extensions.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -1,66 +0,0 @@
1
- # ================================================================
2
- # STAGE 1 — Build Titan (JS → Rust)
3
- # ================================================================
4
- FROM rust:1.91.1 AS builder
5
-
6
- # Install Node for Titan CLI + bundler
7
- RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
8
- && apt-get install -y nodejs
9
-
10
- # Install Titan CLI (latest)
11
- RUN npm install -g @ezetgalaxy/titan@latest
12
-
13
- WORKDIR /app
14
-
15
- # Copy project files
16
- COPY . .
17
-
18
- # Install JS dependencies (needed for Titan DSL + bundler)
19
- RUN npm install
20
-
21
- SHELL ["/bin/bash", "-c"]
22
-
23
- # Extract Titan extensions into .ext
24
- RUN mkdir -p /app/.ext && \
25
- find /app/node_modules -maxdepth 5 -type f -name "titan.json" -print0 | \
26
- while IFS= read -r -d '' file; do \
27
- pkg_dir="$(dirname "$file")"; \
28
- pkg_name="$(basename "$pkg_dir")"; \
29
- echo "Copying Titan extension: $pkg_name from $pkg_dir"; \
30
- cp -r "$pkg_dir" "/app/.ext/$pkg_name"; \
31
- done && \
32
- echo "Extensions in .ext:" && \
33
- ls -R /app/.ext
34
-
35
- # Build Titan metadata + bundle JS actions
36
- RUN titan build
37
-
38
- # Build Rust binary
39
- RUN cd server && cargo build --release
40
-
41
-
42
-
43
- # ================================================================
44
- # STAGE 2 — Runtime Image (Lightweight)
45
- # ================================================================
46
- FROM debian:stable-slim
47
-
48
- WORKDIR /app
49
-
50
- # Copy Rust binary from builder stage
51
- COPY --from=builder /app/server/target/release/titan-server ./titan-server
52
-
53
- # Copy Titan routing metadata
54
- COPY --from=builder /app/server/routes.json ./routes.json
55
- COPY --from=builder /app/server/action_map.json ./action_map.json
56
-
57
- # Copy Titan JS bundles
58
- RUN mkdir -p /app/actions
59
- COPY --from=builder /app/server/actions /app/actions
60
-
61
- # Copy only Titan extensions
62
- COPY --from=builder /app/.ext ./.ext
63
-
64
- EXPOSE 3000
65
-
66
- CMD ["./titan-server"]
@@ -1,3 +0,0 @@
1
- node_modules
2
- npm-debug.log
3
- .git
@@ -1,38 +0,0 @@
1
- # Node & Packages
2
- node_modules/
3
- npm-debug.log*
4
- yarn-debug.log*
5
- yarn-error.log*
6
- package-lock.json
7
- yarn.lock
8
-
9
- # Titan Runtime (Auto-generated - DO NOT COMMIT)
10
- titan/server-bin*
11
- .titan/
12
- .ext/
13
- server/routes.json
14
- server/action_map.json
15
- server/actions/
16
- server/titan/
17
- server/src/actions_rust/
18
-
19
- # Rust Build Artifacts
20
- server/target/
21
- Cargo.lock
22
-
23
- # OS Files
24
- .DS_Store
25
- Thumbs.db
26
- *.tmp
27
- *.bak
28
-
29
- # Environment & Secrets
30
- .env
31
- .env.local
32
- .env.*.local
33
-
34
- # IDEs
35
- .vscode/
36
- .idea/
37
- *.swp
38
- *.swo