@fluixi/start 0.1.0-alpha.74 → 0.1.0-alpha.75
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/adapter.cjs +5 -3
- package/dist/adapter.d.ts +9 -9
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +10 -10
- package/dist/adapter.mjs +5 -3
- package/dist/adapters/entry.cjs +1 -1
- package/dist/adapters/entry.js +1 -1
- package/dist/adapters/entry.mjs +1 -1
- package/dist/adapters/platforms.cjs +1 -1
- package/dist/adapters/platforms.d.ts +2 -2
- package/dist/adapters/platforms.js +8 -8
- package/dist/adapters/platforms.mjs +1 -1
- package/dist/{api-RH6E5UTH.mjs → api-HD7KU3BS.mjs} +1 -1
- package/dist/api.cjs +2 -2
- package/dist/api.js +1 -1
- package/dist/api.mjs +2 -2
- package/dist/commands/{api-RH6E5UTH.mjs → api-HD7KU3BS.mjs} +1 -1
- package/dist/commands/{api-4IYNQRKG.mjs → api-PBT4QZ34.mjs} +1 -1
- package/dist/commands/{api-23MJFSYL.mjs → api-PJL37LV3.mjs} +2 -2
- package/dist/commands/build.cjs +13 -6
- package/dist/commands/build.js +6 -6
- package/dist/commands/build.mjs +13 -6
- package/dist/commands/{chunk-OCPCK4ZJ.mjs → chunk-GFQ4MUIC.mjs} +2 -2
- package/dist/commands/{chunk-NS5GR2GX.mjs → chunk-MTM6M3TC.mjs} +1 -1
- package/dist/commands/dev.cjs +11 -4
- package/dist/commands/dev.js +3 -3
- package/dist/commands/dev.mjs +12 -5
- package/dist/commands/index.cjs +14 -7
- package/dist/commands/index.d.ts +1 -1
- package/dist/commands/index.js +1 -1
- package/dist/commands/index.mjs +15 -8
- package/dist/commands/prerender.cjs +2 -0
- package/dist/commands/prerender.d.ts +1 -1
- package/dist/commands/prerender.js +2 -2
- package/dist/commands/prerender.mjs +2 -0
- package/dist/commands/start.cjs +2 -0
- package/dist/commands/start.d.ts +1 -1
- package/dist/commands/start.js +2 -2
- package/dist/commands/start.mjs +2 -0
- package/dist/config.cjs +7 -1
- package/dist/config.d.ts +24 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -6
- package/dist/config.mjs +7 -1
- package/dist/define-config.cjs +32 -0
- package/dist/define-config.d.ts +12 -0
- package/dist/define-config.d.ts.map +1 -0
- package/dist/define-config.js +3 -0
- package/dist/define-config.mjs +7 -0
- package/dist/di.cjs +1 -1
- package/dist/di.d.ts +4 -4
- package/dist/di.d.ts.map +1 -1
- package/dist/di.js +9 -9
- package/dist/di.mjs +1 -1
- package/dist/document.d.ts +1 -1
- package/dist/document.js +1 -1
- package/dist/generated-api.cjs +1 -1
- package/dist/generated-api.js +1 -1
- package/dist/generated-api.mjs +1 -1
- package/dist/generated-server-fns.cjs +1 -1
- package/dist/generated-server-fns.mjs +1 -1
- package/dist/handler-core.cjs +1 -1
- package/dist/handler-core.d.ts +2 -2
- package/dist/handler-core.js +2 -2
- package/dist/handler-core.mjs +1 -1
- package/dist/handler.cjs +1 -0
- package/dist/handler.d.ts +3 -3
- package/dist/handler.js +3 -3
- package/dist/handler.mjs +2 -0
- package/dist/head.cjs +1 -1
- package/dist/head.d.ts +1 -1
- package/dist/head.js +1 -1
- package/dist/head.mjs +1 -1
- package/dist/image-loader.cjs +37 -0
- package/dist/image-loader.d.ts +25 -0
- package/dist/image-loader.d.ts.map +1 -0
- package/dist/image-loader.js +18 -0
- package/dist/image-loader.mjs +12 -0
- package/dist/image.cjs +13 -8
- package/dist/image.d.ts +2 -19
- package/dist/image.d.ts.map +1 -1
- package/dist/image.js +5 -21
- package/dist/image.mjs +14 -8
- package/dist/index.cjs +5 -738
- package/dist/index.d.ts +28 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -17
- package/dist/index.mjs +4 -710
- package/dist/interceptors.cjs +1 -0
- package/dist/interceptors.js +1 -1
- package/dist/interceptors.mjs +2 -0
- package/dist/internal.cjs +9 -4
- package/dist/internal.d.ts +6 -6
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +23 -15
- package/dist/internal.mjs +9 -4
- package/dist/middleware.d.ts +3 -3
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +1 -1
- package/dist/preload.cjs +1 -1
- package/dist/preload.js +1 -1
- package/dist/preload.mjs +1 -1
- package/dist/router.cjs +1 -1
- package/dist/router.d.ts +3 -3
- package/dist/router.js +3 -3
- package/dist/router.mjs +1 -1
- package/dist/server-fn-setup.cjs +1 -1
- package/dist/server-fn-setup.d.ts +1 -1
- package/dist/server-fn-setup.js +2 -2
- package/dist/server-fn-setup.mjs +1 -1
- package/dist/server-fn.cjs +1 -1
- package/dist/server-fn.d.ts +2 -2
- package/dist/server-fn.js +2 -2
- package/dist/server-fn.mjs +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/ui.cjs +1 -1
- package/dist/ui.js +1 -1
- package/dist/ui.mjs +1 -1
- package/package.json +25 -7
package/dist/index.mjs
CHANGED
|
@@ -1,106 +1,9 @@
|
|
|
1
|
-
/*! @fluixi/start v0.1.0-alpha.
|
|
1
|
+
/*! @fluixi/start v0.1.0-alpha.75 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
|
|
3
|
-
// src/config.ts
|
|
4
|
-
import { pathToFileURL } from "node:url";
|
|
5
|
-
import { existsSync } from "node:fs";
|
|
6
|
-
import { writeFile, unlink } from "node:fs/promises";
|
|
7
|
-
import { resolve, isAbsolute } from "node:path";
|
|
3
|
+
// src/define-config.ts
|
|
8
4
|
function defineConfig(config) {
|
|
9
5
|
return config;
|
|
10
6
|
}
|
|
11
|
-
function resolveConfig(config = {}) {
|
|
12
|
-
const root = resolve(config.root ?? process.cwd());
|
|
13
|
-
return {
|
|
14
|
-
root,
|
|
15
|
-
ssr: config.ssr ?? true,
|
|
16
|
-
port: config.port ?? 3e3,
|
|
17
|
-
serverEntry: config.serverEntry ?? "src/entry-server.ts",
|
|
18
|
-
clientEntry: config.clientEntry ?? "src/entry-client.ts",
|
|
19
|
-
template: config.template ?? "index.html",
|
|
20
|
-
mountId: config.mountId ?? "root",
|
|
21
|
-
routesDir: config.routesDir ?? "src/routes",
|
|
22
|
-
apiDir: config.apiDir ?? "src/api",
|
|
23
|
-
middleware: config.middleware ?? "src/middleware.ts",
|
|
24
|
-
ssrNoExternal: config.ssrNoExternal ?? [],
|
|
25
|
-
resolve: config.resolve ?? [],
|
|
26
|
-
adapter: config.adapter,
|
|
27
|
-
i18n: resolveI18n(config.i18n),
|
|
28
|
-
prerender: resolvePrerender(config.prerender)
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
function resolvePrerender(prerender) {
|
|
32
|
-
if (!prerender) return false;
|
|
33
|
-
const opts = typeof prerender === "object" ? prerender : {};
|
|
34
|
-
return {
|
|
35
|
-
routes: opts.routes?.length ? opts.routes : ["/"],
|
|
36
|
-
crawl: opts.crawl ?? true
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
function resolveI18n(i18n) {
|
|
40
|
-
if (i18n === false) return false;
|
|
41
|
-
const opts = typeof i18n === "object" ? i18n : {};
|
|
42
|
-
return {
|
|
43
|
-
dir: opts.dir ?? "src/i18n",
|
|
44
|
-
defaultLocale: opts.defaultLocale,
|
|
45
|
-
locales: opts.locales
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
var CONFIG_NAMES = [
|
|
49
|
-
"fluixi.config.ts",
|
|
50
|
-
"fluixi.config.mts",
|
|
51
|
-
"fluixi.config.mjs",
|
|
52
|
-
"fluixi.config.js"
|
|
53
|
-
];
|
|
54
|
-
async function loadConfig(root = process.cwd()) {
|
|
55
|
-
for (const name of CONFIG_NAMES) {
|
|
56
|
-
const file = resolve(root, name);
|
|
57
|
-
if (existsSync(file)) return loadConfigFile(file);
|
|
58
|
-
}
|
|
59
|
-
return {};
|
|
60
|
-
}
|
|
61
|
-
async function loadConfigFile(file) {
|
|
62
|
-
if (!/\.[mc]?ts$/.test(file)) {
|
|
63
|
-
const mod = await import(
|
|
64
|
-
/* @vite-ignore */
|
|
65
|
-
pathToFileURL(file).href
|
|
66
|
-
);
|
|
67
|
-
return mod.default ?? mod;
|
|
68
|
-
}
|
|
69
|
-
const esbuild = await import("esbuild");
|
|
70
|
-
const { outputFiles } = await esbuild.build({
|
|
71
|
-
entryPoints: [file],
|
|
72
|
-
bundle: true,
|
|
73
|
-
write: false,
|
|
74
|
-
format: "esm",
|
|
75
|
-
platform: "node",
|
|
76
|
-
target: `node${process.versions.node.split(".")[0]}`,
|
|
77
|
-
sourcemap: "inline",
|
|
78
|
-
plugins: [
|
|
79
|
-
{
|
|
80
|
-
name: "fluixi:externalize-bare",
|
|
81
|
-
setup(b) {
|
|
82
|
-
b.onResolve({ filter: /.*/ }, (args) => {
|
|
83
|
-
if (args.kind === "entry-point") return null;
|
|
84
|
-
if (args.path.startsWith(".") || isAbsolute(args.path)) return null;
|
|
85
|
-
return { path: args.path, external: true };
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
]
|
|
90
|
-
});
|
|
91
|
-
const tempFile = `${file}.timestamp-${Date.now()}-${Math.random().toString(16).slice(2)}.mjs`;
|
|
92
|
-
await writeFile(tempFile, outputFiles[0].text);
|
|
93
|
-
try {
|
|
94
|
-
const mod = await import(
|
|
95
|
-
/* @vite-ignore */
|
|
96
|
-
pathToFileURL(tempFile).href
|
|
97
|
-
);
|
|
98
|
-
return mod.default ?? mod;
|
|
99
|
-
} finally {
|
|
100
|
-
await unlink(tempFile).catch(() => {
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
7
|
|
|
105
8
|
// src/index.ts
|
|
106
9
|
import { html, svg } from "@fluixi/core";
|
|
@@ -186,11 +89,6 @@ function guardHandler(handler, onError) {
|
|
|
186
89
|
}
|
|
187
90
|
|
|
188
91
|
// src/handler.ts
|
|
189
|
-
import { createServer as createHttpServer } from "node:http";
|
|
190
|
-
import { stat } from "node:fs/promises";
|
|
191
|
-
import { createReadStream } from "node:fs";
|
|
192
|
-
import { Readable } from "node:stream";
|
|
193
|
-
import { join, extname } from "node:path";
|
|
194
92
|
function streamDocument(head, body, tail) {
|
|
195
93
|
const enc = new TextEncoder();
|
|
196
94
|
const stream = new ReadableStream({
|
|
@@ -232,107 +130,6 @@ function createRequestHandler(render) {
|
|
|
232
130
|
}
|
|
233
131
|
};
|
|
234
132
|
}
|
|
235
|
-
function nodeToRequest(req) {
|
|
236
|
-
const host = req.headers.host ?? "localhost";
|
|
237
|
-
const url = `http://${host}${req.url ?? "/"}`;
|
|
238
|
-
const headers = new Headers();
|
|
239
|
-
for (const [k, v] of Object.entries(req.headers)) {
|
|
240
|
-
if (Array.isArray(v)) v.forEach((x) => headers.append(k, x));
|
|
241
|
-
else if (v != null) headers.set(k, v);
|
|
242
|
-
}
|
|
243
|
-
const method = req.method ?? "GET";
|
|
244
|
-
const init = { method, headers };
|
|
245
|
-
if (method !== "GET" && method !== "HEAD") {
|
|
246
|
-
init.body = req;
|
|
247
|
-
init.duplex = "half";
|
|
248
|
-
}
|
|
249
|
-
return new Request(url, init);
|
|
250
|
-
}
|
|
251
|
-
async function sendResponse(res, response) {
|
|
252
|
-
res.statusCode = response.status;
|
|
253
|
-
response.headers.forEach((value, key) => res.setHeader(key, value));
|
|
254
|
-
const body = response.body;
|
|
255
|
-
if (!body) {
|
|
256
|
-
res.end(await response.text().catch(() => ""));
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
const reader = body.getReader();
|
|
260
|
-
try {
|
|
261
|
-
for (; ; ) {
|
|
262
|
-
const { done, value } = await reader.read();
|
|
263
|
-
if (done) break;
|
|
264
|
-
res.write(value);
|
|
265
|
-
}
|
|
266
|
-
} finally {
|
|
267
|
-
res.end();
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
function toNodeHandler(handler) {
|
|
271
|
-
return async (req, res) => {
|
|
272
|
-
const response = await handler(nodeToRequest(req));
|
|
273
|
-
await sendResponse(res, response);
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
function serveNode(handler, opts = {}) {
|
|
277
|
-
const port = opts.port ?? 3e3;
|
|
278
|
-
const node = toNodeHandler(handler);
|
|
279
|
-
const server = createHttpServer((req, res) => {
|
|
280
|
-
node(req, res).catch((e) => {
|
|
281
|
-
res.statusCode = 500;
|
|
282
|
-
res.end(String(e?.stack || e));
|
|
283
|
-
});
|
|
284
|
-
});
|
|
285
|
-
server.listen(
|
|
286
|
-
port,
|
|
287
|
-
() => opts.onListen ? opts.onListen(port) : console.log(` fluixi → http://localhost:${port}`)
|
|
288
|
-
);
|
|
289
|
-
return server;
|
|
290
|
-
}
|
|
291
|
-
var MIME = {
|
|
292
|
-
".js": "text/javascript",
|
|
293
|
-
".mjs": "text/javascript",
|
|
294
|
-
".css": "text/css",
|
|
295
|
-
".html": "text/html",
|
|
296
|
-
".json": "application/json",
|
|
297
|
-
".svg": "image/svg+xml",
|
|
298
|
-
".png": "image/png",
|
|
299
|
-
".jpg": "image/jpeg",
|
|
300
|
-
".jpeg": "image/jpeg",
|
|
301
|
-
".webp": "image/webp",
|
|
302
|
-
".ico": "image/x-icon",
|
|
303
|
-
".woff": "font/woff",
|
|
304
|
-
".woff2": "font/woff2",
|
|
305
|
-
".map": "application/json"
|
|
306
|
-
};
|
|
307
|
-
function withStaticFiles(handler, dir) {
|
|
308
|
-
return async (request) => {
|
|
309
|
-
const { pathname } = new URL(request.url);
|
|
310
|
-
if (pathname !== "/" && extname(pathname)) {
|
|
311
|
-
const file = join(dir, decodeURIComponent(pathname));
|
|
312
|
-
try {
|
|
313
|
-
const s = await stat(file);
|
|
314
|
-
if (s.isFile()) {
|
|
315
|
-
const body = Readable.toWeb(createReadStream(file));
|
|
316
|
-
return new Response(body, {
|
|
317
|
-
headers: {
|
|
318
|
-
"content-type": MIME[extname(file).toLowerCase()] ?? "application/octet-stream",
|
|
319
|
-
"content-length": String(s.size)
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
} catch {
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
return handler(request);
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// src/adapter.ts
|
|
331
|
-
import { readFile as readFile2 } from "node:fs/promises";
|
|
332
|
-
import { existsSync as existsSync3, readFileSync } from "node:fs";
|
|
333
|
-
import { resolve as resolve2, join as join3, dirname } from "node:path";
|
|
334
|
-
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
335
|
-
import { createRequire } from "node:module";
|
|
336
133
|
|
|
337
134
|
// src/middleware.ts
|
|
338
135
|
function defineMiddleware(mw) {
|
|
@@ -395,385 +192,6 @@ function createHandlerFrom({ template, mod, cfg, middleware, preload }) {
|
|
|
395
192
|
return guardHandler(composeMiddleware(normalizeMiddleware(middleware), core));
|
|
396
193
|
}
|
|
397
194
|
|
|
398
|
-
// src/preload.ts
|
|
399
|
-
import { matchRoutes } from "@fluixi/core/router";
|
|
400
|
-
function createPreloader(assets) {
|
|
401
|
-
const patterns = Object.keys(assets ?? {});
|
|
402
|
-
if (!patterns.length) return () => [];
|
|
403
|
-
const routes = patterns.map((path) => ({ path, meta: { path } }));
|
|
404
|
-
return (pathname) => {
|
|
405
|
-
const matched = matchRoutes(routes, pathname)?.matched;
|
|
406
|
-
const leaf = matched?.[matched.length - 1];
|
|
407
|
-
const pattern = leaf?.route.meta?.path;
|
|
408
|
-
return pattern ? assets[pattern] ?? [] : [];
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// src/adapters/platforms.ts
|
|
413
|
-
import { mkdir, writeFile as writeFile2, readFile, cp, readdir } from "node:fs/promises";
|
|
414
|
-
import { existsSync as existsSync2 } from "node:fs";
|
|
415
|
-
import { join as join2, relative } from "node:path";
|
|
416
|
-
|
|
417
|
-
// src/adapters/entry.ts
|
|
418
|
-
function preamble({ serverEntry, middleware, template, ssr, mountId, routeAssets }) {
|
|
419
|
-
return [
|
|
420
|
-
`import { createHandlerFrom } from '@fluixi/start/handler-core';`,
|
|
421
|
-
`import { createPreloader } from '@fluixi/start/preload';`,
|
|
422
|
-
`import * as server from ${JSON.stringify(serverEntry)};`,
|
|
423
|
-
middleware ? `import * as middleware from ${JSON.stringify(middleware)};` : "",
|
|
424
|
-
``,
|
|
425
|
-
`const template = ${JSON.stringify(template)};`,
|
|
426
|
-
// Inlined for the same reason as the template: this runs as an uploaded file, with
|
|
427
|
-
// no dist/server beside it to read.
|
|
428
|
-
`const routeAssets = ${JSON.stringify(routeAssets)};`,
|
|
429
|
-
`const handler = createHandlerFrom({`,
|
|
430
|
-
` template,`,
|
|
431
|
-
` mod: server,`,
|
|
432
|
-
` cfg: { ssr: ${ssr}, mountId: ${JSON.stringify(mountId)} },`,
|
|
433
|
-
` preload: createPreloader(routeAssets),`,
|
|
434
|
-
middleware ? ` middleware,` : "",
|
|
435
|
-
`});`
|
|
436
|
-
].filter(Boolean).join("\n");
|
|
437
|
-
}
|
|
438
|
-
function cloudflareEntry(source) {
|
|
439
|
-
return `${preamble(source)}
|
|
440
|
-
|
|
441
|
-
const prerendered = new Set(${JSON.stringify(source.prerendered)});
|
|
442
|
-
|
|
443
|
-
export default {
|
|
444
|
-
async fetch(request, env, ctx) {
|
|
445
|
-
// Static first, but only for what is static. ASSETS answers "/" with index.html
|
|
446
|
-
// whether that is a prerendered page or the shell, so asking about every path
|
|
447
|
-
// costs an SSR app its home page. Extension means a file, prerendered means a
|
|
448
|
-
// page, the rest is the handler's — the rule \`withStaticFiles\` already uses.
|
|
449
|
-
const { pathname } = new URL(request.url);
|
|
450
|
-
if (env && env.ASSETS && (prerendered.has(pathname) || /\\.[^/]+$/.test(pathname))) {
|
|
451
|
-
const asset = await env.ASSETS.fetch(request.clone());
|
|
452
|
-
if (asset.status !== 404) return asset;
|
|
453
|
-
}
|
|
454
|
-
return handler(request, { env, ctx });
|
|
455
|
-
},
|
|
456
|
-
};
|
|
457
|
-
`;
|
|
458
|
-
}
|
|
459
|
-
function netlifyEntry(source) {
|
|
460
|
-
return `${preamble(source)}
|
|
461
|
-
|
|
462
|
-
export default async (request, context) => handler(request, { context });
|
|
463
|
-
|
|
464
|
-
export const config = { path: '/*', preferStatic: true };
|
|
465
|
-
`;
|
|
466
|
-
}
|
|
467
|
-
function vercelEntry(source) {
|
|
468
|
-
return `${preamble(source)}
|
|
469
|
-
|
|
470
|
-
export default async (req, res) => {
|
|
471
|
-
const proto = req.headers['x-forwarded-proto'] || 'https';
|
|
472
|
-
const host = req.headers['x-forwarded-host'] || req.headers.host;
|
|
473
|
-
|
|
474
|
-
const headers = new Headers();
|
|
475
|
-
for (const [name, value] of Object.entries(req.headers)) {
|
|
476
|
-
if (Array.isArray(value)) for (const one of value) headers.append(name, one);
|
|
477
|
-
else if (value !== undefined) headers.set(name, value);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// A body has to be read off the stream before it can be handed to Request; only
|
|
481
|
-
// GET and HEAD are guaranteed not to have one.
|
|
482
|
-
let body;
|
|
483
|
-
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
484
|
-
const chunks = [];
|
|
485
|
-
for await (const chunk of req) chunks.push(chunk);
|
|
486
|
-
if (chunks.length) body = new Blob(chunks);
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
const response = await handler(
|
|
490
|
-
new Request(new URL(req.url, \`\${proto}://\${host}\`), { method: req.method, headers, body }),
|
|
491
|
-
);
|
|
492
|
-
|
|
493
|
-
res.statusCode = response.status;
|
|
494
|
-
// set-cookie is the one header that legitimately repeats; folding it into one line
|
|
495
|
-
// breaks the cookies.
|
|
496
|
-
for (const [name, value] of response.headers) {
|
|
497
|
-
if (name.toLowerCase() !== 'set-cookie') res.setHeader(name, value);
|
|
498
|
-
}
|
|
499
|
-
const cookies = response.headers.getSetCookie?.() ?? [];
|
|
500
|
-
if (cookies.length) res.setHeader('set-cookie', cookies);
|
|
501
|
-
|
|
502
|
-
if (response.body) for await (const chunk of response.body) res.write(chunk);
|
|
503
|
-
res.end();
|
|
504
|
-
};
|
|
505
|
-
`;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
// src/adapters/platforms.ts
|
|
509
|
-
async function entrySource(ctx, from, prerendered) {
|
|
510
|
-
const template = await readTemplate(ctx.clientDir, ctx.serverDir);
|
|
511
|
-
const assetFile = join2(ctx.serverDir, "route-assets.json");
|
|
512
|
-
const routeAssets = existsSync2(assetFile) ? JSON.parse(await readFile(assetFile, "utf-8")) : {};
|
|
513
|
-
const middleware = join2(ctx.serverDir, "middleware.js");
|
|
514
|
-
const rel = (file) => {
|
|
515
|
-
const path = join2(ctx.serverDir, file).replace(/\\/g, "/");
|
|
516
|
-
return path.startsWith("/") ? path : `./${path}`;
|
|
517
|
-
};
|
|
518
|
-
return {
|
|
519
|
-
serverEntry: rel("entry-server.js"),
|
|
520
|
-
middleware: existsSync2(middleware) ? rel("middleware.js") : null,
|
|
521
|
-
template,
|
|
522
|
-
ssr: ctx.cfg.ssr,
|
|
523
|
-
mountId: ctx.cfg.mountId,
|
|
524
|
-
prerendered,
|
|
525
|
-
routeAssets
|
|
526
|
-
};
|
|
527
|
-
}
|
|
528
|
-
function indexIsPage(template, mountId) {
|
|
529
|
-
const mount = new RegExp(`<([a-z-]+)[^>]*\\sid=["']${mountId}["'][^>]*>`, "i").exec(template);
|
|
530
|
-
if (!mount) return false;
|
|
531
|
-
return !template.slice(mount.index + mount[0].length).trimStart().startsWith("</");
|
|
532
|
-
}
|
|
533
|
-
function skipWhenStatic(ctx, name) {
|
|
534
|
-
if (ctx.hasServer) return false;
|
|
535
|
-
console.log(` fluixi: no server entry — ${name} gets the static output alone.`);
|
|
536
|
-
return true;
|
|
537
|
-
}
|
|
538
|
-
async function appendRedirect(clientDir, rule) {
|
|
539
|
-
const file = join2(clientDir, "_redirects");
|
|
540
|
-
const existing = await readFile(file, "utf-8").catch(() => "");
|
|
541
|
-
if (existing.includes(rule)) return;
|
|
542
|
-
const separator = existing && !existing.endsWith("\n") ? "\n" : "";
|
|
543
|
-
await writeFile2(file, `${existing}${separator}${rule}
|
|
544
|
-
`);
|
|
545
|
-
}
|
|
546
|
-
var SPA_FALLBACK = "/* /index.html 200";
|
|
547
|
-
var CF_MAX_RULES = 100;
|
|
548
|
-
async function prerenderedRoutes(dir, mountId) {
|
|
549
|
-
const out = [];
|
|
550
|
-
const walk = async (current) => {
|
|
551
|
-
for (const entry of await readdir(current, { withFileTypes: true })) {
|
|
552
|
-
const path = join2(current, entry.name);
|
|
553
|
-
if (entry.isDirectory()) {
|
|
554
|
-
if (entry.name === "assets" || entry.name.startsWith(".")) continue;
|
|
555
|
-
await walk(path);
|
|
556
|
-
} else if (entry.name.endsWith(".html")) {
|
|
557
|
-
const rel = relative(dir, path).replace(/\\/g, "/").replace(/index\.html$/, "").replace(/\.html$/, "");
|
|
558
|
-
out.push("/" + rel.replace(/\/$/, ""));
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
};
|
|
562
|
-
await walk(dir);
|
|
563
|
-
const index = await readFile(join2(dir, "index.html"), "utf-8").catch(() => "");
|
|
564
|
-
const root = indexIsPage(index, mountId);
|
|
565
|
-
return out.filter((r) => r !== "/" || root).sort();
|
|
566
|
-
}
|
|
567
|
-
var cloudflareAdapter = {
|
|
568
|
-
name: "cloudflare",
|
|
569
|
-
bundle: "inline",
|
|
570
|
-
serve({ handler }) {
|
|
571
|
-
return { fetch: handler };
|
|
572
|
-
},
|
|
573
|
-
async build(ctx) {
|
|
574
|
-
if (skipWhenStatic(ctx, "cloudflare")) return;
|
|
575
|
-
const out = join2(ctx.clientDir, "_worker.js");
|
|
576
|
-
const prerendered = await prerenderedRoutes(ctx.clientDir, ctx.cfg.mountId);
|
|
577
|
-
await ctx.bundleEntry(cloudflareEntry(await entrySource(ctx, out, prerendered)), out);
|
|
578
|
-
const base = ["/assets/*", "/_worker.js"];
|
|
579
|
-
const room = CF_MAX_RULES - base.length;
|
|
580
|
-
const exclude = [...base, ...prerendered.slice(0, room)];
|
|
581
|
-
if (prerendered.length > room) {
|
|
582
|
-
console.warn(
|
|
583
|
-
` fluixi: ${prerendered.length} prerendered routes exceed Cloudflare's ${CF_MAX_RULES}-rule limit for _routes.json; ${prerendered.length - room} will invoke the worker to serve a static file.`
|
|
584
|
-
);
|
|
585
|
-
}
|
|
586
|
-
await writeFile2(
|
|
587
|
-
join2(ctx.clientDir, "_routes.json"),
|
|
588
|
-
JSON.stringify({ version: 1, include: ["/*"], exclude }, null, 2) + "\n"
|
|
589
|
-
);
|
|
590
|
-
}
|
|
591
|
-
};
|
|
592
|
-
var netlifyAdapter = {
|
|
593
|
-
name: "netlify",
|
|
594
|
-
bundle: "inline",
|
|
595
|
-
serve({ handler }) {
|
|
596
|
-
return { fetch: handler };
|
|
597
|
-
},
|
|
598
|
-
async build(ctx) {
|
|
599
|
-
if (skipWhenStatic(ctx, "netlify")) return appendRedirect(ctx.clientDir, SPA_FALLBACK);
|
|
600
|
-
const dir = join2(ctx.root, ".netlify", "functions-internal");
|
|
601
|
-
await mkdir(dir, { recursive: true });
|
|
602
|
-
const out = join2(dir, "fluixi-server.mjs");
|
|
603
|
-
const prerendered = await prerenderedRoutes(ctx.clientDir, ctx.cfg.mountId);
|
|
604
|
-
await ctx.bundleEntry(netlifyEntry(await entrySource(ctx, out, prerendered)), out);
|
|
605
|
-
await writeFile2(
|
|
606
|
-
join2(dir, "fluixi-server.json"),
|
|
607
|
-
JSON.stringify({ config: { path: "/*", preferStatic: true }, version: 1 }, null, 2) + "\n"
|
|
608
|
-
);
|
|
609
|
-
if (!prerendered.includes("/")) {
|
|
610
|
-
await appendRedirect(ctx.clientDir, "/ /.netlify/functions/fluixi-server 200!");
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
};
|
|
614
|
-
var vercelAdapter = {
|
|
615
|
-
name: "vercel",
|
|
616
|
-
bundle: "inline",
|
|
617
|
-
serve({ handler }) {
|
|
618
|
-
return { fetch: handler };
|
|
619
|
-
},
|
|
620
|
-
async build(ctx) {
|
|
621
|
-
const output = join2(ctx.root, ".vercel", "output");
|
|
622
|
-
await mkdir(output, { recursive: true });
|
|
623
|
-
await cp(ctx.clientDir, join2(output, "static"), { recursive: true });
|
|
624
|
-
if (skipWhenStatic(ctx, "vercel")) {
|
|
625
|
-
await writeFile2(
|
|
626
|
-
join2(output, "config.json"),
|
|
627
|
-
JSON.stringify(
|
|
628
|
-
{
|
|
629
|
-
version: 3,
|
|
630
|
-
// The filesystem phase alone answers 404 for a client route, since nothing
|
|
631
|
-
// is on disk at that path; the catch-all is what makes it a SPA.
|
|
632
|
-
routes: [{ handle: "filesystem" }, { src: "/(.*)", dest: "/index.html" }]
|
|
633
|
-
},
|
|
634
|
-
null,
|
|
635
|
-
2
|
|
636
|
-
) + "\n"
|
|
637
|
-
);
|
|
638
|
-
return;
|
|
639
|
-
}
|
|
640
|
-
const fn = join2(output, "functions", "index.func");
|
|
641
|
-
await mkdir(fn, { recursive: true });
|
|
642
|
-
const out = join2(fn, "index.mjs");
|
|
643
|
-
const prerendered = await prerenderedRoutes(ctx.clientDir, ctx.cfg.mountId);
|
|
644
|
-
await ctx.bundleEntry(vercelEntry(await entrySource(ctx, out, prerendered)), out);
|
|
645
|
-
await writeFile2(
|
|
646
|
-
join2(fn, ".vc-config.json"),
|
|
647
|
-
JSON.stringify(
|
|
648
|
-
{ runtime: "nodejs20.x", handler: "index.mjs", launcherType: "Nodejs", shouldAddHelpers: false },
|
|
649
|
-
null,
|
|
650
|
-
2
|
|
651
|
-
) + "\n"
|
|
652
|
-
);
|
|
653
|
-
await writeFile2(
|
|
654
|
-
join2(output, "config.json"),
|
|
655
|
-
JSON.stringify(
|
|
656
|
-
{
|
|
657
|
-
version: 3,
|
|
658
|
-
routes: [
|
|
659
|
-
// The filesystem holds a shell at `/index.html`, so `/` has to be claimed
|
|
660
|
-
// before that phase or it is served unrendered. Skipped when `/` really is
|
|
661
|
-
// a prerendered page, which the filesystem should answer.
|
|
662
|
-
...prerendered.includes("/") ? [] : [{ src: "/", dest: "/index" }],
|
|
663
|
-
// A prerendered page or an asset wins; only a miss reaches the function.
|
|
664
|
-
{ handle: "filesystem" },
|
|
665
|
-
{ src: "/(.*)", dest: "/index" }
|
|
666
|
-
]
|
|
667
|
-
},
|
|
668
|
-
null,
|
|
669
|
-
2
|
|
670
|
-
) + "\n"
|
|
671
|
-
);
|
|
672
|
-
}
|
|
673
|
-
};
|
|
674
|
-
|
|
675
|
-
// src/adapter.ts
|
|
676
|
-
async function createProdHandler(config = {}) {
|
|
677
|
-
const cfg = resolveConfig(config);
|
|
678
|
-
const clientDir = resolve2(cfg.root, "dist/client");
|
|
679
|
-
const template = await readTemplate(clientDir, resolve2(cfg.root, "dist/server"));
|
|
680
|
-
const serverEntry = resolve2(cfg.root, "dist/server", "entry-server.js");
|
|
681
|
-
const mod = existsSync3(serverEntry) ? await import(
|
|
682
|
-
/* @vite-ignore */
|
|
683
|
-
pathToFileURL2(serverEntry).href
|
|
684
|
-
) : {};
|
|
685
|
-
const mwFile = resolve2(cfg.root, "dist/server", "middleware.js");
|
|
686
|
-
const middleware = existsSync3(mwFile) ? await import(
|
|
687
|
-
/* @vite-ignore */
|
|
688
|
-
pathToFileURL2(mwFile).href
|
|
689
|
-
) : void 0;
|
|
690
|
-
return createHandlerFrom({ template, mod, cfg, middleware, preload: await loadPreloader(cfg) });
|
|
691
|
-
}
|
|
692
|
-
async function readTemplate(clientDir, serverDir) {
|
|
693
|
-
const stashed = join3(serverDir, "template.html");
|
|
694
|
-
return readFile2(existsSync3(stashed) ? stashed : join3(clientDir, "index.html"), "utf-8");
|
|
695
|
-
}
|
|
696
|
-
async function loadPreloader(cfg) {
|
|
697
|
-
const file = resolve2(cfg.root, "dist/server", "route-assets.json");
|
|
698
|
-
if (!existsSync3(file)) return void 0;
|
|
699
|
-
try {
|
|
700
|
-
return createPreloader(JSON.parse(await readFile2(file, "utf-8")));
|
|
701
|
-
} catch {
|
|
702
|
-
return void 0;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
var nodeAdapter = {
|
|
706
|
-
name: "node",
|
|
707
|
-
// A Node server runs from the app directory, so node_modules is right there: keep the
|
|
708
|
-
// framework as imports instead of copying it into the bundle.
|
|
709
|
-
bundle: "external",
|
|
710
|
-
async serve({ handler, cfg, clientDir }) {
|
|
711
|
-
serveNode(withStaticFiles(handler, clientDir), {
|
|
712
|
-
port: cfg.port,
|
|
713
|
-
onListen: (p) => console.log(` fluixi start (node) → http://localhost:${p}`)
|
|
714
|
-
});
|
|
715
|
-
}
|
|
716
|
-
};
|
|
717
|
-
var webAdapter = {
|
|
718
|
-
name: "web",
|
|
719
|
-
// An edge/serverless runtime uploads a file, not an install: nothing may be left to
|
|
720
|
-
// resolve at runtime, so everything goes in the bundle.
|
|
721
|
-
bundle: "inline",
|
|
722
|
-
serve({ handler }) {
|
|
723
|
-
return { fetch: handler };
|
|
724
|
-
}
|
|
725
|
-
};
|
|
726
|
-
var GENERATED_SUBPATHS = /* @__PURE__ */ new Set(["./routes", "./server-fns", "./api-routes"]);
|
|
727
|
-
function ssrBuildOptions(cfg) {
|
|
728
|
-
const noExternal = cfg.ssrNoExternal.length ? cfg.ssrNoExternal : void 0;
|
|
729
|
-
const mode = cfg.adapter?.bundle;
|
|
730
|
-
if (mode === "inline") return { noExternal: true };
|
|
731
|
-
if (mode !== "external") return { noExternal };
|
|
732
|
-
const external = frameworkDeps(cfg.root).filter((name) => !cfg.ssrNoExternal.includes(name)).flatMap((name) => withSubpaths(cfg.root, name));
|
|
733
|
-
if (!external.length) {
|
|
734
|
-
console.warn(
|
|
735
|
-
` fluixi: adapter "${cfg.adapter?.name}" builds an externalized server, but no fluixi or @fluixi/* dependency was found in ${join3(cfg.root, "package.json")} — bundling everything.`
|
|
736
|
-
);
|
|
737
|
-
}
|
|
738
|
-
return { noExternal, external: external.length ? external : void 0 };
|
|
739
|
-
}
|
|
740
|
-
function frameworkDeps(root) {
|
|
741
|
-
const pkg = readPackage(join3(root, "package.json"));
|
|
742
|
-
if (!pkg) return [];
|
|
743
|
-
const declared = { ...pkg.dependencies, ...pkg.peerDependencies, ...pkg.optionalDependencies };
|
|
744
|
-
return Object.keys(declared).filter((id) => id === "@fluixi/core" || id.startsWith("@fluixi/"));
|
|
745
|
-
}
|
|
746
|
-
function withSubpaths(root, name) {
|
|
747
|
-
const exports = resolvePackage(root, name)?.exports;
|
|
748
|
-
if (!exports || typeof exports !== "object") return [name];
|
|
749
|
-
const ids = [name];
|
|
750
|
-
for (const key of Object.keys(exports)) {
|
|
751
|
-
if (!key.startsWith("./") || key.includes("*")) continue;
|
|
752
|
-
if (key === "./package.json" || GENERATED_SUBPATHS.has(key)) continue;
|
|
753
|
-
ids.push(`${name}/${key.slice(2)}`);
|
|
754
|
-
}
|
|
755
|
-
return ids;
|
|
756
|
-
}
|
|
757
|
-
function resolvePackage(root, name) {
|
|
758
|
-
try {
|
|
759
|
-
return readPackage(createRequire(join3(root, "index.js")).resolve(`${name}/package.json`));
|
|
760
|
-
} catch {
|
|
761
|
-
}
|
|
762
|
-
for (let dir = root; ; dir = dirname(dir)) {
|
|
763
|
-
const pkg = readPackage(join3(dir, "node_modules", name, "package.json"));
|
|
764
|
-
if (pkg) return pkg;
|
|
765
|
-
if (dirname(dir) === dir) return void 0;
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
function readPackage(file) {
|
|
769
|
-
if (!existsSync3(file)) return void 0;
|
|
770
|
-
try {
|
|
771
|
-
return JSON.parse(readFileSync(file, "utf-8"));
|
|
772
|
-
} catch {
|
|
773
|
-
return void 0;
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
|
|
777
195
|
// src/server-fn.ts
|
|
778
196
|
var _fetch = (...a) => fetch(...a);
|
|
779
197
|
function setServerFnFetch(f) {
|
|
@@ -812,114 +230,7 @@ async function fetchWithInterceptors(input, init) {
|
|
|
812
230
|
return response;
|
|
813
231
|
}
|
|
814
232
|
|
|
815
|
-
// src/image.ts
|
|
816
|
-
import { readFile as readFile3 } from "node:fs/promises";
|
|
817
|
-
import { resolve as resolvePath, join as join4, extname as extname2, sep } from "node:path";
|
|
818
|
-
var DEFAULT_SIZES = [16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840];
|
|
819
|
-
var MIME2 = {
|
|
820
|
-
".jpg": "image/jpeg",
|
|
821
|
-
".jpeg": "image/jpeg",
|
|
822
|
-
".png": "image/png",
|
|
823
|
-
".webp": "image/webp",
|
|
824
|
-
".avif": "image/avif",
|
|
825
|
-
".gif": "image/gif",
|
|
826
|
-
".svg": "image/svg+xml"
|
|
827
|
-
};
|
|
828
|
-
var sharpModule;
|
|
829
|
-
async function loadSharp() {
|
|
830
|
-
if (sharpModule !== void 0) return sharpModule;
|
|
831
|
-
try {
|
|
832
|
-
const name = "sharp";
|
|
833
|
-
sharpModule = (await import(
|
|
834
|
-
/* @vite-ignore */
|
|
835
|
-
name
|
|
836
|
-
)).default;
|
|
837
|
-
} catch {
|
|
838
|
-
sharpModule = null;
|
|
839
|
-
}
|
|
840
|
-
return sharpModule;
|
|
841
|
-
}
|
|
842
|
-
var defaultTransform = async (input, { width, quality, format }) => {
|
|
843
|
-
const sharp = await loadSharp();
|
|
844
|
-
if (!sharp) return null;
|
|
845
|
-
const pipe = sharp(input).rotate().resize({ width, withoutEnlargement: true });
|
|
846
|
-
if (format === "avif") return { data: new Uint8Array(await pipe.avif({ quality }).toBuffer()), contentType: "image/avif" };
|
|
847
|
-
if (format === "webp") return { data: new Uint8Array(await pipe.webp({ quality }).toBuffer()), contentType: "image/webp" };
|
|
848
|
-
if (format === "png") return { data: new Uint8Array(await pipe.png().toBuffer()), contentType: "image/png" };
|
|
849
|
-
return { data: new Uint8Array(await pipe.jpeg({ quality, mozjpeg: true }).toBuffer()), contentType: "image/jpeg" };
|
|
850
|
-
};
|
|
851
|
-
function imageResponse(body, contentType, maxAge) {
|
|
852
|
-
return new Response(body, {
|
|
853
|
-
headers: {
|
|
854
|
-
"content-type": contentType,
|
|
855
|
-
"cache-control": `public, max-age=${maxAge}, immutable`,
|
|
856
|
-
vary: "Accept"
|
|
857
|
-
}
|
|
858
|
-
});
|
|
859
|
-
}
|
|
860
|
-
function createImageHandler(options = {}) {
|
|
861
|
-
const root = resolvePath(options.root ?? join4(process.cwd(), "public"));
|
|
862
|
-
const domains = new Set((options.domains ?? []).map((d) => d.toLowerCase()));
|
|
863
|
-
const sizes = options.sizes ?? DEFAULT_SIZES;
|
|
864
|
-
const maxQuality = options.quality ?? 80;
|
|
865
|
-
const maxAge = options.cacheMaxAge ?? 60 * 60 * 24 * 365;
|
|
866
|
-
const transform = options.transform ?? defaultTransform;
|
|
867
|
-
const cacheMax = options.cache === false ? 0 : typeof options.cache === "number" ? options.cache : 100;
|
|
868
|
-
const cache = /* @__PURE__ */ new Map();
|
|
869
|
-
return async (request) => {
|
|
870
|
-
const url = new URL(request.url);
|
|
871
|
-
const src = url.searchParams.get("url") ?? url.searchParams.get("src");
|
|
872
|
-
const width = Number(url.searchParams.get("w"));
|
|
873
|
-
const quality = Math.min(Math.max(Number(url.searchParams.get("q")) || maxQuality, 1), 100);
|
|
874
|
-
if (!src) return new Response('missing "url"', { status: 400 });
|
|
875
|
-
if (!Number.isInteger(width) || !sizes.includes(width)) return new Response('invalid "w"', { status: 400 });
|
|
876
|
-
const accept = request.headers.get("accept") ?? "";
|
|
877
|
-
const format = accept.includes("image/avif") ? "avif" : accept.includes("image/webp") ? "webp" : "original";
|
|
878
|
-
const key = `${src}|${width}|${quality}|${format}`;
|
|
879
|
-
const hit = cache.get(key);
|
|
880
|
-
if (hit) return imageResponse(hit.body, hit.contentType, maxAge);
|
|
881
|
-
let input;
|
|
882
|
-
let sourceType;
|
|
883
|
-
if (/^https?:\/\//i.test(src)) {
|
|
884
|
-
let host;
|
|
885
|
-
try {
|
|
886
|
-
host = new URL(src).hostname.toLowerCase();
|
|
887
|
-
} catch {
|
|
888
|
-
return new Response("bad url", { status: 400 });
|
|
889
|
-
}
|
|
890
|
-
if (!domains.has(host)) return new Response("domain not allowed", { status: 403 });
|
|
891
|
-
const res = await fetch(src);
|
|
892
|
-
if (!res.ok) return new Response("upstream error", { status: 502 });
|
|
893
|
-
input = new Uint8Array(await res.arrayBuffer());
|
|
894
|
-
sourceType = res.headers.get("content-type") ?? "application/octet-stream";
|
|
895
|
-
} else {
|
|
896
|
-
const filePath = resolvePath(root, src.startsWith("/") ? src.slice(1) : src);
|
|
897
|
-
if (filePath !== root && !filePath.startsWith(root + sep)) return new Response("forbidden", { status: 403 });
|
|
898
|
-
try {
|
|
899
|
-
input = new Uint8Array(await readFile3(filePath));
|
|
900
|
-
} catch {
|
|
901
|
-
return new Response("not found", { status: 404 });
|
|
902
|
-
}
|
|
903
|
-
sourceType = MIME2[extname2(filePath).toLowerCase()] ?? "application/octet-stream";
|
|
904
|
-
}
|
|
905
|
-
if (sourceType === "image/svg+xml" || sourceType === "image/gif") {
|
|
906
|
-
return imageResponse(input, sourceType, maxAge);
|
|
907
|
-
}
|
|
908
|
-
let out = null;
|
|
909
|
-
try {
|
|
910
|
-
out = await transform(input, { width, quality, format, contentType: sourceType });
|
|
911
|
-
} catch {
|
|
912
|
-
out = null;
|
|
913
|
-
}
|
|
914
|
-
const body = out?.data ?? input;
|
|
915
|
-
const contentType = out?.contentType ?? sourceType;
|
|
916
|
-
if (cacheMax > 0) {
|
|
917
|
-
if (cache.size >= cacheMax) cache.delete(cache.keys().next().value);
|
|
918
|
-
cache.set(key, { body, contentType });
|
|
919
|
-
}
|
|
920
|
-
return imageResponse(body, contentType, maxAge);
|
|
921
|
-
};
|
|
922
|
-
}
|
|
233
|
+
// src/image-loader.ts
|
|
923
234
|
function imageLoader(options = {}) {
|
|
924
235
|
const path = options.path ?? "/api/image";
|
|
925
236
|
return ({ src, width, quality }) => {
|
|
@@ -934,12 +245,8 @@ import { getRequestLocals, getLocals } from "@fluixi/server";
|
|
|
934
245
|
export {
|
|
935
246
|
addInterceptor,
|
|
936
247
|
clearInterceptors,
|
|
937
|
-
cloudflareAdapter,
|
|
938
248
|
composeMiddleware,
|
|
939
249
|
createHandlerFrom,
|
|
940
|
-
createImageHandler,
|
|
941
|
-
createProdHandler,
|
|
942
|
-
createRequestHandler,
|
|
943
250
|
defineConfig,
|
|
944
251
|
defineMiddleware,
|
|
945
252
|
fetchWithInterceptors,
|
|
@@ -949,20 +256,7 @@ export {
|
|
|
949
256
|
imageLoader,
|
|
950
257
|
injectApp,
|
|
951
258
|
injectAppAndHead,
|
|
952
|
-
loadConfig,
|
|
953
|
-
netlifyAdapter,
|
|
954
|
-
nodeAdapter,
|
|
955
|
-
nodeToRequest,
|
|
956
259
|
normalizeMiddleware,
|
|
957
|
-
resolveConfig,
|
|
958
|
-
sendResponse,
|
|
959
|
-
serveNode,
|
|
960
260
|
splitTemplate,
|
|
961
|
-
|
|
962
|
-
streamDocument,
|
|
963
|
-
svg,
|
|
964
|
-
toNodeHandler,
|
|
965
|
-
vercelAdapter,
|
|
966
|
-
webAdapter,
|
|
967
|
-
withStaticFiles
|
|
261
|
+
svg
|
|
968
262
|
};
|