@flight-framework/cli 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +97 -3076
- package/dist/bin.js.map +1 -1
- package/dist/index.js +97 -3076
- package/dist/index.js.map +1 -1
- package/package.json +53 -50
- package/templates/base/README.md.template +26 -0
- package/templates/base/_gitignore +25 -0
- package/templates/base/flight.config.ts.template +10 -0
- package/templates/base/styles/global.css +58 -0
- package/templates/htmx/index.html +19 -0
- package/templates/htmx/package.json.template +14 -0
- package/templates/htmx/vite.config.ts +6 -0
- package/templates/lit/index.html +15 -0
- package/templates/lit/package.json.template +19 -0
- package/templates/lit/src/app-root.ts +18 -0
- package/templates/lit/src/entry-client.ts +5 -0
- package/templates/lit/src/entry-server.ts +9 -0
- package/templates/lit/tsconfig.json +19 -0
- package/templates/lit/vite.config.ts +6 -0
- package/templates/preact/index.html +15 -0
- package/templates/preact/package.json.template +20 -0
- package/templates/preact/src/App.tsx +8 -0
- package/templates/preact/src/entry-client.tsx +11 -0
- package/templates/preact/src/entry-server.tsx +6 -0
- package/templates/preact/tsconfig.json +19 -0
- package/templates/preact/vite.config.ts +8 -0
- package/templates/qwik/index.html +15 -0
- package/templates/qwik/package.json.template +18 -0
- package/templates/qwik/src/App.tsx +10 -0
- package/templates/qwik/src/entry-client.tsx +4 -0
- package/templates/qwik/src/entry-server.tsx +9 -0
- package/templates/qwik/tsconfig.json +19 -0
- package/templates/qwik/vite.config.ts +8 -0
- package/templates/react/index.html +13 -0
- package/templates/react/package.json.template +22 -0
- package/templates/react/src/App.tsx +8 -0
- package/templates/react/src/entry-client.tsx +11 -0
- package/templates/react/src/entry-server.tsx +6 -0
- package/templates/react/tsconfig.json +20 -0
- package/templates/react/vite.config.ts +12 -0
- package/templates/solid/index.html +15 -0
- package/templates/solid/package.json.template +19 -0
- package/templates/solid/src/App.tsx +8 -0
- package/templates/solid/src/entry-client.tsx +11 -0
- package/templates/solid/src/entry-server.tsx +6 -0
- package/templates/solid/tsconfig.json +19 -0
- package/templates/solid/vite.config.ts +8 -0
- package/templates/svelte/index.html +15 -0
- package/templates/svelte/package.json.template +19 -0
- package/templates/svelte/src/App.svelte +4 -0
- package/templates/svelte/src/entry-client.ts +7 -0
- package/templates/svelte/src/entry-server.ts +7 -0
- package/templates/svelte/tsconfig.json +18 -0
- package/templates/svelte/vite.config.ts +8 -0
- package/templates/vanilla/index.html +15 -0
- package/templates/vanilla/package.json.template +15 -0
- package/templates/vanilla/src/main.ts +10 -0
- package/templates/vanilla/tsconfig.json +17 -0
- package/templates/vanilla/vite.config.ts +6 -0
- package/templates/vue/index.html +15 -0
- package/templates/vue/package.json.template +19 -0
- package/templates/vue/src/App.vue +6 -0
- package/templates/vue/src/entry-client.ts +12 -0
- package/templates/vue/src/entry-server.ts +8 -0
- package/templates/vue/tsconfig.json +18 -0
- package/templates/vue/vite.config.ts +8 -0
- package/LICENSE +0 -21
package/dist/index.js
CHANGED
|
@@ -1,2098 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
2
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
5
3
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
6
4
|
}) : x)(function(x) {
|
|
7
5
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
8
6
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
9
7
|
});
|
|
10
|
-
var __esm = (fn, res) => function __init() {
|
|
11
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
-
};
|
|
13
|
-
var __export = (target, all) => {
|
|
14
|
-
for (var name in all)
|
|
15
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
// ../core/dist/chunk-WAGCTWGY.js
|
|
19
|
-
function defineConfig(config) {
|
|
20
|
-
return config;
|
|
21
|
-
}
|
|
22
|
-
function resolveConfig(userConfig = {}) {
|
|
23
|
-
return {
|
|
24
|
-
root: userConfig.root ?? process.cwd(),
|
|
25
|
-
adapter: userConfig.adapter ?? DEFAULT_CONFIG.adapter,
|
|
26
|
-
ui: {
|
|
27
|
-
...DEFAULT_CONFIG.ui,
|
|
28
|
-
...userConfig.ui
|
|
29
|
-
},
|
|
30
|
-
rendering: {
|
|
31
|
-
...DEFAULT_CONFIG.rendering,
|
|
32
|
-
...userConfig.rendering
|
|
33
|
-
},
|
|
34
|
-
dev: {
|
|
35
|
-
...DEFAULT_CONFIG.dev,
|
|
36
|
-
...userConfig.dev
|
|
37
|
-
},
|
|
38
|
-
build: {
|
|
39
|
-
...DEFAULT_CONFIG.build,
|
|
40
|
-
...userConfig.build
|
|
41
|
-
},
|
|
42
|
-
vite: userConfig.vite,
|
|
43
|
-
plugins: userConfig.plugins ?? []
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
async function findConfigFile(root) {
|
|
47
|
-
const { existsSync: existsSync3 } = await import("fs");
|
|
48
|
-
const { join: join4 } = await import("path");
|
|
49
|
-
for (const file of CONFIG_FILES) {
|
|
50
|
-
const path = join4(root, file);
|
|
51
|
-
if (existsSync3(path)) {
|
|
52
|
-
return path;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
async function loadConfig(root = process.cwd()) {
|
|
58
|
-
const configFile = await findConfigFile(root);
|
|
59
|
-
if (!configFile) {
|
|
60
|
-
return resolveConfig({ root });
|
|
61
|
-
}
|
|
62
|
-
try {
|
|
63
|
-
const { pathToFileURL } = await import("url");
|
|
64
|
-
const configUrl = pathToFileURL(configFile).href;
|
|
65
|
-
const module = await import(configUrl);
|
|
66
|
-
const userConfig = module.default;
|
|
67
|
-
return resolveConfig({
|
|
68
|
-
...userConfig,
|
|
69
|
-
root
|
|
70
|
-
});
|
|
71
|
-
} catch (error2) {
|
|
72
|
-
console.error(`Failed to load config from ${configFile}:`, error2);
|
|
73
|
-
return resolveConfig({ root });
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
var DEFAULT_CONFIG, CONFIG_FILES;
|
|
77
|
-
var init_chunk_WAGCTWGY = __esm({
|
|
78
|
-
"../core/dist/chunk-WAGCTWGY.js"() {
|
|
79
|
-
"use strict";
|
|
80
|
-
DEFAULT_CONFIG = {
|
|
81
|
-
adapter: null,
|
|
82
|
-
ui: {
|
|
83
|
-
framework: "vanilla"
|
|
84
|
-
},
|
|
85
|
-
rendering: {
|
|
86
|
-
default: "ssr",
|
|
87
|
-
routes: {}
|
|
88
|
-
},
|
|
89
|
-
dev: {
|
|
90
|
-
port: 5173,
|
|
91
|
-
host: "localhost",
|
|
92
|
-
open: false,
|
|
93
|
-
https: false,
|
|
94
|
-
proxy: {}
|
|
95
|
-
},
|
|
96
|
-
build: {
|
|
97
|
-
outDir: "dist",
|
|
98
|
-
srcDir: "src",
|
|
99
|
-
publicDir: "public",
|
|
100
|
-
routesDir: "src/routes",
|
|
101
|
-
sourcemap: false,
|
|
102
|
-
minify: true,
|
|
103
|
-
target: "es2022"
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
CONFIG_FILES = [
|
|
107
|
-
"flight.config.ts",
|
|
108
|
-
"flight.config.js",
|
|
109
|
-
"flight.config.mjs",
|
|
110
|
-
"flight.config.mts"
|
|
111
|
-
];
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// ../../node_modules/.pnpm/radix3@1.1.2/node_modules/radix3/dist/index.mjs
|
|
116
|
-
function createRouter(options = {}) {
|
|
117
|
-
const ctx = {
|
|
118
|
-
options,
|
|
119
|
-
rootNode: createRadixNode(),
|
|
120
|
-
staticRoutesMap: {}
|
|
121
|
-
};
|
|
122
|
-
const normalizeTrailingSlash = (p) => options.strictTrailingSlash ? p : p.replace(/\/$/, "") || "/";
|
|
123
|
-
if (options.routes) {
|
|
124
|
-
for (const path in options.routes) {
|
|
125
|
-
insert(ctx, normalizeTrailingSlash(path), options.routes[path]);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return {
|
|
129
|
-
ctx,
|
|
130
|
-
lookup: (path) => lookup(ctx, normalizeTrailingSlash(path)),
|
|
131
|
-
insert: (path, data) => insert(ctx, normalizeTrailingSlash(path), data),
|
|
132
|
-
remove: (path) => remove(ctx, normalizeTrailingSlash(path))
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
function lookup(ctx, path) {
|
|
136
|
-
const staticPathNode = ctx.staticRoutesMap[path];
|
|
137
|
-
if (staticPathNode) {
|
|
138
|
-
return staticPathNode.data;
|
|
139
|
-
}
|
|
140
|
-
const sections = path.split("/");
|
|
141
|
-
const params = {};
|
|
142
|
-
let paramsFound = false;
|
|
143
|
-
let wildcardNode = null;
|
|
144
|
-
let node = ctx.rootNode;
|
|
145
|
-
let wildCardParam = null;
|
|
146
|
-
for (let i = 0; i < sections.length; i++) {
|
|
147
|
-
const section = sections[i];
|
|
148
|
-
if (node.wildcardChildNode !== null) {
|
|
149
|
-
wildcardNode = node.wildcardChildNode;
|
|
150
|
-
wildCardParam = sections.slice(i).join("/");
|
|
151
|
-
}
|
|
152
|
-
const nextNode = node.children.get(section);
|
|
153
|
-
if (nextNode === void 0) {
|
|
154
|
-
if (node && node.placeholderChildren.length > 1) {
|
|
155
|
-
const remaining = sections.length - i;
|
|
156
|
-
node = node.placeholderChildren.find((c) => c.maxDepth === remaining) || null;
|
|
157
|
-
} else {
|
|
158
|
-
node = node.placeholderChildren[0] || null;
|
|
159
|
-
}
|
|
160
|
-
if (!node) {
|
|
161
|
-
break;
|
|
162
|
-
}
|
|
163
|
-
if (node.paramName) {
|
|
164
|
-
params[node.paramName] = section;
|
|
165
|
-
}
|
|
166
|
-
paramsFound = true;
|
|
167
|
-
} else {
|
|
168
|
-
node = nextNode;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
if ((node === null || node.data === null) && wildcardNode !== null) {
|
|
172
|
-
node = wildcardNode;
|
|
173
|
-
params[node.paramName || "_"] = wildCardParam;
|
|
174
|
-
paramsFound = true;
|
|
175
|
-
}
|
|
176
|
-
if (!node) {
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
if (paramsFound) {
|
|
180
|
-
return {
|
|
181
|
-
...node.data,
|
|
182
|
-
params: paramsFound ? params : void 0
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
return node.data;
|
|
186
|
-
}
|
|
187
|
-
function insert(ctx, path, data) {
|
|
188
|
-
let isStaticRoute = true;
|
|
189
|
-
const sections = path.split("/");
|
|
190
|
-
let node = ctx.rootNode;
|
|
191
|
-
let _unnamedPlaceholderCtr = 0;
|
|
192
|
-
const matchedNodes = [node];
|
|
193
|
-
for (const section of sections) {
|
|
194
|
-
let childNode;
|
|
195
|
-
if (childNode = node.children.get(section)) {
|
|
196
|
-
node = childNode;
|
|
197
|
-
} else {
|
|
198
|
-
const type = getNodeType(section);
|
|
199
|
-
childNode = createRadixNode({ type, parent: node });
|
|
200
|
-
node.children.set(section, childNode);
|
|
201
|
-
if (type === NODE_TYPES.PLACEHOLDER) {
|
|
202
|
-
childNode.paramName = section === "*" ? `_${_unnamedPlaceholderCtr++}` : section.slice(1);
|
|
203
|
-
node.placeholderChildren.push(childNode);
|
|
204
|
-
isStaticRoute = false;
|
|
205
|
-
} else if (type === NODE_TYPES.WILDCARD) {
|
|
206
|
-
node.wildcardChildNode = childNode;
|
|
207
|
-
childNode.paramName = section.slice(
|
|
208
|
-
3
|
|
209
|
-
/* "**:" */
|
|
210
|
-
) || "_";
|
|
211
|
-
isStaticRoute = false;
|
|
212
|
-
}
|
|
213
|
-
matchedNodes.push(childNode);
|
|
214
|
-
node = childNode;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
for (const [depth, node2] of matchedNodes.entries()) {
|
|
218
|
-
node2.maxDepth = Math.max(matchedNodes.length - depth, node2.maxDepth || 0);
|
|
219
|
-
}
|
|
220
|
-
node.data = data;
|
|
221
|
-
if (isStaticRoute === true) {
|
|
222
|
-
ctx.staticRoutesMap[path] = node;
|
|
223
|
-
}
|
|
224
|
-
return node;
|
|
225
|
-
}
|
|
226
|
-
function remove(ctx, path) {
|
|
227
|
-
let success = false;
|
|
228
|
-
const sections = path.split("/");
|
|
229
|
-
let node = ctx.rootNode;
|
|
230
|
-
for (const section of sections) {
|
|
231
|
-
node = node.children.get(section);
|
|
232
|
-
if (!node) {
|
|
233
|
-
return success;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
if (node.data) {
|
|
237
|
-
const lastSection = sections.at(-1) || "";
|
|
238
|
-
node.data = null;
|
|
239
|
-
if (Object.keys(node.children).length === 0 && node.parent) {
|
|
240
|
-
node.parent.children.delete(lastSection);
|
|
241
|
-
node.parent.wildcardChildNode = null;
|
|
242
|
-
node.parent.placeholderChildren = [];
|
|
243
|
-
}
|
|
244
|
-
success = true;
|
|
245
|
-
}
|
|
246
|
-
return success;
|
|
247
|
-
}
|
|
248
|
-
function createRadixNode(options = {}) {
|
|
249
|
-
return {
|
|
250
|
-
type: options.type || NODE_TYPES.NORMAL,
|
|
251
|
-
maxDepth: 0,
|
|
252
|
-
parent: options.parent || null,
|
|
253
|
-
children: /* @__PURE__ */ new Map(),
|
|
254
|
-
data: options.data || null,
|
|
255
|
-
paramName: options.paramName || null,
|
|
256
|
-
wildcardChildNode: null,
|
|
257
|
-
placeholderChildren: []
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
function getNodeType(str) {
|
|
261
|
-
if (str.startsWith("**")) {
|
|
262
|
-
return NODE_TYPES.WILDCARD;
|
|
263
|
-
}
|
|
264
|
-
if (str[0] === ":" || str === "*") {
|
|
265
|
-
return NODE_TYPES.PLACEHOLDER;
|
|
266
|
-
}
|
|
267
|
-
return NODE_TYPES.NORMAL;
|
|
268
|
-
}
|
|
269
|
-
var NODE_TYPES;
|
|
270
|
-
var init_dist = __esm({
|
|
271
|
-
"../../node_modules/.pnpm/radix3@1.1.2/node_modules/radix3/dist/index.mjs"() {
|
|
272
|
-
"use strict";
|
|
273
|
-
NODE_TYPES = {
|
|
274
|
-
NORMAL: 0,
|
|
275
|
-
WILDCARD: 1,
|
|
276
|
-
PLACEHOLDER: 2
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// ../http/dist/index.js
|
|
282
|
-
var dist_exports = {};
|
|
283
|
-
__export(dist_exports, {
|
|
284
|
-
FlightHttp: () => FlightHttp,
|
|
285
|
-
Router: () => Router,
|
|
286
|
-
createContext: () => createContext,
|
|
287
|
-
createServer: () => createServer
|
|
288
|
-
});
|
|
289
|
-
function createContext(request, params = {}, env = {}) {
|
|
290
|
-
const variables = {};
|
|
291
|
-
return {
|
|
292
|
-
req: request,
|
|
293
|
-
env,
|
|
294
|
-
params,
|
|
295
|
-
variables,
|
|
296
|
-
// Response helpers
|
|
297
|
-
json(data, status = 200) {
|
|
298
|
-
return new Response(JSON.stringify(data), {
|
|
299
|
-
status,
|
|
300
|
-
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
301
|
-
});
|
|
302
|
-
},
|
|
303
|
-
text(text, status = 200) {
|
|
304
|
-
return new Response(text, {
|
|
305
|
-
status,
|
|
306
|
-
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
307
|
-
});
|
|
308
|
-
},
|
|
309
|
-
html(html, status = 200) {
|
|
310
|
-
return new Response(html, {
|
|
311
|
-
status,
|
|
312
|
-
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
313
|
-
});
|
|
314
|
-
},
|
|
315
|
-
redirect(url, status = 302) {
|
|
316
|
-
return new Response(null, {
|
|
317
|
-
status,
|
|
318
|
-
headers: { Location: url }
|
|
319
|
-
});
|
|
320
|
-
},
|
|
321
|
-
// Variable getter/setter
|
|
322
|
-
get(key) {
|
|
323
|
-
return variables[key];
|
|
324
|
-
},
|
|
325
|
-
set(key, value) {
|
|
326
|
-
variables[key] = value;
|
|
327
|
-
},
|
|
328
|
-
// Request helpers
|
|
329
|
-
header(name) {
|
|
330
|
-
return request.headers.get(name);
|
|
331
|
-
},
|
|
332
|
-
cookie(name) {
|
|
333
|
-
const cookieHeader = request.headers.get("cookie");
|
|
334
|
-
if (!cookieHeader) return void 0;
|
|
335
|
-
const cookies2 = parseCookies(cookieHeader);
|
|
336
|
-
return cookies2[name];
|
|
337
|
-
}
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
function parseCookies(cookieHeader) {
|
|
341
|
-
const cookies2 = {};
|
|
342
|
-
for (const cookie of cookieHeader.split(";")) {
|
|
343
|
-
const [name, ...rest] = cookie.trim().split("=");
|
|
344
|
-
if (name) {
|
|
345
|
-
cookies2[name] = rest.join("=");
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
return cookies2;
|
|
349
|
-
}
|
|
350
|
-
function createServer(options = {}) {
|
|
351
|
-
return new FlightHttp(options);
|
|
352
|
-
}
|
|
353
|
-
var Router, FlightHttp;
|
|
354
|
-
var init_dist2 = __esm({
|
|
355
|
-
"../http/dist/index.js"() {
|
|
356
|
-
"use strict";
|
|
357
|
-
init_dist();
|
|
358
|
-
Router = class {
|
|
359
|
-
radix;
|
|
360
|
-
routes = [];
|
|
361
|
-
constructor() {
|
|
362
|
-
this.radix = createRouter();
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Add a route
|
|
366
|
-
*/
|
|
367
|
-
add(method, path, handler) {
|
|
368
|
-
const normalizedPath = this.normalizePath(path);
|
|
369
|
-
let node = this.radix.lookup(normalizedPath);
|
|
370
|
-
if (!node) {
|
|
371
|
-
node = { handlers: /* @__PURE__ */ new Map() };
|
|
372
|
-
this.radix.insert(normalizedPath, node);
|
|
373
|
-
}
|
|
374
|
-
node.handlers.set(method, handler);
|
|
375
|
-
this.routes.push({
|
|
376
|
-
method,
|
|
377
|
-
path: normalizedPath,
|
|
378
|
-
handler,
|
|
379
|
-
middleware: []
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Match a request to a route
|
|
384
|
-
*/
|
|
385
|
-
match(method, path) {
|
|
386
|
-
const normalizedPath = this.normalizePath(path);
|
|
387
|
-
const result = this.radix.lookup(normalizedPath);
|
|
388
|
-
if (!result) {
|
|
389
|
-
return null;
|
|
390
|
-
}
|
|
391
|
-
let handler = result.handlers.get(method);
|
|
392
|
-
if (!handler) {
|
|
393
|
-
handler = result.handlers.get("*");
|
|
394
|
-
}
|
|
395
|
-
if (!handler) {
|
|
396
|
-
return null;
|
|
397
|
-
}
|
|
398
|
-
const params = result.params || {};
|
|
399
|
-
return { handler, params };
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Get all registered routes
|
|
403
|
-
*/
|
|
404
|
-
getRoutes() {
|
|
405
|
-
return [...this.routes];
|
|
406
|
-
}
|
|
407
|
-
/**
|
|
408
|
-
* Normalize path
|
|
409
|
-
*/
|
|
410
|
-
normalizePath(path) {
|
|
411
|
-
if (!path.startsWith("/")) {
|
|
412
|
-
path = "/" + path;
|
|
413
|
-
}
|
|
414
|
-
if (path !== "/" && path.endsWith("/")) {
|
|
415
|
-
path = path.slice(0, -1);
|
|
416
|
-
}
|
|
417
|
-
path = path.replace(/\[([^\]]+)\]/g, ":$1");
|
|
418
|
-
path = path.replace(/\[\.\.\.([\w]+)\]/g, "**");
|
|
419
|
-
return path;
|
|
420
|
-
}
|
|
421
|
-
/**
|
|
422
|
-
* Extract params from matched path
|
|
423
|
-
* @deprecated radix3 handles param extraction internally
|
|
424
|
-
*/
|
|
425
|
-
_extractParams(pattern, actualPath) {
|
|
426
|
-
const params = {};
|
|
427
|
-
const patternParts = pattern.split("/");
|
|
428
|
-
const actualParts = actualPath.split("/");
|
|
429
|
-
for (let i = 0; i < patternParts.length; i++) {
|
|
430
|
-
const patternPart = patternParts[i];
|
|
431
|
-
if (!patternPart) continue;
|
|
432
|
-
if (patternPart.startsWith(":")) {
|
|
433
|
-
const paramName = patternPart.slice(1);
|
|
434
|
-
params[paramName] = actualParts[i] || "";
|
|
435
|
-
} else if (patternPart === "**") {
|
|
436
|
-
const paramName = "slug";
|
|
437
|
-
params[paramName] = actualParts.slice(i).join("/");
|
|
438
|
-
break;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
return params;
|
|
442
|
-
}
|
|
443
|
-
};
|
|
444
|
-
FlightHttp = class _FlightHttp {
|
|
445
|
-
router;
|
|
446
|
-
globalMiddleware = [];
|
|
447
|
-
notFoundHandler;
|
|
448
|
-
errorHandler;
|
|
449
|
-
basePath;
|
|
450
|
-
constructor(options = {}) {
|
|
451
|
-
this.router = new Router();
|
|
452
|
-
this.basePath = options.basePath || "";
|
|
453
|
-
this.notFoundHandler = (c) => c.json(
|
|
454
|
-
{ error: "Not Found", path: new URL(c.req.url).pathname },
|
|
455
|
-
404
|
|
456
|
-
);
|
|
457
|
-
this.errorHandler = (error2, c) => c.json(
|
|
458
|
-
{ error: error2.message || "Internal Server Error" },
|
|
459
|
-
500
|
|
460
|
-
);
|
|
461
|
-
}
|
|
462
|
-
// ========================================================================
|
|
463
|
-
// Route Registration
|
|
464
|
-
// ========================================================================
|
|
465
|
-
get(path, ...handlers) {
|
|
466
|
-
return this.addRoute("GET", path, handlers);
|
|
467
|
-
}
|
|
468
|
-
post(path, ...handlers) {
|
|
469
|
-
return this.addRoute("POST", path, handlers);
|
|
470
|
-
}
|
|
471
|
-
put(path, ...handlers) {
|
|
472
|
-
return this.addRoute("PUT", path, handlers);
|
|
473
|
-
}
|
|
474
|
-
delete(path, ...handlers) {
|
|
475
|
-
return this.addRoute("DELETE", path, handlers);
|
|
476
|
-
}
|
|
477
|
-
patch(path, ...handlers) {
|
|
478
|
-
return this.addRoute("PATCH", path, handlers);
|
|
479
|
-
}
|
|
480
|
-
options(path, ...handlers) {
|
|
481
|
-
return this.addRoute("OPTIONS", path, handlers);
|
|
482
|
-
}
|
|
483
|
-
head(path, ...handlers) {
|
|
484
|
-
return this.addRoute("HEAD", path, handlers);
|
|
485
|
-
}
|
|
486
|
-
all(path, ...handlers) {
|
|
487
|
-
return this.addRoute("*", path, handlers);
|
|
488
|
-
}
|
|
489
|
-
// ========================================================================
|
|
490
|
-
// Middleware
|
|
491
|
-
// ========================================================================
|
|
492
|
-
use(...handlers) {
|
|
493
|
-
this.globalMiddleware.push(...handlers);
|
|
494
|
-
return this;
|
|
495
|
-
}
|
|
496
|
-
// ========================================================================
|
|
497
|
-
// Sub-routing
|
|
498
|
-
// ========================================================================
|
|
499
|
-
route(path, router) {
|
|
500
|
-
if (router instanceof _FlightHttp) {
|
|
501
|
-
const routes = router.router.getRoutes();
|
|
502
|
-
for (const route of routes) {
|
|
503
|
-
const fullPath = this.basePath + path + route.path;
|
|
504
|
-
this.router.add(route.method, fullPath, route.handler);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
return this;
|
|
508
|
-
}
|
|
509
|
-
// ========================================================================
|
|
510
|
-
// Error Handling
|
|
511
|
-
// ========================================================================
|
|
512
|
-
notFound(handler) {
|
|
513
|
-
this.notFoundHandler = handler;
|
|
514
|
-
return this;
|
|
515
|
-
}
|
|
516
|
-
onError(handler) {
|
|
517
|
-
this.errorHandler = handler;
|
|
518
|
-
return this;
|
|
519
|
-
}
|
|
520
|
-
// ========================================================================
|
|
521
|
-
// Core Fetch Handler
|
|
522
|
-
// ========================================================================
|
|
523
|
-
async fetch(request, options = {}) {
|
|
524
|
-
const url = new URL(request.url);
|
|
525
|
-
const path = url.pathname;
|
|
526
|
-
const method = request.method.toUpperCase();
|
|
527
|
-
const match = this.router.match(method, path);
|
|
528
|
-
const context = createContext(
|
|
529
|
-
request,
|
|
530
|
-
match?.params || {},
|
|
531
|
-
options.env || {}
|
|
532
|
-
);
|
|
533
|
-
try {
|
|
534
|
-
const middlewares = [...this.globalMiddleware];
|
|
535
|
-
if (match) {
|
|
536
|
-
const composed = this.composeMiddleware(
|
|
537
|
-
middlewares,
|
|
538
|
-
match.handler
|
|
539
|
-
);
|
|
540
|
-
return await composed(context);
|
|
541
|
-
} else {
|
|
542
|
-
if (middlewares.length > 0) {
|
|
543
|
-
const composed = this.composeMiddleware(
|
|
544
|
-
middlewares,
|
|
545
|
-
this.notFoundHandler
|
|
546
|
-
);
|
|
547
|
-
return await composed(context);
|
|
548
|
-
}
|
|
549
|
-
return await this.notFoundHandler(context);
|
|
550
|
-
}
|
|
551
|
-
} catch (error2) {
|
|
552
|
-
console.error("[Flight HTTP] Error:", error2);
|
|
553
|
-
return await this.errorHandler(
|
|
554
|
-
error2 instanceof Error ? error2 : new Error(String(error2)),
|
|
555
|
-
context
|
|
556
|
-
);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
// ========================================================================
|
|
560
|
-
// Listen (Node.js adapter will override this)
|
|
561
|
-
// ========================================================================
|
|
562
|
-
listen(options) {
|
|
563
|
-
const port = typeof options === "number" ? options : options?.port || 3e3;
|
|
564
|
-
console.log(`[Flight HTTP] Call adapter-specific listen() to start server on port ${port}`);
|
|
565
|
-
console.log('[Flight HTTP] Import from "@flight/http/node" or "@flight/http/bun"');
|
|
566
|
-
}
|
|
567
|
-
// ========================================================================
|
|
568
|
-
// Private Methods
|
|
569
|
-
// ========================================================================
|
|
570
|
-
addRoute(method, path, handlers) {
|
|
571
|
-
const mainHandler = handlers[handlers.length - 1];
|
|
572
|
-
const routeMiddleware = handlers.slice(0, -1);
|
|
573
|
-
const fullPath = this.basePath + path;
|
|
574
|
-
if (routeMiddleware.length > 0) {
|
|
575
|
-
const composedHandler = this.composeMiddleware(routeMiddleware, mainHandler);
|
|
576
|
-
this.router.add(method, fullPath, composedHandler);
|
|
577
|
-
} else {
|
|
578
|
-
this.router.add(method, fullPath, mainHandler);
|
|
579
|
-
}
|
|
580
|
-
return this;
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* Compose middleware chain with final handler
|
|
584
|
-
*/
|
|
585
|
-
composeMiddleware(middlewares, handler) {
|
|
586
|
-
return async (c) => {
|
|
587
|
-
let index = 0;
|
|
588
|
-
const dispatch = async () => {
|
|
589
|
-
if (index < middlewares.length) {
|
|
590
|
-
const middleware = middlewares[index++];
|
|
591
|
-
if (middleware) {
|
|
592
|
-
return await middleware(c, dispatch);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
return await handler(c);
|
|
596
|
-
};
|
|
597
|
-
return await dispatch();
|
|
598
|
-
};
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
}
|
|
602
|
-
});
|
|
603
|
-
|
|
604
|
-
// ../core/dist/chunk-I5RHYGX6.js
|
|
605
|
-
import { readdir } from "fs/promises";
|
|
606
|
-
import { join as join2, extname, basename } from "path";
|
|
607
|
-
async function scanRoutes(options) {
|
|
608
|
-
const {
|
|
609
|
-
directory,
|
|
610
|
-
extensions = [".ts", ".js"]
|
|
611
|
-
} = options;
|
|
612
|
-
const routes = [];
|
|
613
|
-
const errors = [];
|
|
614
|
-
async function scanDir(dir, basePath = "") {
|
|
615
|
-
try {
|
|
616
|
-
const entries = await readdir(dir, { withFileTypes: true });
|
|
617
|
-
for (const entry of entries) {
|
|
618
|
-
const fullPath = join2(dir, entry.name);
|
|
619
|
-
if (entry.isDirectory()) {
|
|
620
|
-
if (entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
621
|
-
continue;
|
|
622
|
-
}
|
|
623
|
-
await scanDir(fullPath, `${basePath}/${entry.name}`);
|
|
624
|
-
} else if (entry.isFile()) {
|
|
625
|
-
const ext = extname(entry.name);
|
|
626
|
-
if (!extensions.includes(ext)) {
|
|
627
|
-
continue;
|
|
628
|
-
}
|
|
629
|
-
const routeInfo = parseRouteFile(entry.name, basePath);
|
|
630
|
-
if (routeInfo && routeInfo.method && routeInfo.path) {
|
|
631
|
-
routes.push({
|
|
632
|
-
method: routeInfo.method,
|
|
633
|
-
path: routeInfo.path,
|
|
634
|
-
filePath: fullPath,
|
|
635
|
-
type: routeInfo.type
|
|
636
|
-
});
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
} catch (error2) {
|
|
641
|
-
errors.push(`Failed to scan ${dir}: ${error2}`);
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
await scanDir(directory);
|
|
645
|
-
return { routes, errors };
|
|
646
|
-
}
|
|
647
|
-
function parseRouteFile(filename, basePath) {
|
|
648
|
-
const ext = extname(filename);
|
|
649
|
-
const nameWithoutExt = basename(filename, ext);
|
|
650
|
-
if (nameWithoutExt.startsWith("_")) {
|
|
651
|
-
return null;
|
|
652
|
-
}
|
|
653
|
-
let type = "api";
|
|
654
|
-
let routeName = nameWithoutExt;
|
|
655
|
-
let method = "ALL";
|
|
656
|
-
const pageMatch = nameWithoutExt.match(/^(.+)?\.page$/i);
|
|
657
|
-
if (pageMatch) {
|
|
658
|
-
type = "page";
|
|
659
|
-
method = "GET";
|
|
660
|
-
routeName = pageMatch[1] || "index";
|
|
661
|
-
} else {
|
|
662
|
-
const methodMatch = nameWithoutExt.match(/^(.+)\.(get|post|put|delete|patch|head|options)$/i);
|
|
663
|
-
if (methodMatch) {
|
|
664
|
-
routeName = methodMatch[1] || nameWithoutExt;
|
|
665
|
-
method = (methodMatch[2] || "ALL").toUpperCase();
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
if (basePath.startsWith("/api") || basePath.includes("/api/")) {
|
|
669
|
-
type = "api";
|
|
670
|
-
}
|
|
671
|
-
let path = basePath;
|
|
672
|
-
if (routeName !== "index") {
|
|
673
|
-
path = `${basePath}/${convertToRoutePath(routeName)}`;
|
|
674
|
-
}
|
|
675
|
-
if (!path.startsWith("/")) {
|
|
676
|
-
path = "/" + path;
|
|
677
|
-
}
|
|
678
|
-
if (path !== "/" && path.endsWith("/")) {
|
|
679
|
-
path = path.slice(0, -1);
|
|
680
|
-
}
|
|
681
|
-
return { method, path, type };
|
|
682
|
-
}
|
|
683
|
-
function convertToRoutePath(name) {
|
|
684
|
-
if (name.startsWith("[[...") && name.endsWith("]]")) {
|
|
685
|
-
const paramName = name.slice(5, -2);
|
|
686
|
-
return `:${paramName}*`;
|
|
687
|
-
}
|
|
688
|
-
if (name.startsWith("[...") && name.endsWith("]")) {
|
|
689
|
-
const paramName = name.slice(4, -1);
|
|
690
|
-
return `:${paramName}+`;
|
|
691
|
-
}
|
|
692
|
-
if (name.startsWith("[") && name.endsWith("]")) {
|
|
693
|
-
const paramName = name.slice(1, -1);
|
|
694
|
-
return `:${paramName}`;
|
|
695
|
-
}
|
|
696
|
-
return name;
|
|
697
|
-
}
|
|
698
|
-
async function loadRoutes(scanResult) {
|
|
699
|
-
const loadedRoutes = [];
|
|
700
|
-
for (const route of scanResult.routes) {
|
|
701
|
-
try {
|
|
702
|
-
const module = await import(route.filePath);
|
|
703
|
-
if (route.type === "page") {
|
|
704
|
-
const component = module.default;
|
|
705
|
-
const meta = module.meta || module.metadata || {};
|
|
706
|
-
if (component) {
|
|
707
|
-
loadedRoutes.push({
|
|
708
|
-
...route,
|
|
709
|
-
component,
|
|
710
|
-
meta
|
|
711
|
-
});
|
|
712
|
-
}
|
|
713
|
-
continue;
|
|
714
|
-
}
|
|
715
|
-
if (route.method === "ALL") {
|
|
716
|
-
const methods = ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"];
|
|
717
|
-
for (const method of methods) {
|
|
718
|
-
if (typeof module[method] === "function") {
|
|
719
|
-
loadedRoutes.push({
|
|
720
|
-
...route,
|
|
721
|
-
method,
|
|
722
|
-
handler: module[method]
|
|
723
|
-
});
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
if (typeof module.default === "function") {
|
|
727
|
-
loadedRoutes.push({
|
|
728
|
-
...route,
|
|
729
|
-
method: "ALL",
|
|
730
|
-
handler: module.default
|
|
731
|
-
});
|
|
732
|
-
}
|
|
733
|
-
} else {
|
|
734
|
-
const handler = module[route.method] || module.default;
|
|
735
|
-
if (typeof handler === "function") {
|
|
736
|
-
loadedRoutes.push({
|
|
737
|
-
...route,
|
|
738
|
-
handler
|
|
739
|
-
});
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
} catch (error2) {
|
|
743
|
-
console.error(`[Flight] Failed to load route ${route.filePath}:`, error2);
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
return loadedRoutes;
|
|
747
|
-
}
|
|
748
|
-
async function createFileRouter(options) {
|
|
749
|
-
let routes = [];
|
|
750
|
-
async function refresh() {
|
|
751
|
-
const scanResult = await scanRoutes(options);
|
|
752
|
-
if (scanResult.errors.length > 0) {
|
|
753
|
-
console.warn("[Flight] Route scan errors:", scanResult.errors);
|
|
754
|
-
}
|
|
755
|
-
routes = await loadRoutes(scanResult);
|
|
756
|
-
console.log(`[Flight] Loaded ${routes.length} routes from ${options.directory}`);
|
|
757
|
-
}
|
|
758
|
-
await refresh();
|
|
759
|
-
return {
|
|
760
|
-
get routes() {
|
|
761
|
-
return routes;
|
|
762
|
-
},
|
|
763
|
-
refresh
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
var init_chunk_I5RHYGX6 = __esm({
|
|
767
|
-
"../core/dist/chunk-I5RHYGX6.js"() {
|
|
768
|
-
"use strict";
|
|
769
|
-
}
|
|
770
|
-
});
|
|
771
|
-
|
|
772
|
-
// ../core/dist/file-router/index.js
|
|
773
|
-
var file_router_exports = {};
|
|
774
|
-
__export(file_router_exports, {
|
|
775
|
-
createFileRouter: () => createFileRouter,
|
|
776
|
-
loadRoutes: () => loadRoutes,
|
|
777
|
-
scanRoutes: () => scanRoutes
|
|
778
|
-
});
|
|
779
|
-
var init_file_router = __esm({
|
|
780
|
-
"../core/dist/file-router/index.js"() {
|
|
781
|
-
"use strict";
|
|
782
|
-
init_chunk_I5RHYGX6();
|
|
783
|
-
}
|
|
784
|
-
});
|
|
785
|
-
|
|
786
|
-
// ../core/dist/chunk-TKXN7KGE.js
|
|
787
|
-
function registerAction(action) {
|
|
788
|
-
actionRegistry.set(action.id, action);
|
|
789
|
-
}
|
|
790
|
-
function getAction(id) {
|
|
791
|
-
return actionRegistry.get(id);
|
|
792
|
-
}
|
|
793
|
-
async function executeAction(actionId, args) {
|
|
794
|
-
const action = getAction(actionId);
|
|
795
|
-
if (!action) {
|
|
796
|
-
return {
|
|
797
|
-
success: false,
|
|
798
|
-
error: `Action not found: ${actionId}`
|
|
799
|
-
};
|
|
800
|
-
}
|
|
801
|
-
try {
|
|
802
|
-
const result = await action.fn(...args);
|
|
803
|
-
return {
|
|
804
|
-
success: true,
|
|
805
|
-
data: result
|
|
806
|
-
};
|
|
807
|
-
} catch (error2) {
|
|
808
|
-
if (isRedirectError(error2)) {
|
|
809
|
-
throw error2;
|
|
810
|
-
}
|
|
811
|
-
console.error(`[Flight] Action error (${actionId}):`, error2);
|
|
812
|
-
return {
|
|
813
|
-
success: false,
|
|
814
|
-
error: error2 instanceof Error ? error2.message : "Unknown error"
|
|
815
|
-
};
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
async function executeFormAction(actionId, formData) {
|
|
819
|
-
return executeAction(actionId, [formData]);
|
|
820
|
-
}
|
|
821
|
-
function cookies() {
|
|
822
|
-
const cookieStore = globalThis.__flightCookies;
|
|
823
|
-
if (!cookieStore) {
|
|
824
|
-
console.warn("[Flight] Cookies not available outside of action context");
|
|
825
|
-
return {
|
|
826
|
-
get: () => void 0,
|
|
827
|
-
set: () => {
|
|
828
|
-
},
|
|
829
|
-
delete: () => {
|
|
830
|
-
}
|
|
831
|
-
};
|
|
832
|
-
}
|
|
833
|
-
return cookieStore;
|
|
834
|
-
}
|
|
835
|
-
function redirect(url) {
|
|
836
|
-
throw new RedirectError(url);
|
|
837
|
-
}
|
|
838
|
-
function isRedirectError(error2) {
|
|
839
|
-
return error2 instanceof RedirectError;
|
|
840
|
-
}
|
|
841
|
-
function parseFormData(formData) {
|
|
842
|
-
const result = {};
|
|
843
|
-
formData.forEach((value, key) => {
|
|
844
|
-
result[key] = String(value);
|
|
845
|
-
});
|
|
846
|
-
return result;
|
|
847
|
-
}
|
|
848
|
-
async function handleActionRequest(request) {
|
|
849
|
-
const url = new URL(request.url);
|
|
850
|
-
const actionPath = url.pathname;
|
|
851
|
-
const match = actionPath.match(/^\/__flight_action\/(.+)$/);
|
|
852
|
-
if (!match) {
|
|
853
|
-
return new Response(JSON.stringify({ error: "Invalid action path" }), {
|
|
854
|
-
status: 400,
|
|
855
|
-
headers: { "Content-Type": "application/json" }
|
|
856
|
-
});
|
|
857
|
-
}
|
|
858
|
-
const actionId = match[1];
|
|
859
|
-
if (!actionId) {
|
|
860
|
-
return new Response(JSON.stringify({ error: "Missing action ID" }), {
|
|
861
|
-
status: 400,
|
|
862
|
-
headers: { "Content-Type": "application/json" }
|
|
863
|
-
});
|
|
864
|
-
}
|
|
865
|
-
try {
|
|
866
|
-
let result;
|
|
867
|
-
const contentType = request.headers.get("content-type") || "";
|
|
868
|
-
if (contentType.includes("application/x-www-form-urlencoded") || contentType.includes("multipart/form-data")) {
|
|
869
|
-
const formData = await request.formData();
|
|
870
|
-
result = await executeFormAction(actionId, formData);
|
|
871
|
-
} else {
|
|
872
|
-
const args = await request.json();
|
|
873
|
-
result = await executeAction(actionId, Array.isArray(args) ? args : [args]);
|
|
874
|
-
}
|
|
875
|
-
return new Response(JSON.stringify(result), {
|
|
876
|
-
status: result.success ? 200 : 400,
|
|
877
|
-
headers: { "Content-Type": "application/json" }
|
|
878
|
-
});
|
|
879
|
-
} catch (error2) {
|
|
880
|
-
if (isRedirectError(error2)) {
|
|
881
|
-
return new Response(null, {
|
|
882
|
-
status: 303,
|
|
883
|
-
headers: { Location: error2.url }
|
|
884
|
-
});
|
|
885
|
-
}
|
|
886
|
-
return new Response(JSON.stringify({
|
|
887
|
-
success: false,
|
|
888
|
-
error: error2 instanceof Error ? error2.message : "Unknown error"
|
|
889
|
-
}), {
|
|
890
|
-
status: 500,
|
|
891
|
-
headers: { "Content-Type": "application/json" }
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
var actionRegistry, RedirectError;
|
|
896
|
-
var init_chunk_TKXN7KGE = __esm({
|
|
897
|
-
"../core/dist/chunk-TKXN7KGE.js"() {
|
|
898
|
-
"use strict";
|
|
899
|
-
actionRegistry = /* @__PURE__ */ new Map();
|
|
900
|
-
RedirectError = class extends Error {
|
|
901
|
-
url;
|
|
902
|
-
constructor(url) {
|
|
903
|
-
super(`Redirect to ${url}`);
|
|
904
|
-
this.name = "RedirectError";
|
|
905
|
-
this.url = url;
|
|
906
|
-
}
|
|
907
|
-
};
|
|
908
|
-
}
|
|
909
|
-
});
|
|
910
|
-
|
|
911
|
-
// ../core/dist/chunk-AJ3IBYXT.js
|
|
912
|
-
function createRouteContext(request, params = {}) {
|
|
913
|
-
const url = new URL(request.url);
|
|
914
|
-
return {
|
|
915
|
-
params,
|
|
916
|
-
searchParams: url.searchParams
|
|
917
|
-
};
|
|
918
|
-
}
|
|
919
|
-
function json(data, init) {
|
|
920
|
-
const headers = new Headers(init?.headers);
|
|
921
|
-
headers.set("Content-Type", "application/json; charset=utf-8");
|
|
922
|
-
return new Response(JSON.stringify(data), {
|
|
923
|
-
...init,
|
|
924
|
-
headers
|
|
925
|
-
});
|
|
926
|
-
}
|
|
927
|
-
function redirect2(url, status = 302) {
|
|
928
|
-
return new Response(null, {
|
|
929
|
-
status,
|
|
930
|
-
headers: { Location: url }
|
|
931
|
-
});
|
|
932
|
-
}
|
|
933
|
-
function error(message, status = 500) {
|
|
934
|
-
return new Response(JSON.stringify({ error: message }), {
|
|
935
|
-
status,
|
|
936
|
-
headers: { "Content-Type": "application/json" }
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
async function parseBody(request) {
|
|
940
|
-
const contentType = request.headers.get("content-type") || "";
|
|
941
|
-
if (contentType.includes("application/json")) {
|
|
942
|
-
return await request.json();
|
|
943
|
-
}
|
|
944
|
-
if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
945
|
-
const formData = await request.formData();
|
|
946
|
-
const obj = {};
|
|
947
|
-
formData.forEach((value, key) => {
|
|
948
|
-
obj[key] = String(value);
|
|
949
|
-
});
|
|
950
|
-
return obj;
|
|
951
|
-
}
|
|
952
|
-
throw new Error(`Unsupported content type: ${contentType}`);
|
|
953
|
-
}
|
|
954
|
-
var init_chunk_AJ3IBYXT = __esm({
|
|
955
|
-
"../core/dist/chunk-AJ3IBYXT.js"() {
|
|
956
|
-
"use strict";
|
|
957
|
-
}
|
|
958
|
-
});
|
|
959
|
-
|
|
960
|
-
// ../core/dist/chunk-QEFGUHYD.js
|
|
961
|
-
async function createStreamingSSR(config) {
|
|
962
|
-
const { shell, shellEnd, suspenseBoundaries = [], options = {} } = config;
|
|
963
|
-
let shellResolved = false;
|
|
964
|
-
let allResolved = false;
|
|
965
|
-
let abortController = null;
|
|
966
|
-
let resolveShell;
|
|
967
|
-
const shellReady = new Promise((resolve5) => {
|
|
968
|
-
resolveShell = resolve5;
|
|
969
|
-
});
|
|
970
|
-
let resolveAll;
|
|
971
|
-
const allReady = new Promise((resolve5) => {
|
|
972
|
-
resolveAll = resolve5;
|
|
973
|
-
});
|
|
974
|
-
const encoder = new TextEncoder();
|
|
975
|
-
const stream = new ReadableStream({
|
|
976
|
-
async start(controller) {
|
|
977
|
-
try {
|
|
978
|
-
const shellWithPlaceholders = buildShellWithPlaceholders(
|
|
979
|
-
shell,
|
|
980
|
-
suspenseBoundaries,
|
|
981
|
-
shellEnd,
|
|
982
|
-
options
|
|
983
|
-
);
|
|
984
|
-
controller.enqueue(encoder.encode(shellWithPlaceholders));
|
|
985
|
-
shellResolved = true;
|
|
986
|
-
options.onShellReady?.();
|
|
987
|
-
resolveShell();
|
|
988
|
-
if (suspenseBoundaries.length > 0) {
|
|
989
|
-
await streamSuspenseContent(controller, encoder, suspenseBoundaries, options);
|
|
990
|
-
}
|
|
991
|
-
if (options.bootstrapScripts?.length || options.bootstrapModules?.length) {
|
|
992
|
-
const hydrationScript = buildHydrationScript(options);
|
|
993
|
-
controller.enqueue(encoder.encode(hydrationScript));
|
|
994
|
-
}
|
|
995
|
-
allResolved = true;
|
|
996
|
-
options.onAllReady?.();
|
|
997
|
-
resolveAll();
|
|
998
|
-
controller.close();
|
|
999
|
-
} catch (error2) {
|
|
1000
|
-
if (!shellResolved) {
|
|
1001
|
-
options.onShellError?.(error2);
|
|
1002
|
-
}
|
|
1003
|
-
options.onError?.(error2);
|
|
1004
|
-
controller.error(error2);
|
|
1005
|
-
}
|
|
1006
|
-
},
|
|
1007
|
-
cancel() {
|
|
1008
|
-
abortController?.abort();
|
|
1009
|
-
}
|
|
1010
|
-
});
|
|
1011
|
-
const abort = () => {
|
|
1012
|
-
abortController?.abort();
|
|
1013
|
-
};
|
|
1014
|
-
if (options.timeoutMs) {
|
|
1015
|
-
abortController = new AbortController();
|
|
1016
|
-
setTimeout(() => {
|
|
1017
|
-
if (!allResolved) {
|
|
1018
|
-
abort();
|
|
1019
|
-
}
|
|
1020
|
-
}, options.timeoutMs);
|
|
1021
|
-
}
|
|
1022
|
-
return {
|
|
1023
|
-
stream,
|
|
1024
|
-
abort,
|
|
1025
|
-
shellReady,
|
|
1026
|
-
allReady
|
|
1027
|
-
};
|
|
1028
|
-
}
|
|
1029
|
-
function buildShellWithPlaceholders(shell, boundaries, shellEnd, options) {
|
|
1030
|
-
let html = shell;
|
|
1031
|
-
if (options.bootstrapScriptContent) {
|
|
1032
|
-
html += `<script>${options.bootstrapScriptContent}</script>`;
|
|
1033
|
-
}
|
|
1034
|
-
for (const boundary of boundaries) {
|
|
1035
|
-
html += `
|
|
1036
|
-
<!--$?--><template id="B:${boundary.id}"></template>
|
|
1037
|
-
${boundary.fallback}
|
|
1038
|
-
<!--/$-->`;
|
|
1039
|
-
}
|
|
1040
|
-
html += shellEnd;
|
|
1041
|
-
return html;
|
|
1042
|
-
}
|
|
1043
|
-
async function streamSuspenseContent(controller, encoder, boundaries, options) {
|
|
1044
|
-
const pending = boundaries.map(async (boundary) => {
|
|
1045
|
-
try {
|
|
1046
|
-
const content = await boundary.contentPromise;
|
|
1047
|
-
return { boundary, content, error: null };
|
|
1048
|
-
} catch (error2) {
|
|
1049
|
-
return { boundary, content: null, error: error2 };
|
|
1050
|
-
}
|
|
1051
|
-
});
|
|
1052
|
-
const results = await Promise.allSettled(pending);
|
|
1053
|
-
for (const result of results) {
|
|
1054
|
-
if (result.status === "fulfilled") {
|
|
1055
|
-
const { boundary, content, error: error2 } = result.value;
|
|
1056
|
-
if (error2) {
|
|
1057
|
-
const errorScript = buildErrorReplacement(boundary.id, error2.message);
|
|
1058
|
-
controller.enqueue(encoder.encode(errorScript));
|
|
1059
|
-
options.onError?.(error2);
|
|
1060
|
-
} else if (content) {
|
|
1061
|
-
const replacementScript = buildContentReplacement(boundary.id, content);
|
|
1062
|
-
controller.enqueue(encoder.encode(replacementScript));
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
}
|
|
1067
|
-
function buildContentReplacement(id, content) {
|
|
1068
|
-
const escaped = content.replace(/\\/g, "\\\\").replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r");
|
|
1069
|
-
return `
|
|
1070
|
-
<script>
|
|
1071
|
-
(function(){
|
|
1072
|
-
var b=document.getElementById("B:${id}");
|
|
1073
|
-
if(b){
|
|
1074
|
-
var p=b.previousSibling;
|
|
1075
|
-
while(p&&p.nodeType===8&&p.data==="$?")p=p.previousSibling;
|
|
1076
|
-
var n=b.nextSibling;
|
|
1077
|
-
var f=document.createDocumentFragment();
|
|
1078
|
-
var t=document.createElement("template");
|
|
1079
|
-
t.innerHTML="${escaped}";
|
|
1080
|
-
while(t.content.firstChild)f.appendChild(t.content.firstChild);
|
|
1081
|
-
if(n&&n.nodeType===8&&n.data==="/$"){
|
|
1082
|
-
var s=n.nextSibling;
|
|
1083
|
-
while(s&&s!==b){var x=s.nextSibling;s.parentNode.removeChild(s);s=x;}
|
|
1084
|
-
}
|
|
1085
|
-
b.parentNode.replaceChild(f,b);
|
|
1086
|
-
}
|
|
1087
|
-
})();
|
|
1088
|
-
</script>`;
|
|
1089
|
-
}
|
|
1090
|
-
function buildErrorReplacement(id, message) {
|
|
1091
|
-
const escaped = message.replace(/'/g, "\\'").replace(/"/g, '\\"');
|
|
1092
|
-
return `
|
|
1093
|
-
<script>
|
|
1094
|
-
(function(){
|
|
1095
|
-
var b=document.getElementById("B:${id}");
|
|
1096
|
-
if(b){
|
|
1097
|
-
var t=document.createElement("div");
|
|
1098
|
-
t.className="streaming-error";
|
|
1099
|
-
t.textContent="Error: ${escaped}";
|
|
1100
|
-
b.parentNode.replaceChild(t,b);
|
|
1101
|
-
}
|
|
1102
|
-
})();
|
|
1103
|
-
</script>`;
|
|
1104
|
-
}
|
|
1105
|
-
function buildHydrationScript(options) {
|
|
1106
|
-
let scripts = "";
|
|
1107
|
-
if (options.bootstrapScripts?.length) {
|
|
1108
|
-
for (const src of options.bootstrapScripts) {
|
|
1109
|
-
const nonceAttr = options.nonce ? ` nonce="${options.nonce}"` : "";
|
|
1110
|
-
scripts += `<script src="${src}"${nonceAttr} async></script>`;
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
if (options.bootstrapModules?.length) {
|
|
1114
|
-
for (const src of options.bootstrapModules) {
|
|
1115
|
-
const nonceAttr = options.nonce ? ` nonce="${options.nonce}"` : "";
|
|
1116
|
-
scripts += `<script type="module" src="${src}"${nonceAttr}></script>`;
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
return scripts;
|
|
1120
|
-
}
|
|
1121
|
-
function createStreamingResponse(stream, options = {}) {
|
|
1122
|
-
return new Response(stream, {
|
|
1123
|
-
status: options.status || 200,
|
|
1124
|
-
headers: {
|
|
1125
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
1126
|
-
"Transfer-Encoding": "chunked",
|
|
1127
|
-
"X-Content-Type-Options": "nosniff",
|
|
1128
|
-
...options.headers
|
|
1129
|
-
}
|
|
1130
|
-
});
|
|
1131
|
-
}
|
|
1132
|
-
async function renderWithStreaming(config) {
|
|
1133
|
-
const { layout, page, suspense = {}, bootstrapScripts, timeoutMs } = config;
|
|
1134
|
-
const pageContent = await page();
|
|
1135
|
-
const boundaries = Object.entries(suspense).map(
|
|
1136
|
-
([id, { fallback, content }]) => ({
|
|
1137
|
-
id,
|
|
1138
|
-
fallback,
|
|
1139
|
-
contentPromise: content
|
|
1140
|
-
})
|
|
1141
|
-
);
|
|
1142
|
-
const result = await createStreamingSSR({
|
|
1143
|
-
shell: layout({ children: pageContent }),
|
|
1144
|
-
shellEnd: "",
|
|
1145
|
-
suspenseBoundaries: boundaries,
|
|
1146
|
-
options: {
|
|
1147
|
-
bootstrapScripts,
|
|
1148
|
-
timeoutMs
|
|
1149
|
-
}
|
|
1150
|
-
});
|
|
1151
|
-
return createStreamingResponse(result.stream);
|
|
1152
|
-
}
|
|
1153
|
-
function createLazyContent(fetcher, renderer, fallback) {
|
|
1154
|
-
return {
|
|
1155
|
-
fallback,
|
|
1156
|
-
content: fetcher().then(renderer)
|
|
1157
|
-
};
|
|
1158
|
-
}
|
|
1159
|
-
async function streamParallel(boundaries) {
|
|
1160
|
-
return boundaries.map((b) => ({
|
|
1161
|
-
id: b.id,
|
|
1162
|
-
fallback: b.fallback,
|
|
1163
|
-
contentPromise: b.content()
|
|
1164
|
-
}));
|
|
1165
|
-
}
|
|
1166
|
-
async function streamSequential(boundaries) {
|
|
1167
|
-
const result = [];
|
|
1168
|
-
for (const b of boundaries) {
|
|
1169
|
-
result.push({
|
|
1170
|
-
id: b.id,
|
|
1171
|
-
fallback: b.fallback,
|
|
1172
|
-
contentPromise: b.content()
|
|
1173
|
-
});
|
|
1174
|
-
}
|
|
1175
|
-
return result;
|
|
1176
|
-
}
|
|
1177
|
-
var init_chunk_QEFGUHYD = __esm({
|
|
1178
|
-
"../core/dist/chunk-QEFGUHYD.js"() {
|
|
1179
|
-
"use strict";
|
|
1180
|
-
}
|
|
1181
|
-
});
|
|
1182
|
-
|
|
1183
|
-
// ../core/dist/chunk-AFSKXC6V.js
|
|
1184
|
-
function hasUseClientDirective(source) {
|
|
1185
|
-
const firstLine = source.trim().split("\n")[0] ?? "";
|
|
1186
|
-
return /^['"]use client['"];?/.test(firstLine);
|
|
1187
|
-
}
|
|
1188
|
-
function hasUseServerDirective(source) {
|
|
1189
|
-
const firstLine = source.trim().split("\n")[0] ?? "";
|
|
1190
|
-
return /^['"]use server['"];?/.test(firstLine);
|
|
1191
|
-
}
|
|
1192
|
-
function detectComponentType(source) {
|
|
1193
|
-
if (hasUseClientDirective(source)) return "client";
|
|
1194
|
-
if (hasUseServerDirective(source)) return "server";
|
|
1195
|
-
return "hybrid";
|
|
1196
|
-
}
|
|
1197
|
-
async function executeServerComponent(component, props, context) {
|
|
1198
|
-
try {
|
|
1199
|
-
const result = await component(props, context);
|
|
1200
|
-
return result;
|
|
1201
|
-
} catch (error2) {
|
|
1202
|
-
console.error("[Flight] Server component error:", error2);
|
|
1203
|
-
throw error2;
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
function createRenderContext(request, params = {}) {
|
|
1207
|
-
const url = new URL(request.url);
|
|
1208
|
-
const cookies2 = /* @__PURE__ */ new Map();
|
|
1209
|
-
const cookieHeader = request.headers.get("cookie") || "";
|
|
1210
|
-
cookieHeader.split(";").forEach((cookie) => {
|
|
1211
|
-
const [key, value] = cookie.trim().split("=");
|
|
1212
|
-
if (key && value) cookies2.set(key, value);
|
|
1213
|
-
});
|
|
1214
|
-
return {
|
|
1215
|
-
request,
|
|
1216
|
-
params,
|
|
1217
|
-
searchParams: url.searchParams,
|
|
1218
|
-
headers: request.headers,
|
|
1219
|
-
cookies: cookies2
|
|
1220
|
-
};
|
|
1221
|
-
}
|
|
1222
|
-
async function serverFetch(url, options = {}) {
|
|
1223
|
-
const { revalidate = 60, tags = [], ...fetchOptions } = options;
|
|
1224
|
-
const cacheKey = `${url}:${JSON.stringify(fetchOptions)}`;
|
|
1225
|
-
const cached = fetchCache.get(cacheKey);
|
|
1226
|
-
if (cached) {
|
|
1227
|
-
const age = Date.now() - cached.timestamp;
|
|
1228
|
-
if (revalidate === false || age < revalidate * 1e3) {
|
|
1229
|
-
return cached.data;
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
const response = await fetch(url, fetchOptions);
|
|
1233
|
-
if (!response.ok) {
|
|
1234
|
-
throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);
|
|
1235
|
-
}
|
|
1236
|
-
const data = await response.json();
|
|
1237
|
-
if (revalidate !== false) {
|
|
1238
|
-
fetchCache.set(cacheKey, {
|
|
1239
|
-
data,
|
|
1240
|
-
timestamp: Date.now()
|
|
1241
|
-
});
|
|
1242
|
-
}
|
|
1243
|
-
return data;
|
|
1244
|
-
}
|
|
1245
|
-
function revalidateTag(tag) {
|
|
1246
|
-
console.log(`[Flight] Revalidating tag: ${tag}`);
|
|
1247
|
-
}
|
|
1248
|
-
function revalidatePath(path) {
|
|
1249
|
-
console.log(`[Flight] Revalidating path: ${path}`);
|
|
1250
|
-
}
|
|
1251
|
-
function serializeProps(props) {
|
|
1252
|
-
function preProcess(value) {
|
|
1253
|
-
if (value instanceof Date) {
|
|
1254
|
-
return { __type: "Date", value: value.toISOString() };
|
|
1255
|
-
}
|
|
1256
|
-
if (value instanceof Map) {
|
|
1257
|
-
return { __type: "Map", value: Array.from(value.entries()).map(([k, v]) => [preProcess(k), preProcess(v)]) };
|
|
1258
|
-
}
|
|
1259
|
-
if (value instanceof Set) {
|
|
1260
|
-
return { __type: "Set", value: Array.from(value).map(preProcess) };
|
|
1261
|
-
}
|
|
1262
|
-
if (typeof value === "bigint") {
|
|
1263
|
-
return { __type: "BigInt", value: value.toString() };
|
|
1264
|
-
}
|
|
1265
|
-
if (typeof value === "function") {
|
|
1266
|
-
return void 0;
|
|
1267
|
-
}
|
|
1268
|
-
if (Array.isArray(value)) {
|
|
1269
|
-
return value.map(preProcess);
|
|
1270
|
-
}
|
|
1271
|
-
if (value && typeof value === "object") {
|
|
1272
|
-
const result = {};
|
|
1273
|
-
for (const [k, v] of Object.entries(value)) {
|
|
1274
|
-
result[k] = preProcess(v);
|
|
1275
|
-
}
|
|
1276
|
-
return result;
|
|
1277
|
-
}
|
|
1278
|
-
return value;
|
|
1279
|
-
}
|
|
1280
|
-
return JSON.stringify(preProcess(props));
|
|
1281
|
-
}
|
|
1282
|
-
function deserializeProps(serialized) {
|
|
1283
|
-
return JSON.parse(serialized, (_key, value) => {
|
|
1284
|
-
if (value && typeof value === "object" && "__type" in value) {
|
|
1285
|
-
switch (value.__type) {
|
|
1286
|
-
case "Date":
|
|
1287
|
-
return new Date(value.value);
|
|
1288
|
-
case "Map":
|
|
1289
|
-
return new Map(value.value);
|
|
1290
|
-
case "Set":
|
|
1291
|
-
return new Set(value.value);
|
|
1292
|
-
case "BigInt":
|
|
1293
|
-
return BigInt(value.value);
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
return value;
|
|
1297
|
-
});
|
|
1298
|
-
}
|
|
1299
|
-
function createClientBoundary(componentId, props, fallback) {
|
|
1300
|
-
const serializedProps = serializeProps(props);
|
|
1301
|
-
return `
|
|
1302
|
-
<!--flight-client:${componentId}-->
|
|
1303
|
-
<div data-flight-component="${componentId}" data-flight-props='${serializedProps.replace(/'/g, "'")}'>
|
|
1304
|
-
${fallback || "<div>Loading...</div>"}
|
|
1305
|
-
</div>
|
|
1306
|
-
<!--/flight-client-->
|
|
1307
|
-
<script type="module">
|
|
1308
|
-
(async function() {
|
|
1309
|
-
const component = await import('/_flight/components/${componentId}.js');
|
|
1310
|
-
const props = JSON.parse('${serializedProps.replace(/'/g, "\\'")}');
|
|
1311
|
-
const container = document.querySelector('[data-flight-component="${componentId}"]');
|
|
1312
|
-
if (container && component.default) {
|
|
1313
|
-
// Hydrate with the framework's hydration method
|
|
1314
|
-
if (typeof component.hydrate === 'function') {
|
|
1315
|
-
component.hydrate(container, props);
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1318
|
-
})();
|
|
1319
|
-
</script>`;
|
|
1320
|
-
}
|
|
1321
|
-
function createAsyncComponent(fetcher, renderer) {
|
|
1322
|
-
const component = async (props, context) => {
|
|
1323
|
-
const data = await fetcher(props, context);
|
|
1324
|
-
return renderer(data, props);
|
|
1325
|
-
};
|
|
1326
|
-
component.__flight_server = true;
|
|
1327
|
-
return component;
|
|
1328
|
-
}
|
|
1329
|
-
function composeComponents(...components) {
|
|
1330
|
-
return async () => {
|
|
1331
|
-
const results = await Promise.all(
|
|
1332
|
-
components.map(async (comp) => await comp())
|
|
1333
|
-
);
|
|
1334
|
-
return results.join("");
|
|
1335
|
-
};
|
|
1336
|
-
}
|
|
1337
|
-
function withErrorBoundary(component, errorFallback) {
|
|
1338
|
-
return async (props, context) => {
|
|
1339
|
-
try {
|
|
1340
|
-
return await component(props, context);
|
|
1341
|
-
} catch (error2) {
|
|
1342
|
-
console.error("[Flight] Server component error:", error2);
|
|
1343
|
-
return errorFallback(error2);
|
|
1344
|
-
}
|
|
1345
|
-
};
|
|
1346
|
-
}
|
|
1347
|
-
function notFound() {
|
|
1348
|
-
const error2 = new Error("Not Found");
|
|
1349
|
-
error2.__flight_not_found = true;
|
|
1350
|
-
throw error2;
|
|
1351
|
-
}
|
|
1352
|
-
function isNotFoundError(error2) {
|
|
1353
|
-
return error2 instanceof Error && error2.__flight_not_found === true;
|
|
1354
|
-
}
|
|
1355
|
-
function redirect3(url, type = "replace") {
|
|
1356
|
-
const error2 = new Error(`Redirect: ${url}`);
|
|
1357
|
-
error2.__flight_redirect = { url, type };
|
|
1358
|
-
throw error2;
|
|
1359
|
-
}
|
|
1360
|
-
function isRedirectError2(error2) {
|
|
1361
|
-
if (error2 instanceof Error && error2.__flight_redirect) {
|
|
1362
|
-
return error2.__flight_redirect;
|
|
1363
|
-
}
|
|
1364
|
-
return null;
|
|
1365
|
-
}
|
|
1366
|
-
var fetchCache;
|
|
1367
|
-
var init_chunk_AFSKXC6V = __esm({
|
|
1368
|
-
"../core/dist/chunk-AFSKXC6V.js"() {
|
|
1369
|
-
"use strict";
|
|
1370
|
-
fetchCache = /* @__PURE__ */ new Map();
|
|
1371
|
-
}
|
|
1372
|
-
});
|
|
1373
|
-
|
|
1374
|
-
// ../core/dist/chunk-ZVC3ZWLM.js
|
|
1375
|
-
var init_chunk_ZVC3ZWLM = __esm({
|
|
1376
|
-
"../core/dist/chunk-ZVC3ZWLM.js"() {
|
|
1377
|
-
"use strict";
|
|
1378
|
-
}
|
|
1379
|
-
});
|
|
1380
|
-
|
|
1381
|
-
// ../core/dist/chunk-3AIQVGTM.js
|
|
1382
|
-
function createCache(options = {}) {
|
|
1383
|
-
const {
|
|
1384
|
-
adapter = new MemoryCacheAdapter(),
|
|
1385
|
-
defaultTTL,
|
|
1386
|
-
prefix = ""
|
|
1387
|
-
} = options;
|
|
1388
|
-
const tagIndex = /* @__PURE__ */ new Map();
|
|
1389
|
-
function prefixKey(key) {
|
|
1390
|
-
return prefix ? `${prefix}:${key}` : key;
|
|
1391
|
-
}
|
|
1392
|
-
return {
|
|
1393
|
-
async get(key) {
|
|
1394
|
-
const entry = await adapter.get(prefixKey(key));
|
|
1395
|
-
if (!entry) return void 0;
|
|
1396
|
-
if (entry.staleAt && Date.now() > entry.staleAt) {
|
|
1397
|
-
return entry.value;
|
|
1398
|
-
}
|
|
1399
|
-
return entry.value;
|
|
1400
|
-
},
|
|
1401
|
-
async set(key, value, opts) {
|
|
1402
|
-
const ttl = opts?.ttl ?? defaultTTL;
|
|
1403
|
-
const now = Date.now();
|
|
1404
|
-
const entry = {
|
|
1405
|
-
value,
|
|
1406
|
-
createdAt: now,
|
|
1407
|
-
tags: opts?.tags
|
|
1408
|
-
};
|
|
1409
|
-
if (ttl) {
|
|
1410
|
-
entry.expiresAt = now + ttl * 1e3;
|
|
1411
|
-
if (opts?.swr) {
|
|
1412
|
-
entry.staleAt = now + (ttl - opts.swr) * 1e3;
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
const fullKey = prefixKey(key);
|
|
1416
|
-
await adapter.set(fullKey, entry);
|
|
1417
|
-
if (opts?.tags) {
|
|
1418
|
-
for (const tag of opts.tags) {
|
|
1419
|
-
if (!tagIndex.has(tag)) {
|
|
1420
|
-
tagIndex.set(tag, /* @__PURE__ */ new Set());
|
|
1421
|
-
}
|
|
1422
|
-
tagIndex.get(tag).add(fullKey);
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
},
|
|
1426
|
-
async delete(key) {
|
|
1427
|
-
return adapter.delete(prefixKey(key));
|
|
1428
|
-
},
|
|
1429
|
-
async has(key) {
|
|
1430
|
-
return adapter.has(prefixKey(key));
|
|
1431
|
-
},
|
|
1432
|
-
async clear() {
|
|
1433
|
-
await adapter.clear();
|
|
1434
|
-
tagIndex.clear();
|
|
1435
|
-
},
|
|
1436
|
-
async invalidateTag(tag) {
|
|
1437
|
-
const keys = tagIndex.get(tag);
|
|
1438
|
-
if (!keys) return;
|
|
1439
|
-
for (const key of keys) {
|
|
1440
|
-
await adapter.delete(key);
|
|
1441
|
-
}
|
|
1442
|
-
tagIndex.delete(tag);
|
|
1443
|
-
},
|
|
1444
|
-
async getOrSet(key, factory, opts) {
|
|
1445
|
-
const cached2 = await this.get(key);
|
|
1446
|
-
if (cached2 !== void 0) {
|
|
1447
|
-
return cached2;
|
|
1448
|
-
}
|
|
1449
|
-
const value = await factory();
|
|
1450
|
-
await this.set(key, value, opts);
|
|
1451
|
-
return value;
|
|
1452
|
-
}
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
var MemoryCacheAdapter;
|
|
1456
|
-
var init_chunk_3AIQVGTM = __esm({
|
|
1457
|
-
"../core/dist/chunk-3AIQVGTM.js"() {
|
|
1458
|
-
"use strict";
|
|
1459
|
-
MemoryCacheAdapter = class {
|
|
1460
|
-
name = "memory";
|
|
1461
|
-
store = /* @__PURE__ */ new Map();
|
|
1462
|
-
async get(key) {
|
|
1463
|
-
const entry = this.store.get(key);
|
|
1464
|
-
if (!entry) return void 0;
|
|
1465
|
-
if (entry.expiresAt && Date.now() > entry.expiresAt) {
|
|
1466
|
-
this.store.delete(key);
|
|
1467
|
-
return void 0;
|
|
1468
|
-
}
|
|
1469
|
-
return entry;
|
|
1470
|
-
}
|
|
1471
|
-
async set(key, entry) {
|
|
1472
|
-
this.store.set(key, entry);
|
|
1473
|
-
}
|
|
1474
|
-
async delete(key) {
|
|
1475
|
-
return this.store.delete(key);
|
|
1476
|
-
}
|
|
1477
|
-
async has(key) {
|
|
1478
|
-
const entry = await this.get(key);
|
|
1479
|
-
return entry !== void 0;
|
|
1480
|
-
}
|
|
1481
|
-
async clear() {
|
|
1482
|
-
this.store.clear();
|
|
1483
|
-
}
|
|
1484
|
-
async keys(pattern) {
|
|
1485
|
-
const allKeys = Array.from(this.store.keys());
|
|
1486
|
-
if (!pattern) return allKeys;
|
|
1487
|
-
const regex = new RegExp(pattern.replace(/\*/g, ".*"));
|
|
1488
|
-
return allKeys.filter((key) => regex.test(key));
|
|
1489
|
-
}
|
|
1490
|
-
};
|
|
1491
|
-
}
|
|
1492
|
-
});
|
|
1493
|
-
|
|
1494
|
-
// ../core/dist/chunk-Q4C5CCHK.js
|
|
1495
|
-
var init_chunk_Q4C5CCHK = __esm({
|
|
1496
|
-
"../core/dist/chunk-Q4C5CCHK.js"() {
|
|
1497
|
-
"use strict";
|
|
1498
|
-
}
|
|
1499
|
-
});
|
|
1500
|
-
|
|
1501
|
-
// ../core/dist/chunk-GCQZ4FHI.js
|
|
1502
|
-
function createRouter2(options = {}) {
|
|
1503
|
-
const ctx = {
|
|
1504
|
-
options,
|
|
1505
|
-
rootNode: createRadixNode2(),
|
|
1506
|
-
staticRoutesMap: {}
|
|
1507
|
-
};
|
|
1508
|
-
const normalizeTrailingSlash = (p) => options.strictTrailingSlash ? p : p.replace(/\/$/, "") || "/";
|
|
1509
|
-
if (options.routes) {
|
|
1510
|
-
for (const path in options.routes) {
|
|
1511
|
-
insert2(ctx, normalizeTrailingSlash(path), options.routes[path]);
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
return {
|
|
1515
|
-
ctx,
|
|
1516
|
-
lookup: (path) => lookup2(ctx, normalizeTrailingSlash(path)),
|
|
1517
|
-
insert: (path, data) => insert2(ctx, normalizeTrailingSlash(path), data),
|
|
1518
|
-
remove: (path) => remove2(ctx, normalizeTrailingSlash(path))
|
|
1519
|
-
};
|
|
1520
|
-
}
|
|
1521
|
-
function lookup2(ctx, path) {
|
|
1522
|
-
const staticPathNode = ctx.staticRoutesMap[path];
|
|
1523
|
-
if (staticPathNode) {
|
|
1524
|
-
return staticPathNode.data;
|
|
1525
|
-
}
|
|
1526
|
-
const sections = path.split("/");
|
|
1527
|
-
const params = {};
|
|
1528
|
-
let paramsFound = false;
|
|
1529
|
-
let wildcardNode = null;
|
|
1530
|
-
let node = ctx.rootNode;
|
|
1531
|
-
let wildCardParam = null;
|
|
1532
|
-
for (let i = 0; i < sections.length; i++) {
|
|
1533
|
-
const section = sections[i];
|
|
1534
|
-
if (node.wildcardChildNode !== null) {
|
|
1535
|
-
wildcardNode = node.wildcardChildNode;
|
|
1536
|
-
wildCardParam = sections.slice(i).join("/");
|
|
1537
|
-
}
|
|
1538
|
-
const nextNode = node.children.get(section);
|
|
1539
|
-
if (nextNode === void 0) {
|
|
1540
|
-
if (node && node.placeholderChildren.length > 1) {
|
|
1541
|
-
const remaining = sections.length - i;
|
|
1542
|
-
node = node.placeholderChildren.find((c) => c.maxDepth === remaining) || null;
|
|
1543
|
-
} else {
|
|
1544
|
-
node = node.placeholderChildren[0] || null;
|
|
1545
|
-
}
|
|
1546
|
-
if (!node) {
|
|
1547
|
-
break;
|
|
1548
|
-
}
|
|
1549
|
-
if (node.paramName) {
|
|
1550
|
-
params[node.paramName] = section;
|
|
1551
|
-
}
|
|
1552
|
-
paramsFound = true;
|
|
1553
|
-
} else {
|
|
1554
|
-
node = nextNode;
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
if ((node === null || node.data === null) && wildcardNode !== null) {
|
|
1558
|
-
node = wildcardNode;
|
|
1559
|
-
params[node.paramName || "_"] = wildCardParam;
|
|
1560
|
-
paramsFound = true;
|
|
1561
|
-
}
|
|
1562
|
-
if (!node) {
|
|
1563
|
-
return null;
|
|
1564
|
-
}
|
|
1565
|
-
if (paramsFound) {
|
|
1566
|
-
return {
|
|
1567
|
-
...node.data,
|
|
1568
|
-
params: paramsFound ? params : void 0
|
|
1569
|
-
};
|
|
1570
|
-
}
|
|
1571
|
-
return node.data;
|
|
1572
|
-
}
|
|
1573
|
-
function insert2(ctx, path, data) {
|
|
1574
|
-
let isStaticRoute = true;
|
|
1575
|
-
const sections = path.split("/");
|
|
1576
|
-
let node = ctx.rootNode;
|
|
1577
|
-
let _unnamedPlaceholderCtr = 0;
|
|
1578
|
-
const matchedNodes = [node];
|
|
1579
|
-
for (const section of sections) {
|
|
1580
|
-
let childNode;
|
|
1581
|
-
if (childNode = node.children.get(section)) {
|
|
1582
|
-
node = childNode;
|
|
1583
|
-
} else {
|
|
1584
|
-
const type = getNodeType2(section);
|
|
1585
|
-
childNode = createRadixNode2({ type, parent: node });
|
|
1586
|
-
node.children.set(section, childNode);
|
|
1587
|
-
if (type === NODE_TYPES2.PLACEHOLDER) {
|
|
1588
|
-
childNode.paramName = section === "*" ? `_${_unnamedPlaceholderCtr++}` : section.slice(1);
|
|
1589
|
-
node.placeholderChildren.push(childNode);
|
|
1590
|
-
isStaticRoute = false;
|
|
1591
|
-
} else if (type === NODE_TYPES2.WILDCARD) {
|
|
1592
|
-
node.wildcardChildNode = childNode;
|
|
1593
|
-
childNode.paramName = section.slice(
|
|
1594
|
-
3
|
|
1595
|
-
/* "**:" */
|
|
1596
|
-
) || "_";
|
|
1597
|
-
isStaticRoute = false;
|
|
1598
|
-
}
|
|
1599
|
-
matchedNodes.push(childNode);
|
|
1600
|
-
node = childNode;
|
|
1601
|
-
}
|
|
1602
|
-
}
|
|
1603
|
-
for (const [depth, node2] of matchedNodes.entries()) {
|
|
1604
|
-
node2.maxDepth = Math.max(matchedNodes.length - depth, node2.maxDepth || 0);
|
|
1605
|
-
}
|
|
1606
|
-
node.data = data;
|
|
1607
|
-
if (isStaticRoute === true) {
|
|
1608
|
-
ctx.staticRoutesMap[path] = node;
|
|
1609
|
-
}
|
|
1610
|
-
return node;
|
|
1611
|
-
}
|
|
1612
|
-
function remove2(ctx, path) {
|
|
1613
|
-
let success = false;
|
|
1614
|
-
const sections = path.split("/");
|
|
1615
|
-
let node = ctx.rootNode;
|
|
1616
|
-
for (const section of sections) {
|
|
1617
|
-
node = node.children.get(section);
|
|
1618
|
-
if (!node) {
|
|
1619
|
-
return success;
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
if (node.data) {
|
|
1623
|
-
const lastSection = sections.at(-1) || "";
|
|
1624
|
-
node.data = null;
|
|
1625
|
-
if (Object.keys(node.children).length === 0 && node.parent) {
|
|
1626
|
-
node.parent.children.delete(lastSection);
|
|
1627
|
-
node.parent.wildcardChildNode = null;
|
|
1628
|
-
node.parent.placeholderChildren = [];
|
|
1629
|
-
}
|
|
1630
|
-
success = true;
|
|
1631
|
-
}
|
|
1632
|
-
return success;
|
|
1633
|
-
}
|
|
1634
|
-
function createRadixNode2(options = {}) {
|
|
1635
|
-
return {
|
|
1636
|
-
type: options.type || NODE_TYPES2.NORMAL,
|
|
1637
|
-
maxDepth: 0,
|
|
1638
|
-
parent: options.parent || null,
|
|
1639
|
-
children: /* @__PURE__ */ new Map(),
|
|
1640
|
-
data: options.data || null,
|
|
1641
|
-
paramName: options.paramName || null,
|
|
1642
|
-
wildcardChildNode: null,
|
|
1643
|
-
placeholderChildren: []
|
|
1644
|
-
};
|
|
1645
|
-
}
|
|
1646
|
-
function getNodeType2(str) {
|
|
1647
|
-
if (str.startsWith("**")) {
|
|
1648
|
-
return NODE_TYPES2.WILDCARD;
|
|
1649
|
-
}
|
|
1650
|
-
if (str[0] === ":" || str === "*") {
|
|
1651
|
-
return NODE_TYPES2.PLACEHOLDER;
|
|
1652
|
-
}
|
|
1653
|
-
return NODE_TYPES2.NORMAL;
|
|
1654
|
-
}
|
|
1655
|
-
function convertPattern(pattern) {
|
|
1656
|
-
return pattern.replace(/\[\.\.\.(\w+)\]/g, "**:$1").replace(/\[(\w+)\]/g, ":$1");
|
|
1657
|
-
}
|
|
1658
|
-
function createRouter22() {
|
|
1659
|
-
const radix = createRouter2();
|
|
1660
|
-
const routeMap = /* @__PURE__ */ new Map();
|
|
1661
|
-
return {
|
|
1662
|
-
add(route) {
|
|
1663
|
-
const radixPath = convertPattern(route.path);
|
|
1664
|
-
radix.insert(radixPath, route);
|
|
1665
|
-
routeMap.set(route.path, route);
|
|
1666
|
-
},
|
|
1667
|
-
addAll(routes) {
|
|
1668
|
-
for (const route of routes) {
|
|
1669
|
-
this.add(route);
|
|
1670
|
-
}
|
|
1671
|
-
},
|
|
1672
|
-
match(path) {
|
|
1673
|
-
const result = radix.lookup(path);
|
|
1674
|
-
if (!result) {
|
|
1675
|
-
return null;
|
|
1676
|
-
}
|
|
1677
|
-
const params = {};
|
|
1678
|
-
if (result.params) {
|
|
1679
|
-
for (const [key, value] of Object.entries(result.params)) {
|
|
1680
|
-
if (value !== void 0) {
|
|
1681
|
-
params[key] = value;
|
|
1682
|
-
}
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
return {
|
|
1686
|
-
route: result,
|
|
1687
|
-
params,
|
|
1688
|
-
path
|
|
1689
|
-
};
|
|
1690
|
-
},
|
|
1691
|
-
routes() {
|
|
1692
|
-
return Array.from(routeMap.values());
|
|
1693
|
-
},
|
|
1694
|
-
remove(path) {
|
|
1695
|
-
if (routeMap.has(path)) {
|
|
1696
|
-
const radixPath = convertPattern(path);
|
|
1697
|
-
radix.remove(radixPath);
|
|
1698
|
-
routeMap.delete(path);
|
|
1699
|
-
return true;
|
|
1700
|
-
}
|
|
1701
|
-
return false;
|
|
1702
|
-
}
|
|
1703
|
-
};
|
|
1704
|
-
}
|
|
1705
|
-
var NODE_TYPES2;
|
|
1706
|
-
var init_chunk_GCQZ4FHI = __esm({
|
|
1707
|
-
"../core/dist/chunk-GCQZ4FHI.js"() {
|
|
1708
|
-
"use strict";
|
|
1709
|
-
NODE_TYPES2 = {
|
|
1710
|
-
NORMAL: 0,
|
|
1711
|
-
WILDCARD: 1,
|
|
1712
|
-
PLACEHOLDER: 2
|
|
1713
|
-
};
|
|
1714
|
-
}
|
|
1715
|
-
});
|
|
1716
|
-
|
|
1717
|
-
// ../core/dist/chunk-KWFX6WHG.js
|
|
1718
|
-
function createMiddlewareChain() {
|
|
1719
|
-
const stack = [];
|
|
1720
|
-
function use(pathOrMiddleware, maybeMiddleware) {
|
|
1721
|
-
if (typeof pathOrMiddleware === "function") {
|
|
1722
|
-
stack.push({ handler: pathOrMiddleware });
|
|
1723
|
-
} else if (typeof pathOrMiddleware === "string" && maybeMiddleware) {
|
|
1724
|
-
stack.push({ path: pathOrMiddleware, handler: maybeMiddleware });
|
|
1725
|
-
} else if (typeof pathOrMiddleware === "object") {
|
|
1726
|
-
stack.push(pathOrMiddleware);
|
|
1727
|
-
}
|
|
1728
|
-
return chain;
|
|
1729
|
-
}
|
|
1730
|
-
async function execute(ctx) {
|
|
1731
|
-
let index = -1;
|
|
1732
|
-
async function dispatch(i) {
|
|
1733
|
-
if (i <= index) {
|
|
1734
|
-
throw new Error("next() called multiple times");
|
|
1735
|
-
}
|
|
1736
|
-
index = i;
|
|
1737
|
-
if (i >= stack.length) {
|
|
1738
|
-
return;
|
|
1739
|
-
}
|
|
1740
|
-
const definition = stack[i];
|
|
1741
|
-
if (!definition) {
|
|
1742
|
-
return dispatch(i + 1);
|
|
1743
|
-
}
|
|
1744
|
-
if (!shouldRun(definition, ctx)) {
|
|
1745
|
-
return dispatch(i + 1);
|
|
1746
|
-
}
|
|
1747
|
-
await definition.handler(ctx, () => dispatch(i + 1));
|
|
1748
|
-
}
|
|
1749
|
-
await dispatch(0);
|
|
1750
|
-
}
|
|
1751
|
-
const chain = {
|
|
1752
|
-
use,
|
|
1753
|
-
execute,
|
|
1754
|
-
middlewares: () => [...stack]
|
|
1755
|
-
};
|
|
1756
|
-
return chain;
|
|
1757
|
-
}
|
|
1758
|
-
function shouldRun(def, ctx) {
|
|
1759
|
-
if (def.methods && !def.methods.includes(ctx.method.toUpperCase())) {
|
|
1760
|
-
return false;
|
|
1761
|
-
}
|
|
1762
|
-
if (def.path) {
|
|
1763
|
-
const path = ctx.url.pathname;
|
|
1764
|
-
if (typeof def.path === "string") {
|
|
1765
|
-
if (def.path.endsWith("*")) {
|
|
1766
|
-
const prefix = def.path.slice(0, -1);
|
|
1767
|
-
if (!path.startsWith(prefix)) {
|
|
1768
|
-
return false;
|
|
1769
|
-
}
|
|
1770
|
-
} else if (def.path !== path) {
|
|
1771
|
-
return false;
|
|
1772
|
-
}
|
|
1773
|
-
} else if (def.path instanceof RegExp) {
|
|
1774
|
-
if (!def.path.test(path)) {
|
|
1775
|
-
return false;
|
|
1776
|
-
}
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
return true;
|
|
1780
|
-
}
|
|
1781
|
-
function createContextFromRequest(request, params = {}) {
|
|
1782
|
-
const url = new URL(request.url);
|
|
1783
|
-
return {
|
|
1784
|
-
url,
|
|
1785
|
-
method: request.method,
|
|
1786
|
-
headers: request.headers,
|
|
1787
|
-
params,
|
|
1788
|
-
query: url.searchParams,
|
|
1789
|
-
locals: {},
|
|
1790
|
-
request,
|
|
1791
|
-
status: 200,
|
|
1792
|
-
responseHeaders: new Headers()
|
|
1793
|
-
};
|
|
1794
|
-
}
|
|
1795
|
-
function createResponseFromContext(ctx) {
|
|
1796
|
-
return new Response(ctx.responseBody, {
|
|
1797
|
-
status: ctx.status,
|
|
1798
|
-
headers: ctx.responseHeaders
|
|
1799
|
-
});
|
|
1800
|
-
}
|
|
1801
|
-
var init_chunk_KWFX6WHG = __esm({
|
|
1802
|
-
"../core/dist/chunk-KWFX6WHG.js"() {
|
|
1803
|
-
"use strict";
|
|
1804
|
-
}
|
|
1805
|
-
});
|
|
1806
|
-
|
|
1807
|
-
// ../core/dist/chunk-Y22KEW2F.js
|
|
1808
|
-
function detectRuntime() {
|
|
1809
|
-
if (typeof Bun !== "undefined") return "bun";
|
|
1810
|
-
if (typeof Deno !== "undefined") return "deno";
|
|
1811
|
-
if (typeof process !== "undefined" && process.versions?.node) return "node";
|
|
1812
|
-
return "unknown";
|
|
1813
|
-
}
|
|
1814
|
-
function createServer2(options = {}) {
|
|
1815
|
-
const config = resolveConfig(options.config ?? {});
|
|
1816
|
-
const router = createRouter22();
|
|
1817
|
-
const middlewareChain = createMiddlewareChain();
|
|
1818
|
-
const deps = {
|
|
1819
|
-
db: options.db,
|
|
1820
|
-
auth: options.auth,
|
|
1821
|
-
email: options.email
|
|
1822
|
-
};
|
|
1823
|
-
function addRoute(method, path, handler) {
|
|
1824
|
-
const methods = Array.isArray(method) ? method : [method];
|
|
1825
|
-
const methodSet = new Set(methods.map((m) => m.toUpperCase()));
|
|
1826
|
-
const existingMatch = router.match(path);
|
|
1827
|
-
if (existingMatch && existingMatch.route.path === path) {
|
|
1828
|
-
for (const m of methodSet) {
|
|
1829
|
-
existingMatch.route.handler.methods.add(m);
|
|
1830
|
-
}
|
|
1831
|
-
existingMatch.route.handler.handler = handler;
|
|
1832
|
-
} else {
|
|
1833
|
-
router.add({
|
|
1834
|
-
path,
|
|
1835
|
-
handler: { methods: methodSet, handler }
|
|
1836
|
-
});
|
|
1837
|
-
}
|
|
1838
|
-
return server;
|
|
1839
|
-
}
|
|
1840
|
-
function useMiddleware(pathOrMiddleware, maybeMiddleware) {
|
|
1841
|
-
if (typeof pathOrMiddleware === "string" && maybeMiddleware) {
|
|
1842
|
-
middlewareChain.use(pathOrMiddleware, maybeMiddleware);
|
|
1843
|
-
} else if (typeof pathOrMiddleware === "function") {
|
|
1844
|
-
middlewareChain.use(pathOrMiddleware);
|
|
1845
|
-
}
|
|
1846
|
-
return server;
|
|
1847
|
-
}
|
|
1848
|
-
async function handle(request) {
|
|
1849
|
-
const url = new URL(request.url);
|
|
1850
|
-
const method = request.method.toUpperCase();
|
|
1851
|
-
const ctx = createContextFromRequest(request);
|
|
1852
|
-
await middlewareChain.execute(ctx);
|
|
1853
|
-
if (ctx.responseBody !== void 0) {
|
|
1854
|
-
return createResponseFromContext(ctx);
|
|
1855
|
-
}
|
|
1856
|
-
const match = router.match(url.pathname);
|
|
1857
|
-
if (!match) {
|
|
1858
|
-
return new Response("Not Found", { status: 404 });
|
|
1859
|
-
}
|
|
1860
|
-
if (!match.route.handler.methods.has(method) && !match.route.handler.methods.has("*")) {
|
|
1861
|
-
return new Response("Method Not Allowed", { status: 405 });
|
|
1862
|
-
}
|
|
1863
|
-
const handlerContext = {
|
|
1864
|
-
request,
|
|
1865
|
-
params: match.params,
|
|
1866
|
-
query: url.searchParams,
|
|
1867
|
-
url,
|
|
1868
|
-
locals: ctx.locals,
|
|
1869
|
-
...deps
|
|
1870
|
-
};
|
|
1871
|
-
try {
|
|
1872
|
-
return await match.route.handler.handler(handlerContext);
|
|
1873
|
-
} catch (error2) {
|
|
1874
|
-
console.error("Route handler error:", error2);
|
|
1875
|
-
return new Response("Internal Server Error", { status: 500 });
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
async function listen(portOrOptions) {
|
|
1879
|
-
const opts = typeof portOrOptions === "number" ? { port: portOrOptions } : portOrOptions ?? {};
|
|
1880
|
-
const port = opts.port ?? config.dev.port ?? 3e3;
|
|
1881
|
-
const hostname = opts.hostname ?? "localhost";
|
|
1882
|
-
const adapter = options.adapter ?? config.adapter;
|
|
1883
|
-
if (adapter?.listen) {
|
|
1884
|
-
await adapter.listen(server, port);
|
|
1885
|
-
return;
|
|
1886
|
-
}
|
|
1887
|
-
const runtime = detectRuntime();
|
|
1888
|
-
switch (runtime) {
|
|
1889
|
-
case "bun":
|
|
1890
|
-
await startBunServer(port, hostname, opts.onListen);
|
|
1891
|
-
break;
|
|
1892
|
-
case "deno":
|
|
1893
|
-
await startDenoServer(port, hostname, opts.onListen);
|
|
1894
|
-
break;
|
|
1895
|
-
case "node":
|
|
1896
|
-
default:
|
|
1897
|
-
await startNodeServer(port, hostname, opts.onListen);
|
|
1898
|
-
break;
|
|
1899
|
-
}
|
|
1900
|
-
}
|
|
1901
|
-
async function startNodeServer(port, hostname, onListen) {
|
|
1902
|
-
const { createServer: createHttpServer } = await import("http");
|
|
1903
|
-
const httpServer = createHttpServer(async (req, res) => {
|
|
1904
|
-
const url = new URL(req.url || "/", `http://${hostname}:${port}`);
|
|
1905
|
-
const headers = new Headers();
|
|
1906
|
-
for (const [key, value] of Object.entries(req.headers)) {
|
|
1907
|
-
if (value) {
|
|
1908
|
-
const headerValue = Array.isArray(value) ? value[0] : value;
|
|
1909
|
-
if (headerValue) headers.set(key, headerValue);
|
|
1910
|
-
}
|
|
1911
|
-
}
|
|
1912
|
-
let body;
|
|
1913
|
-
if (["POST", "PUT", "PATCH"].includes(req.method || "")) {
|
|
1914
|
-
body = await new Promise((resolve5) => {
|
|
1915
|
-
let data = "";
|
|
1916
|
-
req.on("data", (chunk) => data += chunk);
|
|
1917
|
-
req.on("end", () => resolve5(data));
|
|
1918
|
-
});
|
|
1919
|
-
}
|
|
1920
|
-
const request = new Request(url.toString(), {
|
|
1921
|
-
method: req.method,
|
|
1922
|
-
headers,
|
|
1923
|
-
body: body || void 0
|
|
1924
|
-
});
|
|
1925
|
-
try {
|
|
1926
|
-
const response = await handle(request);
|
|
1927
|
-
res.statusCode = response.status;
|
|
1928
|
-
response.headers.forEach((value, key) => {
|
|
1929
|
-
res.setHeader(key, value);
|
|
1930
|
-
});
|
|
1931
|
-
const responseBody = await response.text();
|
|
1932
|
-
res.end(responseBody);
|
|
1933
|
-
} catch (error2) {
|
|
1934
|
-
console.error("Server error:", error2);
|
|
1935
|
-
res.statusCode = 500;
|
|
1936
|
-
res.setHeader("Content-Type", "application/json");
|
|
1937
|
-
res.end(JSON.stringify({ error: "Internal Server Error" }));
|
|
1938
|
-
}
|
|
1939
|
-
});
|
|
1940
|
-
return new Promise((resolve5) => {
|
|
1941
|
-
httpServer.listen(port, hostname, () => {
|
|
1942
|
-
const info = { port, hostname };
|
|
1943
|
-
if (onListen) {
|
|
1944
|
-
onListen(info);
|
|
1945
|
-
} else {
|
|
1946
|
-
console.log(`
|
|
1947
|
-
\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
|
|
1948
|
-
\u2551 Flight Server (Node.js) \u2551
|
|
1949
|
-
\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
|
|
1950
|
-
\u2551 Server: http://${hostname}:${port.toString().padEnd(37)}\u2551
|
|
1951
|
-
\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
|
|
1952
|
-
`);
|
|
1953
|
-
}
|
|
1954
|
-
resolve5();
|
|
1955
|
-
});
|
|
1956
|
-
});
|
|
1957
|
-
}
|
|
1958
|
-
async function startBunServer(port, hostname, onListen) {
|
|
1959
|
-
Bun.serve({
|
|
1960
|
-
port,
|
|
1961
|
-
hostname,
|
|
1962
|
-
fetch: handle
|
|
1963
|
-
});
|
|
1964
|
-
const info = { port, hostname };
|
|
1965
|
-
if (onListen) {
|
|
1966
|
-
onListen(info);
|
|
1967
|
-
} else {
|
|
1968
|
-
console.log(`
|
|
1969
|
-
\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
|
|
1970
|
-
\u2551 Flight Server (Bun) \u2551
|
|
1971
|
-
\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
|
|
1972
|
-
\u2551 Server: http://${hostname}:${port.toString().padEnd(37)}\u2551
|
|
1973
|
-
\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
|
|
1974
|
-
`);
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
async function startDenoServer(port, hostname, onListen) {
|
|
1978
|
-
Deno.serve({ port, hostname }, handle);
|
|
1979
|
-
const info = { port, hostname };
|
|
1980
|
-
if (onListen) {
|
|
1981
|
-
onListen(info);
|
|
1982
|
-
} else {
|
|
1983
|
-
console.log(`
|
|
1984
|
-
\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
|
|
1985
|
-
\u2551 Flight Server (Deno) \u2551
|
|
1986
|
-
\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
|
|
1987
|
-
\u2551 Server: http://${hostname}:${port.toString().padEnd(37)}\u2551
|
|
1988
|
-
\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
|
|
1989
|
-
`);
|
|
1990
|
-
}
|
|
1991
|
-
}
|
|
1992
|
-
const server = {
|
|
1993
|
-
route: addRoute,
|
|
1994
|
-
get: (path, handler) => addRoute("GET", path, handler),
|
|
1995
|
-
post: (path, handler) => addRoute("POST", path, handler),
|
|
1996
|
-
put: (path, handler) => addRoute("PUT", path, handler),
|
|
1997
|
-
delete: (path, handler) => addRoute("DELETE", path, handler),
|
|
1998
|
-
patch: (path, handler) => addRoute("PATCH", path, handler),
|
|
1999
|
-
use: useMiddleware,
|
|
2000
|
-
handle,
|
|
2001
|
-
listen,
|
|
2002
|
-
fetch: handle,
|
|
2003
|
-
// Alias for Bun/Deno compatibility
|
|
2004
|
-
get config() {
|
|
2005
|
-
return config;
|
|
2006
|
-
},
|
|
2007
|
-
get router() {
|
|
2008
|
-
return router;
|
|
2009
|
-
},
|
|
2010
|
-
get middleware() {
|
|
2011
|
-
return middlewareChain;
|
|
2012
|
-
}
|
|
2013
|
-
};
|
|
2014
|
-
return server;
|
|
2015
|
-
}
|
|
2016
|
-
var init_chunk_Y22KEW2F = __esm({
|
|
2017
|
-
"../core/dist/chunk-Y22KEW2F.js"() {
|
|
2018
|
-
"use strict";
|
|
2019
|
-
init_chunk_GCQZ4FHI();
|
|
2020
|
-
init_chunk_KWFX6WHG();
|
|
2021
|
-
init_chunk_WAGCTWGY();
|
|
2022
|
-
}
|
|
2023
|
-
});
|
|
2024
|
-
|
|
2025
|
-
// ../core/dist/index.js
|
|
2026
|
-
var dist_exports2 = {};
|
|
2027
|
-
__export(dist_exports2, {
|
|
2028
|
-
RedirectError: () => RedirectError,
|
|
2029
|
-
VERSION: () => VERSION2,
|
|
2030
|
-
actionRedirect: () => redirect,
|
|
2031
|
-
composeComponents: () => composeComponents,
|
|
2032
|
-
cookies: () => cookies,
|
|
2033
|
-
createAsyncComponent: () => createAsyncComponent,
|
|
2034
|
-
createCache: () => createCache,
|
|
2035
|
-
createClientBoundary: () => createClientBoundary,
|
|
2036
|
-
createFileRouter: () => createFileRouter,
|
|
2037
|
-
createLazyContent: () => createLazyContent,
|
|
2038
|
-
createMiddlewareChain: () => createMiddlewareChain,
|
|
2039
|
-
createRenderContext: () => createRenderContext,
|
|
2040
|
-
createRouteContext: () => createRouteContext,
|
|
2041
|
-
createRouter: () => createRouter22,
|
|
2042
|
-
createServer: () => createServer2,
|
|
2043
|
-
createStreamingResponse: () => createStreamingResponse,
|
|
2044
|
-
createStreamingSSR: () => createStreamingSSR,
|
|
2045
|
-
defineConfig: () => defineConfig,
|
|
2046
|
-
deserializeProps: () => deserializeProps,
|
|
2047
|
-
detectComponentType: () => detectComponentType,
|
|
2048
|
-
error: () => error,
|
|
2049
|
-
executeAction: () => executeAction,
|
|
2050
|
-
executeFormAction: () => executeFormAction,
|
|
2051
|
-
executeServerComponent: () => executeServerComponent,
|
|
2052
|
-
getAction: () => getAction,
|
|
2053
|
-
handleActionRequest: () => handleActionRequest,
|
|
2054
|
-
hasUseClientDirective: () => hasUseClientDirective,
|
|
2055
|
-
hasUseServerDirective: () => hasUseServerDirective,
|
|
2056
|
-
isNotFoundError: () => isNotFoundError,
|
|
2057
|
-
isRedirectError: () => isRedirectError,
|
|
2058
|
-
isRscRedirectError: () => isRedirectError2,
|
|
2059
|
-
json: () => json,
|
|
2060
|
-
loadRoutes: () => loadRoutes,
|
|
2061
|
-
notFound: () => notFound,
|
|
2062
|
-
parseBody: () => parseBody,
|
|
2063
|
-
parseFormData: () => parseFormData,
|
|
2064
|
-
redirect: () => redirect2,
|
|
2065
|
-
registerAction: () => registerAction,
|
|
2066
|
-
renderWithStreaming: () => renderWithStreaming,
|
|
2067
|
-
revalidatePath: () => revalidatePath,
|
|
2068
|
-
revalidateTag: () => revalidateTag,
|
|
2069
|
-
rscRedirect: () => redirect3,
|
|
2070
|
-
scanRoutes: () => scanRoutes,
|
|
2071
|
-
serializeProps: () => serializeProps,
|
|
2072
|
-
serverFetch: () => serverFetch,
|
|
2073
|
-
streamParallel: () => streamParallel,
|
|
2074
|
-
streamSequential: () => streamSequential,
|
|
2075
|
-
withErrorBoundary: () => withErrorBoundary
|
|
2076
|
-
});
|
|
2077
|
-
var VERSION2;
|
|
2078
|
-
var init_dist3 = __esm({
|
|
2079
|
-
"../core/dist/index.js"() {
|
|
2080
|
-
"use strict";
|
|
2081
|
-
init_chunk_I5RHYGX6();
|
|
2082
|
-
init_chunk_TKXN7KGE();
|
|
2083
|
-
init_chunk_AJ3IBYXT();
|
|
2084
|
-
init_chunk_QEFGUHYD();
|
|
2085
|
-
init_chunk_AFSKXC6V();
|
|
2086
|
-
init_chunk_ZVC3ZWLM();
|
|
2087
|
-
init_chunk_3AIQVGTM();
|
|
2088
|
-
init_chunk_Q4C5CCHK();
|
|
2089
|
-
init_chunk_Y22KEW2F();
|
|
2090
|
-
init_chunk_GCQZ4FHI();
|
|
2091
|
-
init_chunk_KWFX6WHG();
|
|
2092
|
-
init_chunk_WAGCTWGY();
|
|
2093
|
-
VERSION2 = "0.0.1";
|
|
2094
|
-
}
|
|
2095
|
-
});
|
|
2096
8
|
|
|
2097
9
|
// src/index.ts
|
|
2098
10
|
import { cac } from "cac";
|
|
@@ -2102,11 +14,25 @@ import pc5 from "picocolors";
|
|
|
2102
14
|
var VERSION = "0.0.1";
|
|
2103
15
|
|
|
2104
16
|
// src/commands/create.ts
|
|
2105
|
-
import { existsSync, mkdirSync, writeFileSync,
|
|
2106
|
-
import { join, resolve } from "path";
|
|
17
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, copyFileSync, unlinkSync } from "fs";
|
|
18
|
+
import { join, resolve, dirname } from "path";
|
|
2107
19
|
import { execSync } from "child_process";
|
|
20
|
+
import { fileURLToPath } from "url";
|
|
2108
21
|
import pc from "picocolors";
|
|
2109
22
|
import prompts from "prompts";
|
|
23
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
var TEMPLATES_DIR = resolve(__dirname, "../../templates");
|
|
25
|
+
var UI_FRAMEWORKS = [
|
|
26
|
+
{ title: "React", value: "react", description: "The library for web and native user interfaces" },
|
|
27
|
+
{ title: "Vue", value: "vue", description: "The progressive JavaScript framework" },
|
|
28
|
+
{ title: "Svelte", value: "svelte", description: "Cybernetically enhanced web apps" },
|
|
29
|
+
{ title: "Solid", value: "solid", description: "Simple and performant reactivity" },
|
|
30
|
+
{ title: "Preact", value: "preact", description: "Fast 3kB alternative to React" },
|
|
31
|
+
{ title: "Qwik", value: "qwik", description: "Resumable framework with O(1) loading" },
|
|
32
|
+
{ title: "Lit", value: "lit", description: "Fast, lightweight Web Components" },
|
|
33
|
+
{ title: "Htmx", value: "htmx", description: "HTML over the wire, no JavaScript" },
|
|
34
|
+
{ title: "Vanilla", value: "vanilla", description: "No framework, just TypeScript" }
|
|
35
|
+
];
|
|
2110
36
|
async function createCommand(name, options) {
|
|
2111
37
|
printLogo();
|
|
2112
38
|
console.log(pc.cyan("\n[*] Creating a new Flight project...\n"));
|
|
@@ -2135,17 +61,7 @@ async function createCommand(name, options) {
|
|
|
2135
61
|
type: "select",
|
|
2136
62
|
name: "ui",
|
|
2137
63
|
message: "Choose your UI framework:",
|
|
2138
|
-
choices:
|
|
2139
|
-
{ title: "React", value: "react", description: "The library for web and native user interfaces" },
|
|
2140
|
-
{ title: "Vue", value: "vue", description: "The progressive JavaScript framework" },
|
|
2141
|
-
{ title: "Svelte", value: "svelte", description: "Cybernetically enhanced web apps" },
|
|
2142
|
-
{ title: "Solid", value: "solid", description: "Simple and performant reactivity" },
|
|
2143
|
-
{ title: "Preact", value: "preact", description: "Fast 3kB alternative to React" },
|
|
2144
|
-
{ title: "Qwik", value: "qwik", description: "Resumable framework with O(1) loading" },
|
|
2145
|
-
{ title: "Lit", value: "lit", description: "Fast, lightweight Web Components" },
|
|
2146
|
-
{ title: "Htmx", value: "htmx", description: "HTML over the wire, no JavaScript" },
|
|
2147
|
-
{ title: "Vanilla", value: "vanilla", description: "No framework, just JavaScript" }
|
|
2148
|
-
],
|
|
64
|
+
choices: UI_FRAMEWORKS,
|
|
2149
65
|
initial: 0
|
|
2150
66
|
});
|
|
2151
67
|
uiFramework = response.ui;
|
|
@@ -2174,11 +90,7 @@ async function createCommand(name, options) {
|
|
|
2174
90
|
Creating project in ${projectPath}...
|
|
2175
91
|
`));
|
|
2176
92
|
try {
|
|
2177
|
-
|
|
2178
|
-
name: projectName,
|
|
2179
|
-
ui: uiFramework,
|
|
2180
|
-
typescript: options.ts
|
|
2181
|
-
});
|
|
93
|
+
copyTemplate(projectPath, uiFramework, projectName);
|
|
2182
94
|
console.log(pc.green("\u2713") + " Project structure created");
|
|
2183
95
|
if (options.git) {
|
|
2184
96
|
try {
|
|
@@ -2213,8 +125,8 @@ ${pc.dim("Your project is 100% yours:")}
|
|
|
2213
125
|
|
|
2214
126
|
${pc.cyan("Happy flying!")}
|
|
2215
127
|
`);
|
|
2216
|
-
} catch (
|
|
2217
|
-
console.error(pc.red("Failed to create project:"),
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error(pc.red("Failed to create project:"), error);
|
|
2218
130
|
process.exit(1);
|
|
2219
131
|
}
|
|
2220
132
|
}
|
|
@@ -2224,952 +136,59 @@ function detectPackageManager() {
|
|
|
2224
136
|
if (process.env.npm_config_user_agent?.includes("bun")) return "bun";
|
|
2225
137
|
return "npm";
|
|
2226
138
|
}
|
|
2227
|
-
function
|
|
2228
|
-
const
|
|
2229
|
-
const
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
"
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
mkdirSync(join(projectPath, dir), { recursive: true });
|
|
2239
|
-
}
|
|
2240
|
-
const vitePlugin = getVitePlugin(ui);
|
|
2241
|
-
const vitePluginImport = getVitePluginImport(ui);
|
|
2242
|
-
const packageJson = {
|
|
2243
|
-
name,
|
|
2244
|
-
version: "0.0.1",
|
|
2245
|
-
private: true,
|
|
2246
|
-
type: "module",
|
|
2247
|
-
scripts: {
|
|
2248
|
-
dev: "vite",
|
|
2249
|
-
build: "vite build",
|
|
2250
|
-
preview: "vite preview",
|
|
2251
|
-
"flight:dev": "flight dev",
|
|
2252
|
-
"flight:build": "flight build"
|
|
2253
|
-
},
|
|
2254
|
-
dependencies: {},
|
|
2255
|
-
devDependencies: {
|
|
2256
|
-
"vite": "^6.0.0",
|
|
2257
|
-
...typescript ? {
|
|
2258
|
-
"typescript": "^5.7.0",
|
|
2259
|
-
"@types/node": "^22.0.0"
|
|
2260
|
-
} : {}
|
|
2261
|
-
}
|
|
139
|
+
function copyTemplate(projectPath, ui, projectName) {
|
|
140
|
+
const baseDir = join(TEMPLATES_DIR, "base");
|
|
141
|
+
const uiDir = join(TEMPLATES_DIR, ui);
|
|
142
|
+
mkdirSync(projectPath, { recursive: true });
|
|
143
|
+
mkdirSync(join(projectPath, "src"), { recursive: true });
|
|
144
|
+
mkdirSync(join(projectPath, "src/styles"), { recursive: true });
|
|
145
|
+
mkdirSync(join(projectPath, "public"), { recursive: true });
|
|
146
|
+
const vars = {
|
|
147
|
+
"{{PROJECT_NAME}}": projectName,
|
|
148
|
+
"{{UI_FRAMEWORK}}": ui,
|
|
149
|
+
"{{LANGUAGE}}": "TypeScript"
|
|
2262
150
|
};
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
151
|
+
copyDirWithTemplates(baseDir, projectPath, vars);
|
|
152
|
+
copyDirWithTemplates(uiDir, projectPath, vars);
|
|
153
|
+
const gitignoreSrc = join(projectPath, "_gitignore");
|
|
154
|
+
const gitignoreDest = join(projectPath, ".gitignore");
|
|
155
|
+
if (existsSync(gitignoreSrc)) {
|
|
156
|
+
copyFileSync(gitignoreSrc, gitignoreDest);
|
|
157
|
+
unlinkSync(gitignoreSrc);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function copyDirWithTemplates(srcDir, destDir, vars) {
|
|
161
|
+
if (!existsSync(srcDir)) return;
|
|
162
|
+
const entries = readdirSync(srcDir, { withFileTypes: true });
|
|
163
|
+
for (const entry of entries) {
|
|
164
|
+
const srcPath = join(srcDir, entry.name);
|
|
165
|
+
let destName = entry.name;
|
|
166
|
+
let isTemplate = false;
|
|
167
|
+
if (destName.endsWith(".template")) {
|
|
168
|
+
destName = destName.replace(".template", "");
|
|
169
|
+
isTemplate = true;
|
|
170
|
+
}
|
|
171
|
+
const destPath = join(destDir, destName);
|
|
172
|
+
if (entry.isDirectory()) {
|
|
173
|
+
mkdirSync(destPath, { recursive: true });
|
|
174
|
+
copyDirWithTemplates(srcPath, destPath, vars);
|
|
175
|
+
} else {
|
|
176
|
+
let content = readFileSync(srcPath, "utf-8");
|
|
177
|
+
if (isTemplate || destName.endsWith(".json") || destName.endsWith(".html") || destName.endsWith(".md")) {
|
|
178
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
179
|
+
content = content.replaceAll(key, value);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
writeFileSync(destPath, content);
|
|
2270
183
|
}
|
|
2271
|
-
} else if (ui === "vue") {
|
|
2272
|
-
packageJson.dependencies["vue"] = "^3.5.0";
|
|
2273
|
-
packageJson.devDependencies["@vitejs/plugin-vue"] = "^5.2.0";
|
|
2274
|
-
} else if (ui === "svelte") {
|
|
2275
|
-
packageJson.dependencies["svelte"] = "^5.0.0";
|
|
2276
|
-
packageJson.devDependencies["@sveltejs/vite-plugin-svelte"] = "^4.0.0";
|
|
2277
|
-
} else if (ui === "solid") {
|
|
2278
|
-
packageJson.dependencies["solid-js"] = "^1.9.0";
|
|
2279
|
-
packageJson.devDependencies["vite-plugin-solid"] = "^2.10.0";
|
|
2280
|
-
} else if (ui === "preact") {
|
|
2281
|
-
packageJson.dependencies["preact"] = "^10.25.0";
|
|
2282
|
-
packageJson.devDependencies["@preact/preset-vite"] = "^2.9.0";
|
|
2283
|
-
packageJson.devDependencies["preact-render-to-string"] = "^6.5.0";
|
|
2284
|
-
} else if (ui === "qwik") {
|
|
2285
|
-
packageJson.dependencies["@builder.io/qwik"] = "^2.0.0";
|
|
2286
|
-
packageJson.devDependencies["@builder.io/qwik-city"] = "^2.0.0";
|
|
2287
|
-
} else if (ui === "lit") {
|
|
2288
|
-
packageJson.dependencies["lit"] = "^3.2.0";
|
|
2289
|
-
packageJson.devDependencies["@lit-labs/ssr"] = "^3.3.0";
|
|
2290
|
-
} else if (ui === "htmx") {
|
|
2291
|
-
packageJson.dependencies["htmx.org"] = "^2.0.0";
|
|
2292
|
-
}
|
|
2293
|
-
writeFileSync(
|
|
2294
|
-
join(projectPath, "package.json"),
|
|
2295
|
-
JSON.stringify(packageJson, null, 2)
|
|
2296
|
-
);
|
|
2297
|
-
const viteConfig = `import { defineConfig } from 'vite';
|
|
2298
|
-
${vitePluginImport}
|
|
2299
|
-
|
|
2300
|
-
// https://vite.dev/config/
|
|
2301
|
-
export default defineConfig({
|
|
2302
|
-
plugins: [${vitePlugin}],
|
|
2303
|
-
server: {
|
|
2304
|
-
port: 5173,
|
|
2305
|
-
open: false,
|
|
2306
|
-
},
|
|
2307
|
-
build: {
|
|
2308
|
-
target: 'es2022',
|
|
2309
|
-
sourcemap: true,
|
|
2310
|
-
},
|
|
2311
|
-
});
|
|
2312
|
-
`;
|
|
2313
|
-
writeFileSync(join(projectPath, `vite.config.${ext}`), viteConfig);
|
|
2314
|
-
const indexHtml = createIndexHtml(name, ui);
|
|
2315
|
-
writeFileSync(join(projectPath, "index.html"), indexHtml);
|
|
2316
|
-
const clientEntry = createClientEntry(ui, typescript);
|
|
2317
|
-
writeFileSync(join(projectPath, `src/entry-client.${extx}`), clientEntry);
|
|
2318
|
-
const serverEntry = createServerEntry(ui, typescript);
|
|
2319
|
-
writeFileSync(join(projectPath, `src/entry-server.${extx}`), serverEntry);
|
|
2320
|
-
const appComponent = createAppComponent(ui, typescript);
|
|
2321
|
-
const appExt = ui === "svelte" ? "svelte" : ui === "vue" ? "vue" : extx;
|
|
2322
|
-
writeFileSync(join(projectPath, `src/App.${appExt}`), appComponent);
|
|
2323
|
-
const globalStyles = createGlobalStyles();
|
|
2324
|
-
writeFileSync(join(projectPath, "src/styles/global.css"), globalStyles);
|
|
2325
|
-
const flightConfig = `// Flight Framework Configuration
|
|
2326
|
-
// SSR enabled by default
|
|
2327
|
-
|
|
2328
|
-
export default {
|
|
2329
|
-
ui: {
|
|
2330
|
-
framework: '${ui}',
|
|
2331
|
-
},
|
|
2332
|
-
rendering: {
|
|
2333
|
-
default: 'ssr', // Server-side rendering enabled
|
|
2334
|
-
},
|
|
2335
|
-
};
|
|
2336
|
-
`;
|
|
2337
|
-
writeFileSync(join(projectPath, `flight.config.${ext}`), flightConfig);
|
|
2338
|
-
if (typescript) {
|
|
2339
|
-
const tsconfig = {
|
|
2340
|
-
compilerOptions: {
|
|
2341
|
-
target: "ES2022",
|
|
2342
|
-
module: "ESNext",
|
|
2343
|
-
moduleResolution: "bundler",
|
|
2344
|
-
lib: ["ES2022", "DOM", "DOM.Iterable"],
|
|
2345
|
-
strict: true,
|
|
2346
|
-
noEmit: true,
|
|
2347
|
-
esModuleInterop: true,
|
|
2348
|
-
skipLibCheck: true,
|
|
2349
|
-
forceConsistentCasingInFileNames: true,
|
|
2350
|
-
resolveJsonModule: true,
|
|
2351
|
-
isolatedModules: true,
|
|
2352
|
-
verbatimModuleSyntax: true,
|
|
2353
|
-
jsx: ui === "react" || ui === "preact" ? "react-jsx" : ui === "solid" ? "preserve" : void 0,
|
|
2354
|
-
jsxImportSource: ui === "preact" ? "preact" : ui === "solid" ? "solid-js" : void 0
|
|
2355
|
-
},
|
|
2356
|
-
include: ["src"],
|
|
2357
|
-
exclude: ["node_modules"]
|
|
2358
|
-
};
|
|
2359
|
-
writeFileSync(
|
|
2360
|
-
join(projectPath, "tsconfig.json"),
|
|
2361
|
-
JSON.stringify(tsconfig, null, 2)
|
|
2362
|
-
);
|
|
2363
|
-
}
|
|
2364
|
-
const gitignore = `# Dependencies
|
|
2365
|
-
node_modules/
|
|
2366
|
-
|
|
2367
|
-
# Build output
|
|
2368
|
-
dist/
|
|
2369
|
-
.output/
|
|
2370
|
-
|
|
2371
|
-
# Environment
|
|
2372
|
-
.env
|
|
2373
|
-
.env.*
|
|
2374
|
-
!.env.example
|
|
2375
|
-
|
|
2376
|
-
# Logs
|
|
2377
|
-
*.log
|
|
2378
|
-
npm-debug.log*
|
|
2379
|
-
|
|
2380
|
-
# Editor
|
|
2381
|
-
.vscode/
|
|
2382
|
-
.idea/
|
|
2383
|
-
*.swp
|
|
2384
|
-
*.swo
|
|
2385
|
-
|
|
2386
|
-
# OS
|
|
2387
|
-
.DS_Store
|
|
2388
|
-
Thumbs.db
|
|
2389
|
-
`;
|
|
2390
|
-
writeFileSync(join(projectPath, ".gitignore"), gitignore);
|
|
2391
|
-
const readme = `# ${name}
|
|
2392
|
-
|
|
2393
|
-
A modern web application built with Flight Framework.
|
|
2394
|
-
|
|
2395
|
-
## Development
|
|
2396
|
-
|
|
2397
|
-
\`\`\`bash
|
|
2398
|
-
npm run dev
|
|
2399
|
-
\`\`\`
|
|
2400
|
-
|
|
2401
|
-
## Production Build
|
|
2402
|
-
|
|
2403
|
-
\`\`\`bash
|
|
2404
|
-
npm run build
|
|
2405
|
-
npm run preview
|
|
2406
|
-
\`\`\`
|
|
2407
|
-
|
|
2408
|
-
## Tech Stack
|
|
2409
|
-
|
|
2410
|
-
- **Framework**: ${ui.charAt(0).toUpperCase() + ui.slice(1)}
|
|
2411
|
-
- **Build Tool**: Vite 6
|
|
2412
|
-
- **Language**: ${typescript ? "TypeScript" : "JavaScript"}
|
|
2413
|
-
|
|
2414
|
-
## Flight Philosophy
|
|
2415
|
-
|
|
2416
|
-
This project runs on Flight Framework:
|
|
2417
|
-
- **No lock-in** - Deploy anywhere
|
|
2418
|
-
- **No telemetry** - Your code, your privacy
|
|
2419
|
-
- **You choose** - UI, database, auth, hosting
|
|
2420
|
-
`;
|
|
2421
|
-
writeFileSync(join(projectPath, "README.md"), readme);
|
|
2422
|
-
}
|
|
2423
|
-
function getVitePlugin(ui) {
|
|
2424
|
-
switch (ui) {
|
|
2425
|
-
case "react":
|
|
2426
|
-
return "react()";
|
|
2427
|
-
case "vue":
|
|
2428
|
-
return "vue()";
|
|
2429
|
-
case "svelte":
|
|
2430
|
-
return "svelte()";
|
|
2431
|
-
case "solid":
|
|
2432
|
-
return "solid()";
|
|
2433
|
-
case "preact":
|
|
2434
|
-
return "preact()";
|
|
2435
|
-
case "qwik":
|
|
2436
|
-
return "qwikVite()";
|
|
2437
|
-
case "lit":
|
|
2438
|
-
return "";
|
|
2439
|
-
// Lit doesn't need Vite plugin for SSR
|
|
2440
|
-
case "htmx":
|
|
2441
|
-
return "";
|
|
2442
|
-
// HTMX is HTML-only, no plugin needed
|
|
2443
|
-
default:
|
|
2444
|
-
return "";
|
|
2445
|
-
}
|
|
2446
|
-
}
|
|
2447
|
-
function getVitePluginImport(ui) {
|
|
2448
|
-
switch (ui) {
|
|
2449
|
-
case "react":
|
|
2450
|
-
return "import react from '@vitejs/plugin-react';";
|
|
2451
|
-
case "vue":
|
|
2452
|
-
return "import vue from '@vitejs/plugin-vue';";
|
|
2453
|
-
case "svelte":
|
|
2454
|
-
return "import { svelte } from '@sveltejs/vite-plugin-svelte';";
|
|
2455
|
-
case "solid":
|
|
2456
|
-
return "import solid from 'vite-plugin-solid';";
|
|
2457
|
-
case "preact":
|
|
2458
|
-
return "import preact from '@preact/preset-vite';";
|
|
2459
|
-
case "qwik":
|
|
2460
|
-
return "import { qwikVite } from '@builder.io/qwik/optimizer';";
|
|
2461
|
-
case "lit":
|
|
2462
|
-
return "// Lit uses native Web Components, no Vite plugin required";
|
|
2463
|
-
case "htmx":
|
|
2464
|
-
return "// HTMX is HTML-only, no Vite plugin required";
|
|
2465
|
-
default:
|
|
2466
|
-
return "";
|
|
2467
|
-
}
|
|
2468
|
-
}
|
|
2469
|
-
function createIndexHtml(name, ui) {
|
|
2470
|
-
const moduleExt = ui === "svelte" ? "ts" : "tsx";
|
|
2471
|
-
return `<!DOCTYPE html>
|
|
2472
|
-
<html lang="en">
|
|
2473
|
-
<head>
|
|
2474
|
-
<meta charset="UTF-8" />
|
|
2475
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
2476
|
-
<meta name="description" content="${name} - Built with Flight Framework" />
|
|
2477
|
-
<title>${name}</title>
|
|
2478
|
-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
2479
|
-
</head>
|
|
2480
|
-
<body>
|
|
2481
|
-
<div id="root"><!--ssr-outlet--></div>
|
|
2482
|
-
<script type="module" src="/src/entry-client.${moduleExt}"></script>
|
|
2483
|
-
</body>
|
|
2484
|
-
</html>
|
|
2485
|
-
`;
|
|
2486
|
-
}
|
|
2487
|
-
function createClientEntry(ui, _typescript) {
|
|
2488
|
-
switch (ui) {
|
|
2489
|
-
case "react":
|
|
2490
|
-
return `import { hydrateRoot, createRoot } from 'react-dom/client';
|
|
2491
|
-
import App from './App';
|
|
2492
|
-
import './styles/global.css';
|
|
2493
|
-
|
|
2494
|
-
const rootElement = document.getElementById('root');
|
|
2495
|
-
|
|
2496
|
-
if (!rootElement) {
|
|
2497
|
-
throw new Error('Root element not found');
|
|
2498
|
-
}
|
|
2499
|
-
|
|
2500
|
-
// Check if we have SSR content to hydrate
|
|
2501
|
-
if (rootElement.innerHTML.trim()) {
|
|
2502
|
-
hydrateRoot(rootElement, <App />);
|
|
2503
|
-
} else {
|
|
2504
|
-
// CSR fallback
|
|
2505
|
-
createRoot(rootElement).render(<App />);
|
|
2506
|
-
}
|
|
2507
|
-
`;
|
|
2508
|
-
case "vue":
|
|
2509
|
-
return `import { createApp, createSSRApp } from 'vue';
|
|
2510
|
-
import App from './App.vue';
|
|
2511
|
-
import './styles/global.css';
|
|
2512
|
-
|
|
2513
|
-
const rootElement = document.getElementById('root');
|
|
2514
|
-
const hasSSRContent = rootElement?.innerHTML.trim();
|
|
2515
|
-
|
|
2516
|
-
if (hasSSRContent) {
|
|
2517
|
-
createSSRApp(App).mount('#root');
|
|
2518
|
-
} else {
|
|
2519
|
-
createApp(App).mount('#root');
|
|
2520
|
-
}
|
|
2521
|
-
`;
|
|
2522
|
-
case "solid":
|
|
2523
|
-
return `import { hydrate, render } from 'solid-js/web';
|
|
2524
|
-
import App from './App';
|
|
2525
|
-
import './styles/global.css';
|
|
2526
|
-
|
|
2527
|
-
const root = document.getElementById('root');
|
|
2528
|
-
|
|
2529
|
-
if (!root) {
|
|
2530
|
-
throw new Error('Root element not found');
|
|
2531
|
-
}
|
|
2532
|
-
|
|
2533
|
-
// Check for SSR content
|
|
2534
|
-
if (root.innerHTML.trim()) {
|
|
2535
|
-
hydrate(() => <App />, root);
|
|
2536
|
-
} else {
|
|
2537
|
-
render(() => <App />, root);
|
|
2538
|
-
}
|
|
2539
|
-
`;
|
|
2540
|
-
case "preact":
|
|
2541
|
-
return `import { hydrate, render } from 'preact';
|
|
2542
|
-
import App from './App';
|
|
2543
|
-
import './styles/global.css';
|
|
2544
|
-
|
|
2545
|
-
const root = document.getElementById('root');
|
|
2546
|
-
|
|
2547
|
-
if (!root) {
|
|
2548
|
-
throw new Error('Root element not found');
|
|
2549
|
-
}
|
|
2550
|
-
|
|
2551
|
-
// Check for SSR content
|
|
2552
|
-
if (root.innerHTML.trim()) {
|
|
2553
|
-
hydrate(<App />, root);
|
|
2554
|
-
} else {
|
|
2555
|
-
render(<App />, root);
|
|
2556
|
-
}
|
|
2557
|
-
`;
|
|
2558
|
-
case "svelte":
|
|
2559
|
-
return `import App from './App.svelte';
|
|
2560
|
-
import './styles/global.css';
|
|
2561
|
-
|
|
2562
|
-
const target = document.getElementById('root');
|
|
2563
|
-
|
|
2564
|
-
if (!target) {
|
|
2565
|
-
throw new Error('Root element not found');
|
|
2566
|
-
}
|
|
2567
|
-
|
|
2568
|
-
// Hydrate or mount
|
|
2569
|
-
const app = new App({
|
|
2570
|
-
target,
|
|
2571
|
-
hydrate: target.innerHTML.trim() !== '',
|
|
2572
|
-
});
|
|
2573
|
-
|
|
2574
|
-
export default app;
|
|
2575
|
-
`;
|
|
2576
|
-
case "qwik":
|
|
2577
|
-
return `import './styles/global.css';
|
|
2578
|
-
|
|
2579
|
-
/**
|
|
2580
|
-
* Qwik Client Entry
|
|
2581
|
-
* Qwik uses resumability - no hydration needed!
|
|
2582
|
-
* The framework automatically resumes where the server left off.
|
|
2583
|
-
*/
|
|
2584
|
-
console.log('Qwik app resumed!');
|
|
2585
|
-
`;
|
|
2586
|
-
case "lit":
|
|
2587
|
-
return `import './styles/global.css';
|
|
2588
|
-
import './components/app-element.js';
|
|
2589
|
-
|
|
2590
|
-
/**
|
|
2591
|
-
* Lit Client Entry
|
|
2592
|
-
* Web Components hydrate automatically via declarative shadow DOM
|
|
2593
|
-
*/
|
|
2594
|
-
console.log('Lit Web Components ready!');
|
|
2595
|
-
`;
|
|
2596
|
-
case "htmx":
|
|
2597
|
-
return `import './styles/global.css';
|
|
2598
|
-
import 'htmx.org';
|
|
2599
|
-
|
|
2600
|
-
/**
|
|
2601
|
-
* HTMX Client Entry
|
|
2602
|
-
* HTMX handles all interactivity via HTML attributes
|
|
2603
|
-
* No JavaScript framework needed!
|
|
2604
|
-
*/
|
|
2605
|
-
document.body.addEventListener('htmx:afterSwap', (event) => {
|
|
2606
|
-
console.log('HTMX content swapped:', event.detail.target);
|
|
2607
|
-
});
|
|
2608
|
-
|
|
2609
|
-
console.log('HTMX ready!');
|
|
2610
|
-
`;
|
|
2611
|
-
default:
|
|
2612
|
-
return `import './styles/global.css';
|
|
2613
|
-
|
|
2614
|
-
// CSR only for vanilla
|
|
2615
|
-
const root = document.getElementById('root');
|
|
2616
|
-
if (root && !root.innerHTML.trim()) {
|
|
2617
|
-
root.innerHTML = \`
|
|
2618
|
-
<main class="container">
|
|
2619
|
-
<h1>Welcome to Flight \u2708\uFE0F</h1>
|
|
2620
|
-
<p>The agnostic full-stack framework.</p>
|
|
2621
|
-
<p>Maximum flexibility. Zero lock-in.</p>
|
|
2622
|
-
</main>
|
|
2623
|
-
\`;
|
|
2624
|
-
}
|
|
2625
|
-
`;
|
|
2626
|
-
}
|
|
2627
|
-
}
|
|
2628
|
-
function createServerEntry(ui, _typescript) {
|
|
2629
|
-
switch (ui) {
|
|
2630
|
-
case "react":
|
|
2631
|
-
return `import { renderToString } from 'react-dom/server';
|
|
2632
|
-
import App from './App';
|
|
2633
|
-
|
|
2634
|
-
/**
|
|
2635
|
-
* Server-side render function
|
|
2636
|
-
* Called by Flight dev server for each request
|
|
2637
|
-
*/
|
|
2638
|
-
export function render(url: string): string {
|
|
2639
|
-
const html = renderToString(<App />);
|
|
2640
|
-
return html;
|
|
2641
|
-
}
|
|
2642
|
-
`;
|
|
2643
|
-
case "vue":
|
|
2644
|
-
return `import { renderToString } from 'vue/server-renderer';
|
|
2645
|
-
import { createSSRApp } from 'vue';
|
|
2646
|
-
import App from './App.vue';
|
|
2647
|
-
|
|
2648
|
-
/**
|
|
2649
|
-
* Server-side render function
|
|
2650
|
-
*/
|
|
2651
|
-
export async function render(url: string): Promise<string> {
|
|
2652
|
-
const app = createSSRApp(App);
|
|
2653
|
-
const html = await renderToString(app);
|
|
2654
|
-
return html;
|
|
2655
|
-
}
|
|
2656
|
-
`;
|
|
2657
|
-
case "solid":
|
|
2658
|
-
return `import { renderToString } from 'solid-js/web';
|
|
2659
|
-
import App from './App';
|
|
2660
|
-
|
|
2661
|
-
/**
|
|
2662
|
-
* Server-side render function
|
|
2663
|
-
*/
|
|
2664
|
-
export function render(url: string): string {
|
|
2665
|
-
const html = renderToString(() => <App />);
|
|
2666
|
-
return html;
|
|
2667
|
-
}
|
|
2668
|
-
`;
|
|
2669
|
-
case "preact":
|
|
2670
|
-
return `import renderToString from 'preact-render-to-string';
|
|
2671
|
-
import App from './App';
|
|
2672
|
-
|
|
2673
|
-
/**
|
|
2674
|
-
* Server-side render function
|
|
2675
|
-
*/
|
|
2676
|
-
export function render(url: string): string {
|
|
2677
|
-
const html = renderToString(<App />);
|
|
2678
|
-
return html;
|
|
2679
|
-
}
|
|
2680
|
-
`;
|
|
2681
|
-
case "svelte":
|
|
2682
|
-
return `import { render } from 'svelte/server';
|
|
2683
|
-
import App from './App.svelte';
|
|
2684
|
-
|
|
2685
|
-
/**
|
|
2686
|
-
* Server-side render function
|
|
2687
|
-
* Uses Svelte 5 native SSR (no SvelteKit required)
|
|
2688
|
-
*/
|
|
2689
|
-
export function render(url: string): string {
|
|
2690
|
-
const { body, head } = render(App, {
|
|
2691
|
-
props: { url }
|
|
2692
|
-
});
|
|
2693
|
-
return body;
|
|
2694
|
-
}
|
|
2695
|
-
`;
|
|
2696
|
-
case "qwik":
|
|
2697
|
-
return `import { renderToString } from '@builder.io/qwik/server';
|
|
2698
|
-
import App from './App';
|
|
2699
|
-
|
|
2700
|
-
/**
|
|
2701
|
-
* Server-side render function
|
|
2702
|
-
* Qwik: Resumable framework with O(1) loading
|
|
2703
|
-
*/
|
|
2704
|
-
export async function render(url: string): Promise<string> {
|
|
2705
|
-
const { html } = await renderToString(<App />, {
|
|
2706
|
-
containerTagName: 'div',
|
|
2707
|
-
});
|
|
2708
|
-
return html;
|
|
2709
|
-
}
|
|
2710
|
-
`;
|
|
2711
|
-
case "lit":
|
|
2712
|
-
return `import { render } from '@lit-labs/ssr';
|
|
2713
|
-
import { html } from 'lit';
|
|
2714
|
-
import { collectResult } from '@lit-labs/ssr/lib/render-result.js';
|
|
2715
|
-
import './components/app-element.js';
|
|
2716
|
-
|
|
2717
|
-
/**
|
|
2718
|
-
* Server-side render function
|
|
2719
|
-
* Lit: Web Components SSR
|
|
2720
|
-
*/
|
|
2721
|
-
export async function render(url: string): Promise<string> {
|
|
2722
|
-
const result = render(html\`<app-element></app-element>\`);
|
|
2723
|
-
return collectResult(result);
|
|
2724
|
-
}
|
|
2725
|
-
`;
|
|
2726
|
-
case "htmx":
|
|
2727
|
-
return `/**
|
|
2728
|
-
* Server-side render function
|
|
2729
|
-
* HTMX: HTML over the wire - no JavaScript needed
|
|
2730
|
-
*/
|
|
2731
|
-
export function render(url: string): string {
|
|
2732
|
-
return \`
|
|
2733
|
-
<main class="container" hx-boost="true">
|
|
2734
|
-
<div class="hero">
|
|
2735
|
-
<h1>
|
|
2736
|
-
<span class="flight-icon">*</span>
|
|
2737
|
-
Welcome to <span class="gradient-text">Flight</span>
|
|
2738
|
-
</h1>
|
|
2739
|
-
<p class="tagline">The agnostic full-stack framework</p>
|
|
2740
|
-
<p class="subtitle">Maximum flexibility. Zero lock-in.</p>
|
|
2741
|
-
|
|
2742
|
-
<div class="features" hx-get="/api/features" hx-trigger="load" hx-swap="innerHTML">
|
|
2743
|
-
<p>Loading features...</p>
|
|
2744
|
-
</div>
|
|
2745
|
-
|
|
2746
|
-
<div class="cta">
|
|
2747
|
-
<a href="/docs" class="btn btn-primary" hx-boost="true">Get Started</a>
|
|
2748
|
-
<a href="/api" class="btn btn-secondary" hx-boost="true">API Docs</a>
|
|
2749
|
-
</div>
|
|
2750
|
-
</div>
|
|
2751
|
-
</main>
|
|
2752
|
-
\`;
|
|
2753
|
-
}
|
|
2754
|
-
`;
|
|
2755
|
-
default:
|
|
2756
|
-
return `/**
|
|
2757
|
-
* Server-side render function for vanilla JS
|
|
2758
|
-
*/
|
|
2759
|
-
export function render(url: string): string {
|
|
2760
|
-
return \`
|
|
2761
|
-
<main class="container">
|
|
2762
|
-
<h1>Welcome to Flight *</h1>
|
|
2763
|
-
<p>The agnostic full-stack framework.</p>
|
|
2764
|
-
<p>Maximum flexibility. Zero lock-in.</p>
|
|
2765
|
-
</main>
|
|
2766
|
-
\`;
|
|
2767
|
-
}
|
|
2768
|
-
`;
|
|
2769
|
-
}
|
|
2770
|
-
}
|
|
2771
|
-
function createAppComponent(ui, _typescript) {
|
|
2772
|
-
switch (ui) {
|
|
2773
|
-
case "react":
|
|
2774
|
-
case "solid":
|
|
2775
|
-
case "preact":
|
|
2776
|
-
return `export default function App() {
|
|
2777
|
-
return (
|
|
2778
|
-
<main className="container">
|
|
2779
|
-
<div className="hero">
|
|
2780
|
-
<h1>
|
|
2781
|
-
<span className="flight-icon">*</span>
|
|
2782
|
-
Welcome to <span className="gradient-text">Flight</span>
|
|
2783
|
-
</h1>
|
|
2784
|
-
<p className="tagline">The agnostic full-stack framework</p>
|
|
2785
|
-
<p className="subtitle">Maximum flexibility. Zero lock-in.</p>
|
|
2786
|
-
|
|
2787
|
-
<div className="features">
|
|
2788
|
-
<div className="feature">
|
|
2789
|
-
<span className="feature-icon">*</span>
|
|
2790
|
-
<h3>Lightning Fast</h3>
|
|
2791
|
-
<p>Powered by Vite for instant HMR</p>
|
|
2792
|
-
</div>
|
|
2793
|
-
<div className="feature">
|
|
2794
|
-
<span className="feature-icon">*</span>
|
|
2795
|
-
<h3>No Lock-in</h3>
|
|
2796
|
-
<p>Deploy anywhere you want</p>
|
|
2797
|
-
</div>
|
|
2798
|
-
<div className="feature">
|
|
2799
|
-
<span className="feature-icon">*</span>
|
|
2800
|
-
<h3>Privacy First</h3>
|
|
2801
|
-
<p>Zero telemetry, ever</p>
|
|
2802
|
-
</div>
|
|
2803
|
-
</div>
|
|
2804
|
-
|
|
2805
|
-
<div className="cta">
|
|
2806
|
-
<a href="https://github.com" className="btn btn-primary">Get Started</a>
|
|
2807
|
-
<a href="https://github.com" className="btn btn-secondary">Documentation</a>
|
|
2808
|
-
</div>
|
|
2809
|
-
</div>
|
|
2810
|
-
</main>
|
|
2811
|
-
);
|
|
2812
|
-
}
|
|
2813
|
-
`;
|
|
2814
|
-
case "vue":
|
|
2815
|
-
return `<template>
|
|
2816
|
-
<main class="container">
|
|
2817
|
-
<div class="hero">
|
|
2818
|
-
<h1>
|
|
2819
|
-
<span class="flight-icon">*</span>
|
|
2820
|
-
Welcome to <span class="gradient-text">Flight</span>
|
|
2821
|
-
</h1>
|
|
2822
|
-
<p class="tagline">The agnostic full-stack framework</p>
|
|
2823
|
-
<p class="subtitle">Maximum flexibility. Zero lock-in.</p>
|
|
2824
|
-
|
|
2825
|
-
<div class="features">
|
|
2826
|
-
<div class="feature">
|
|
2827
|
-
<span class="feature-icon">*</span>
|
|
2828
|
-
<h3>Lightning Fast</h3>
|
|
2829
|
-
<p>Powered by Vite for instant HMR</p>
|
|
2830
|
-
</div>
|
|
2831
|
-
<div class="feature">
|
|
2832
|
-
<span class="feature-icon">*</span>
|
|
2833
|
-
<h3>No Lock-in</h3>
|
|
2834
|
-
<p>Deploy anywhere you want</p>
|
|
2835
|
-
</div>
|
|
2836
|
-
<div class="feature">
|
|
2837
|
-
<span class="feature-icon">*</span>
|
|
2838
|
-
<h3>Privacy First</h3>
|
|
2839
|
-
<p>Zero telemetry, ever</p>
|
|
2840
|
-
</div>
|
|
2841
|
-
</div>
|
|
2842
|
-
|
|
2843
|
-
<div class="cta">
|
|
2844
|
-
<a href="https://github.com" class="btn btn-primary">Get Started</a>
|
|
2845
|
-
<a href="https://github.com" class="btn btn-secondary">Documentation</a>
|
|
2846
|
-
</div>
|
|
2847
|
-
</div>
|
|
2848
|
-
</main>
|
|
2849
|
-
</template>
|
|
2850
|
-
|
|
2851
|
-
<script setup>
|
|
2852
|
-
// Vue component logic here
|
|
2853
|
-
</script>
|
|
2854
|
-
`;
|
|
2855
|
-
case "svelte":
|
|
2856
|
-
return `<script>
|
|
2857
|
-
// Svelte component logic here
|
|
2858
|
-
</script>
|
|
2859
|
-
|
|
2860
|
-
<main class="container">
|
|
2861
|
-
<div class="hero">
|
|
2862
|
-
<h1>
|
|
2863
|
-
<span class="flight-icon">*</span>
|
|
2864
|
-
Welcome to <span class="gradient-text">Flight</span>
|
|
2865
|
-
</h1>
|
|
2866
|
-
<p class="tagline">The agnostic full-stack framework</p>
|
|
2867
|
-
<p class="subtitle">Maximum flexibility. Zero lock-in.</p>
|
|
2868
|
-
|
|
2869
|
-
<div class="features">
|
|
2870
|
-
<div class="feature">
|
|
2871
|
-
<span class="feature-icon">*</span>
|
|
2872
|
-
<h3>Lightning Fast</h3>
|
|
2873
|
-
<p>Powered by Vite for instant HMR</p>
|
|
2874
|
-
</div>
|
|
2875
|
-
<div class="feature">
|
|
2876
|
-
<span class="feature-icon">*</span>
|
|
2877
|
-
<h3>No Lock-in</h3>
|
|
2878
|
-
<p>Deploy anywhere you want</p>
|
|
2879
|
-
</div>
|
|
2880
|
-
<div class="feature">
|
|
2881
|
-
<span class="feature-icon">*</span>
|
|
2882
|
-
<h3>Privacy First</h3>
|
|
2883
|
-
<p>Zero telemetry, ever</p>
|
|
2884
|
-
</div>
|
|
2885
|
-
</div>
|
|
2886
|
-
|
|
2887
|
-
<div class="cta">
|
|
2888
|
-
<a href="https://github.com" class="btn btn-primary">Get Started</a>
|
|
2889
|
-
<a href="https://github.com" class="btn btn-secondary">Documentation</a>
|
|
2890
|
-
</div>
|
|
2891
|
-
</div>
|
|
2892
|
-
</main>
|
|
2893
|
-
`;
|
|
2894
|
-
default:
|
|
2895
|
-
return `export function render() {
|
|
2896
|
-
return \`
|
|
2897
|
-
<main class="container">
|
|
2898
|
-
<h1>Welcome to Flight *</h1>
|
|
2899
|
-
<p>The agnostic full-stack framework.</p>
|
|
2900
|
-
</main>
|
|
2901
|
-
\`;
|
|
2902
|
-
}
|
|
2903
|
-
`;
|
|
2904
184
|
}
|
|
2905
185
|
}
|
|
2906
|
-
function createGlobalStyles() {
|
|
2907
|
-
return `/* Flight Framework - 2026 Modern CSS */
|
|
2908
|
-
|
|
2909
|
-
:root {
|
|
2910
|
-
/* Colors - Dark theme by default */
|
|
2911
|
-
--color-bg: #0a0a0f;
|
|
2912
|
-
--color-bg-secondary: #12121a;
|
|
2913
|
-
--color-text: #f0f0f5;
|
|
2914
|
-
--color-text-muted: #8888a0;
|
|
2915
|
-
--color-primary: #6366f1;
|
|
2916
|
-
--color-primary-light: #818cf8;
|
|
2917
|
-
--color-secondary: #22d3ee;
|
|
2918
|
-
--color-accent: #f472b6;
|
|
2919
|
-
--color-border: #2a2a3a;
|
|
2920
|
-
|
|
2921
|
-
/* Gradients */
|
|
2922
|
-
--gradient-primary: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
|
|
2923
|
-
--gradient-text: linear-gradient(135deg, var(--color-primary-light) 0%, var(--color-secondary) 50%, var(--color-accent) 100%);
|
|
2924
|
-
|
|
2925
|
-
/* Spacing */
|
|
2926
|
-
--space-xs: 0.25rem;
|
|
2927
|
-
--space-sm: 0.5rem;
|
|
2928
|
-
--space-md: 1rem;
|
|
2929
|
-
--space-lg: 2rem;
|
|
2930
|
-
--space-xl: 4rem;
|
|
2931
|
-
|
|
2932
|
-
/* Typography */
|
|
2933
|
-
--font-sans: 'Inter', system-ui, -apple-system, sans-serif;
|
|
2934
|
-
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
|
2935
|
-
|
|
2936
|
-
/* Effects */
|
|
2937
|
-
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
2938
|
-
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.4);
|
|
2939
|
-
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.5);
|
|
2940
|
-
--shadow-glow: 0 0 40px rgba(99, 102, 241, 0.3);
|
|
2941
|
-
|
|
2942
|
-
/* Transitions */
|
|
2943
|
-
--transition-fast: 150ms ease;
|
|
2944
|
-
--transition-normal: 250ms ease;
|
|
2945
|
-
--transition-slow: 400ms ease;
|
|
2946
|
-
|
|
2947
|
-
/* Border radius */
|
|
2948
|
-
--radius-sm: 0.375rem;
|
|
2949
|
-
--radius-md: 0.75rem;
|
|
2950
|
-
--radius-lg: 1rem;
|
|
2951
|
-
--radius-full: 9999px;
|
|
2952
|
-
}
|
|
2953
|
-
|
|
2954
|
-
/* Reset */
|
|
2955
|
-
*, *::before, *::after {
|
|
2956
|
-
box-sizing: border-box;
|
|
2957
|
-
margin: 0;
|
|
2958
|
-
padding: 0;
|
|
2959
|
-
}
|
|
2960
|
-
|
|
2961
|
-
html {
|
|
2962
|
-
font-size: 16px;
|
|
2963
|
-
scroll-behavior: smooth;
|
|
2964
|
-
-webkit-font-smoothing: antialiased;
|
|
2965
|
-
-moz-osx-font-smoothing: grayscale;
|
|
2966
|
-
}
|
|
2967
|
-
|
|
2968
|
-
body {
|
|
2969
|
-
font-family: var(--font-sans);
|
|
2970
|
-
background: var(--color-bg);
|
|
2971
|
-
color: var(--color-text);
|
|
2972
|
-
line-height: 1.6;
|
|
2973
|
-
min-height: 100vh;
|
|
2974
|
-
}
|
|
2975
|
-
|
|
2976
|
-
/* Typography */
|
|
2977
|
-
h1, h2, h3, h4, h5, h6 {
|
|
2978
|
-
line-height: 1.2;
|
|
2979
|
-
font-weight: 700;
|
|
2980
|
-
}
|
|
2981
|
-
|
|
2982
|
-
h1 { font-size: clamp(2.5rem, 5vw, 4rem); }
|
|
2983
|
-
h2 { font-size: clamp(1.75rem, 3vw, 2.5rem); }
|
|
2984
|
-
h3 { font-size: clamp(1.25rem, 2vw, 1.5rem); }
|
|
2985
|
-
|
|
2986
|
-
a {
|
|
2987
|
-
color: var(--color-primary-light);
|
|
2988
|
-
text-decoration: none;
|
|
2989
|
-
transition: color var(--transition-fast);
|
|
2990
|
-
}
|
|
2991
|
-
|
|
2992
|
-
a:hover {
|
|
2993
|
-
color: var(--color-secondary);
|
|
2994
|
-
}
|
|
2995
|
-
|
|
2996
|
-
/* Container */
|
|
2997
|
-
.container {
|
|
2998
|
-
width: 100%;
|
|
2999
|
-
max-width: 1200px;
|
|
3000
|
-
margin: 0 auto;
|
|
3001
|
-
padding: var(--space-lg);
|
|
3002
|
-
}
|
|
3003
|
-
|
|
3004
|
-
/* Hero Section */
|
|
3005
|
-
.hero {
|
|
3006
|
-
display: flex;
|
|
3007
|
-
flex-direction: column;
|
|
3008
|
-
align-items: center;
|
|
3009
|
-
justify-content: center;
|
|
3010
|
-
min-height: 100vh;
|
|
3011
|
-
text-align: center;
|
|
3012
|
-
gap: var(--space-lg);
|
|
3013
|
-
}
|
|
3014
|
-
|
|
3015
|
-
.flight-icon {
|
|
3016
|
-
display: inline-block;
|
|
3017
|
-
font-size: 1.2em;
|
|
3018
|
-
margin-right: var(--space-sm);
|
|
3019
|
-
animation: float 3s ease-in-out infinite;
|
|
3020
|
-
}
|
|
3021
|
-
|
|
3022
|
-
@keyframes float {
|
|
3023
|
-
0%, 100% { transform: translateY(0) rotate(-5deg); }
|
|
3024
|
-
50% { transform: translateY(-10px) rotate(5deg); }
|
|
3025
|
-
}
|
|
3026
|
-
|
|
3027
|
-
.gradient-text {
|
|
3028
|
-
background: var(--gradient-text);
|
|
3029
|
-
-webkit-background-clip: text;
|
|
3030
|
-
-webkit-text-fill-color: transparent;
|
|
3031
|
-
background-clip: text;
|
|
3032
|
-
}
|
|
3033
|
-
|
|
3034
|
-
.tagline {
|
|
3035
|
-
font-size: clamp(1.25rem, 2.5vw, 1.75rem);
|
|
3036
|
-
color: var(--color-text);
|
|
3037
|
-
font-weight: 500;
|
|
3038
|
-
}
|
|
3039
|
-
|
|
3040
|
-
.subtitle {
|
|
3041
|
-
font-size: clamp(1rem, 2vw, 1.25rem);
|
|
3042
|
-
color: var(--color-text-muted);
|
|
3043
|
-
}
|
|
3044
|
-
|
|
3045
|
-
/* Features Grid */
|
|
3046
|
-
.features {
|
|
3047
|
-
display: grid;
|
|
3048
|
-
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
3049
|
-
gap: var(--space-lg);
|
|
3050
|
-
width: 100%;
|
|
3051
|
-
max-width: 900px;
|
|
3052
|
-
margin-top: var(--space-xl);
|
|
3053
|
-
}
|
|
3054
|
-
|
|
3055
|
-
.feature {
|
|
3056
|
-
background: var(--color-bg-secondary);
|
|
3057
|
-
border: 1px solid var(--color-border);
|
|
3058
|
-
border-radius: var(--radius-lg);
|
|
3059
|
-
padding: var(--space-lg);
|
|
3060
|
-
text-align: center;
|
|
3061
|
-
transition: all var(--transition-normal);
|
|
3062
|
-
}
|
|
3063
|
-
|
|
3064
|
-
.feature:hover {
|
|
3065
|
-
border-color: var(--color-primary);
|
|
3066
|
-
box-shadow: var(--shadow-glow);
|
|
3067
|
-
transform: translateY(-4px);
|
|
3068
|
-
}
|
|
3069
|
-
|
|
3070
|
-
.feature-icon {
|
|
3071
|
-
font-size: 2.5rem;
|
|
3072
|
-
display: block;
|
|
3073
|
-
margin-bottom: var(--space-md);
|
|
3074
|
-
}
|
|
3075
|
-
|
|
3076
|
-
.feature h3 {
|
|
3077
|
-
margin-bottom: var(--space-sm);
|
|
3078
|
-
color: var(--color-text);
|
|
3079
|
-
}
|
|
3080
|
-
|
|
3081
|
-
.feature p {
|
|
3082
|
-
color: var(--color-text-muted);
|
|
3083
|
-
font-size: 0.95rem;
|
|
3084
|
-
}
|
|
3085
|
-
|
|
3086
|
-
/* Buttons */
|
|
3087
|
-
.cta {
|
|
3088
|
-
display: flex;
|
|
3089
|
-
gap: var(--space-md);
|
|
3090
|
-
margin-top: var(--space-xl);
|
|
3091
|
-
flex-wrap: wrap;
|
|
3092
|
-
justify-content: center;
|
|
3093
|
-
}
|
|
3094
|
-
|
|
3095
|
-
.btn {
|
|
3096
|
-
display: inline-flex;
|
|
3097
|
-
align-items: center;
|
|
3098
|
-
justify-content: center;
|
|
3099
|
-
padding: var(--space-md) var(--space-lg);
|
|
3100
|
-
font-size: 1rem;
|
|
3101
|
-
font-weight: 600;
|
|
3102
|
-
border-radius: var(--radius-md);
|
|
3103
|
-
border: none;
|
|
3104
|
-
cursor: pointer;
|
|
3105
|
-
transition: all var(--transition-fast);
|
|
3106
|
-
text-decoration: none;
|
|
3107
|
-
}
|
|
3108
|
-
|
|
3109
|
-
.btn-primary {
|
|
3110
|
-
background: var(--gradient-primary);
|
|
3111
|
-
color: white;
|
|
3112
|
-
box-shadow: var(--shadow-md);
|
|
3113
|
-
}
|
|
3114
|
-
|
|
3115
|
-
.btn-primary:hover {
|
|
3116
|
-
transform: translateY(-2px);
|
|
3117
|
-
box-shadow: var(--shadow-lg), var(--shadow-glow);
|
|
3118
|
-
color: white;
|
|
3119
|
-
}
|
|
3120
|
-
|
|
3121
|
-
.btn-secondary {
|
|
3122
|
-
background: transparent;
|
|
3123
|
-
color: var(--color-text);
|
|
3124
|
-
border: 1px solid var(--color-border);
|
|
3125
|
-
}
|
|
3126
|
-
|
|
3127
|
-
.btn-secondary:hover {
|
|
3128
|
-
border-color: var(--color-primary);
|
|
3129
|
-
color: var(--color-primary-light);
|
|
3130
|
-
}
|
|
3131
|
-
|
|
3132
|
-
/* Responsive */
|
|
3133
|
-
@media (max-width: 768px) {
|
|
3134
|
-
.container {
|
|
3135
|
-
padding: var(--space-md);
|
|
3136
|
-
}
|
|
3137
|
-
|
|
3138
|
-
.hero {
|
|
3139
|
-
padding: var(--space-lg) 0;
|
|
3140
|
-
}
|
|
3141
|
-
|
|
3142
|
-
.features {
|
|
3143
|
-
grid-template-columns: 1fr;
|
|
3144
|
-
}
|
|
3145
|
-
}
|
|
3146
|
-
|
|
3147
|
-
/* Dark mode is default, but support light mode */
|
|
3148
|
-
@media (prefers-color-scheme: light) {
|
|
3149
|
-
:root {
|
|
3150
|
-
--color-bg: #fafafa;
|
|
3151
|
-
--color-bg-secondary: #ffffff;
|
|
3152
|
-
--color-text: #1a1a2e;
|
|
3153
|
-
--color-text-muted: #64648a;
|
|
3154
|
-
--color-border: #e0e0e8;
|
|
3155
|
-
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
3156
|
-
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.12);
|
|
3157
|
-
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.16);
|
|
3158
|
-
--shadow-glow: 0 0 40px rgba(99, 102, 241, 0.15);
|
|
3159
|
-
}
|
|
3160
|
-
}
|
|
3161
|
-
`;
|
|
3162
|
-
}
|
|
3163
186
|
|
|
3164
187
|
// src/commands/dev.ts
|
|
3165
|
-
import { resolve as resolve2, join as
|
|
3166
|
-
import { readFileSync, existsSync as existsSync2 } from "fs";
|
|
188
|
+
import { resolve as resolve2, join as join2 } from "path";
|
|
189
|
+
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
3167
190
|
import pc2 from "picocolors";
|
|
3168
|
-
|
|
3169
|
-
// ../core/dist/config/index.js
|
|
3170
|
-
init_chunk_WAGCTWGY();
|
|
3171
|
-
|
|
3172
|
-
// src/commands/dev.ts
|
|
191
|
+
import { loadConfig } from "@flight-framework/core/config";
|
|
3173
192
|
async function devCommand(options) {
|
|
3174
193
|
const startTime = Date.now();
|
|
3175
194
|
printLogo();
|
|
@@ -3181,18 +200,18 @@ async function devCommand(options) {
|
|
|
3181
200
|
const host = options.host ?? config.dev.host;
|
|
3182
201
|
const open = options.open ?? config.dev.open;
|
|
3183
202
|
const ssrEnabled = options.ssr ?? config.rendering?.default === "ssr";
|
|
3184
|
-
const entryServerPath =
|
|
203
|
+
const entryServerPath = join2(root, "src", "entry-server.tsx");
|
|
3185
204
|
const hasSSREntry = existsSync2(entryServerPath);
|
|
3186
205
|
const { createServer: createViteServer } = await import("vite");
|
|
3187
206
|
let flightHttpAvailable = false;
|
|
3188
207
|
let flightRouterAvailable = false;
|
|
3189
208
|
try {
|
|
3190
|
-
await
|
|
209
|
+
await import("@flight-framework/http");
|
|
3191
210
|
flightHttpAvailable = true;
|
|
3192
211
|
} catch {
|
|
3193
212
|
}
|
|
3194
213
|
try {
|
|
3195
|
-
await
|
|
214
|
+
await import("@flight-framework/core/file-router");
|
|
3196
215
|
flightRouterAvailable = true;
|
|
3197
216
|
} catch {
|
|
3198
217
|
}
|
|
@@ -3208,7 +227,7 @@ async function devCommand(options) {
|
|
|
3208
227
|
},
|
|
3209
228
|
appType: ssrEnabled && hasSSREntry ? "custom" : "spa",
|
|
3210
229
|
plugins: [
|
|
3211
|
-
// Add Flight plugin when @flight/http is available
|
|
230
|
+
// Add Flight plugin when @flight-framework/http is available
|
|
3212
231
|
flightHttpAvailable ? flightDevPlugin(root) : null
|
|
3213
232
|
].filter(Boolean)
|
|
3214
233
|
});
|
|
@@ -3226,7 +245,7 @@ async function devCommand(options) {
|
|
|
3226
245
|
${host === true || host === "0.0.0.0" ? ` ${pc2.cyan("\u279C")} Network: ${pc2.cyan(`http://${getNetworkAddress()}:${port}/`)}` : ""}
|
|
3227
246
|
|
|
3228
247
|
${isSSR ? pc2.green("\u2713") : pc2.yellow("\u25CB")} SSR ${isSSR ? "enabled (streaming)" : "disabled (CSR mode)"}
|
|
3229
|
-
${flightHttpAvailable ? pc2.green("\u2713") : pc2.yellow("\u25CB")} @flight/http ${flightHttpAvailable ? "enabled" : "not installed"}
|
|
248
|
+
${flightHttpAvailable ? pc2.green("\u2713") : pc2.yellow("\u25CB")} @flight-framework/http ${flightHttpAvailable ? "enabled" : "not installed"}
|
|
3230
249
|
${flightRouterAvailable ? pc2.green("\u2713") : pc2.yellow("\u25CB")} File-based routing ${flightRouterAvailable ? "enabled" : "not available"}
|
|
3231
250
|
|
|
3232
251
|
${pc2.dim("press")} ${pc2.bold("h")} ${pc2.dim("to show help")}
|
|
@@ -3234,8 +253,8 @@ async function devCommand(options) {
|
|
|
3234
253
|
if (!isSSR) {
|
|
3235
254
|
vite.bindCLIShortcuts({ print: true });
|
|
3236
255
|
}
|
|
3237
|
-
} catch (
|
|
3238
|
-
console.error(pc2.red("\nFailed to start dev server:"),
|
|
256
|
+
} catch (error) {
|
|
257
|
+
console.error(pc2.red("\nFailed to start dev server:"), error);
|
|
3239
258
|
process.exit(1);
|
|
3240
259
|
}
|
|
3241
260
|
}
|
|
@@ -3243,9 +262,9 @@ async function startSSRServer(vite, root, port, host) {
|
|
|
3243
262
|
const { createServer: createHttpServer } = await import("http");
|
|
3244
263
|
let pageRouter = null;
|
|
3245
264
|
try {
|
|
3246
|
-
const { createFileRouter
|
|
3247
|
-
pageRouter = await
|
|
3248
|
-
directory:
|
|
265
|
+
const { createFileRouter } = await import("@flight-framework/core/file-router");
|
|
266
|
+
pageRouter = await createFileRouter({
|
|
267
|
+
directory: join2(root, "src", "routes"),
|
|
3249
268
|
extensions: [".tsx", ".ts", ".jsx", ".js"]
|
|
3250
269
|
});
|
|
3251
270
|
console.log(pc2.green(` \u2713 Page router loaded: ${pageRouter.routes.filter((r) => r.type === "page").length} pages`));
|
|
@@ -3259,15 +278,15 @@ async function startSSRServer(vite, root, port, host) {
|
|
|
3259
278
|
return;
|
|
3260
279
|
}
|
|
3261
280
|
try {
|
|
3262
|
-
let template =
|
|
3263
|
-
|
|
281
|
+
let template = readFileSync2(
|
|
282
|
+
join2(root, "index.html"),
|
|
3264
283
|
"utf-8"
|
|
3265
284
|
);
|
|
3266
285
|
template = await vite.transformIndexHtml(url, template);
|
|
3267
286
|
let appHtml = "";
|
|
3268
287
|
if (pageRouter) {
|
|
3269
288
|
const pageRoute = pageRouter.routes.find(
|
|
3270
|
-
(r) => r.type === "page" &&
|
|
289
|
+
(r) => r.type === "page" && matchPath(r.path, pathname)
|
|
3271
290
|
);
|
|
3272
291
|
if (pageRoute && pageRoute.component) {
|
|
3273
292
|
const mod = await vite.ssrLoadModule(pageRoute.filePath.replace(root, ""));
|
|
@@ -3316,17 +335,17 @@ function flightDevPlugin(root) {
|
|
|
3316
335
|
const url = req.url || "/";
|
|
3317
336
|
if (url.startsWith("/__flight_action/")) {
|
|
3318
337
|
try {
|
|
3319
|
-
const { handleActionRequest
|
|
338
|
+
const { handleActionRequest } = await import("@flight-framework/core");
|
|
3320
339
|
const webRequest = await nodeToWebRequest(req);
|
|
3321
|
-
const response = await
|
|
340
|
+
const response = await handleActionRequest(webRequest);
|
|
3322
341
|
res.statusCode = response.status;
|
|
3323
342
|
response.headers.forEach((value, key) => {
|
|
3324
343
|
res.setHeader(key, value);
|
|
3325
344
|
});
|
|
3326
345
|
const body = await response.text();
|
|
3327
346
|
res.end(body);
|
|
3328
|
-
} catch (
|
|
3329
|
-
console.error("[Flight] Action error:",
|
|
347
|
+
} catch (error) {
|
|
348
|
+
console.error("[Flight] Action error:", error);
|
|
3330
349
|
res.statusCode = 500;
|
|
3331
350
|
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
3332
351
|
}
|
|
@@ -3334,9 +353,9 @@ function flightDevPlugin(root) {
|
|
|
3334
353
|
}
|
|
3335
354
|
if (url.startsWith("/api/")) {
|
|
3336
355
|
try {
|
|
3337
|
-
const { createFileRouter
|
|
3338
|
-
const routesDir =
|
|
3339
|
-
const router = await
|
|
356
|
+
const { createFileRouter } = await import("@flight-framework/core/file-router");
|
|
357
|
+
const routesDir = join2(root, "src", "routes");
|
|
358
|
+
const router = await createFileRouter({ directory: routesDir });
|
|
3340
359
|
const route = router.routes.find((r) => {
|
|
3341
360
|
return matchPath(r.path, url);
|
|
3342
361
|
});
|
|
@@ -3351,7 +370,7 @@ function flightDevPlugin(root) {
|
|
|
3351
370
|
res.end(body);
|
|
3352
371
|
return;
|
|
3353
372
|
}
|
|
3354
|
-
} catch (
|
|
373
|
+
} catch (error) {
|
|
3355
374
|
}
|
|
3356
375
|
}
|
|
3357
376
|
next();
|
|
@@ -3414,13 +433,14 @@ function getNetworkAddress() {
|
|
|
3414
433
|
// src/commands/build.ts
|
|
3415
434
|
import { resolve as resolve3 } from "path";
|
|
3416
435
|
import pc3 from "picocolors";
|
|
436
|
+
import { loadConfig as loadConfig2 } from "@flight-framework/core/config";
|
|
3417
437
|
async function buildCommand(options) {
|
|
3418
438
|
const startTime = Date.now();
|
|
3419
439
|
printLogo();
|
|
3420
440
|
console.log(pc3.cyan("\n[*] Building Flight project for production...\n"));
|
|
3421
441
|
try {
|
|
3422
442
|
const root = resolve3(process.cwd());
|
|
3423
|
-
const config = await
|
|
443
|
+
const config = await loadConfig2(root);
|
|
3424
444
|
const outDir = options.outDir ?? config.build.outDir;
|
|
3425
445
|
const sourcemap = options.sourcemap ?? config.build.sourcemap;
|
|
3426
446
|
const minify = options.minify ?? config.build.minify;
|
|
@@ -3479,8 +499,8 @@ ${pc3.dim("To deploy:")}
|
|
|
3479
499
|
${pc3.dim("\u2022")} Upload ${outDir}/ to your server
|
|
3480
500
|
${pc3.dim("\u2022")} Or use your configured adapter
|
|
3481
501
|
`);
|
|
3482
|
-
} catch (
|
|
3483
|
-
console.error(pc3.red("\nBuild failed:"),
|
|
502
|
+
} catch (error) {
|
|
503
|
+
console.error(pc3.red("\nBuild failed:"), error);
|
|
3484
504
|
process.exit(1);
|
|
3485
505
|
}
|
|
3486
506
|
}
|
|
@@ -3488,12 +508,13 @@ ${pc3.dim("To deploy:")}
|
|
|
3488
508
|
// src/commands/preview.ts
|
|
3489
509
|
import { resolve as resolve4 } from "path";
|
|
3490
510
|
import pc4 from "picocolors";
|
|
511
|
+
import { loadConfig as loadConfig3 } from "@flight-framework/core/config";
|
|
3491
512
|
async function previewCommand(options) {
|
|
3492
513
|
printLogo();
|
|
3493
514
|
console.log(pc4.cyan("\n\u2708\uFE0F Starting Flight preview server...\n"));
|
|
3494
515
|
try {
|
|
3495
516
|
const root = resolve4(process.cwd());
|
|
3496
|
-
const config = await
|
|
517
|
+
const config = await loadConfig3(root);
|
|
3497
518
|
const port = options.port ? parseInt(options.port, 10) : config.dev.port + 1;
|
|
3498
519
|
const host = options.host ?? config.dev.host;
|
|
3499
520
|
const open = options.open ?? false;
|
|
@@ -3519,8 +540,8 @@ async function previewCommand(options) {
|
|
|
3519
540
|
${pc4.dim("For development, use")} ${pc4.bold("flight dev")}
|
|
3520
541
|
`);
|
|
3521
542
|
server.printUrls();
|
|
3522
|
-
} catch (
|
|
3523
|
-
console.error(pc4.red("\nFailed to start preview server:"),
|
|
543
|
+
} catch (error) {
|
|
544
|
+
console.error(pc4.red("\nFailed to start preview server:"), error);
|
|
3524
545
|
process.exit(1);
|
|
3525
546
|
}
|
|
3526
547
|
}
|
|
@@ -3554,8 +575,8 @@ function run() {
|
|
|
3554
575
|
printLogo();
|
|
3555
576
|
}
|
|
3556
577
|
cli.runMatchedCommand();
|
|
3557
|
-
} catch (
|
|
3558
|
-
console.error(pc5.red("Error:"),
|
|
578
|
+
} catch (error) {
|
|
579
|
+
console.error(pc5.red("Error:"), error instanceof Error ? error.message : error);
|
|
3559
580
|
process.exit(1);
|
|
3560
581
|
}
|
|
3561
582
|
}
|