@fluixi/start 0.1.0-alpha.72 → 0.1.0-alpha.74

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.
Files changed (64) hide show
  1. package/dist/adapter.cjs +748 -0
  2. package/dist/adapter.mjs +717 -0
  3. package/dist/adapters/entry.cjs +122 -0
  4. package/dist/adapters/entry.mjs +95 -0
  5. package/dist/adapters/platforms.cjs +311 -0
  6. package/dist/adapters/platforms.mjs +284 -0
  7. package/dist/api-RH6E5UTH.mjs +114 -0
  8. package/dist/api.cjs +145 -0
  9. package/dist/api.mjs +116 -0
  10. package/dist/commands/api-23MJFSYL.mjs +17 -0
  11. package/dist/commands/api-4IYNQRKG.mjs +16 -0
  12. package/dist/commands/api-RH6E5UTH.mjs +114 -0
  13. package/dist/commands/build.cjs +870 -0
  14. package/dist/commands/build.mjs +710 -0
  15. package/dist/commands/chunk-NS5GR2GX.mjs +115 -0
  16. package/dist/commands/chunk-OCPCK4ZJ.mjs +117 -0
  17. package/dist/commands/dev.cjs +663 -0
  18. package/dist/commands/dev.mjs +505 -0
  19. package/dist/commands/index.cjs +1138 -0
  20. package/dist/commands/index.mjs +975 -0
  21. package/dist/commands/prerender.cjs +402 -0
  22. package/dist/commands/prerender.mjs +375 -0
  23. package/dist/commands/start.cjs +461 -0
  24. package/dist/commands/start.mjs +426 -0
  25. package/dist/config.cjs +144 -0
  26. package/dist/config.mjs +108 -0
  27. package/dist/di.cjs +200 -0
  28. package/dist/di.mjs +169 -0
  29. package/dist/document.cjs +115 -0
  30. package/dist/document.mjs +86 -0
  31. package/dist/generated-api.cjs +43 -0
  32. package/dist/generated-api.mjs +18 -0
  33. package/dist/generated-server-fns.cjs +43 -0
  34. package/dist/generated-server-fns.mjs +18 -0
  35. package/dist/handler-core.cjs +211 -0
  36. package/dist/handler-core.mjs +185 -0
  37. package/dist/handler.cjs +181 -0
  38. package/dist/handler.mjs +150 -0
  39. package/dist/head.cjs +25 -0
  40. package/dist/head.mjs +4 -0
  41. package/dist/image.cjs +146 -0
  42. package/dist/image.mjs +120 -0
  43. package/dist/index.cjs +1036 -0
  44. package/dist/index.mjs +968 -0
  45. package/dist/interceptors.cjs +71 -0
  46. package/dist/interceptors.mjs +42 -0
  47. package/dist/internal.cjs +388 -0
  48. package/dist/internal.d.ts.map +1 -1
  49. package/dist/internal.js +6 -2
  50. package/dist/internal.mjs +218 -0
  51. package/dist/middleware.cjs +58 -0
  52. package/dist/middleware.mjs +31 -0
  53. package/dist/preload.cjs +42 -0
  54. package/dist/preload.mjs +18 -0
  55. package/dist/router.cjs +25 -0
  56. package/dist/router.mjs +4 -0
  57. package/dist/server-fn-setup.cjs +46 -0
  58. package/dist/server-fn-setup.mjs +22 -0
  59. package/dist/server-fn.cjs +109 -0
  60. package/dist/server-fn.mjs +79 -0
  61. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  62. package/dist/ui.cjs +123 -0
  63. package/dist/ui.mjs +93 -0
  64. package/package.json +45 -25
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/adapters/entry.ts
21
+ var entry_exports = {};
22
+ __export(entry_exports, {
23
+ cloudflareEntry: () => cloudflareEntry,
24
+ netlifyEntry: () => netlifyEntry,
25
+ vercelEntry: () => vercelEntry
26
+ });
27
+ module.exports = __toCommonJS(entry_exports);
28
+ function preamble({ serverEntry, middleware, template, ssr, mountId, routeAssets }) {
29
+ return [
30
+ `import { createHandlerFrom } from '@fluixi/start/handler-core';`,
31
+ `import { createPreloader } from '@fluixi/start/preload';`,
32
+ `import * as server from ${JSON.stringify(serverEntry)};`,
33
+ middleware ? `import * as middleware from ${JSON.stringify(middleware)};` : "",
34
+ ``,
35
+ `const template = ${JSON.stringify(template)};`,
36
+ // Inlined for the same reason as the template: this runs as an uploaded file, with
37
+ // no dist/server beside it to read.
38
+ `const routeAssets = ${JSON.stringify(routeAssets)};`,
39
+ `const handler = createHandlerFrom({`,
40
+ ` template,`,
41
+ ` mod: server,`,
42
+ ` cfg: { ssr: ${ssr}, mountId: ${JSON.stringify(mountId)} },`,
43
+ ` preload: createPreloader(routeAssets),`,
44
+ middleware ? ` middleware,` : "",
45
+ `});`
46
+ ].filter(Boolean).join("\n");
47
+ }
48
+ function cloudflareEntry(source) {
49
+ return `${preamble(source)}
50
+
51
+ const prerendered = new Set(${JSON.stringify(source.prerendered)});
52
+
53
+ export default {
54
+ async fetch(request, env, ctx) {
55
+ // Static first, but only for what is static. ASSETS answers "/" with index.html
56
+ // whether that is a prerendered page or the shell, so asking about every path
57
+ // costs an SSR app its home page. Extension means a file, prerendered means a
58
+ // page, the rest is the handler's — the rule \`withStaticFiles\` already uses.
59
+ const { pathname } = new URL(request.url);
60
+ if (env && env.ASSETS && (prerendered.has(pathname) || /\\.[^/]+$/.test(pathname))) {
61
+ const asset = await env.ASSETS.fetch(request.clone());
62
+ if (asset.status !== 404) return asset;
63
+ }
64
+ return handler(request, { env, ctx });
65
+ },
66
+ };
67
+ `;
68
+ }
69
+ function netlifyEntry(source) {
70
+ return `${preamble(source)}
71
+
72
+ export default async (request, context) => handler(request, { context });
73
+
74
+ export const config = { path: '/*', preferStatic: true };
75
+ `;
76
+ }
77
+ function vercelEntry(source) {
78
+ return `${preamble(source)}
79
+
80
+ export default async (req, res) => {
81
+ const proto = req.headers['x-forwarded-proto'] || 'https';
82
+ const host = req.headers['x-forwarded-host'] || req.headers.host;
83
+
84
+ const headers = new Headers();
85
+ for (const [name, value] of Object.entries(req.headers)) {
86
+ if (Array.isArray(value)) for (const one of value) headers.append(name, one);
87
+ else if (value !== undefined) headers.set(name, value);
88
+ }
89
+
90
+ // A body has to be read off the stream before it can be handed to Request; only
91
+ // GET and HEAD are guaranteed not to have one.
92
+ let body;
93
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
94
+ const chunks = [];
95
+ for await (const chunk of req) chunks.push(chunk);
96
+ if (chunks.length) body = new Blob(chunks);
97
+ }
98
+
99
+ const response = await handler(
100
+ new Request(new URL(req.url, \`\${proto}://\${host}\`), { method: req.method, headers, body }),
101
+ );
102
+
103
+ res.statusCode = response.status;
104
+ // set-cookie is the one header that legitimately repeats; folding it into one line
105
+ // breaks the cookies.
106
+ for (const [name, value] of response.headers) {
107
+ if (name.toLowerCase() !== 'set-cookie') res.setHeader(name, value);
108
+ }
109
+ const cookies = response.headers.getSetCookie?.() ?? [];
110
+ if (cookies.length) res.setHeader('set-cookie', cookies);
111
+
112
+ if (response.body) for await (const chunk of response.body) res.write(chunk);
113
+ res.end();
114
+ };
115
+ `;
116
+ }
117
+ // Annotate the CommonJS export names for ESM import in node:
118
+ 0 && (module.exports = {
119
+ cloudflareEntry,
120
+ netlifyEntry,
121
+ vercelEntry
122
+ });
@@ -0,0 +1,95 @@
1
+ // src/adapters/entry.ts
2
+ function preamble({ serverEntry, middleware, template, ssr, mountId, routeAssets }) {
3
+ return [
4
+ `import { createHandlerFrom } from '@fluixi/start/handler-core';`,
5
+ `import { createPreloader } from '@fluixi/start/preload';`,
6
+ `import * as server from ${JSON.stringify(serverEntry)};`,
7
+ middleware ? `import * as middleware from ${JSON.stringify(middleware)};` : "",
8
+ ``,
9
+ `const template = ${JSON.stringify(template)};`,
10
+ // Inlined for the same reason as the template: this runs as an uploaded file, with
11
+ // no dist/server beside it to read.
12
+ `const routeAssets = ${JSON.stringify(routeAssets)};`,
13
+ `const handler = createHandlerFrom({`,
14
+ ` template,`,
15
+ ` mod: server,`,
16
+ ` cfg: { ssr: ${ssr}, mountId: ${JSON.stringify(mountId)} },`,
17
+ ` preload: createPreloader(routeAssets),`,
18
+ middleware ? ` middleware,` : "",
19
+ `});`
20
+ ].filter(Boolean).join("\n");
21
+ }
22
+ function cloudflareEntry(source) {
23
+ return `${preamble(source)}
24
+
25
+ const prerendered = new Set(${JSON.stringify(source.prerendered)});
26
+
27
+ export default {
28
+ async fetch(request, env, ctx) {
29
+ // Static first, but only for what is static. ASSETS answers "/" with index.html
30
+ // whether that is a prerendered page or the shell, so asking about every path
31
+ // costs an SSR app its home page. Extension means a file, prerendered means a
32
+ // page, the rest is the handler's — the rule \`withStaticFiles\` already uses.
33
+ const { pathname } = new URL(request.url);
34
+ if (env && env.ASSETS && (prerendered.has(pathname) || /\\.[^/]+$/.test(pathname))) {
35
+ const asset = await env.ASSETS.fetch(request.clone());
36
+ if (asset.status !== 404) return asset;
37
+ }
38
+ return handler(request, { env, ctx });
39
+ },
40
+ };
41
+ `;
42
+ }
43
+ function netlifyEntry(source) {
44
+ return `${preamble(source)}
45
+
46
+ export default async (request, context) => handler(request, { context });
47
+
48
+ export const config = { path: '/*', preferStatic: true };
49
+ `;
50
+ }
51
+ function vercelEntry(source) {
52
+ return `${preamble(source)}
53
+
54
+ export default async (req, res) => {
55
+ const proto = req.headers['x-forwarded-proto'] || 'https';
56
+ const host = req.headers['x-forwarded-host'] || req.headers.host;
57
+
58
+ const headers = new Headers();
59
+ for (const [name, value] of Object.entries(req.headers)) {
60
+ if (Array.isArray(value)) for (const one of value) headers.append(name, one);
61
+ else if (value !== undefined) headers.set(name, value);
62
+ }
63
+
64
+ // A body has to be read off the stream before it can be handed to Request; only
65
+ // GET and HEAD are guaranteed not to have one.
66
+ let body;
67
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
68
+ const chunks = [];
69
+ for await (const chunk of req) chunks.push(chunk);
70
+ if (chunks.length) body = new Blob(chunks);
71
+ }
72
+
73
+ const response = await handler(
74
+ new Request(new URL(req.url, \`\${proto}://\${host}\`), { method: req.method, headers, body }),
75
+ );
76
+
77
+ res.statusCode = response.status;
78
+ // set-cookie is the one header that legitimately repeats; folding it into one line
79
+ // breaks the cookies.
80
+ for (const [name, value] of response.headers) {
81
+ if (name.toLowerCase() !== 'set-cookie') res.setHeader(name, value);
82
+ }
83
+ const cookies = response.headers.getSetCookie?.() ?? [];
84
+ if (cookies.length) res.setHeader('set-cookie', cookies);
85
+
86
+ if (response.body) for await (const chunk of response.body) res.write(chunk);
87
+ res.end();
88
+ };
89
+ `;
90
+ }
91
+ export {
92
+ cloudflareEntry,
93
+ netlifyEntry,
94
+ vercelEntry
95
+ };
@@ -0,0 +1,311 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/adapters/platforms.ts
21
+ var platforms_exports = {};
22
+ __export(platforms_exports, {
23
+ cloudflareAdapter: () => cloudflareAdapter,
24
+ netlifyAdapter: () => netlifyAdapter,
25
+ vercelAdapter: () => vercelAdapter
26
+ });
27
+ module.exports = __toCommonJS(platforms_exports);
28
+ var import_promises2 = require("node:fs/promises");
29
+ var import_node_fs2 = require("node:fs");
30
+ var import_node_path2 = require("node:path");
31
+
32
+ // src/adapter.ts
33
+ var import_promises = require("node:fs/promises");
34
+ var import_node_fs = require("node:fs");
35
+ var import_node_path = require("node:path");
36
+
37
+ // src/document.ts
38
+ var import_head = require("@fluixi/head");
39
+
40
+ // src/preload.ts
41
+ var import_router = require("@fluixi/core/router");
42
+
43
+ // src/adapter.ts
44
+ async function readTemplate(clientDir, serverDir) {
45
+ const stashed = (0, import_node_path.join)(serverDir, "template.html");
46
+ return (0, import_promises.readFile)((0, import_node_fs.existsSync)(stashed) ? stashed : (0, import_node_path.join)(clientDir, "index.html"), "utf-8");
47
+ }
48
+
49
+ // src/adapters/entry.ts
50
+ function preamble({ serverEntry, middleware, template, ssr, mountId, routeAssets }) {
51
+ return [
52
+ `import { createHandlerFrom } from '@fluixi/start/handler-core';`,
53
+ `import { createPreloader } from '@fluixi/start/preload';`,
54
+ `import * as server from ${JSON.stringify(serverEntry)};`,
55
+ middleware ? `import * as middleware from ${JSON.stringify(middleware)};` : "",
56
+ ``,
57
+ `const template = ${JSON.stringify(template)};`,
58
+ // Inlined for the same reason as the template: this runs as an uploaded file, with
59
+ // no dist/server beside it to read.
60
+ `const routeAssets = ${JSON.stringify(routeAssets)};`,
61
+ `const handler = createHandlerFrom({`,
62
+ ` template,`,
63
+ ` mod: server,`,
64
+ ` cfg: { ssr: ${ssr}, mountId: ${JSON.stringify(mountId)} },`,
65
+ ` preload: createPreloader(routeAssets),`,
66
+ middleware ? ` middleware,` : "",
67
+ `});`
68
+ ].filter(Boolean).join("\n");
69
+ }
70
+ function cloudflareEntry(source) {
71
+ return `${preamble(source)}
72
+
73
+ const prerendered = new Set(${JSON.stringify(source.prerendered)});
74
+
75
+ export default {
76
+ async fetch(request, env, ctx) {
77
+ // Static first, but only for what is static. ASSETS answers "/" with index.html
78
+ // whether that is a prerendered page or the shell, so asking about every path
79
+ // costs an SSR app its home page. Extension means a file, prerendered means a
80
+ // page, the rest is the handler's — the rule \`withStaticFiles\` already uses.
81
+ const { pathname } = new URL(request.url);
82
+ if (env && env.ASSETS && (prerendered.has(pathname) || /\\.[^/]+$/.test(pathname))) {
83
+ const asset = await env.ASSETS.fetch(request.clone());
84
+ if (asset.status !== 404) return asset;
85
+ }
86
+ return handler(request, { env, ctx });
87
+ },
88
+ };
89
+ `;
90
+ }
91
+ function netlifyEntry(source) {
92
+ return `${preamble(source)}
93
+
94
+ export default async (request, context) => handler(request, { context });
95
+
96
+ export const config = { path: '/*', preferStatic: true };
97
+ `;
98
+ }
99
+ function vercelEntry(source) {
100
+ return `${preamble(source)}
101
+
102
+ export default async (req, res) => {
103
+ const proto = req.headers['x-forwarded-proto'] || 'https';
104
+ const host = req.headers['x-forwarded-host'] || req.headers.host;
105
+
106
+ const headers = new Headers();
107
+ for (const [name, value] of Object.entries(req.headers)) {
108
+ if (Array.isArray(value)) for (const one of value) headers.append(name, one);
109
+ else if (value !== undefined) headers.set(name, value);
110
+ }
111
+
112
+ // A body has to be read off the stream before it can be handed to Request; only
113
+ // GET and HEAD are guaranteed not to have one.
114
+ let body;
115
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
116
+ const chunks = [];
117
+ for await (const chunk of req) chunks.push(chunk);
118
+ if (chunks.length) body = new Blob(chunks);
119
+ }
120
+
121
+ const response = await handler(
122
+ new Request(new URL(req.url, \`\${proto}://\${host}\`), { method: req.method, headers, body }),
123
+ );
124
+
125
+ res.statusCode = response.status;
126
+ // set-cookie is the one header that legitimately repeats; folding it into one line
127
+ // breaks the cookies.
128
+ for (const [name, value] of response.headers) {
129
+ if (name.toLowerCase() !== 'set-cookie') res.setHeader(name, value);
130
+ }
131
+ const cookies = response.headers.getSetCookie?.() ?? [];
132
+ if (cookies.length) res.setHeader('set-cookie', cookies);
133
+
134
+ if (response.body) for await (const chunk of response.body) res.write(chunk);
135
+ res.end();
136
+ };
137
+ `;
138
+ }
139
+
140
+ // src/adapters/platforms.ts
141
+ async function entrySource(ctx, from, prerendered) {
142
+ const template = await readTemplate(ctx.clientDir, ctx.serverDir);
143
+ const assetFile = (0, import_node_path2.join)(ctx.serverDir, "route-assets.json");
144
+ const routeAssets = (0, import_node_fs2.existsSync)(assetFile) ? JSON.parse(await (0, import_promises2.readFile)(assetFile, "utf-8")) : {};
145
+ const middleware = (0, import_node_path2.join)(ctx.serverDir, "middleware.js");
146
+ const rel = (file) => {
147
+ const path = (0, import_node_path2.join)(ctx.serverDir, file).replace(/\\/g, "/");
148
+ return path.startsWith("/") ? path : `./${path}`;
149
+ };
150
+ return {
151
+ serverEntry: rel("entry-server.js"),
152
+ middleware: (0, import_node_fs2.existsSync)(middleware) ? rel("middleware.js") : null,
153
+ template,
154
+ ssr: ctx.cfg.ssr,
155
+ mountId: ctx.cfg.mountId,
156
+ prerendered,
157
+ routeAssets
158
+ };
159
+ }
160
+ function indexIsPage(template, mountId) {
161
+ const mount = new RegExp(`<([a-z-]+)[^>]*\\sid=["']${mountId}["'][^>]*>`, "i").exec(template);
162
+ if (!mount) return false;
163
+ return !template.slice(mount.index + mount[0].length).trimStart().startsWith("</");
164
+ }
165
+ function skipWhenStatic(ctx, name) {
166
+ if (ctx.hasServer) return false;
167
+ console.log(` fluixi: no server entry — ${name} gets the static output alone.`);
168
+ return true;
169
+ }
170
+ async function appendRedirect(clientDir, rule) {
171
+ const file = (0, import_node_path2.join)(clientDir, "_redirects");
172
+ const existing = await (0, import_promises2.readFile)(file, "utf-8").catch(() => "");
173
+ if (existing.includes(rule)) return;
174
+ const separator = existing && !existing.endsWith("\n") ? "\n" : "";
175
+ await (0, import_promises2.writeFile)(file, `${existing}${separator}${rule}
176
+ `);
177
+ }
178
+ var SPA_FALLBACK = "/* /index.html 200";
179
+ var CF_MAX_RULES = 100;
180
+ async function prerenderedRoutes(dir, mountId) {
181
+ const out = [];
182
+ const walk = async (current) => {
183
+ for (const entry of await (0, import_promises2.readdir)(current, { withFileTypes: true })) {
184
+ const path = (0, import_node_path2.join)(current, entry.name);
185
+ if (entry.isDirectory()) {
186
+ if (entry.name === "assets" || entry.name.startsWith(".")) continue;
187
+ await walk(path);
188
+ } else if (entry.name.endsWith(".html")) {
189
+ const rel = (0, import_node_path2.relative)(dir, path).replace(/\\/g, "/").replace(/index\.html$/, "").replace(/\.html$/, "");
190
+ out.push("/" + rel.replace(/\/$/, ""));
191
+ }
192
+ }
193
+ };
194
+ await walk(dir);
195
+ const index = await (0, import_promises2.readFile)((0, import_node_path2.join)(dir, "index.html"), "utf-8").catch(() => "");
196
+ const root = indexIsPage(index, mountId);
197
+ return out.filter((r) => r !== "/" || root).sort();
198
+ }
199
+ var cloudflareAdapter = {
200
+ name: "cloudflare",
201
+ bundle: "inline",
202
+ serve({ handler }) {
203
+ return { fetch: handler };
204
+ },
205
+ async build(ctx) {
206
+ if (skipWhenStatic(ctx, "cloudflare")) return;
207
+ const out = (0, import_node_path2.join)(ctx.clientDir, "_worker.js");
208
+ const prerendered = await prerenderedRoutes(ctx.clientDir, ctx.cfg.mountId);
209
+ await ctx.bundleEntry(cloudflareEntry(await entrySource(ctx, out, prerendered)), out);
210
+ const base = ["/assets/*", "/_worker.js"];
211
+ const room = CF_MAX_RULES - base.length;
212
+ const exclude = [...base, ...prerendered.slice(0, room)];
213
+ if (prerendered.length > room) {
214
+ console.warn(
215
+ ` 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.`
216
+ );
217
+ }
218
+ await (0, import_promises2.writeFile)(
219
+ (0, import_node_path2.join)(ctx.clientDir, "_routes.json"),
220
+ JSON.stringify({ version: 1, include: ["/*"], exclude }, null, 2) + "\n"
221
+ );
222
+ }
223
+ };
224
+ var netlifyAdapter = {
225
+ name: "netlify",
226
+ bundle: "inline",
227
+ serve({ handler }) {
228
+ return { fetch: handler };
229
+ },
230
+ async build(ctx) {
231
+ if (skipWhenStatic(ctx, "netlify")) return appendRedirect(ctx.clientDir, SPA_FALLBACK);
232
+ const dir = (0, import_node_path2.join)(ctx.root, ".netlify", "functions-internal");
233
+ await (0, import_promises2.mkdir)(dir, { recursive: true });
234
+ const out = (0, import_node_path2.join)(dir, "fluixi-server.mjs");
235
+ const prerendered = await prerenderedRoutes(ctx.clientDir, ctx.cfg.mountId);
236
+ await ctx.bundleEntry(netlifyEntry(await entrySource(ctx, out, prerendered)), out);
237
+ await (0, import_promises2.writeFile)(
238
+ (0, import_node_path2.join)(dir, "fluixi-server.json"),
239
+ JSON.stringify({ config: { path: "/*", preferStatic: true }, version: 1 }, null, 2) + "\n"
240
+ );
241
+ if (!prerendered.includes("/")) {
242
+ await appendRedirect(ctx.clientDir, "/ /.netlify/functions/fluixi-server 200!");
243
+ }
244
+ }
245
+ };
246
+ var vercelAdapter = {
247
+ name: "vercel",
248
+ bundle: "inline",
249
+ serve({ handler }) {
250
+ return { fetch: handler };
251
+ },
252
+ async build(ctx) {
253
+ const output = (0, import_node_path2.join)(ctx.root, ".vercel", "output");
254
+ await (0, import_promises2.mkdir)(output, { recursive: true });
255
+ await (0, import_promises2.cp)(ctx.clientDir, (0, import_node_path2.join)(output, "static"), { recursive: true });
256
+ if (skipWhenStatic(ctx, "vercel")) {
257
+ await (0, import_promises2.writeFile)(
258
+ (0, import_node_path2.join)(output, "config.json"),
259
+ JSON.stringify(
260
+ {
261
+ version: 3,
262
+ // The filesystem phase alone answers 404 for a client route, since nothing
263
+ // is on disk at that path; the catch-all is what makes it a SPA.
264
+ routes: [{ handle: "filesystem" }, { src: "/(.*)", dest: "/index.html" }]
265
+ },
266
+ null,
267
+ 2
268
+ ) + "\n"
269
+ );
270
+ return;
271
+ }
272
+ const fn = (0, import_node_path2.join)(output, "functions", "index.func");
273
+ await (0, import_promises2.mkdir)(fn, { recursive: true });
274
+ const out = (0, import_node_path2.join)(fn, "index.mjs");
275
+ const prerendered = await prerenderedRoutes(ctx.clientDir, ctx.cfg.mountId);
276
+ await ctx.bundleEntry(vercelEntry(await entrySource(ctx, out, prerendered)), out);
277
+ await (0, import_promises2.writeFile)(
278
+ (0, import_node_path2.join)(fn, ".vc-config.json"),
279
+ JSON.stringify(
280
+ { runtime: "nodejs20.x", handler: "index.mjs", launcherType: "Nodejs", shouldAddHelpers: false },
281
+ null,
282
+ 2
283
+ ) + "\n"
284
+ );
285
+ await (0, import_promises2.writeFile)(
286
+ (0, import_node_path2.join)(output, "config.json"),
287
+ JSON.stringify(
288
+ {
289
+ version: 3,
290
+ routes: [
291
+ // The filesystem holds a shell at `/index.html`, so `/` has to be claimed
292
+ // before that phase or it is served unrendered. Skipped when `/` really is
293
+ // a prerendered page, which the filesystem should answer.
294
+ ...prerendered.includes("/") ? [] : [{ src: "/", dest: "/index" }],
295
+ // A prerendered page or an asset wins; only a miss reaches the function.
296
+ { handle: "filesystem" },
297
+ { src: "/(.*)", dest: "/index" }
298
+ ]
299
+ },
300
+ null,
301
+ 2
302
+ ) + "\n"
303
+ );
304
+ }
305
+ };
306
+ // Annotate the CommonJS export names for ESM import in node:
307
+ 0 && (module.exports = {
308
+ cloudflareAdapter,
309
+ netlifyAdapter,
310
+ vercelAdapter
311
+ });