@flight-framework/core 0.0.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/LICENSE +21 -0
- package/dist/actions/index.d.ts +108 -0
- package/dist/actions/index.js +3 -0
- package/dist/actions/index.js.map +1 -0
- package/dist/adapters/index.d.ts +243 -0
- package/dist/adapters/index.js +3 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/cache/index.d.ts +76 -0
- package/dist/cache/index.js +3 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/chunk-3AIQVGTM.js +120 -0
- package/dist/chunk-3AIQVGTM.js.map +1 -0
- package/dist/chunk-AFSKXC6V.js +188 -0
- package/dist/chunk-AFSKXC6V.js.map +1 -0
- package/dist/chunk-AJ3IBYXT.js +47 -0
- package/dist/chunk-AJ3IBYXT.js.map +1 -0
- package/dist/chunk-GCQZ4FHI.js +245 -0
- package/dist/chunk-GCQZ4FHI.js.map +1 -0
- package/dist/chunk-I5RHYGX6.js +167 -0
- package/dist/chunk-I5RHYGX6.js.map +1 -0
- package/dist/chunk-KWFX6WHG.js +311 -0
- package/dist/chunk-KWFX6WHG.js.map +1 -0
- package/dist/chunk-Q4C5CCHK.js +13 -0
- package/dist/chunk-Q4C5CCHK.js.map +1 -0
- package/dist/chunk-QEFGUHYD.js +221 -0
- package/dist/chunk-QEFGUHYD.js.map +1 -0
- package/dist/chunk-TKXN7KGE.js +145 -0
- package/dist/chunk-TKXN7KGE.js.map +1 -0
- package/dist/chunk-WAGCTWGY.js +93 -0
- package/dist/chunk-WAGCTWGY.js.map +1 -0
- package/dist/chunk-Y22KEW2F.js +223 -0
- package/dist/chunk-Y22KEW2F.js.map +1 -0
- package/dist/chunk-ZVC3ZWLM.js +52 -0
- package/dist/chunk-ZVC3ZWLM.js.map +1 -0
- package/dist/config/index.d.ts +146 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/file-router/index.d.ts +71 -0
- package/dist/file-router/index.js +3 -0
- package/dist/file-router/index.js.map +1 -0
- package/dist/handlers/index.d.ts +59 -0
- package/dist/handlers/index.js +3 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/index.d.ts +152 -0
- package/dist/middleware/index.js +3 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/render/index.d.ts +131 -0
- package/dist/render/index.js +3 -0
- package/dist/render/index.js.map +1 -0
- package/dist/router/index.d.ts +65 -0
- package/dist/router/index.js +3 -0
- package/dist/router/index.js.map +1 -0
- package/dist/rsc/index.d.ts +131 -0
- package/dist/rsc/index.js +3 -0
- package/dist/rsc/index.js.map +1 -0
- package/dist/server/index.d.ts +135 -0
- package/dist/server/index.js +6 -0
- package/dist/server/index.js.map +1 -0
- package/dist/streaming/index.d.ts +169 -0
- package/dist/streaming/index.js +3 -0
- package/dist/streaming/index.js.map +1 -0
- package/package.json +100 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { createRouter } from './chunk-GCQZ4FHI.js';
|
|
2
|
+
import { createMiddlewareChain, createContextFromRequest, createResponseFromContext } from './chunk-KWFX6WHG.js';
|
|
3
|
+
import { resolveConfig } from './chunk-WAGCTWGY.js';
|
|
4
|
+
|
|
5
|
+
// src/server/index.ts
|
|
6
|
+
function detectRuntime() {
|
|
7
|
+
if (typeof Bun !== "undefined") return "bun";
|
|
8
|
+
if (typeof Deno !== "undefined") return "deno";
|
|
9
|
+
if (typeof process !== "undefined" && process.versions?.node) return "node";
|
|
10
|
+
return "unknown";
|
|
11
|
+
}
|
|
12
|
+
function createServer(options = {}) {
|
|
13
|
+
const config = resolveConfig(options.config ?? {});
|
|
14
|
+
const router = createRouter();
|
|
15
|
+
const middlewareChain = createMiddlewareChain();
|
|
16
|
+
const deps = {
|
|
17
|
+
db: options.db,
|
|
18
|
+
auth: options.auth,
|
|
19
|
+
email: options.email
|
|
20
|
+
};
|
|
21
|
+
function addRoute(method, path, handler) {
|
|
22
|
+
const methods = Array.isArray(method) ? method : [method];
|
|
23
|
+
const methodSet = new Set(methods.map((m) => m.toUpperCase()));
|
|
24
|
+
const existingMatch = router.match(path);
|
|
25
|
+
if (existingMatch && existingMatch.route.path === path) {
|
|
26
|
+
for (const m of methodSet) {
|
|
27
|
+
existingMatch.route.handler.methods.add(m);
|
|
28
|
+
}
|
|
29
|
+
existingMatch.route.handler.handler = handler;
|
|
30
|
+
} else {
|
|
31
|
+
router.add({
|
|
32
|
+
path,
|
|
33
|
+
handler: { methods: methodSet, handler }
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return server;
|
|
37
|
+
}
|
|
38
|
+
function useMiddleware(pathOrMiddleware, maybeMiddleware) {
|
|
39
|
+
if (typeof pathOrMiddleware === "string" && maybeMiddleware) {
|
|
40
|
+
middlewareChain.use(pathOrMiddleware, maybeMiddleware);
|
|
41
|
+
} else if (typeof pathOrMiddleware === "function") {
|
|
42
|
+
middlewareChain.use(pathOrMiddleware);
|
|
43
|
+
}
|
|
44
|
+
return server;
|
|
45
|
+
}
|
|
46
|
+
async function handle(request) {
|
|
47
|
+
const url = new URL(request.url);
|
|
48
|
+
const method = request.method.toUpperCase();
|
|
49
|
+
const ctx = createContextFromRequest(request);
|
|
50
|
+
await middlewareChain.execute(ctx);
|
|
51
|
+
if (ctx.responseBody !== void 0) {
|
|
52
|
+
return createResponseFromContext(ctx);
|
|
53
|
+
}
|
|
54
|
+
const match = router.match(url.pathname);
|
|
55
|
+
if (!match) {
|
|
56
|
+
return new Response("Not Found", { status: 404 });
|
|
57
|
+
}
|
|
58
|
+
if (!match.route.handler.methods.has(method) && !match.route.handler.methods.has("*")) {
|
|
59
|
+
return new Response("Method Not Allowed", { status: 405 });
|
|
60
|
+
}
|
|
61
|
+
const handlerContext = {
|
|
62
|
+
request,
|
|
63
|
+
params: match.params,
|
|
64
|
+
query: url.searchParams,
|
|
65
|
+
url,
|
|
66
|
+
locals: ctx.locals,
|
|
67
|
+
...deps
|
|
68
|
+
};
|
|
69
|
+
try {
|
|
70
|
+
return await match.route.handler.handler(handlerContext);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error("Route handler error:", error);
|
|
73
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function listen(portOrOptions) {
|
|
77
|
+
const opts = typeof portOrOptions === "number" ? { port: portOrOptions } : portOrOptions ?? {};
|
|
78
|
+
const port = opts.port ?? config.dev.port ?? 3e3;
|
|
79
|
+
const hostname = opts.hostname ?? "localhost";
|
|
80
|
+
const adapter = options.adapter ?? config.adapter;
|
|
81
|
+
if (adapter?.listen) {
|
|
82
|
+
await adapter.listen(server, port);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const runtime = detectRuntime();
|
|
86
|
+
switch (runtime) {
|
|
87
|
+
case "bun":
|
|
88
|
+
await startBunServer(port, hostname, opts.onListen);
|
|
89
|
+
break;
|
|
90
|
+
case "deno":
|
|
91
|
+
await startDenoServer(port, hostname, opts.onListen);
|
|
92
|
+
break;
|
|
93
|
+
case "node":
|
|
94
|
+
default:
|
|
95
|
+
await startNodeServer(port, hostname, opts.onListen);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function startNodeServer(port, hostname, onListen) {
|
|
100
|
+
const { createServer: createHttpServer } = await import('http');
|
|
101
|
+
const httpServer = createHttpServer(async (req, res) => {
|
|
102
|
+
const url = new URL(req.url || "/", `http://${hostname}:${port}`);
|
|
103
|
+
const headers = new Headers();
|
|
104
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
105
|
+
if (value) {
|
|
106
|
+
const headerValue = Array.isArray(value) ? value[0] : value;
|
|
107
|
+
if (headerValue) headers.set(key, headerValue);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
let body;
|
|
111
|
+
if (["POST", "PUT", "PATCH"].includes(req.method || "")) {
|
|
112
|
+
body = await new Promise((resolve) => {
|
|
113
|
+
let data = "";
|
|
114
|
+
req.on("data", (chunk) => data += chunk);
|
|
115
|
+
req.on("end", () => resolve(data));
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const request = new Request(url.toString(), {
|
|
119
|
+
method: req.method,
|
|
120
|
+
headers,
|
|
121
|
+
body: body || void 0
|
|
122
|
+
});
|
|
123
|
+
try {
|
|
124
|
+
const response = await handle(request);
|
|
125
|
+
res.statusCode = response.status;
|
|
126
|
+
response.headers.forEach((value, key) => {
|
|
127
|
+
res.setHeader(key, value);
|
|
128
|
+
});
|
|
129
|
+
const responseBody = await response.text();
|
|
130
|
+
res.end(responseBody);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.error("Server error:", error);
|
|
133
|
+
res.statusCode = 500;
|
|
134
|
+
res.setHeader("Content-Type", "application/json");
|
|
135
|
+
res.end(JSON.stringify({ error: "Internal Server Error" }));
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
return new Promise((resolve) => {
|
|
139
|
+
httpServer.listen(port, hostname, () => {
|
|
140
|
+
const info = { port, hostname };
|
|
141
|
+
if (onListen) {
|
|
142
|
+
onListen(info);
|
|
143
|
+
} else {
|
|
144
|
+
console.log(`
|
|
145
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
146
|
+
\u2551 Flight Server (Node.js) \u2551
|
|
147
|
+
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
148
|
+
\u2551 Server: http://${hostname}:${port.toString().padEnd(37)}\u2551
|
|
149
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
150
|
+
`);
|
|
151
|
+
}
|
|
152
|
+
resolve();
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
async function startBunServer(port, hostname, onListen) {
|
|
157
|
+
Bun.serve({
|
|
158
|
+
port,
|
|
159
|
+
hostname,
|
|
160
|
+
fetch: handle
|
|
161
|
+
});
|
|
162
|
+
const info = { port, hostname };
|
|
163
|
+
if (onListen) {
|
|
164
|
+
onListen(info);
|
|
165
|
+
} else {
|
|
166
|
+
console.log(`
|
|
167
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
168
|
+
\u2551 Flight Server (Bun) \u2551
|
|
169
|
+
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
170
|
+
\u2551 Server: http://${hostname}:${port.toString().padEnd(37)}\u2551
|
|
171
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
172
|
+
`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async function startDenoServer(port, hostname, onListen) {
|
|
176
|
+
Deno.serve({ port, hostname }, handle);
|
|
177
|
+
const info = { port, hostname };
|
|
178
|
+
if (onListen) {
|
|
179
|
+
onListen(info);
|
|
180
|
+
} else {
|
|
181
|
+
console.log(`
|
|
182
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
183
|
+
\u2551 Flight Server (Deno) \u2551
|
|
184
|
+
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
185
|
+
\u2551 Server: http://${hostname}:${port.toString().padEnd(37)}\u2551
|
|
186
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
187
|
+
`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const server = {
|
|
191
|
+
route: addRoute,
|
|
192
|
+
get: (path, handler) => addRoute("GET", path, handler),
|
|
193
|
+
post: (path, handler) => addRoute("POST", path, handler),
|
|
194
|
+
put: (path, handler) => addRoute("PUT", path, handler),
|
|
195
|
+
delete: (path, handler) => addRoute("DELETE", path, handler),
|
|
196
|
+
patch: (path, handler) => addRoute("PATCH", path, handler),
|
|
197
|
+
use: useMiddleware,
|
|
198
|
+
handle,
|
|
199
|
+
listen,
|
|
200
|
+
fetch: handle,
|
|
201
|
+
// Alias for Bun/Deno compatibility
|
|
202
|
+
get config() {
|
|
203
|
+
return config;
|
|
204
|
+
},
|
|
205
|
+
get router() {
|
|
206
|
+
return router;
|
|
207
|
+
},
|
|
208
|
+
get middleware() {
|
|
209
|
+
return middlewareChain;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
return server;
|
|
213
|
+
}
|
|
214
|
+
function isFlightServer(obj) {
|
|
215
|
+
return typeof obj === "object" && obj !== null && "handle" in obj && "route" in obj && typeof obj.handle === "function";
|
|
216
|
+
}
|
|
217
|
+
function getRuntime() {
|
|
218
|
+
return detectRuntime();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export { createServer, getRuntime, isFlightServer };
|
|
222
|
+
//# sourceMappingURL=chunk-Y22KEW2F.js.map
|
|
223
|
+
//# sourceMappingURL=chunk-Y22KEW2F.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/index.ts"],"names":[],"mappings":"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","file":"chunk-Y22KEW2F.js","sourcesContent":["/**\r\n * Flight Server - Main server factory\r\n * \r\n * Creates a Flight server instance that handles routing, middleware, and rendering.\r\n * This is the primary entry point for Flight applications.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createServer } from '@flight/core';\r\n * \r\n * const server = createServer();\r\n * \r\n * server.get('/api/health', () => Response.json({ status: 'ok' }));\r\n * \r\n * // Just works! Auto-detects Node.js, Bun, or Deno\r\n * server.listen(3000);\r\n * ```\r\n */\r\n\r\nimport { createRouter, type Router } from '../router/index.js';\r\nimport {\r\n createMiddlewareChain,\r\n createContextFromRequest,\r\n createResponseFromContext,\r\n type MiddlewareChain,\r\n type Middleware,\r\n} from '../middleware/index.js';\r\nimport { type FlightConfig, type FlightUserConfig, resolveConfig } from '../config/index.js';\r\nimport type { FlightAdapter } from '../adapters/index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/** Route handler function signature */\r\nexport type RouteHandler = (context: RouteHandlerContext) => Promise<Response> | Response;\r\n\r\n/** Context passed to route handlers */\r\nexport interface RouteHandlerContext {\r\n /** The incoming request */\r\n request: Request;\r\n /** URL parameters from routing */\r\n params: Record<string, string | string[]>;\r\n /** Query parameters */\r\n query: URLSearchParams;\r\n /** Parsed URL */\r\n url: URL;\r\n /** Local data from middleware */\r\n locals: Record<string, unknown>;\r\n /** Database instance (if configured) */\r\n db?: unknown;\r\n /** Auth instance (if configured) */\r\n auth?: unknown;\r\n /** Email instance (if configured) */\r\n email?: unknown;\r\n}\r\n\r\n/** Server options */\r\nexport interface ServerOptions {\r\n /** Server configuration */\r\n config?: FlightUserConfig;\r\n /** Deployment adapter */\r\n adapter?: FlightAdapter;\r\n /** Database instance */\r\n db?: unknown;\r\n /** Auth instance */\r\n auth?: unknown;\r\n /** Email instance */\r\n email?: unknown;\r\n}\r\n\r\n/** Route definition for the server */\r\nexport interface ServerRoute {\r\n /** HTTP method (GET, POST, etc.) */\r\n method: string | string[];\r\n /** Route path pattern */\r\n path: string;\r\n /** Route handler */\r\n handler: RouteHandler;\r\n}\r\n\r\n/** Listen options */\r\nexport interface ListenOptions {\r\n /** Port to listen on (default: 3000) */\r\n port?: number;\r\n /** Hostname to bind to (default: 'localhost') */\r\n hostname?: string;\r\n /** Callback when server starts */\r\n onListen?: (info: { port: number; hostname: string }) => void;\r\n}\r\n\r\n/** Flight Server instance */\r\nexport interface FlightServer {\r\n /** Add a route */\r\n route(method: string | string[], path: string, handler: RouteHandler): FlightServer;\r\n\r\n /** Convenience methods for common HTTP methods */\r\n get(path: string, handler: RouteHandler): FlightServer;\r\n post(path: string, handler: RouteHandler): FlightServer;\r\n put(path: string, handler: RouteHandler): FlightServer;\r\n delete(path: string, handler: RouteHandler): FlightServer;\r\n patch(path: string, handler: RouteHandler): FlightServer;\r\n\r\n /** Add middleware */\r\n use(middleware: Middleware): FlightServer;\r\n use(path: string, middleware: Middleware): FlightServer;\r\n\r\n /** Handle incoming request (Web standard Request/Response) */\r\n handle(request: Request): Promise<Response>;\r\n\r\n /** \r\n * Start the HTTP server\r\n * Auto-detects runtime: Node.js, Bun, or Deno\r\n */\r\n listen(port?: number | ListenOptions): Promise<void>;\r\n\r\n /** Fetch handler for Bun.serve() and Deno.serve() */\r\n fetch(request: Request): Promise<Response>;\r\n\r\n /** Get the resolved configuration */\r\n readonly config: FlightConfig;\r\n\r\n /** Get the router instance */\r\n readonly router: Router<RouteHandler>;\r\n\r\n /** Get the middleware chain */\r\n readonly middleware: MiddlewareChain;\r\n}\r\n\r\n// ============================================================================\r\n// Runtime Detection\r\n// ============================================================================\r\n\r\ntype Runtime = 'node' | 'bun' | 'deno' | 'unknown';\r\n\r\nfunction detectRuntime(): Runtime {\r\n // @ts-expect-error - Bun global\r\n if (typeof Bun !== 'undefined') return 'bun';\r\n // @ts-expect-error - Deno global \r\n if (typeof Deno !== 'undefined') return 'deno';\r\n if (typeof process !== 'undefined' && process.versions?.node) return 'node';\r\n return 'unknown';\r\n}\r\n\r\n// ============================================================================\r\n// Server Implementation\r\n// ============================================================================\r\n\r\ninterface RouteEntry {\r\n methods: Set<string>;\r\n handler: RouteHandler;\r\n}\r\n\r\n/**\r\n * Create a new Flight server instance\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createServer } from '@flight/core';\r\n * \r\n * const server = createServer();\r\n * \r\n * server.get('/api/users', async ({ db }) => {\r\n * const users = await db.query('SELECT * FROM users');\r\n * return Response.json(users);\r\n * });\r\n * \r\n * // Works on Node.js, Bun, and Deno!\r\n * server.listen(3000);\r\n * ```\r\n */\r\nexport function createServer(options: ServerOptions = {}): FlightServer {\r\n const config = resolveConfig(options.config ?? {});\r\n const router = createRouter<RouteEntry>();\r\n const middlewareChain = createMiddlewareChain();\r\n\r\n // Store dependencies\r\n const deps = {\r\n db: options.db,\r\n auth: options.auth,\r\n email: options.email,\r\n };\r\n\r\n function addRoute(method: string | string[], path: string, handler: RouteHandler): FlightServer {\r\n const methods = Array.isArray(method) ? method : [method];\r\n const methodSet = new Set(methods.map(m => m.toUpperCase()));\r\n\r\n // Check if route already exists\r\n const existingMatch = router.match(path);\r\n if (existingMatch && existingMatch.route.path === path) {\r\n // Merge methods\r\n for (const m of methodSet) {\r\n existingMatch.route.handler.methods.add(m);\r\n }\r\n existingMatch.route.handler.handler = handler;\r\n } else {\r\n router.add({\r\n path,\r\n handler: { methods: methodSet, handler },\r\n });\r\n }\r\n\r\n return server;\r\n }\r\n\r\n function useMiddleware(\r\n pathOrMiddleware: string | Middleware,\r\n maybeMiddleware?: Middleware\r\n ): FlightServer {\r\n if (typeof pathOrMiddleware === 'string' && maybeMiddleware) {\r\n middlewareChain.use(pathOrMiddleware, maybeMiddleware);\r\n } else if (typeof pathOrMiddleware === 'function') {\r\n middlewareChain.use(pathOrMiddleware);\r\n }\r\n return server;\r\n }\r\n\r\n async function handle(request: Request): Promise<Response> {\r\n const url = new URL(request.url);\r\n const method = request.method.toUpperCase();\r\n\r\n // Run middleware\r\n const ctx = createContextFromRequest(request);\r\n await middlewareChain.execute(ctx);\r\n\r\n // If middleware already set a response, return it\r\n if (ctx.responseBody !== undefined) {\r\n return createResponseFromContext(ctx);\r\n }\r\n\r\n // Match route\r\n const match = router.match(url.pathname);\r\n if (!match) {\r\n return new Response('Not Found', { status: 404 });\r\n }\r\n\r\n // Check method\r\n if (!match.route.handler.methods.has(method) && !match.route.handler.methods.has('*')) {\r\n return new Response('Method Not Allowed', { status: 405 });\r\n }\r\n\r\n // Build handler context\r\n const handlerContext: RouteHandlerContext = {\r\n request,\r\n params: match.params,\r\n query: url.searchParams,\r\n url,\r\n locals: ctx.locals,\r\n ...deps,\r\n };\r\n\r\n try {\r\n return await match.route.handler.handler(handlerContext);\r\n } catch (error) {\r\n console.error('Route handler error:', error);\r\n return new Response('Internal Server Error', { status: 500 });\r\n }\r\n }\r\n\r\n /**\r\n * Start the HTTP server\r\n * Auto-detects the runtime and uses the appropriate server\r\n */\r\n async function listen(portOrOptions?: number | ListenOptions): Promise<void> {\r\n const opts: ListenOptions = typeof portOrOptions === 'number'\r\n ? { port: portOrOptions }\r\n : portOrOptions ?? {};\r\n\r\n const port = opts.port ?? config.dev.port ?? 3000;\r\n const hostname = opts.hostname ?? 'localhost';\r\n\r\n // Check for custom adapter first\r\n const adapter = options.adapter ?? config.adapter;\r\n if (adapter?.listen) {\r\n await adapter.listen(server, port);\r\n return;\r\n }\r\n\r\n const runtime = detectRuntime();\r\n\r\n switch (runtime) {\r\n case 'bun':\r\n await startBunServer(port, hostname, opts.onListen);\r\n break;\r\n case 'deno':\r\n await startDenoServer(port, hostname, opts.onListen);\r\n break;\r\n case 'node':\r\n default:\r\n await startNodeServer(port, hostname, opts.onListen);\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Start Node.js HTTP server\r\n */\r\n async function startNodeServer(port: number, hostname: string, onListen?: ListenOptions['onListen']): Promise<void> {\r\n const { createServer: createHttpServer } = await import('node:http');\r\n\r\n const httpServer = createHttpServer(async (req, res) => {\r\n const url = new URL(req.url || '/', `http://${hostname}:${port}`);\r\n\r\n // Build headers\r\n const headers = new Headers();\r\n for (const [key, value] of Object.entries(req.headers)) {\r\n if (value) {\r\n const headerValue = Array.isArray(value) ? value[0] : value;\r\n if (headerValue) headers.set(key, headerValue);\r\n }\r\n }\r\n\r\n // Read body for POST/PUT/PATCH\r\n let body: string | undefined;\r\n if (['POST', 'PUT', 'PATCH'].includes(req.method || '')) {\r\n body = await new Promise<string>((resolve) => {\r\n let data = '';\r\n req.on('data', chunk => data += chunk);\r\n req.on('end', () => resolve(data));\r\n });\r\n }\r\n\r\n const request = new Request(url.toString(), {\r\n method: req.method,\r\n headers,\r\n body: body || undefined,\r\n });\r\n\r\n try {\r\n const response = await handle(request);\r\n\r\n res.statusCode = response.status;\r\n response.headers.forEach((value, key) => {\r\n res.setHeader(key, value);\r\n });\r\n\r\n const responseBody = await response.text();\r\n res.end(responseBody);\r\n } catch (error) {\r\n console.error('Server error:', error);\r\n res.statusCode = 500;\r\n res.setHeader('Content-Type', 'application/json');\r\n res.end(JSON.stringify({ error: 'Internal Server Error' }));\r\n }\r\n });\r\n\r\n return new Promise((resolve) => {\r\n httpServer.listen(port, hostname, () => {\r\n const info = { port, hostname };\r\n if (onListen) {\r\n onListen(info);\r\n } else {\r\n console.log(`\r\n╔═══════════════════════════════════════════════════════════╗\r\n║ Flight Server (Node.js) ║\r\n╠═══════════════════════════════════════════════════════════╣\r\n║ Server: http://${hostname}:${port.toString().padEnd(37)}║\r\n╚═══════════════════════════════════════════════════════════╝\r\n`);\r\n }\r\n resolve();\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Start Bun server\r\n */\r\n async function startBunServer(port: number, hostname: string, onListen?: ListenOptions['onListen']): Promise<void> {\r\n // @ts-expect-error - Bun types\r\n Bun.serve({\r\n port,\r\n hostname,\r\n fetch: handle,\r\n });\r\n\r\n const info = { port, hostname };\r\n if (onListen) {\r\n onListen(info);\r\n } else {\r\n console.log(`\r\n╔═══════════════════════════════════════════════════════════╗\r\n║ Flight Server (Bun) ║\r\n╠═══════════════════════════════════════════════════════════╣\r\n║ Server: http://${hostname}:${port.toString().padEnd(37)}║\r\n╚═══════════════════════════════════════════════════════════╝\r\n`);\r\n }\r\n }\r\n\r\n /**\r\n * Start Deno server\r\n */\r\n async function startDenoServer(port: number, hostname: string, onListen?: ListenOptions['onListen']): Promise<void> {\r\n // @ts-expect-error - Deno types\r\n Deno.serve({ port, hostname }, handle);\r\n\r\n const info = { port, hostname };\r\n if (onListen) {\r\n onListen(info);\r\n } else {\r\n console.log(`\r\n╔═══════════════════════════════════════════════════════════╗\r\n║ Flight Server (Deno) ║\r\n╠═══════════════════════════════════════════════════════════╣\r\n║ Server: http://${hostname}:${port.toString().padEnd(37)}║\r\n╚═══════════════════════════════════════════════════════════╝\r\n`);\r\n }\r\n }\r\n\r\n const server: FlightServer = {\r\n route: addRoute,\r\n get: (path, handler) => addRoute('GET', path, handler),\r\n post: (path, handler) => addRoute('POST', path, handler),\r\n put: (path, handler) => addRoute('PUT', path, handler),\r\n delete: (path, handler) => addRoute('DELETE', path, handler),\r\n patch: (path, handler) => addRoute('PATCH', path, handler),\r\n use: useMiddleware as FlightServer['use'],\r\n handle,\r\n listen,\r\n fetch: handle, // Alias for Bun/Deno compatibility\r\n get config() { return config; },\r\n get router() { return router as unknown as Router<RouteHandler>; },\r\n get middleware() { return middlewareChain; },\r\n };\r\n\r\n return server;\r\n}\r\n\r\n// ============================================================================\r\n// Helper Exports\r\n// ============================================================================\r\n\r\n/** Type guard to check if an object is a FlightServer */\r\nexport function isFlightServer(obj: unknown): obj is FlightServer {\r\n return (\r\n typeof obj === 'object' &&\r\n obj !== null &&\r\n 'handle' in obj &&\r\n 'route' in obj &&\r\n typeof (obj as FlightServer).handle === 'function'\r\n );\r\n}\r\n\r\n/** Get current runtime */\r\nexport function getRuntime(): Runtime {\r\n return detectRuntime();\r\n}\r\n\r\n"]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// src/render/index.ts
|
|
2
|
+
function requiresServer(mode) {
|
|
3
|
+
return mode === "ssr" || mode === "isr";
|
|
4
|
+
}
|
|
5
|
+
function canBeStatic(mode) {
|
|
6
|
+
return mode === "ssg" || mode === "isr";
|
|
7
|
+
}
|
|
8
|
+
function isClientOnly(mode) {
|
|
9
|
+
return mode === "csr";
|
|
10
|
+
}
|
|
11
|
+
function createHTMLShell(options) {
|
|
12
|
+
const { head = "", body, scripts = [], styles = [], htmlAttributes = {}, bodyAttributes = {} } = options;
|
|
13
|
+
const htmlAttrs = Object.entries(htmlAttributes).map(([key, value]) => `${key}="${escapeHtml(value)}"`).join(" ");
|
|
14
|
+
const bodyAttrs = Object.entries(bodyAttributes).map(([key, value]) => `${key}="${escapeHtml(value)}"`).join(" ");
|
|
15
|
+
const styleLinks = styles.map((href) => `<link rel="stylesheet" href="${escapeHtml(href)}">`).join("\n ");
|
|
16
|
+
const scriptTags = scripts.map((src) => `<script type="module" src="${escapeHtml(src)}"></script>`).join("\n ");
|
|
17
|
+
return `<!DOCTYPE html>
|
|
18
|
+
<html ${htmlAttrs}>
|
|
19
|
+
<head>
|
|
20
|
+
<meta charset="UTF-8">
|
|
21
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
22
|
+
${styleLinks}
|
|
23
|
+
${head}
|
|
24
|
+
</head>
|
|
25
|
+
<body ${bodyAttrs}>
|
|
26
|
+
${body}
|
|
27
|
+
${scriptTags}
|
|
28
|
+
</body>
|
|
29
|
+
</html>`;
|
|
30
|
+
}
|
|
31
|
+
function escapeHtml(str) {
|
|
32
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
33
|
+
}
|
|
34
|
+
function createCSRShell(options) {
|
|
35
|
+
const { title = "Flight App", entryScript, rootId = "app" } = options;
|
|
36
|
+
const html = createHTMLShell({
|
|
37
|
+
head: `<title>${escapeHtml(title)}</title>`,
|
|
38
|
+
body: `<div id="${rootId}"></div>`,
|
|
39
|
+
scripts: [entryScript]
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
html,
|
|
43
|
+
status: 200,
|
|
44
|
+
headers: {
|
|
45
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { canBeStatic, createCSRShell, createHTMLShell, escapeHtml, isClientOnly, requiresServer };
|
|
51
|
+
//# sourceMappingURL=chunk-ZVC3ZWLM.js.map
|
|
52
|
+
//# sourceMappingURL=chunk-ZVC3ZWLM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/render/index.ts"],"names":[],"mappings":";AA0EO,SAAS,eAAe,IAAA,EAA2B;AACtD,EAAA,OAAO,IAAA,KAAS,SAAS,IAAA,KAAS,KAAA;AACtC;AAKO,SAAS,YAAY,IAAA,EAA2B;AACnD,EAAA,OAAO,IAAA,KAAS,SAAS,IAAA,KAAS,KAAA;AACtC;AAKO,SAAS,aAAa,IAAA,EAA2B;AACpD,EAAA,OAAO,IAAA,KAAS,KAAA;AACpB;AAkDO,SAAS,gBAAgB,OAAA,EAOrB;AACP,EAAA,MAAM,EAAE,IAAA,GAAO,EAAA,EAAI,IAAA,EAAM,OAAA,GAAU,EAAC,EAAG,MAAA,GAAS,EAAC,EAAG,iBAAiB,EAAC,EAAG,cAAA,GAAiB,IAAG,GAAI,OAAA;AAEjG,EAAA,MAAM,SAAA,GAAY,OAAO,OAAA,CAAQ,cAAc,EAC1C,GAAA,CAAI,CAAC,CAAC,GAAA,EAAK,KAAK,MAAM,CAAA,EAAG,GAAG,KAAK,UAAA,CAAW,KAAK,CAAC,CAAA,CAAA,CAAG,CAAA,CACrD,KAAK,GAAG,CAAA;AAEb,EAAA,MAAM,SAAA,GAAY,OAAO,OAAA,CAAQ,cAAc,EAC1C,GAAA,CAAI,CAAC,CAAC,GAAA,EAAK,KAAK,MAAM,CAAA,EAAG,GAAG,KAAK,UAAA,CAAW,KAAK,CAAC,CAAA,CAAA,CAAG,CAAA,CACrD,KAAK,GAAG,CAAA;AAEb,EAAA,MAAM,UAAA,GAAa,MAAA,CACd,GAAA,CAAI,CAAA,IAAA,KAAQ,CAAA,6BAAA,EAAgC,UAAA,CAAW,IAAI,CAAC,CAAA,EAAA,CAAI,CAAA,CAChE,IAAA,CAAK,QAAQ,CAAA;AAElB,EAAA,MAAM,UAAA,GAAa,OAAA,CACd,GAAA,CAAI,CAAA,GAAA,KAAO,CAAA,2BAAA,EAA8B,UAAA,CAAW,GAAG,CAAC,CAAA,WAAA,CAAa,CAAA,CACrE,IAAA,CAAK,QAAQ,CAAA;AAElB,EAAA,OAAO,CAAA;AAAA,MAAA,EACH,SAAS,CAAA;AAAA;AAAA;AAAA;AAAA,IAAA,EAIX,UAAU;AAAA,IAAA,EACV,IAAI;AAAA;AAAA,QAAA,EAEA,SAAS,CAAA;AAAA,IAAA,EACb,IAAI;AAAA,IAAA,EACJ,UAAU;AAAA;AAAA,OAAA,CAAA;AAGhB;AAKO,SAAS,WAAW,GAAA,EAAqB;AAC5C,EAAA,OAAO,IACF,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA,CACrB,OAAA,CAAQ,MAAM,MAAM,CAAA,CACpB,QAAQ,IAAA,EAAM,MAAM,EACpB,OAAA,CAAQ,IAAA,EAAM,QAAQ,CAAA,CACtB,OAAA,CAAQ,MAAM,OAAO,CAAA;AAC9B;AAKO,SAAS,eAAe,OAAA,EAId;AACb,EAAA,MAAM,EAAE,KAAA,GAAQ,YAAA,EAAc,WAAA,EAAa,MAAA,GAAS,OAAM,GAAI,OAAA;AAE9D,EAAA,MAAM,OAAO,eAAA,CAAgB;AAAA,IACzB,IAAA,EAAM,CAAA,OAAA,EAAU,UAAA,CAAW,KAAK,CAAC,CAAA,QAAA,CAAA;AAAA,IACjC,IAAA,EAAM,YAAY,MAAM,CAAA,QAAA,CAAA;AAAA,IACxB,OAAA,EAAS,CAAC,WAAW;AAAA,GACxB,CAAA;AAED,EAAA,OAAO;AAAA,IACH,IAAA;AAAA,IACA,MAAA,EAAQ,GAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACL,cAAA,EAAgB;AAAA;AACpB,GACJ;AACJ","file":"chunk-ZVC3ZWLM.js","sourcesContent":["/**\r\n * Flight Render Engine - Universal rendering primitives\r\n * \r\n * Supports SSR, SSG, CSR, and ISR - the user chooses per route.\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/** Rendering modes supported by Flight */\r\nexport type RenderMode =\r\n | 'ssr' // Server-Side Rendering\r\n | 'ssg' // Static Site Generation\r\n | 'csr' // Client-Side Rendering\r\n | 'isr'; // Incremental Static Regeneration\r\n\r\n/** Context passed to render functions */\r\nexport interface RenderContext {\r\n /** The URL being rendered */\r\n url: URL;\r\n /** Route parameters */\r\n params: Record<string, string | string[]>;\r\n /** Request headers (available in SSR/ISR) */\r\n headers?: Headers;\r\n /** Cookies (available in SSR/ISR) */\r\n cookies?: Record<string, string>;\r\n /** Request method */\r\n method?: string;\r\n /** Request body (for POST/PUT/etc) */\r\n body?: unknown;\r\n /** Custom context data */\r\n locals?: Record<string, unknown>;\r\n}\r\n\r\n/** Result of a render operation */\r\nexport interface RenderResult {\r\n /** HTML content */\r\n html: string;\r\n /** HTTP status code */\r\n status: number;\r\n /** Response headers */\r\n headers: Record<string, string>;\r\n /** Head elements to inject */\r\n head?: {\r\n title?: string;\r\n meta?: Array<{ name?: string; property?: string; content: string }>;\r\n links?: Array<{ rel: string; href: string;[key: string]: string }>;\r\n scripts?: Array<{ src?: string; content?: string; type?: string }>;\r\n styles?: Array<{ href?: string; content?: string }>;\r\n };\r\n}\r\n\r\n/** Configuration for SSG/ISR */\r\nexport interface StaticRenderConfig {\r\n /** Paths to pre-render */\r\n paths: string[] | (() => Promise<string[]>);\r\n /** Fallback behavior for non-pre-rendered paths */\r\n fallback?: 'blocking' | 'prerender' | false;\r\n}\r\n\r\n/** Configuration for ISR */\r\nexport interface ISRConfig extends StaticRenderConfig {\r\n /** Revalidation time in seconds */\r\n revalidate: number;\r\n}\r\n\r\n// ============================================================================\r\n// Render Mode Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Check if a render mode requires server runtime\r\n */\r\nexport function requiresServer(mode: RenderMode): boolean {\r\n return mode === 'ssr' || mode === 'isr';\r\n}\r\n\r\n/**\r\n * Check if a render mode can be statically generated\r\n */\r\nexport function canBeStatic(mode: RenderMode): boolean {\r\n return mode === 'ssg' || mode === 'isr';\r\n}\r\n\r\n/**\r\n * Check if a render mode is purely client-side\r\n */\r\nexport function isClientOnly(mode: RenderMode): boolean {\r\n return mode === 'csr';\r\n}\r\n\r\n// ============================================================================\r\n// Abstract Renderer Interface\r\n// ============================================================================\r\n\r\n/**\r\n * UI Framework Integration Interface\r\n * \r\n * Each UI framework (React, Vue, Svelte, etc.) implements this interface\r\n * to integrate with Flight's render engine.\r\n */\r\nexport interface UIFrameworkAdapter<Component = unknown> {\r\n /** Framework name */\r\n name: string;\r\n\r\n /** \r\n * Render a component to HTML string (for SSR/SSG)\r\n */\r\n renderToString(\r\n component: Component,\r\n context: RenderContext\r\n ): Promise<RenderResult>;\r\n\r\n /**\r\n * Render a component to a stream (for streaming SSR)\r\n */\r\n renderToStream?(\r\n component: Component,\r\n context: RenderContext\r\n ): Promise<ReadableStream<Uint8Array>>;\r\n\r\n /**\r\n * Generate client hydration script\r\n */\r\n getHydrationScript?(component: Component): string;\r\n\r\n /**\r\n * File extensions this adapter handles\r\n */\r\n extensions: string[];\r\n}\r\n\r\n// ============================================================================\r\n// Default HTML Render Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Create a minimal HTML shell\r\n */\r\nexport function createHTMLShell(options: {\r\n head?: string;\r\n body: string;\r\n scripts?: string[];\r\n styles?: string[];\r\n htmlAttributes?: Record<string, string>;\r\n bodyAttributes?: Record<string, string>;\r\n}): string {\r\n const { head = '', body, scripts = [], styles = [], htmlAttributes = {}, bodyAttributes = {} } = options;\r\n\r\n const htmlAttrs = Object.entries(htmlAttributes)\r\n .map(([key, value]) => `${key}=\"${escapeHtml(value)}\"`)\r\n .join(' ');\r\n\r\n const bodyAttrs = Object.entries(bodyAttributes)\r\n .map(([key, value]) => `${key}=\"${escapeHtml(value)}\"`)\r\n .join(' ');\r\n\r\n const styleLinks = styles\r\n .map(href => `<link rel=\"stylesheet\" href=\"${escapeHtml(href)}\">`)\r\n .join('\\n ');\r\n\r\n const scriptTags = scripts\r\n .map(src => `<script type=\"module\" src=\"${escapeHtml(src)}\"></script>`)\r\n .join('\\n ');\r\n\r\n return `<!DOCTYPE html>\r\n<html ${htmlAttrs}>\r\n <head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n ${styleLinks}\r\n ${head}\r\n </head>\r\n <body ${bodyAttrs}>\r\n ${body}\r\n ${scriptTags}\r\n </body>\r\n</html>`;\r\n}\r\n\r\n/**\r\n * Escape HTML special characters\r\n */\r\nexport function escapeHtml(str: string): string {\r\n return str\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''');\r\n}\r\n\r\n/**\r\n * Create a CSR shell (minimal HTML that loads client bundle)\r\n */\r\nexport function createCSRShell(options: {\r\n title?: string;\r\n entryScript: string;\r\n rootId?: string;\r\n}): RenderResult {\r\n const { title = 'Flight App', entryScript, rootId = 'app' } = options;\r\n\r\n const html = createHTMLShell({\r\n head: `<title>${escapeHtml(title)}</title>`,\r\n body: `<div id=\"${rootId}\"></div>`,\r\n scripts: [entryScript],\r\n });\r\n\r\n return {\r\n html,\r\n status: 200,\r\n headers: {\r\n 'Content-Type': 'text/html; charset=utf-8',\r\n },\r\n };\r\n}\r\n"]}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { RenderMode } from '../render/index.js';
|
|
2
|
+
import { FlightAdapter } from '../adapters/index.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Flight Configuration - User configuration system
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** UI Framework configuration */
|
|
9
|
+
interface UIConfig {
|
|
10
|
+
/** The UI framework to use */
|
|
11
|
+
framework?: 'react' | 'vue' | 'svelte' | 'solid' | 'preact' | 'vanilla' | string;
|
|
12
|
+
/** Framework-specific options */
|
|
13
|
+
options?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
/** Rendering configuration */
|
|
16
|
+
interface RenderConfig {
|
|
17
|
+
/** Default render mode */
|
|
18
|
+
default?: RenderMode;
|
|
19
|
+
/** Per-route render mode overrides */
|
|
20
|
+
routes?: Record<string, RenderMode>;
|
|
21
|
+
}
|
|
22
|
+
/** Development server options */
|
|
23
|
+
interface DevConfig {
|
|
24
|
+
/** Port to run dev server on */
|
|
25
|
+
port?: number;
|
|
26
|
+
/** Host to bind to */
|
|
27
|
+
host?: string | boolean;
|
|
28
|
+
/** Open browser on start */
|
|
29
|
+
open?: boolean;
|
|
30
|
+
/** HTTPS configuration */
|
|
31
|
+
https?: boolean | {
|
|
32
|
+
key?: string;
|
|
33
|
+
cert?: string;
|
|
34
|
+
};
|
|
35
|
+
/** Proxy configuration */
|
|
36
|
+
proxy?: Record<string, string | {
|
|
37
|
+
target: string;
|
|
38
|
+
changeOrigin?: boolean;
|
|
39
|
+
rewrite?: (path: string) => string;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
/** Build configuration */
|
|
43
|
+
interface BuildConfig {
|
|
44
|
+
/** Output directory */
|
|
45
|
+
outDir?: string;
|
|
46
|
+
/** Source directory */
|
|
47
|
+
srcDir?: string;
|
|
48
|
+
/** Public assets directory */
|
|
49
|
+
publicDir?: string;
|
|
50
|
+
/** Routes directory */
|
|
51
|
+
routesDir?: string;
|
|
52
|
+
/** Generate sourcemaps */
|
|
53
|
+
sourcemap?: boolean | 'inline' | 'hidden';
|
|
54
|
+
/** Minify output */
|
|
55
|
+
minify?: boolean | 'terser' | 'esbuild';
|
|
56
|
+
/** Target environments */
|
|
57
|
+
target?: string | string[];
|
|
58
|
+
}
|
|
59
|
+
/** Full Flight configuration (resolved) */
|
|
60
|
+
interface FlightConfig {
|
|
61
|
+
/** Root directory */
|
|
62
|
+
root: string;
|
|
63
|
+
/** Deployment adapter */
|
|
64
|
+
adapter: FlightAdapter | null;
|
|
65
|
+
/** UI framework configuration */
|
|
66
|
+
ui: UIConfig;
|
|
67
|
+
/** Rendering configuration */
|
|
68
|
+
rendering: RenderConfig;
|
|
69
|
+
/** Development server options */
|
|
70
|
+
dev: Required<DevConfig>;
|
|
71
|
+
/** Build configuration */
|
|
72
|
+
build: Required<BuildConfig>;
|
|
73
|
+
/** Vite configuration overrides */
|
|
74
|
+
vite?: Record<string, unknown>;
|
|
75
|
+
/** Plugin configurations */
|
|
76
|
+
plugins: FlightPlugin[];
|
|
77
|
+
}
|
|
78
|
+
/** Flight plugin interface */
|
|
79
|
+
interface FlightPlugin {
|
|
80
|
+
/** Plugin name */
|
|
81
|
+
name: string;
|
|
82
|
+
/** Hook into config resolution */
|
|
83
|
+
config?: (config: FlightConfig) => FlightConfig | void | Promise<FlightConfig | void>;
|
|
84
|
+
/** Hook into build start */
|
|
85
|
+
buildStart?: () => void | Promise<void>;
|
|
86
|
+
/** Hook into build end */
|
|
87
|
+
buildEnd?: () => void | Promise<void>;
|
|
88
|
+
/** Hook into dev server start */
|
|
89
|
+
devStart?: () => void | Promise<void>;
|
|
90
|
+
}
|
|
91
|
+
/** User-provided configuration (partial) */
|
|
92
|
+
interface FlightUserConfig {
|
|
93
|
+
/** Root directory (defaults to process.cwd()) */
|
|
94
|
+
root?: string;
|
|
95
|
+
/** Deployment adapter */
|
|
96
|
+
adapter?: FlightAdapter;
|
|
97
|
+
/** UI framework configuration */
|
|
98
|
+
ui?: UIConfig;
|
|
99
|
+
/** Rendering configuration */
|
|
100
|
+
rendering?: RenderConfig;
|
|
101
|
+
/** Development server options */
|
|
102
|
+
dev?: DevConfig;
|
|
103
|
+
/** Build configuration */
|
|
104
|
+
build?: BuildConfig;
|
|
105
|
+
/** Vite configuration overrides */
|
|
106
|
+
vite?: Record<string, unknown>;
|
|
107
|
+
/** Plugins */
|
|
108
|
+
plugins?: FlightPlugin[];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Define Flight configuration
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* // flight.config.ts
|
|
116
|
+
* import { defineConfig } from '@flight/core';
|
|
117
|
+
* import node from '@flight/adapter-node';
|
|
118
|
+
*
|
|
119
|
+
* export default defineConfig({
|
|
120
|
+
* adapter: node(),
|
|
121
|
+
* ui: { framework: 'react' },
|
|
122
|
+
* rendering: {
|
|
123
|
+
* default: 'ssr',
|
|
124
|
+
* routes: {
|
|
125
|
+
* '/blog/*': 'ssg',
|
|
126
|
+
* '/app/*': 'csr',
|
|
127
|
+
* },
|
|
128
|
+
* },
|
|
129
|
+
* });
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
declare function defineConfig(config: FlightUserConfig): FlightUserConfig;
|
|
133
|
+
/**
|
|
134
|
+
* Resolve user config to full config with defaults
|
|
135
|
+
*/
|
|
136
|
+
declare function resolveConfig(userConfig?: FlightUserConfig): FlightConfig;
|
|
137
|
+
/**
|
|
138
|
+
* Find the config file in a directory
|
|
139
|
+
*/
|
|
140
|
+
declare function findConfigFile(root: string): Promise<string | null>;
|
|
141
|
+
/**
|
|
142
|
+
* Load configuration from file
|
|
143
|
+
*/
|
|
144
|
+
declare function loadConfig(root?: string): Promise<FlightConfig>;
|
|
145
|
+
|
|
146
|
+
export { type BuildConfig, type DevConfig, type FlightConfig, type FlightPlugin, type FlightUserConfig, type RenderConfig, type UIConfig, defineConfig, findConfigFile, loadConfig, resolveConfig };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @flight/core - File Router
|
|
3
|
+
*
|
|
4
|
+
* Auto-discovery of routes from file system.
|
|
5
|
+
* Similar to Next.js App Router and Nuxt server/api patterns.
|
|
6
|
+
*/
|
|
7
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
|
|
8
|
+
type Handler = (context: unknown) => Response | Promise<Response>;
|
|
9
|
+
type Middleware = (context: unknown, next: () => Promise<Response>) => Response | Promise<Response>;
|
|
10
|
+
interface FileRoute {
|
|
11
|
+
/** HTTP method (GET, POST, etc) or 'ALL' */
|
|
12
|
+
method: HttpMethod | 'ALL';
|
|
13
|
+
/** Route path with params (e.g., /users/:id) */
|
|
14
|
+
path: string;
|
|
15
|
+
/** Original file path */
|
|
16
|
+
filePath: string;
|
|
17
|
+
/** Handler function (for APIs) */
|
|
18
|
+
handler?: Handler;
|
|
19
|
+
/** Route-specific middleware */
|
|
20
|
+
middleware?: Middleware[];
|
|
21
|
+
/** Route type: 'page' for SSR pages, 'api' for API endpoints */
|
|
22
|
+
type: 'page' | 'api';
|
|
23
|
+
/** Component function (for pages) */
|
|
24
|
+
component?: () => unknown;
|
|
25
|
+
/** Page metadata (title, description, etc) */
|
|
26
|
+
meta?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
interface FileRouterOptions {
|
|
29
|
+
/** Root directory to scan (default: src/routes) */
|
|
30
|
+
directory: string;
|
|
31
|
+
/** File extensions to consider (default: ['.ts', '.js']) */
|
|
32
|
+
extensions?: string[];
|
|
33
|
+
/** Whether to watch for changes (default: false in prod) */
|
|
34
|
+
watch?: boolean;
|
|
35
|
+
}
|
|
36
|
+
interface ScanResult {
|
|
37
|
+
routes: FileRoute[];
|
|
38
|
+
errors: string[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Scan a directory for route files
|
|
42
|
+
*/
|
|
43
|
+
declare function scanRoutes(options: FileRouterOptions): Promise<ScanResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Load routes with their handlers or components
|
|
46
|
+
*/
|
|
47
|
+
declare function loadRoutes(scanResult: ScanResult): Promise<FileRoute[]>;
|
|
48
|
+
interface FileRouter {
|
|
49
|
+
routes: FileRoute[];
|
|
50
|
+
refresh: () => Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create a file-based router
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* import { createFileRouter } from '@flight/core/file-router';
|
|
58
|
+
* import { createServer } from '@flight/http';
|
|
59
|
+
*
|
|
60
|
+
* const router = await createFileRouter({ directory: './src/routes' });
|
|
61
|
+
* const app = createServer();
|
|
62
|
+
*
|
|
63
|
+
* // Register all discovered routes
|
|
64
|
+
* for (const route of router.routes) {
|
|
65
|
+
* app[route.method.toLowerCase()](route.path, route.handler);
|
|
66
|
+
* }
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
declare function createFileRouter(options: FileRouterOptions): Promise<FileRouter>;
|
|
70
|
+
|
|
71
|
+
export { type FileRoute, type FileRouter, type FileRouterOptions, type Handler, type HttpMethod, type Middleware, type ScanResult, createFileRouter, loadRoutes, scanRoutes };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @flight/core - Route Handlers
|
|
3
|
+
*
|
|
4
|
+
* Types and utilities for route handlers.
|
|
5
|
+
* Similar to Next.js Route Handlers pattern.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* HTTP methods supported by route handlers
|
|
9
|
+
*/
|
|
10
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
|
|
11
|
+
/**
|
|
12
|
+
* Context passed to route handlers
|
|
13
|
+
*/
|
|
14
|
+
interface RouteHandlerContext {
|
|
15
|
+
/** Route parameters (e.g., { id: '123' }) */
|
|
16
|
+
params: Record<string, string>;
|
|
17
|
+
/** Query string parameters */
|
|
18
|
+
searchParams: URLSearchParams;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Route handler function signature
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // src/routes/api/users/[id].ts
|
|
26
|
+
* export const GET: RouteHandler = async (request, context) => {
|
|
27
|
+
* const { id } = context.params;
|
|
28
|
+
* return Response.json({ userId: id });
|
|
29
|
+
* };
|
|
30
|
+
*
|
|
31
|
+
* export const PUT: RouteHandler = async (request, context) => {
|
|
32
|
+
* const body = await request.json();
|
|
33
|
+
* return Response.json({ updated: true, data: body });
|
|
34
|
+
* };
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
type RouteHandler = (request: Request, context: RouteHandlerContext) => Response | Promise<Response>;
|
|
38
|
+
/**
|
|
39
|
+
* Create a route handler context from request
|
|
40
|
+
*/
|
|
41
|
+
declare function createRouteContext(request: Request, params?: Record<string, string>): RouteHandlerContext;
|
|
42
|
+
/**
|
|
43
|
+
* Helper to create JSON response
|
|
44
|
+
*/
|
|
45
|
+
declare function json<T>(data: T, init?: ResponseInit): Response;
|
|
46
|
+
/**
|
|
47
|
+
* Helper to create redirect response
|
|
48
|
+
*/
|
|
49
|
+
declare function redirect(url: string, status?: 301 | 302 | 303 | 307 | 308): Response;
|
|
50
|
+
/**
|
|
51
|
+
* Helper to create error response
|
|
52
|
+
*/
|
|
53
|
+
declare function error(message: string, status?: number): Response;
|
|
54
|
+
/**
|
|
55
|
+
* Helper to get request body as typed object
|
|
56
|
+
*/
|
|
57
|
+
declare function parseBody<T>(request: Request): Promise<T>;
|
|
58
|
+
|
|
59
|
+
export { type HttpMethod, type RouteHandler, type RouteHandlerContext, createRouteContext, error, json, parseBody, redirect };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|