@ezetgalaxy/titan 26.9.0 → 26.9.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 +22 -12
- package/index.js +57 -15
- package/package.json +1 -2
- 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/titan.d.ts +117 -0
- package/templates/rust-ts/titan/titan.js +95 -95
- package/templates/ts/Dockerfile +16 -42
- 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.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/app/titan.d.ts +0 -101
- package/templates/ts/app/titan.d.ts +0 -102
- /package/templates/{rust → rust-js}/Dockerfile +0 -0
- /package/templates/{rust → rust-js}/_dockerignore +0 -0
- /package/templates/{rust → rust-js}/_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-ts → rust-js}/app/titan.d.ts +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
package/templates/ts/Dockerfile
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
# ================================================================
|
|
2
|
-
# STAGE 1 — Build
|
|
2
|
+
# STAGE 1 — Build
|
|
3
3
|
# ================================================================
|
|
4
|
-
FROM
|
|
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
|
|
4
|
+
FROM node:20-slim AS builder
|
|
9
5
|
|
|
10
6
|
# Install Titan CLI (latest)
|
|
11
7
|
RUN npm install -g @ezetgalaxy/titan@latest
|
|
@@ -15,52 +11,30 @@ WORKDIR /app
|
|
|
15
11
|
# Copy project files
|
|
16
12
|
COPY . .
|
|
17
13
|
|
|
18
|
-
# Install JS dependencies
|
|
14
|
+
# Install JS dependencies
|
|
19
15
|
RUN npm install
|
|
20
16
|
|
|
21
|
-
|
|
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
|
|
17
|
+
# Build Titan App
|
|
36
18
|
RUN titan build
|
|
37
19
|
|
|
38
|
-
# Build Rust binary
|
|
39
|
-
RUN cd server && cargo build --release
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
20
|
# ================================================================
|
|
44
|
-
# STAGE 2 — Runtime
|
|
21
|
+
# STAGE 2 — Runtime
|
|
45
22
|
# ================================================================
|
|
46
|
-
FROM
|
|
23
|
+
FROM node:20-slim
|
|
47
24
|
|
|
48
25
|
WORKDIR /app
|
|
49
26
|
|
|
50
|
-
# Copy
|
|
51
|
-
COPY --from=builder /app
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
27
|
+
# Copy Titan Build Artifacts
|
|
28
|
+
COPY --from=builder /app/.titan ./.titan
|
|
29
|
+
COPY --from=builder /app/server ./server
|
|
30
|
+
COPY --from=builder /app/package.json ./package.json
|
|
60
31
|
|
|
61
|
-
#
|
|
62
|
-
|
|
32
|
+
# Install dependencies (production only, but for now we might need all if not careful)
|
|
33
|
+
# Actually, the runtime depends on `express`-like behavior?
|
|
34
|
+
# No, Titan pure TS runs via `node .titan/app.js` which might need deps?
|
|
35
|
+
# The user's package.json has dependencies.
|
|
36
|
+
RUN npm install --omit=dev
|
|
63
37
|
|
|
64
38
|
EXPOSE 3000
|
|
65
39
|
|
|
66
|
-
CMD ["
|
|
40
|
+
CMD ["node", ".titan/app.js"]
|
package/templates/ts/app/app.ts
CHANGED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { bundle } from "./bundle.js";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
const cyan = (t) => `\x1b[36m${t}\x1b[0m`;
|
|
6
|
+
const green = (t) => `\x1b[32m${t}\x1b[0m`;
|
|
7
|
+
|
|
8
|
+
const routes = {};
|
|
9
|
+
const dynamicRoutes = {};
|
|
10
|
+
const actionMap = {};
|
|
11
|
+
|
|
12
|
+
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
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @typedef {Object} RouteHandler
|
|
45
|
+
* @property {(value: any) => void} reply - Send a direct response
|
|
46
|
+
* @property {(name: string) => void} action - Bind to a server-side action
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Titan App Builder
|
|
51
|
+
*/
|
|
52
|
+
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);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export default t;
|
|
@@ -2,27 +2,25 @@ import fs from "fs";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import esbuild from "esbuild";
|
|
4
4
|
|
|
5
|
-
const root = process.cwd();
|
|
6
|
-
const actionsDir = path.join(root, "app", "actions");
|
|
7
|
-
const outDir = path.join(root, "server", "actions");
|
|
8
|
-
|
|
9
5
|
export async function bundle() {
|
|
6
|
+
const root = process.cwd();
|
|
7
|
+
const actionsDir = path.join(root, "app", "actions");
|
|
8
|
+
const outDir = path.join(root, "server", "actions");
|
|
9
|
+
|
|
10
10
|
const start = Date.now();
|
|
11
|
-
await bundleJs();
|
|
11
|
+
await bundleJs(actionsDir, outDir);
|
|
12
12
|
// console.log(`[Titan] Bundle finished in ${((Date.now() - start) / 1000).toFixed(2)}s`);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
async function bundleJs() {
|
|
15
|
+
async function bundleJs(actionsDir, outDir) {
|
|
16
16
|
// console.log("[Titan] Bundling JS actions...");
|
|
17
17
|
|
|
18
18
|
fs.mkdirSync(outDir, { recursive: true });
|
|
19
19
|
|
|
20
20
|
// Clean old bundles
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
fs.unlinkSync(path.join(outDir, file));
|
|
25
|
-
}
|
|
21
|
+
const oldFiles = fs.readdirSync(outDir);
|
|
22
|
+
for (const file of oldFiles) {
|
|
23
|
+
fs.unlinkSync(path.join(outDir, file));
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
const files = fs.readdirSync(actionsDir).filter(f => f.endsWith(".js") || f.endsWith(".ts"));
|
|
@@ -231,11 +231,11 @@ async function rebuild() {
|
|
|
231
231
|
bundle: true,
|
|
232
232
|
platform: "node",
|
|
233
233
|
format: "esm",
|
|
234
|
-
|
|
234
|
+
external: ["fs", "path", "esbuild", "chokidar", "typescript"],
|
|
235
235
|
logLevel: "silent"
|
|
236
236
|
});
|
|
237
237
|
|
|
238
|
-
execSync(`node "${compiledApp}"`, { stdio: "
|
|
238
|
+
execSync(`node "${compiledApp}"`, { stdio: "inherit" });
|
|
239
239
|
} else {
|
|
240
240
|
execSync("node app/app.js", { stdio: "ignore" });
|
|
241
241
|
}
|
|
@@ -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 const defineAction = (handler) => handler;
|
|
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
|
---
|