@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.
- package/README.md +39 -17
- package/index.js +227 -120
- package/package.json +17 -5
- package/templates/{js → common}/app/titan.d.ts +1 -1
- package/templates/{rust → rust-js}/package.json +1 -1
- package/templates/rust-ts/app/actions/hello.ts +10 -4
- package/templates/rust-ts/app/app.ts +1 -1
- package/templates/rust-ts/titan/bundle.js +15 -9
- package/templates/rust-ts/titan/dev.js +2 -2
- 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 -0
- package/templates/rust-ts/titan/titan.js +95 -95
- package/templates/ts/app/actions/hello.ts +2 -0
- package/templates/ts/app/app.ts +1 -1
- package/templates/ts/titan/builder.js +121 -0
- package/templates/ts/titan/bundle.js +9 -11
- package/templates/ts/titan/dev.js +2 -2
- package/templates/ts/titan/runtime.d.ts +1 -0
- package/templates/ts/titan/runtime.js +1 -0
- package/templates/ts/titan/titan.d.ts +117 -0
- package/templates/ts/titan/titan.js +95 -95
- package/titanpl-sdk/README.md +4 -4
- package/titanpl-sdk/bin/run.js +74 -77
- package/titanpl-sdk/package.json +1 -1
- package/templates/rust/Dockerfile +0 -66
- package/templates/rust/_dockerignore +0 -3
- package/templates/rust/_gitignore +0 -38
- package/templates/rust/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/rust-ts/app/titan.d.ts +0 -101
- package/templates/ts/Dockerfile +0 -66
- package/templates/ts/_dockerignore +0 -3
- package/templates/ts/_gitignore +0 -38
- package/templates/ts/app/titan.d.ts +0 -102
- /package/templates/{js → common}/Dockerfile +0 -0
- /package/templates/{js → common}/_dockerignore +0 -0
- /package/templates/{js → common}/_gitignore +0 -0
- /package/templates/{rust → rust-js}/app/actions/hello.js +0 -0
- /package/templates/{rust → rust-js}/app/actions/rust_hello.rs +0 -0
- /package/templates/{rust → rust-js}/app/app.js +0 -0
- /package/templates/{rust → rust-js}/jsconfig.json +0 -0
- /package/templates/{rust → rust-js}/server/Cargo.lock +0 -0
- /package/templates/{rust → rust-js}/server/Cargo.toml +0 -0
- /package/templates/{rust → rust-js}/server/src/action_management.rs +0 -0
- /package/templates/{rust → rust-js}/server/src/errors.rs +0 -0
- /package/templates/{rust → rust-js}/server/src/extensions.rs +0 -0
- /package/templates/{rust → rust-js}/server/src/main.rs +0 -0
- /package/templates/{rust → rust-js}/server/src/utils.rs +0 -0
- /package/templates/{rust → rust-js}/titan/bundle.js +0 -0
- /package/templates/{rust → rust-js}/titan/dev.js +0 -0
- /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
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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;
|
package/titanpl-sdk/README.md
CHANGED
|
@@ -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
|
-
```
|
|
79
|
-
export
|
|
80
|
-
t.log
|
|
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
|
---
|
package/titanpl-sdk/bin/run.js
CHANGED
|
@@ -53,85 +53,89 @@ function run() {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
// 3.
|
|
56
|
+
// 3. Setup Test Harness (Mini Titan Project)
|
|
57
57
|
const runDir = path.join(cwd, ".titan_test_run");
|
|
58
|
-
|
|
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
|
-
|
|
72
|
-
|
|
60
|
+
if (isFirstRun) {
|
|
61
|
+
console.log(cyan("Initializing test environment..."));
|
|
73
62
|
fs.mkdirSync(runDir, { recursive: true });
|
|
74
|
-
}
|
|
75
63
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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(
|
|
109
|
-
process.exit(1);
|
|
107
|
+
console.log(cyan("Using existing test environment..."));
|
|
110
108
|
}
|
|
111
109
|
|
|
112
|
-
//
|
|
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
|
|
134
|
-
const
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
243
|
-
console.log(green("
|
|
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
|
|
package/titanpl-sdk/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "titanpl-sdk",
|
|
3
|
-
"version": "0.1.
|
|
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,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
|