@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,393 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // src/api.ts
34
+ var api_exports = {};
35
+ __export(api_exports, {
36
+ API_VIRTUAL_MODULE: () => API_VIRTUAL_MODULE,
37
+ apiRoutesVitePlugin: () => apiRoutesVitePlugin,
38
+ derivePattern: () => derivePattern,
39
+ handleApi: () => handleApi,
40
+ isApiPath: () => isApiPath,
41
+ matchApiRoutes: () => matchApiRoutes
42
+ });
43
+ function derivePattern(rel, prefix = "/api") {
44
+ const segs = rel.split("/").filter(Boolean);
45
+ if (segs[segs.length - 1] === "index") segs.pop();
46
+ const keys = [];
47
+ let rank = 0;
48
+ const parts = segs.map((seg) => {
49
+ const catchAll = seg.match(/^\[\.\.\.(.+)\]$/);
50
+ if (catchAll) {
51
+ keys.push(catchAll[1]);
52
+ return "(.+)";
53
+ }
54
+ const param = seg.match(/^\[(.+)\]$/);
55
+ if (param) {
56
+ keys.push(param[1]);
57
+ rank += 1;
58
+ return "([^/]+)";
59
+ }
60
+ rank += 10;
61
+ return seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
62
+ });
63
+ return { source: `^${prefix}${parts.length ? "/" + parts.join("/") : ""}/?$`, keys, rank };
64
+ }
65
+ function isApiPath(pathname, prefix = "/api") {
66
+ return pathname === prefix || pathname.startsWith(prefix + "/");
67
+ }
68
+ function matchApiRoutes(routes, pathname) {
69
+ for (const r of [...routes].sort((a, b) => b.rank - a.rank)) {
70
+ const m = new RegExp(r.source).exec(pathname);
71
+ if (!m) continue;
72
+ const params = {};
73
+ r.keys.forEach((k, i) => params[k] = decodeURIComponent(m[i + 1] ?? ""));
74
+ return { mod: r.mod, params };
75
+ }
76
+ return null;
77
+ }
78
+ async function handleApi(routes, request, prefix = "/api") {
79
+ const pathname = new URL(request.url).pathname;
80
+ const match = matchApiRoutes(routes, pathname);
81
+ if (!match) return new Response("Not Found", { status: 404 });
82
+ const fn = match.mod[request.method];
83
+ if (typeof fn !== "function") {
84
+ const allow = METHODS.filter((m) => typeof match.mod[m] === "function").join(", ");
85
+ return new Response("Method Not Allowed", { status: 405, headers: allow ? { allow } : void 0 });
86
+ }
87
+ const out = await fn(request, { params: match.params });
88
+ if (out instanceof Response) return out;
89
+ return new Response(JSON.stringify(out ?? null), { headers: { "content-type": "application/json; charset=utf-8" } });
90
+ }
91
+ function scanFiles(dir, base = dir) {
92
+ let out = [];
93
+ let entries = [];
94
+ try {
95
+ entries = (0, import_node_fs.readdirSync)(dir);
96
+ } catch {
97
+ return out;
98
+ }
99
+ for (const name of entries) {
100
+ const full = (0, import_node_path.join)(dir, name);
101
+ if ((0, import_node_fs.statSync)(full).isDirectory()) out = out.concat(scanFiles(full, base));
102
+ else if (/\.(ts|tsx|js|mjs)$/.test(name) && !/\.(spec|test)\./.test(name)) out.push(full);
103
+ }
104
+ return out;
105
+ }
106
+ function apiRoutesVitePlugin(opts) {
107
+ let root = process.cwd();
108
+ const prefix = opts.prefix ?? "/api";
109
+ const id = "\0" + API_VMOD;
110
+ return {
111
+ name: "fluixi-api",
112
+ // Must beat node resolution: '@fluixi/start/api-routes' is a real file in this package,
113
+ // so without `pre` Vite resolves the typed stub and the generated table never loads ,
114
+ // the app builds and every API route 404s.
115
+ enforce: "pre",
116
+ configResolved(config) {
117
+ root = config.root || root;
118
+ },
119
+ resolveId(source) {
120
+ return source === API_VMOD || source === "@fluixi/start/api-routes" ? id : null;
121
+ },
122
+ load(source) {
123
+ if (source !== id) return null;
124
+ const dir = (0, import_node_path.resolve)(root, opts.dir);
125
+ const files = scanFiles(dir);
126
+ const imports = [];
127
+ const entries = [];
128
+ files.forEach((file, i) => {
129
+ const rel = (0, import_node_path.relative)(dir, file).replace(/\.(ts|tsx|js|mjs)$/, "").split(/[\\/]/).join("/");
130
+ const { source: src, keys, rank } = derivePattern(rel, prefix);
131
+ imports.push(`import * as _${i} from ${JSON.stringify(file)};`);
132
+ entries.push(`{ source: ${JSON.stringify(src)}, keys: ${JSON.stringify(keys)}, rank: ${rank}, mod: _${i} }`);
133
+ });
134
+ return `import { isApiPath, handleApi } from '@fluixi/start/api';
135
+ ${imports.join("\n")}
136
+ const routes = [${entries.join(",")}];
137
+ export const isApiRequest = (request) => isApiPath(new URL(request.url).pathname, ${JSON.stringify(prefix)});
138
+ export const handleApiRequest = (request) => handleApi(routes, request, ${JSON.stringify(prefix)});
139
+ `;
140
+ }
141
+ };
142
+ }
143
+ var import_node_fs, import_node_path, API_VMOD, METHODS, API_VIRTUAL_MODULE;
144
+ var init_api = __esm({
145
+ "src/api.ts"() {
146
+ "use strict";
147
+ import_node_fs = require("node:fs");
148
+ import_node_path = require("node:path");
149
+ API_VMOD = "virtual:fluixi-api";
150
+ METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"];
151
+ API_VIRTUAL_MODULE = API_VMOD;
152
+ }
153
+ });
154
+
155
+ // src/internal.ts
156
+ var internal_exports = {};
157
+ __export(internal_exports, {
158
+ I18N_VMOD: () => I18N_VMOD,
159
+ SERVER_FNS_VMOD: () => SERVER_FNS_VMOD,
160
+ fluixiPlugins: () => fluixiPlugins,
161
+ guardHandler: () => guardHandler,
162
+ i18nVitePlugin: () => i18nVitePlugin,
163
+ injectApp: () => injectApp,
164
+ injectAppAndHead: () => injectAppAndHead,
165
+ installCrashGuards: () => installCrashGuards,
166
+ loadServerEnv: () => loadServerEnv,
167
+ splitTemplate: () => splitTemplate,
168
+ startTypesPlugin: () => startTypesPlugin
169
+ });
170
+ module.exports = __toCommonJS(internal_exports);
171
+ var import_node_fs2 = require("node:fs");
172
+ var import_node_path2 = require("node:path");
173
+
174
+ // src/document.ts
175
+ var import_head = require("@fluixi/head");
176
+ function injectApp(template, appHtml, mountId = "root") {
177
+ const mount = new RegExp(`<div id=["']${mountId}["']\\s*>\\s*</div>`);
178
+ if (mount.test(template)) {
179
+ return template.replace(mount, `<div id="${mountId}">${appHtml}</div>`);
180
+ }
181
+ if (template.includes("<!--ssr-outlet-->")) {
182
+ return template.replace("<!--ssr-outlet-->", appHtml);
183
+ }
184
+ return template.replace("</body>", `<div id="${mountId}">${appHtml}</div></body>`);
185
+ }
186
+ function splitTemplate(template, mountId = "root") {
187
+ const mount = new RegExp(`<div id=["']${mountId}["']\\s*>\\s*</div>`);
188
+ const m = template.match(mount);
189
+ if (m && m.index !== void 0) {
190
+ return {
191
+ head: template.slice(0, m.index) + `<div id="${mountId}">`,
192
+ tail: `</div>` + template.slice(m.index + m[0].length)
193
+ };
194
+ }
195
+ const outlet = template.indexOf("<!--ssr-outlet-->");
196
+ if (outlet !== -1) {
197
+ return {
198
+ head: template.slice(0, outlet),
199
+ tail: template.slice(outlet + "<!--ssr-outlet-->".length)
200
+ };
201
+ }
202
+ const body = template.indexOf("</body>");
203
+ if (body !== -1) {
204
+ return {
205
+ head: template.slice(0, body) + `<div id="${mountId}">`,
206
+ tail: `</div>` + template.slice(body)
207
+ };
208
+ }
209
+ return { head: template, tail: "" };
210
+ }
211
+ function setHtmlAttr(html, name, value) {
212
+ const existing = new RegExp(`(<html\\b[^>]*?)\\s${name}="[^"]*"`, "i");
213
+ if (existing.test(html)) return html.replace(existing, `$1 ${name}="${value}"`);
214
+ return html.replace(/<html\b/i, `<html ${name}="${value}"`);
215
+ }
216
+ function injectAppAndHead(template, rendered, mountId = "root") {
217
+ const { head, body } = (0, import_head.extractHeadMarker)(rendered);
218
+ let html = injectApp(template, body, mountId);
219
+ if (head) {
220
+ if (head.headHtml) {
221
+ if (/<title[\s>]/i.test(head.headHtml)) html = html.replace(/<title>[\s\S]*?<\/title>/i, "");
222
+ html = html.replace("</head>", `${head.headHtml}</head>`);
223
+ }
224
+ for (const [k, v] of Object.entries(head.htmlAttrs)) html = setHtmlAttr(html, k, v);
225
+ }
226
+ return html;
227
+ }
228
+ function guardHandler(handler, onError) {
229
+ return async (request) => {
230
+ try {
231
+ return await handler(request);
232
+ } catch (e) {
233
+ onError?.(e);
234
+ return new Response(String(e?.stack || e), {
235
+ status: 500,
236
+ headers: { "content-type": "text/plain; charset=utf-8" }
237
+ });
238
+ }
239
+ };
240
+ }
241
+
242
+ // src/internal.ts
243
+ var SERVER_FNS_VMOD = "virtual:fluixi-server-fns";
244
+ var I18N_VMOD = "virtual:fluixi-i18n";
245
+ function i18nVitePlugin(opts) {
246
+ let root = process.cwd();
247
+ const id = "\0" + I18N_VMOD;
248
+ return {
249
+ name: "fluixi-i18n",
250
+ configResolved(config) {
251
+ root = config.root || root;
252
+ },
253
+ resolveId(source) {
254
+ return source === I18N_VMOD ? id : null;
255
+ },
256
+ load(source) {
257
+ if (source !== id) return null;
258
+ const dir = (0, import_node_path2.resolve)(root, opts.dir);
259
+ let files = [];
260
+ try {
261
+ files = (0, import_node_fs2.readdirSync)(dir).filter((f) => f.endsWith(".json"));
262
+ } catch {
263
+ }
264
+ const discovered = files.map((f) => f.replace(/\.json$/, "")).sort();
265
+ const locales = opts.locales?.length ? opts.locales : discovered;
266
+ const defaultLocale = opts.defaultLocale ?? locales[0] ?? "en";
267
+ const imports = locales.map((l, i) => `import _${i} from ${JSON.stringify((0, import_node_path2.resolve)(dir, l + ".json"))};`).join("\n");
268
+ const messages = `export const messages = {${locales.map((l, i) => `${JSON.stringify(l)}:_${i}`).join(",")}};`;
269
+ return `${imports}
270
+ export const locales = ${JSON.stringify(locales)};
271
+ export const defaultLocale = ${JSON.stringify(defaultLocale)};
272
+ ${messages}
273
+ `;
274
+ }
275
+ };
276
+ }
277
+ async function loadServerEnv(root, mode) {
278
+ const { loadEnv } = await import("vite");
279
+ const env = loadEnv(mode, root, "");
280
+ for (const [k, v] of Object.entries(env)) {
281
+ if (process.env[k] === void 0) process.env[k] = v;
282
+ }
283
+ }
284
+ function i18nTypeBlock(root, i18n) {
285
+ const dir = (0, import_node_path2.resolve)(root, i18n.dir);
286
+ let discovered = [];
287
+ try {
288
+ discovered = (0, import_node_fs2.readdirSync)(dir).filter((f) => f.endsWith(".json")).map((f) => f.replace(/\.json$/, "")).sort();
289
+ } catch {
290
+ }
291
+ const locales = i18n.locales?.length ? i18n.locales : discovered;
292
+ const defaultLocale = i18n.defaultLocale ?? locales[0] ?? "en";
293
+ const typed = locales.length > 0 && locales.every((l) => discovered.includes(l));
294
+ if (!typed) {
295
+ return [
296
+ `declare module 'virtual:fluixi-i18n' {`,
297
+ ` export const messages: Record<string, Record<string, unknown>>;`,
298
+ ` export const locales: string[];`,
299
+ ` export const defaultLocale: string;`,
300
+ `}`
301
+ ];
302
+ }
303
+ const srcDir = (0, import_node_path2.resolve)(root, "src");
304
+ const toSpec = (l) => {
305
+ const rel = (0, import_node_path2.relative)(srcDir, (0, import_node_path2.resolve)(dir, l + ".json")).split(/[\\/]/).join("/");
306
+ return rel.startsWith(".") ? rel : "./" + rel;
307
+ };
308
+ const entries = locales.map((l) => ` ${JSON.stringify(l)}: (typeof import(${JSON.stringify(toSpec(l))}))['default'];`);
309
+ const tuple = locales.map((l) => JSON.stringify(l)).join(", ");
310
+ return [
311
+ `declare module 'virtual:fluixi-i18n' {`,
312
+ ` export const messages: {`,
313
+ ...entries,
314
+ ` };`,
315
+ ` export const locales: readonly [${tuple}];`,
316
+ ` export const defaultLocale: ${JSON.stringify(defaultLocale)};`,
317
+ `}`
318
+ ];
319
+ }
320
+ function startTypesPlugin(cfg) {
321
+ let root = process.cwd();
322
+ return {
323
+ name: "fluixi-start-types",
324
+ configResolved(config) {
325
+ root = config.root || root;
326
+ },
327
+ buildStart() {
328
+ const blocks = [];
329
+ if (cfg.i18n) blocks.push(...i18nTypeBlock(root, cfg.i18n));
330
+ if (blocks.length === 0) return;
331
+ const content = `// Auto-generated by @fluixi/start, do not edit.
332
+ ${blocks.join("\n")}
333
+ `;
334
+ const file = (0, import_node_path2.resolve)(root, "src/fluixi-start-env.d.ts");
335
+ try {
336
+ if (!(0, import_node_fs2.existsSync)(file) || (0, import_node_fs2.readFileSync)(file, "utf8") !== content) (0, import_node_fs2.writeFileSync)(file, content);
337
+ } catch {
338
+ }
339
+ }
340
+ };
341
+ }
342
+ async function fluixiPlugins(cfg) {
343
+ const { fluixi, fluixiRoutesPlugin } = await import("@fluixi/core/plugins");
344
+ const { serverFunctionsVitePlugin } = await import("@fluixi/compiler/integrations");
345
+ const plugins = [
346
+ serverFunctionsVitePlugin(),
347
+ fluixiRoutesPlugin({ routesDir: cfg.routesDir, polyfills: false }),
348
+ // The app's component-resolution rules reach the compiler here; without this an SSR
349
+ // app has no way to say where an unimported tag comes from.
350
+ //
351
+ // `fluixi()` and not `createVitePlugin()`: the latter is the bare compiler integration,
352
+ // and the reactive graph: agent, source marks, /__fluixi/graph, is composed on top of
353
+ // it by the former. A start app got no graph at all until this changed.
354
+ // Everything the app declared for the compiler, with `resolve` still usable on its
355
+ // own because it is the one most apps set. A start app never writes
356
+ // `fluixi()` itself, so without this passthrough the plugin's other options
357
+ // (propsDestructure and the rest) had nowhere to be declared.
358
+ fluixi({ ...cfg.vitePlugin ?? {}, ...cfg.resolve ? { resolve: cfg.resolve } : {} })
359
+ ];
360
+ if (cfg.plugins?.length) plugins.push(...cfg.plugins);
361
+ if (cfg.i18n) plugins.push(i18nVitePlugin(cfg.i18n));
362
+ const { apiRoutesVitePlugin: apiRoutesVitePlugin2 } = await Promise.resolve().then(() => (init_api(), api_exports));
363
+ plugins.push(apiRoutesVitePlugin2({ dir: cfg.apiDir }));
364
+ plugins.push(startTypesPlugin(cfg));
365
+ return plugins;
366
+ }
367
+ var _guardsInstalled = false;
368
+ function installCrashGuards() {
369
+ if (_guardsInstalled) return;
370
+ _guardsInstalled = true;
371
+ process.on(
372
+ "unhandledRejection",
373
+ (reason) => console.warn("[fluixi] unhandled rejection (backend likely down) —", reason?.message || reason)
374
+ );
375
+ process.on(
376
+ "uncaughtException",
377
+ (err) => console.warn("[fluixi] uncaught exception —", err?.message || err)
378
+ );
379
+ }
380
+ // Annotate the CommonJS export names for ESM import in node:
381
+ 0 && (module.exports = {
382
+ I18N_VMOD,
383
+ SERVER_FNS_VMOD,
384
+ fluixiPlugins,
385
+ guardHandler,
386
+ i18nVitePlugin,
387
+ injectApp,
388
+ injectAppAndHead,
389
+ installCrashGuards,
390
+ loadServerEnv,
391
+ splitTemplate,
392
+ startTypesPlugin
393
+ });
@@ -5,7 +5,7 @@ export declare const SERVER_FNS_VMOD = "virtual:fluixi-server-fns";
5
5
  export declare const I18N_VMOD = "virtual:fluixi-i18n";
6
6
  /**
7
7
  * Auto-discover translations. Scans `<dir>/<locale>.json` (e.g. `src/i18n/en.json`, `fr.json`)
8
- * and provides `virtual:fluixi-i18n` exporting `{ messages, locales, defaultLocale }` wire it
8
+ * and provides `virtual:fluixi-i18n` exporting `{ messages, locales, defaultLocale }`, wire it
9
9
  * into the built-in i18n in one line:
10
10
  *
11
11
  * import { createI18n } from '@fluixi/core/i18n';
@@ -20,12 +20,12 @@ export declare function i18nVitePlugin(opts: {
20
20
  locales?: string[];
21
21
  }): any;
22
22
  /**
23
- * Load env files into `process.env` for SERVER code the framework's environment manager.
23
+ * Load env files into `process.env` for SERVER code, the framework's environment manager.
24
24
  *
25
25
  * SECURITY MODEL (Vite-aligned): only `VITE_`-prefixed vars are exposed to the client (via
26
26
  * `import.meta.env`, inlined into the browser bundle). Everything else is server-only. This
27
27
  * loads ALL vars (`.env`, `.env.local`, `.env.[mode]`, `.env.[mode].local`) into `process.env`
28
- * so loaders + `"use server"` functions can read secrets WITHOUT ever exposing non-`VITE_`
28
+ * so loaders + `"use server"` functions can read secrets, WITHOUT ever exposing non-`VITE_`
29
29
  * vars to the browser. A real (OS) env var always wins, so deploys/secret managers override files.
30
30
  *
31
31
  * Result: `process.env.STRIPE_SECRET` works on the server and never ships to the web; only
@@ -36,14 +36,14 @@ export declare function loadServerEnv(root: string, mode: string): Promise<void>
36
36
  * Auto-generate ambient TypeScript declarations for @fluixi/start's virtual modules
37
37
  * (`virtual:fluixi-server-fns`, `virtual:fluixi-i18n`) into `src/fluixi-start-env.d.ts`, the
38
38
  * way the routes plugin writes `fluixi-env.d.ts`. So apps NEVER hand-write these `declare
39
- * module` blocks the modules AND their types are both generated. Idempotent (only writes on
39
+ * module` blocks: the modules AND their types are both generated. Idempotent (only writes on
40
40
  * change), runs in dev + build.
41
41
  */
42
42
  export declare function startTypesPlugin(cfg: ResolvedConfig): any;
43
43
  /**
44
44
  * The fluixi build plugins @fluixi/start provides by default: file-based routing
45
45
  * (fluixiRoutesPlugin → virtual:fluixi-routes) + the JSX/SSR transform
46
- * (createVitePlugin). This is what makes start "sit on top of fluixi" apps get
46
+ * (createVitePlugin). This is what makes start "sit on top of fluixi", apps get
47
47
  * zero-config routing + SSR. Apps using `fluixi dev|build` should therefore NOT add
48
48
  * these to their own vite.config (start owns them); keep vite.config for app-specific
49
49
  * bits only (optimizeDeps, ssr.noExternal via config, etc.).
@@ -52,7 +52,7 @@ export declare function fluixiPlugins(cfg: ResolvedConfig): Promise<any[]>;
52
52
  export { injectApp, splitTemplate, injectAppAndHead, guardHandler, } from './document.js';
53
53
  /**
54
54
  * A render fires the route's data fetches eagerly; if the backend is down those
55
- * promises can reject AFTER we've already responded, with nothing awaiting them
55
+ * promises can reject AFTER we've already responded, with nothing awaiting them ,
56
56
  * a floating rejection would kill the dev server. Swallow + log instead.
57
57
  */
58
58
  export declare function installCrashGuards(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,6FAA6F;AAC7F,eAAO,MAAM,eAAe,8BAA8B,CAAC;AAE3D,wGAAwG;AACxG,eAAO,MAAM,SAAS,wBAAwB,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,GAAG,CAoCrG;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7E;AA6DD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,GAAG,CA0BzD;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CA0BvE;AAED,OAAO,EACL,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,YAAY,GACb,MAAM,eAAe,CAAC;AAIvB;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CASzC"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,6FAA6F;AAC7F,eAAO,MAAM,eAAe,8BAA8B,CAAC;AAE3D,wGAAwG;AACxG,eAAO,MAAM,SAAS,wBAAwB,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,GAAG,CAoCrG;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7E;AA6DD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,GAAG,CA0BzD;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAiCvE;AAED,OAAO,EACL,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,YAAY,GACb,MAAM,eAAe,CAAC;AAIvB;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CASzC"}
package/dist/internal.js CHANGED
@@ -6,7 +6,7 @@ export const SERVER_FNS_VMOD = 'virtual:fluixi-server-fns';
6
6
  export const I18N_VMOD = 'virtual:fluixi-i18n';
7
7
  /**
8
8
  * Auto-discover translations. Scans `<dir>/<locale>.json` (e.g. `src/i18n/en.json`, `fr.json`)
9
- * and provides `virtual:fluixi-i18n` exporting `{ messages, locales, defaultLocale }` wire it
9
+ * and provides `virtual:fluixi-i18n` exporting `{ messages, locales, defaultLocale }`, wire it
10
10
  * into the built-in i18n in one line:
11
11
  *
12
12
  * import { createI18n } from '@fluixi/core/i18n';
@@ -53,12 +53,12 @@ export function i18nVitePlugin(opts) {
53
53
  };
54
54
  }
55
55
  /**
56
- * Load env files into `process.env` for SERVER code the framework's environment manager.
56
+ * Load env files into `process.env` for SERVER code, the framework's environment manager.
57
57
  *
58
58
  * SECURITY MODEL (Vite-aligned): only `VITE_`-prefixed vars are exposed to the client (via
59
59
  * `import.meta.env`, inlined into the browser bundle). Everything else is server-only. This
60
60
  * loads ALL vars (`.env`, `.env.local`, `.env.[mode]`, `.env.[mode].local`) into `process.env`
61
- * so loaders + `"use server"` functions can read secrets WITHOUT ever exposing non-`VITE_`
61
+ * so loaders + `"use server"` functions can read secrets, WITHOUT ever exposing non-`VITE_`
62
62
  * vars to the browser. A real (OS) env var always wins, so deploys/secret managers override files.
63
63
  *
64
64
  * Result: `process.env.STRIPE_SECRET` works on the server and never ships to the web; only
@@ -73,12 +73,12 @@ export async function loadServerEnv(root, mode) {
73
73
  }
74
74
  }
75
75
  /**
76
- * Build the `declare module 'virtual:fluixi-i18n'` block TYPED off the actual JSON files
76
+ * Build the `declare module 'virtual:fluixi-i18n'` block, TYPED off the actual JSON files
77
77
  * so `createI18n({ messages })` infers translation keys end-to-end from auto-discovery.
78
78
  *
79
79
  * Instead of typing `messages` as `Record<string, unknown>` (which erases keys), we reference
80
80
  * each `<locale>.json` via `(typeof import('./i18n/en.json'))['default']`. TS reads the JSON's
81
- * real shape, so `t('…')` autocompletes keys discovered from `src/i18n/*.json` no codegen of
81
+ * real shape, so `t('…')` autocompletes keys discovered from `src/i18n/*.json`, no codegen of
82
82
  * the key union, the compiler derives it. Falls back to the loose shape when no files exist yet
83
83
  * (or a configured locale has no file), keeping the module typed-but-open rather than broken.
84
84
  *
@@ -130,7 +130,7 @@ function i18nTypeBlock(root, i18n) {
130
130
  * Auto-generate ambient TypeScript declarations for @fluixi/start's virtual modules
131
131
  * (`virtual:fluixi-server-fns`, `virtual:fluixi-i18n`) into `src/fluixi-start-env.d.ts`, the
132
132
  * way the routes plugin writes `fluixi-env.d.ts`. So apps NEVER hand-write these `declare
133
- * module` blocks the modules AND their types are both generated. Idempotent (only writes on
133
+ * module` blocks: the modules AND their types are both generated. Idempotent (only writes on
134
134
  * change), runs in dev + build.
135
135
  */
136
136
  export function startTypesPlugin(cfg) {
@@ -145,21 +145,21 @@ export function startTypesPlugin(cfg) {
145
145
  // have fixed signatures, so they moved to real package entries
146
146
  // (`@fluixi/start/server-fns`, `@fluixi/start/api-routes`) whose types ship with the
147
147
  // package. i18n cannot follow: its `messages` type is derived from the app's own JSON
148
- // (`typeof import('./i18n/en.json')`) and its `locales` is a literal tuple that is
148
+ // (`typeof import('./i18n/en.json')`) and its `locales` is a literal tuple, that is
149
149
  // what makes keys autocomplete, and no static entry can express it.
150
150
  const blocks = [];
151
151
  if (cfg.i18n)
152
152
  blocks.push(...i18nTypeBlock(root, cfg.i18n));
153
153
  if (blocks.length === 0)
154
- return; // no i18n configured nothing left to declare
155
- const content = `// Auto-generated by @fluixi/start do not edit.\n${blocks.join('\n')}\n`;
154
+ return; // no i18n configured: nothing left to declare
155
+ const content = `// Auto-generated by @fluixi/start, do not edit.\n${blocks.join('\n')}\n`;
156
156
  const file = resolvePath(root, 'src/fluixi-start-env.d.ts');
157
157
  try {
158
158
  if (!existsSync(file) || readFileSync(file, 'utf8') !== content)
159
159
  writeFileSync(file, content);
160
160
  }
161
161
  catch {
162
- /* read-only fs (some CI) types are a dev convenience, build still works */
162
+ /* read-only fs (some CI), types are a dev convenience, build still works */
163
163
  }
164
164
  },
165
165
  };
@@ -167,7 +167,7 @@ export function startTypesPlugin(cfg) {
167
167
  /**
168
168
  * The fluixi build plugins @fluixi/start provides by default: file-based routing
169
169
  * (fluixiRoutesPlugin → virtual:fluixi-routes) + the JSX/SSR transform
170
- * (createVitePlugin). This is what makes start "sit on top of fluixi" apps get
170
+ * (createVitePlugin). This is what makes start "sit on top of fluixi", apps get
171
171
  * zero-config routing + SSR. Apps using `fluixi dev|build` should therefore NOT add
172
172
  * these to their own vite.config (start owns them); keep vite.config for app-specific
173
173
  * bits only (optimizeDeps, ssr.noExternal via config, etc.).
@@ -175,7 +175,7 @@ export function startTypesPlugin(cfg) {
175
175
  export async function fluixiPlugins(cfg) {
176
176
  const { fluixi, fluixiRoutesPlugin } = await import('@fluixi/core/plugins');
177
177
  const { serverFunctionsVitePlugin } = await import('@fluixi/compiler/integrations');
178
- // polyfills:false the meta-framework is SSR-first; the browser node-polyfill shims
178
+ // polyfills:false: the meta-framework is SSR-first; the browser node-polyfill shims
179
179
  // break server rendering. Apps that need Buffer/process in the browser opt in later.
180
180
  // serverFunctionsVitePlugin applies the "use server" transform (client RPC stub /
181
181
  // server registration) per-build via the ssr flag.
@@ -186,10 +186,18 @@ export async function fluixiPlugins(cfg) {
186
186
  // app has no way to say where an unimported tag comes from.
187
187
  //
188
188
  // `fluixi()` and not `createVitePlugin()`: the latter is the bare compiler integration,
189
- // and the reactive graph agent, source marks, /__fluixi/graph is composed on top of
189
+ // and the reactive graph: agent, source marks, /__fluixi/graph, is composed on top of
190
190
  // it by the former. A start app got no graph at all until this changed.
191
- fluixi({ resolve: cfg.resolve }),
191
+ // Everything the app declared for the compiler, with `resolve` still usable on its
192
+ // own because it is the one most apps set. A start app never writes
193
+ // `fluixi()` itself, so without this passthrough the plugin's other options
194
+ // (propsDestructure and the rest) had nowhere to be declared.
195
+ fluixi({ ...(cfg.vitePlugin ?? {}), ...(cfg.resolve ? { resolve: cfg.resolve } : {}) }),
192
196
  ];
197
+ // The app's own, after the framework's: a plugin that transforms css or assets runs
198
+ // on what the framework produced rather than racing it.
199
+ if (cfg.plugins?.length)
200
+ plugins.push(...cfg.plugins);
193
201
  // Auto-discover translations (src/i18n/<locale>.json → virtual:fluixi-i18n) unless disabled.
194
202
  if (cfg.i18n)
195
203
  plugins.push(i18nVitePlugin(cfg.i18n));
@@ -204,7 +212,7 @@ export { injectApp, splitTemplate, injectAppAndHead, guardHandler, } from './doc
204
212
  let _guardsInstalled = false;
205
213
  /**
206
214
  * A render fires the route's data fetches eagerly; if the backend is down those
207
- * promises can reject AFTER we've already responded, with nothing awaiting them
215
+ * promises can reject AFTER we've already responded, with nothing awaiting them ,
208
216
  * a floating rejection would kill the dev server. Swallow + log instead.
209
217
  */
210
218
  export function installCrashGuards() {