@fluixi/start 0.1.0-alpha.73 → 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.
Files changed (123) hide show
  1. package/dist/adapter.cjs +750 -0
  2. package/dist/adapter.d.ts +9 -9
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/adapter.js +10 -10
  5. package/dist/adapter.mjs +719 -0
  6. package/dist/adapters/entry.cjs +122 -0
  7. package/dist/adapters/entry.js +1 -1
  8. package/dist/adapters/entry.mjs +95 -0
  9. package/dist/adapters/platforms.cjs +311 -0
  10. package/dist/adapters/platforms.d.ts +2 -2
  11. package/dist/adapters/platforms.js +8 -8
  12. package/dist/adapters/platforms.mjs +284 -0
  13. package/dist/api-HD7KU3BS.mjs +114 -0
  14. package/dist/api.cjs +145 -0
  15. package/dist/api.js +1 -1
  16. package/dist/api.mjs +116 -0
  17. package/dist/commands/api-HD7KU3BS.mjs +114 -0
  18. package/dist/commands/api-PBT4QZ34.mjs +16 -0
  19. package/dist/commands/api-PJL37LV3.mjs +17 -0
  20. package/dist/commands/build.cjs +877 -0
  21. package/dist/commands/build.js +6 -6
  22. package/dist/commands/build.mjs +717 -0
  23. package/dist/commands/chunk-GFQ4MUIC.mjs +117 -0
  24. package/dist/commands/chunk-MTM6M3TC.mjs +115 -0
  25. package/dist/commands/dev.cjs +670 -0
  26. package/dist/commands/dev.js +3 -3
  27. package/dist/commands/dev.mjs +512 -0
  28. package/dist/commands/index.cjs +1145 -0
  29. package/dist/commands/index.d.ts +1 -1
  30. package/dist/commands/index.js +1 -1
  31. package/dist/commands/index.mjs +982 -0
  32. package/dist/commands/prerender.cjs +404 -0
  33. package/dist/commands/prerender.d.ts +1 -1
  34. package/dist/commands/prerender.js +2 -2
  35. package/dist/commands/prerender.mjs +377 -0
  36. package/dist/commands/start.cjs +463 -0
  37. package/dist/commands/start.d.ts +1 -1
  38. package/dist/commands/start.js +2 -2
  39. package/dist/commands/start.mjs +428 -0
  40. package/dist/config.cjs +150 -0
  41. package/dist/config.d.ts +24 -7
  42. package/dist/config.d.ts.map +1 -1
  43. package/dist/config.js +8 -6
  44. package/dist/config.mjs +114 -0
  45. package/dist/define-config.cjs +32 -0
  46. package/dist/define-config.d.ts +12 -0
  47. package/dist/define-config.d.ts.map +1 -0
  48. package/dist/define-config.js +3 -0
  49. package/dist/define-config.mjs +7 -0
  50. package/dist/di.cjs +200 -0
  51. package/dist/di.d.ts +4 -4
  52. package/dist/di.d.ts.map +1 -1
  53. package/dist/di.js +9 -9
  54. package/dist/di.mjs +169 -0
  55. package/dist/document.cjs +115 -0
  56. package/dist/document.d.ts +1 -1
  57. package/dist/document.js +1 -1
  58. package/dist/document.mjs +86 -0
  59. package/dist/generated-api.cjs +43 -0
  60. package/dist/generated-api.js +1 -1
  61. package/dist/generated-api.mjs +18 -0
  62. package/dist/generated-server-fns.cjs +43 -0
  63. package/dist/generated-server-fns.mjs +18 -0
  64. package/dist/handler-core.cjs +211 -0
  65. package/dist/handler-core.d.ts +2 -2
  66. package/dist/handler-core.js +2 -2
  67. package/dist/handler-core.mjs +185 -0
  68. package/dist/handler.cjs +182 -0
  69. package/dist/handler.d.ts +3 -3
  70. package/dist/handler.js +3 -3
  71. package/dist/handler.mjs +152 -0
  72. package/dist/head.cjs +25 -0
  73. package/dist/head.d.ts +1 -1
  74. package/dist/head.js +1 -1
  75. package/dist/head.mjs +4 -0
  76. package/dist/image-loader.cjs +37 -0
  77. package/dist/image-loader.d.ts +25 -0
  78. package/dist/image-loader.d.ts.map +1 -0
  79. package/dist/image-loader.js +18 -0
  80. package/dist/image-loader.mjs +12 -0
  81. package/dist/image.cjs +151 -0
  82. package/dist/image.d.ts +2 -19
  83. package/dist/image.d.ts.map +1 -1
  84. package/dist/image.js +5 -21
  85. package/dist/image.mjs +126 -0
  86. package/dist/index.cjs +303 -0
  87. package/dist/index.d.ts +28 -8
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +33 -17
  90. package/dist/index.mjs +262 -0
  91. package/dist/interceptors.cjs +72 -0
  92. package/dist/interceptors.js +1 -1
  93. package/dist/interceptors.mjs +44 -0
  94. package/dist/internal.cjs +393 -0
  95. package/dist/internal.d.ts +6 -6
  96. package/dist/internal.d.ts.map +1 -1
  97. package/dist/internal.js +23 -15
  98. package/dist/internal.mjs +223 -0
  99. package/dist/middleware.cjs +58 -0
  100. package/dist/middleware.d.ts +3 -3
  101. package/dist/middleware.d.ts.map +1 -1
  102. package/dist/middleware.js +1 -1
  103. package/dist/middleware.mjs +31 -0
  104. package/dist/preload.cjs +42 -0
  105. package/dist/preload.js +1 -1
  106. package/dist/preload.mjs +18 -0
  107. package/dist/router.cjs +25 -0
  108. package/dist/router.d.ts +3 -3
  109. package/dist/router.js +3 -3
  110. package/dist/router.mjs +4 -0
  111. package/dist/server-fn-setup.cjs +46 -0
  112. package/dist/server-fn-setup.d.ts +1 -1
  113. package/dist/server-fn-setup.js +2 -2
  114. package/dist/server-fn-setup.mjs +22 -0
  115. package/dist/server-fn.cjs +109 -0
  116. package/dist/server-fn.d.ts +2 -2
  117. package/dist/server-fn.js +2 -2
  118. package/dist/server-fn.mjs +79 -0
  119. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  120. package/dist/ui.cjs +123 -0
  121. package/dist/ui.js +1 -1
  122. package/dist/ui.mjs +93 -0
  123. package/package.json +63 -25
@@ -0,0 +1,428 @@
1
+ // src/commands/start.ts
2
+ import { resolve as resolve3 } from "node:path";
3
+
4
+ // src/config.ts
5
+ import { resolve, isAbsolute } from "node:path";
6
+ function resolveConfig(config = {}) {
7
+ const root = resolve(config.root ?? process.cwd());
8
+ return {
9
+ root,
10
+ ssr: config.ssr ?? true,
11
+ port: config.port ?? 3e3,
12
+ serverEntry: config.serverEntry ?? "src/entry-server.ts",
13
+ clientEntry: config.clientEntry ?? "src/entry-client.ts",
14
+ template: config.template ?? "index.html",
15
+ mountId: config.mountId ?? "root",
16
+ routesDir: config.routesDir ?? "src/routes",
17
+ apiDir: config.apiDir ?? "src/api",
18
+ middleware: config.middleware ?? "src/middleware.ts",
19
+ ssrNoExternal: config.ssrNoExternal ?? [],
20
+ resolve: config.resolve ?? [],
21
+ vitePlugin: config.vitePlugin ?? {},
22
+ plugins: config.plugins ?? [],
23
+ adapter: config.adapter,
24
+ i18n: resolveI18n(config.i18n),
25
+ prerender: resolvePrerender(config.prerender)
26
+ };
27
+ }
28
+ function resolvePrerender(prerender) {
29
+ if (!prerender) return false;
30
+ const opts = typeof prerender === "object" ? prerender : {};
31
+ return {
32
+ routes: opts.routes?.length ? opts.routes : ["/"],
33
+ crawl: opts.crawl ?? true
34
+ };
35
+ }
36
+ function resolveI18n(i18n) {
37
+ if (i18n === false) return false;
38
+ const opts = typeof i18n === "object" ? i18n : {};
39
+ return {
40
+ dir: opts.dir ?? "src/i18n",
41
+ defaultLocale: opts.defaultLocale,
42
+ locales: opts.locales
43
+ };
44
+ }
45
+
46
+ // src/document.ts
47
+ import { extractHeadMarker } from "@fluixi/head";
48
+ function injectApp(template, appHtml, mountId = "root") {
49
+ const mount = new RegExp(`<div id=["']${mountId}["']\\s*>\\s*</div>`);
50
+ if (mount.test(template)) {
51
+ return template.replace(mount, `<div id="${mountId}">${appHtml}</div>`);
52
+ }
53
+ if (template.includes("<!--ssr-outlet-->")) {
54
+ return template.replace("<!--ssr-outlet-->", appHtml);
55
+ }
56
+ return template.replace("</body>", `<div id="${mountId}">${appHtml}</div></body>`);
57
+ }
58
+ function splitTemplate(template, mountId = "root") {
59
+ const mount = new RegExp(`<div id=["']${mountId}["']\\s*>\\s*</div>`);
60
+ const m = template.match(mount);
61
+ if (m && m.index !== void 0) {
62
+ return {
63
+ head: template.slice(0, m.index) + `<div id="${mountId}">`,
64
+ tail: `</div>` + template.slice(m.index + m[0].length)
65
+ };
66
+ }
67
+ const outlet = template.indexOf("<!--ssr-outlet-->");
68
+ if (outlet !== -1) {
69
+ return {
70
+ head: template.slice(0, outlet),
71
+ tail: template.slice(outlet + "<!--ssr-outlet-->".length)
72
+ };
73
+ }
74
+ const body = template.indexOf("</body>");
75
+ if (body !== -1) {
76
+ return {
77
+ head: template.slice(0, body) + `<div id="${mountId}">`,
78
+ tail: `</div>` + template.slice(body)
79
+ };
80
+ }
81
+ return { head: template, tail: "" };
82
+ }
83
+ function injectPreload(template, files) {
84
+ const tags = files.filter((file) => !template.includes(file)).map(
85
+ (file) => file.endsWith(".css") ? `<link rel="stylesheet" href="${file}">` : (
86
+ // `modulepreload` also fetches the chunk's own static imports.
87
+ `<link rel="modulepreload" href="${file}">`
88
+ )
89
+ );
90
+ if (tags.length === 0) return template;
91
+ const head = template.indexOf("</head>");
92
+ if (head === -1) return template;
93
+ return template.slice(0, head) + tags.join("") + template.slice(head);
94
+ }
95
+ function setHtmlAttr(html, name, value) {
96
+ const existing = new RegExp(`(<html\\b[^>]*?)\\s${name}="[^"]*"`, "i");
97
+ if (existing.test(html)) return html.replace(existing, `$1 ${name}="${value}"`);
98
+ return html.replace(/<html\b/i, `<html ${name}="${value}"`);
99
+ }
100
+ function injectAppAndHead(template, rendered, mountId = "root") {
101
+ const { head, body } = extractHeadMarker(rendered);
102
+ let html = injectApp(template, body, mountId);
103
+ if (head) {
104
+ if (head.headHtml) {
105
+ if (/<title[\s>]/i.test(head.headHtml)) html = html.replace(/<title>[\s\S]*?<\/title>/i, "");
106
+ html = html.replace("</head>", `${head.headHtml}</head>`);
107
+ }
108
+ for (const [k, v] of Object.entries(head.htmlAttrs)) html = setHtmlAttr(html, k, v);
109
+ }
110
+ return html;
111
+ }
112
+ function guardHandler(handler, onError) {
113
+ return async (request) => {
114
+ try {
115
+ return await handler(request);
116
+ } catch (e) {
117
+ onError?.(e);
118
+ return new Response(String(e?.stack || e), {
119
+ status: 500,
120
+ headers: { "content-type": "text/plain; charset=utf-8" }
121
+ });
122
+ }
123
+ };
124
+ }
125
+
126
+ // src/internal.ts
127
+ async function loadServerEnv(root, mode) {
128
+ const { loadEnv } = await import("vite");
129
+ const env = loadEnv(mode, root, "");
130
+ for (const [k, v] of Object.entries(env)) {
131
+ if (process.env[k] === void 0) process.env[k] = v;
132
+ }
133
+ }
134
+ var _guardsInstalled = false;
135
+ function installCrashGuards() {
136
+ if (_guardsInstalled) return;
137
+ _guardsInstalled = true;
138
+ process.on(
139
+ "unhandledRejection",
140
+ (reason) => console.warn("[fluixi] unhandled rejection (backend likely down) —", reason?.message || reason)
141
+ );
142
+ process.on(
143
+ "uncaughtException",
144
+ (err) => console.warn("[fluixi] uncaught exception —", err?.message || err)
145
+ );
146
+ }
147
+
148
+ // src/adapter.ts
149
+ import { readFile } from "node:fs/promises";
150
+ import { existsSync, readFileSync } from "node:fs";
151
+ import { resolve as resolve2, join as join2, dirname } from "node:path";
152
+ import { pathToFileURL } from "node:url";
153
+
154
+ // src/handler.ts
155
+ import { createServer as createHttpServer } from "node:http";
156
+ import { stat } from "node:fs/promises";
157
+ import { createReadStream } from "node:fs";
158
+ import { Readable } from "node:stream";
159
+ import { join, extname } from "node:path";
160
+ function streamDocument(head, body, tail) {
161
+ const enc = new TextEncoder();
162
+ const stream = new ReadableStream({
163
+ async start(controller) {
164
+ try {
165
+ controller.enqueue(enc.encode(head));
166
+ const reader = body.getReader();
167
+ for (; ; ) {
168
+ const { done, value } = await reader.read();
169
+ if (done) break;
170
+ controller.enqueue(value);
171
+ }
172
+ controller.enqueue(enc.encode(tail));
173
+ controller.close();
174
+ } catch (err) {
175
+ controller.error(err);
176
+ }
177
+ }
178
+ });
179
+ return new Response(stream, {
180
+ status: 200,
181
+ headers: { "content-type": "text/html; charset=utf-8" }
182
+ });
183
+ }
184
+ function createRequestHandler(render) {
185
+ return async (request) => {
186
+ const url = new URL(request.url);
187
+ try {
188
+ const html = await render(url.pathname + url.search, request);
189
+ return new Response(html, {
190
+ status: 200,
191
+ headers: { "content-type": "text/html; charset=utf-8" }
192
+ });
193
+ } catch (e) {
194
+ return new Response(String(e?.stack || e), {
195
+ status: 500,
196
+ headers: { "content-type": "text/plain; charset=utf-8" }
197
+ });
198
+ }
199
+ };
200
+ }
201
+ function nodeToRequest(req) {
202
+ const host = req.headers.host ?? "localhost";
203
+ const url = `http://${host}${req.url ?? "/"}`;
204
+ const headers = new Headers();
205
+ for (const [k, v] of Object.entries(req.headers)) {
206
+ if (Array.isArray(v)) v.forEach((x) => headers.append(k, x));
207
+ else if (v != null) headers.set(k, v);
208
+ }
209
+ const method = req.method ?? "GET";
210
+ const init = { method, headers };
211
+ if (method !== "GET" && method !== "HEAD") {
212
+ init.body = req;
213
+ init.duplex = "half";
214
+ }
215
+ return new Request(url, init);
216
+ }
217
+ async function sendResponse(res, response) {
218
+ res.statusCode = response.status;
219
+ response.headers.forEach((value, key) => res.setHeader(key, value));
220
+ const body = response.body;
221
+ if (!body) {
222
+ res.end(await response.text().catch(() => ""));
223
+ return;
224
+ }
225
+ const reader = body.getReader();
226
+ try {
227
+ for (; ; ) {
228
+ const { done, value } = await reader.read();
229
+ if (done) break;
230
+ res.write(value);
231
+ }
232
+ } finally {
233
+ res.end();
234
+ }
235
+ }
236
+ function toNodeHandler(handler) {
237
+ return async (req, res) => {
238
+ const response = await handler(nodeToRequest(req));
239
+ await sendResponse(res, response);
240
+ };
241
+ }
242
+ function serveNode(handler, opts = {}) {
243
+ const port = opts.port ?? 3e3;
244
+ const node = toNodeHandler(handler);
245
+ const server = createHttpServer((req, res) => {
246
+ node(req, res).catch((e) => {
247
+ res.statusCode = 500;
248
+ res.end(String(e?.stack || e));
249
+ });
250
+ });
251
+ server.listen(
252
+ port,
253
+ () => opts.onListen ? opts.onListen(port) : console.log(` fluixi → http://localhost:${port}`)
254
+ );
255
+ return server;
256
+ }
257
+ var MIME = {
258
+ ".js": "text/javascript",
259
+ ".mjs": "text/javascript",
260
+ ".css": "text/css",
261
+ ".html": "text/html",
262
+ ".json": "application/json",
263
+ ".svg": "image/svg+xml",
264
+ ".png": "image/png",
265
+ ".jpg": "image/jpeg",
266
+ ".jpeg": "image/jpeg",
267
+ ".webp": "image/webp",
268
+ ".ico": "image/x-icon",
269
+ ".woff": "font/woff",
270
+ ".woff2": "font/woff2",
271
+ ".map": "application/json"
272
+ };
273
+ function withStaticFiles(handler, dir) {
274
+ return async (request) => {
275
+ const { pathname } = new URL(request.url);
276
+ if (pathname !== "/" && extname(pathname)) {
277
+ const file = join(dir, decodeURIComponent(pathname));
278
+ try {
279
+ const s = await stat(file);
280
+ if (s.isFile()) {
281
+ const body = Readable.toWeb(createReadStream(file));
282
+ return new Response(body, {
283
+ headers: {
284
+ "content-type": MIME[extname(file).toLowerCase()] ?? "application/octet-stream",
285
+ "content-length": String(s.size)
286
+ }
287
+ });
288
+ }
289
+ } catch {
290
+ }
291
+ }
292
+ return handler(request);
293
+ };
294
+ }
295
+
296
+ // src/middleware.ts
297
+ function normalizeMiddleware(mod) {
298
+ const def = mod?.default ?? mod;
299
+ if (def == null) return [];
300
+ if (Array.isArray(def)) return def.filter((m) => typeof m === "function");
301
+ return typeof def === "function" ? [def] : [];
302
+ }
303
+ function composeMiddleware(middlewares, core) {
304
+ if (middlewares.length === 0) return core;
305
+ return (request) => {
306
+ let lastCalled = -1;
307
+ const dispatch = (i) => {
308
+ if (i <= lastCalled) {
309
+ return Promise.reject(new Error("middleware called next() more than once"));
310
+ }
311
+ lastCalled = i;
312
+ const mw = middlewares[i];
313
+ if (!mw) return Promise.resolve(core(request));
314
+ return Promise.resolve(mw(request, () => dispatch(i + 1)));
315
+ };
316
+ return dispatch(0);
317
+ };
318
+ }
319
+
320
+ // src/handler-core.ts
321
+ function createHandlerFrom({ template, mod, cfg, middleware, preload }) {
322
+ const withPreload = (html, pathname) => preload ? injectPreload(html, preload(pathname)) : html;
323
+ let core;
324
+ if (!cfg.ssr) {
325
+ core = createRequestHandler(async (url) => withPreload(template, url.split("?")[0]));
326
+ } else if (typeof mod.renderStream === "function") {
327
+ core = async (request) => {
328
+ const url = new URL(request.url);
329
+ const { head, tail } = splitTemplate(withPreload(template, url.pathname), cfg.mountId);
330
+ const body = await mod.renderStream(url.pathname + url.search, request);
331
+ return streamDocument(head, body, tail);
332
+ };
333
+ } else {
334
+ const render = mod.render ?? mod.default;
335
+ core = createRequestHandler(
336
+ async (url, request) => (
337
+ // `url` here is `pathname + search`; matching only ever wants the path.
338
+ injectAppAndHead(withPreload(template, url.split("?")[0]), await render(url, request), cfg.mountId)
339
+ )
340
+ );
341
+ }
342
+ if (typeof mod.handleServerFn === "function" && typeof mod.isServerFnRequest === "function") {
343
+ const render = core;
344
+ core = async (request) => mod.isServerFnRequest(request) ? mod.handleServerFn(request) : render(request);
345
+ }
346
+ if (typeof mod.handleApiRequest === "function" && typeof mod.isApiRequest === "function") {
347
+ const next = core;
348
+ core = async (request) => mod.isApiRequest(request) ? mod.handleApiRequest(request) : next(request);
349
+ }
350
+ if (!middleware) return guardHandler(core);
351
+ return guardHandler(composeMiddleware(normalizeMiddleware(middleware), core));
352
+ }
353
+
354
+ // src/preload.ts
355
+ import { matchRoutes } from "@fluixi/core/router";
356
+ function createPreloader(assets) {
357
+ const patterns = Object.keys(assets ?? {});
358
+ if (!patterns.length) return () => [];
359
+ const routes = patterns.map((path) => ({ path, meta: { path } }));
360
+ return (pathname) => {
361
+ const matched = matchRoutes(routes, pathname)?.matched;
362
+ const leaf = matched?.[matched.length - 1];
363
+ const pattern = leaf?.route.meta?.path;
364
+ return pattern ? assets[pattern] ?? [] : [];
365
+ };
366
+ }
367
+
368
+ // src/adapter.ts
369
+ async function createProdHandler(config = {}) {
370
+ const cfg = resolveConfig(config);
371
+ const clientDir = resolve2(cfg.root, "dist/client");
372
+ const template = await readTemplate(clientDir, resolve2(cfg.root, "dist/server"));
373
+ const serverEntry = resolve2(cfg.root, "dist/server", "entry-server.js");
374
+ const mod = existsSync(serverEntry) ? await import(
375
+ /* @vite-ignore */
376
+ pathToFileURL(serverEntry).href
377
+ ) : {};
378
+ const mwFile = resolve2(cfg.root, "dist/server", "middleware.js");
379
+ const middleware = existsSync(mwFile) ? await import(
380
+ /* @vite-ignore */
381
+ pathToFileURL(mwFile).href
382
+ ) : void 0;
383
+ return createHandlerFrom({ template, mod, cfg, middleware, preload: await loadPreloader(cfg) });
384
+ }
385
+ async function readTemplate(clientDir, serverDir) {
386
+ const stashed = join2(serverDir, "template.html");
387
+ return readFile(existsSync(stashed) ? stashed : join2(clientDir, "index.html"), "utf-8");
388
+ }
389
+ async function loadPreloader(cfg) {
390
+ const file = resolve2(cfg.root, "dist/server", "route-assets.json");
391
+ if (!existsSync(file)) return void 0;
392
+ try {
393
+ return createPreloader(JSON.parse(await readFile(file, "utf-8")));
394
+ } catch {
395
+ return void 0;
396
+ }
397
+ }
398
+ var nodeAdapter = {
399
+ name: "node",
400
+ // A Node server runs from the app directory, so node_modules is right there: keep the
401
+ // framework as imports instead of copying it into the bundle.
402
+ bundle: "external",
403
+ async serve({ handler, cfg, clientDir }) {
404
+ serveNode(withStaticFiles(handler, clientDir), {
405
+ port: cfg.port,
406
+ onListen: (p) => console.log(` fluixi start (node) → http://localhost:${p}`)
407
+ });
408
+ }
409
+ };
410
+
411
+ // src/commands/start.ts
412
+ async function start(config = {}) {
413
+ const cfg = resolveConfig(config);
414
+ installCrashGuards();
415
+ await loadServerEnv(cfg.root, "production");
416
+ const clientDir = resolve3(cfg.root, "dist/client");
417
+ const handler = await createProdHandler(cfg);
418
+ const adapter = cfg.adapter ?? nodeAdapter;
419
+ const served = await adapter.serve({ handler, cfg, clientDir });
420
+ if (served && typeof served === "object" && "fetch" in served) {
421
+ console.log(
422
+ ` fluixi: the "${adapter.name}" adapter exports a fetch handler — there is no server to start. Deploy dist/ and let the platform invoke it, or run \`fluixi start\` with a filesystem adapter (nodeAdapter).`
423
+ );
424
+ }
425
+ }
426
+ export {
427
+ start
428
+ };
@@ -0,0 +1,150 @@
1
+ /*! @fluixi/start v0.1.0-alpha.75 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/config.ts
32
+ var config_exports = {};
33
+ __export(config_exports, {
34
+ defineConfig: () => defineConfig,
35
+ loadConfig: () => loadConfig,
36
+ resolveConfig: () => resolveConfig
37
+ });
38
+ module.exports = __toCommonJS(config_exports);
39
+ var import_node_url = require("node:url");
40
+ var import_node_fs = require("node:fs");
41
+ var import_promises = require("node:fs/promises");
42
+ var import_node_path = require("node:path");
43
+
44
+ // src/define-config.ts
45
+ function defineConfig(config) {
46
+ return config;
47
+ }
48
+
49
+ // src/config.ts
50
+ function resolveConfig(config = {}) {
51
+ const root = (0, import_node_path.resolve)(config.root ?? process.cwd());
52
+ return {
53
+ root,
54
+ ssr: config.ssr ?? true,
55
+ port: config.port ?? 3e3,
56
+ serverEntry: config.serverEntry ?? "src/entry-server.ts",
57
+ clientEntry: config.clientEntry ?? "src/entry-client.ts",
58
+ template: config.template ?? "index.html",
59
+ mountId: config.mountId ?? "root",
60
+ routesDir: config.routesDir ?? "src/routes",
61
+ apiDir: config.apiDir ?? "src/api",
62
+ middleware: config.middleware ?? "src/middleware.ts",
63
+ ssrNoExternal: config.ssrNoExternal ?? [],
64
+ resolve: config.resolve ?? [],
65
+ vitePlugin: config.vitePlugin ?? {},
66
+ plugins: config.plugins ?? [],
67
+ adapter: config.adapter,
68
+ i18n: resolveI18n(config.i18n),
69
+ prerender: resolvePrerender(config.prerender)
70
+ };
71
+ }
72
+ function resolvePrerender(prerender) {
73
+ if (!prerender) return false;
74
+ const opts = typeof prerender === "object" ? prerender : {};
75
+ return {
76
+ routes: opts.routes?.length ? opts.routes : ["/"],
77
+ crawl: opts.crawl ?? true
78
+ };
79
+ }
80
+ function resolveI18n(i18n) {
81
+ if (i18n === false) return false;
82
+ const opts = typeof i18n === "object" ? i18n : {};
83
+ return {
84
+ dir: opts.dir ?? "src/i18n",
85
+ defaultLocale: opts.defaultLocale,
86
+ locales: opts.locales
87
+ };
88
+ }
89
+ var CONFIG_NAMES = [
90
+ "fluixi.config.ts",
91
+ "fluixi.config.mts",
92
+ "fluixi.config.mjs",
93
+ "fluixi.config.js"
94
+ ];
95
+ async function loadConfig(root = process.cwd()) {
96
+ for (const name of CONFIG_NAMES) {
97
+ const file = (0, import_node_path.resolve)(root, name);
98
+ if ((0, import_node_fs.existsSync)(file)) return loadConfigFile(file);
99
+ }
100
+ return {};
101
+ }
102
+ async function loadConfigFile(file) {
103
+ if (!/\.[mc]?ts$/.test(file)) {
104
+ const mod = await import(
105
+ /* @vite-ignore */
106
+ (0, import_node_url.pathToFileURL)(file).href
107
+ );
108
+ return mod.default ?? mod;
109
+ }
110
+ const esbuild = await import("esbuild");
111
+ const { outputFiles } = await esbuild.build({
112
+ entryPoints: [file],
113
+ bundle: true,
114
+ write: false,
115
+ format: "esm",
116
+ platform: "node",
117
+ target: `node${process.versions.node.split(".")[0]}`,
118
+ sourcemap: "inline",
119
+ plugins: [
120
+ {
121
+ name: "fluixi:externalize-bare",
122
+ setup(b) {
123
+ b.onResolve({ filter: /.*/ }, (args) => {
124
+ if (args.kind === "entry-point") return null;
125
+ if (args.path.startsWith(".") || (0, import_node_path.isAbsolute)(args.path)) return null;
126
+ return { path: args.path, external: true };
127
+ });
128
+ }
129
+ }
130
+ ]
131
+ });
132
+ const tempFile = `${file}.timestamp-${Date.now()}-${Math.random().toString(16).slice(2)}.mjs`;
133
+ await (0, import_promises.writeFile)(tempFile, outputFiles[0].text);
134
+ try {
135
+ const mod = await import(
136
+ /* @vite-ignore */
137
+ (0, import_node_url.pathToFileURL)(tempFile).href
138
+ );
139
+ return mod.default ?? mod;
140
+ } finally {
141
+ await (0, import_promises.unlink)(tempFile).catch(() => {
142
+ });
143
+ }
144
+ }
145
+ // Annotate the CommonJS export names for ESM import in node:
146
+ 0 && (module.exports = {
147
+ defineConfig,
148
+ loadConfig,
149
+ resolveConfig
150
+ });
package/dist/config.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { Adapter } from './adapter.js';
2
2
  import type { ComponentResolverRule } from '@fluixi/compiler';
3
3
  /**
4
4
  * Fluixi app config. Place in `fluixi.config.{ts,js,mjs}` at the app root and wrap
5
- * with `defineConfig` for types. Everything is optional the defaults match the
5
+ * with `defineConfig` for types. Everything is optional, the defaults match the
6
6
  * conventional layout (src/entry-server.ts, src/entry-client.ts, index.html).
7
7
  */
8
8
  export interface FluixiConfig {
@@ -10,7 +10,7 @@ export interface FluixiConfig {
10
10
  root?: string;
11
11
  /**
12
12
  * Render mode. `true` (default) = SSR: the server entry renders HTML per request. `false`
13
- * = SPA: the server serves the static shell and the client renders but you still get the
13
+ * = SPA: the server serves the static shell and the client renders, but you still get the
14
14
  * full @fluixi/start server (file routing, middleware, env, and `/_server` server functions).
15
15
  * The same app code runs either way; flip this to choose where the first paint happens.
16
16
  */
@@ -31,7 +31,7 @@ export interface FluixiConfig {
31
31
  apiDir?: string;
32
32
  /** Request middleware module (default-exports `defineMiddleware([...])`). Default: src/middleware.ts */
33
33
  middleware?: string;
34
- /** SSR deps Vite must bundle (no-external) e.g. ESM packages without file extensions. */
34
+ /** SSR deps Vite must bundle (no-external), e.g. ESM packages without file extensions. */
35
35
  ssrNoExternal?: string[];
36
36
  /**
37
37
  * Where a capitalised tag with no import in scope comes from.
@@ -41,9 +41,26 @@ export interface FluixiConfig {
41
41
  * so a whole directory is one rule rather than a list to maintain.
42
42
  *
43
43
  * Only needed for tags you don't import. A `load:` directive works on your own import
44
- * too see the docs on load strategies.
44
+ * too: see the docs on load strategies.
45
45
  */
46
46
  resolve?: readonly ComponentResolverRule[];
47
+ /**
48
+ * Options handed to the fluixi vite plugin.
49
+ *
50
+ * A start app does not write `fluixi()` into a vite config, the framework adds the
51
+ * plugin itself, so this is where its options go: `propsDestructure`, and anything
52
+ * else the compiler takes. `resolve` above is the shorthand for the one most apps
53
+ * set, and wins over a `resolve` given here.
54
+ */
55
+ vitePlugin?: Record<string, unknown>;
56
+ /**
57
+ * Extra vite plugins, appended after the framework's own.
58
+ *
59
+ * A start app has no vite config of its own, so a plugin it needs but the framework
60
+ * does not ship, a css engine for instance, is declared here instead of forcing a
61
+ * second config file into the project.
62
+ */
63
+ plugins?: unknown[];
47
64
  /**
48
65
  * Deploy target. Decides how `fluixi build` bundles the server (see the adapter's
49
66
  * `bundle` mode) and how `fluixi start` serves it. Unset keeps Vite's own bundling
@@ -54,7 +71,7 @@ export interface FluixiConfig {
54
71
  * Built-in i18n auto-discovery. Scans `<dir>/<locale>.json` and exposes them as
55
72
  * `virtual:fluixi-i18n` (`{ messages, locales, defaultLocale }`) to feed `createI18n`.
56
73
  * `false` disables it; an object configures the folder / locales / default. Default: enabled
57
- * with `src/i18n` a no-op until that folder has `*.json` files, so it's effectively opt-in.
74
+ * with `src/i18n`: a no-op until that folder has `*.json` files, so it's effectively opt-in.
58
75
  */
59
76
  i18n?: boolean | {
60
77
  dir?: string;
@@ -91,13 +108,13 @@ export type ResolvedConfig = Required<Omit<FluixiConfig, 'ssrNoExternal' | 'i18n
91
108
  adapter?: Adapter;
92
109
  };
93
110
  /** Identity helper for editor types in `fluixi.config.ts`. */
94
- export declare function defineConfig(config: FluixiConfig): FluixiConfig;
111
+ export { defineConfig } from './define-config.js';
95
112
  /** Apply defaults. */
96
113
  export declare function resolveConfig(config?: FluixiConfig): ResolvedConfig;
97
114
  /**
98
115
  * Load `fluixi.config.{ts,mts,mjs,js}` from the app root. TypeScript configs are
99
116
  * bundled on the fly with esbuild and imported; plain ESM is imported directly.
100
- * No config is fine too every field has a default.
117
+ * No config is fine too: every field has a default.
101
118
  */
102
119
  export declare function loadConfig(root?: string): Promise<FluixiConfig>;
103
120
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE9D;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6GAA6G;IAC7G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wGAAwG;IACxG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2FAA2F;IAC3F,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC9E;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC9D;AAED,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,sDAAsD;AACtD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,CACnC,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC,CACvE,GAAG;IACF,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,EAAE,YAAY,GAAG,KAAK,CAAC;IAC3B,SAAS,EAAE,iBAAiB,GAAG,KAAK,CAAC;IACrC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAE/D;AAED,sBAAsB;AACtB,wBAAgB,aAAa,CAAC,MAAM,GAAE,YAAiB,GAAG,cAAc,CAmBvE;AAgCD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,SAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAM5E"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE9D;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6GAA6G;IAC7G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wGAAwG;IACxG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0FAA0F;IAC1F,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC9E;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC9D;AAED,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,sDAAsD;AACtD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,CACnC,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC,CACvE,GAAG;IACF,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,EAAE,YAAY,GAAG,KAAK,CAAC;IAC3B,SAAS,EAAE,iBAAiB,GAAG,KAAK,CAAC;IACrC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,8DAA8D;AAG9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,sBAAsB;AACtB,wBAAgB,aAAa,CAAC,MAAM,GAAE,YAAiB,GAAG,cAAc,CAqBvE;AAgCD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,SAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAM5E"}