@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.
- package/dist/adapter.cjs +750 -0
- package/dist/adapter.d.ts +9 -9
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +10 -10
- package/dist/adapter.mjs +719 -0
- package/dist/adapters/entry.cjs +122 -0
- package/dist/adapters/entry.js +1 -1
- package/dist/adapters/entry.mjs +95 -0
- package/dist/adapters/platforms.cjs +311 -0
- package/dist/adapters/platforms.d.ts +2 -2
- package/dist/adapters/platforms.js +8 -8
- package/dist/adapters/platforms.mjs +284 -0
- package/dist/api-HD7KU3BS.mjs +114 -0
- package/dist/api.cjs +145 -0
- package/dist/api.js +1 -1
- package/dist/api.mjs +116 -0
- package/dist/commands/api-HD7KU3BS.mjs +114 -0
- package/dist/commands/api-PBT4QZ34.mjs +16 -0
- package/dist/commands/api-PJL37LV3.mjs +17 -0
- package/dist/commands/build.cjs +877 -0
- package/dist/commands/build.js +6 -6
- package/dist/commands/build.mjs +717 -0
- package/dist/commands/chunk-GFQ4MUIC.mjs +117 -0
- package/dist/commands/chunk-MTM6M3TC.mjs +115 -0
- package/dist/commands/dev.cjs +670 -0
- package/dist/commands/dev.js +3 -3
- package/dist/commands/dev.mjs +512 -0
- package/dist/commands/index.cjs +1145 -0
- package/dist/commands/index.d.ts +1 -1
- package/dist/commands/index.js +1 -1
- package/dist/commands/index.mjs +982 -0
- package/dist/commands/prerender.cjs +404 -0
- package/dist/commands/prerender.d.ts +1 -1
- package/dist/commands/prerender.js +2 -2
- package/dist/commands/prerender.mjs +377 -0
- package/dist/commands/start.cjs +463 -0
- package/dist/commands/start.d.ts +1 -1
- package/dist/commands/start.js +2 -2
- package/dist/commands/start.mjs +428 -0
- package/dist/config.cjs +150 -0
- package/dist/config.d.ts +24 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -6
- package/dist/config.mjs +114 -0
- package/dist/define-config.cjs +32 -0
- package/dist/define-config.d.ts +12 -0
- package/dist/define-config.d.ts.map +1 -0
- package/dist/define-config.js +3 -0
- package/dist/define-config.mjs +7 -0
- package/dist/di.cjs +200 -0
- package/dist/di.d.ts +4 -4
- package/dist/di.d.ts.map +1 -1
- package/dist/di.js +9 -9
- package/dist/di.mjs +169 -0
- package/dist/document.cjs +115 -0
- package/dist/document.d.ts +1 -1
- package/dist/document.js +1 -1
- package/dist/document.mjs +86 -0
- package/dist/generated-api.cjs +43 -0
- package/dist/generated-api.js +1 -1
- package/dist/generated-api.mjs +18 -0
- package/dist/generated-server-fns.cjs +43 -0
- package/dist/generated-server-fns.mjs +18 -0
- package/dist/handler-core.cjs +211 -0
- package/dist/handler-core.d.ts +2 -2
- package/dist/handler-core.js +2 -2
- package/dist/handler-core.mjs +185 -0
- package/dist/handler.cjs +182 -0
- package/dist/handler.d.ts +3 -3
- package/dist/handler.js +3 -3
- package/dist/handler.mjs +152 -0
- package/dist/head.cjs +25 -0
- package/dist/head.d.ts +1 -1
- package/dist/head.js +1 -1
- package/dist/head.mjs +4 -0
- package/dist/image-loader.cjs +37 -0
- package/dist/image-loader.d.ts +25 -0
- package/dist/image-loader.d.ts.map +1 -0
- package/dist/image-loader.js +18 -0
- package/dist/image-loader.mjs +12 -0
- package/dist/image.cjs +151 -0
- package/dist/image.d.ts +2 -19
- package/dist/image.d.ts.map +1 -1
- package/dist/image.js +5 -21
- package/dist/image.mjs +126 -0
- package/dist/index.cjs +303 -0
- package/dist/index.d.ts +28 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -17
- package/dist/index.mjs +262 -0
- package/dist/interceptors.cjs +72 -0
- package/dist/interceptors.js +1 -1
- package/dist/interceptors.mjs +44 -0
- package/dist/internal.cjs +393 -0
- package/dist/internal.d.ts +6 -6
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +23 -15
- package/dist/internal.mjs +223 -0
- package/dist/middleware.cjs +58 -0
- package/dist/middleware.d.ts +3 -3
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +1 -1
- package/dist/middleware.mjs +31 -0
- package/dist/preload.cjs +42 -0
- package/dist/preload.js +1 -1
- package/dist/preload.mjs +18 -0
- package/dist/router.cjs +25 -0
- package/dist/router.d.ts +3 -3
- package/dist/router.js +3 -3
- package/dist/router.mjs +4 -0
- package/dist/server-fn-setup.cjs +46 -0
- package/dist/server-fn-setup.d.ts +1 -1
- package/dist/server-fn-setup.js +2 -2
- package/dist/server-fn-setup.mjs +22 -0
- package/dist/server-fn.cjs +109 -0
- package/dist/server-fn.d.ts +2 -2
- package/dist/server-fn.js +2 -2
- package/dist/server-fn.mjs +79 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/ui.cjs +123 -0
- package/dist/ui.js +1 -1
- package/dist/ui.mjs +93 -0
- 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
|
+
});
|
package/dist/internal.d.ts
CHANGED
|
@@ -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 }
|
|
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
|
|
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
|
|
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
|
|
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"
|
|
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;
|
package/dist/internal.d.ts.map
CHANGED
|
@@ -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,
|
|
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 }
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
155
|
-
const content = `// Auto-generated by @fluixi/start
|
|
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)
|
|
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"
|
|
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
|
|
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
|
|
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
|
-
|
|
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() {
|