@finesoft/front 0.1.12 → 0.1.14
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/app-MYBG3TGV.js +10 -0
- package/dist/app-MYBG3TGV.js.map +1 -0
- package/dist/browser.js +12 -10
- package/dist/chunk-2VETWTN5.js +88 -0
- package/dist/chunk-2VETWTN5.js.map +1 -0
- package/dist/chunk-FYP2ZYYV.js +25 -0
- package/dist/chunk-FYP2ZYYV.js.map +1 -0
- package/dist/{chunk-OVGQ4NUA.js → chunk-RVKDILGM.js} +2 -327
- package/dist/chunk-RVKDILGM.js.map +1 -0
- package/dist/chunk-T2AQHAYK.js +337 -0
- package/dist/chunk-T2AQHAYK.js.map +1 -0
- package/dist/chunk-Z4MHYAS3.js +108 -0
- package/dist/chunk-Z4MHYAS3.js.map +1 -0
- package/dist/index.cjs +1801 -833
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +202 -1
- package/dist/index.d.ts +202 -1
- package/dist/index.js +702 -170
- package/dist/index.js.map +1 -1
- package/dist/locale-YK3THSI6.js +7 -0
- package/dist/locale-YK3THSI6.js.map +1 -0
- package/dist/src-7D236CLJ.js +19 -0
- package/dist/src-7D236CLJ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-OVGQ4NUA.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
History,
|
|
3
|
+
createPrefetchedIntentsFromDom,
|
|
4
|
+
deserializeServerData,
|
|
5
|
+
registerActionHandlers,
|
|
6
|
+
registerExternalUrlHandler,
|
|
7
|
+
registerFlowActionHandler,
|
|
8
|
+
startBrowserApp,
|
|
9
|
+
tryScroll
|
|
10
|
+
} from "./chunk-T2AQHAYK.js";
|
|
11
|
+
import {
|
|
12
|
+
createSSRApp
|
|
13
|
+
} from "./chunk-Z4MHYAS3.js";
|
|
14
|
+
import {
|
|
15
|
+
SSR_PLACEHOLDERS,
|
|
16
|
+
createSSRRender,
|
|
17
|
+
injectSSRContent,
|
|
18
|
+
serializeServerData,
|
|
19
|
+
ssrRender
|
|
20
|
+
} from "./chunk-2VETWTN5.js";
|
|
1
21
|
import {
|
|
2
22
|
ACTION_KINDS,
|
|
3
23
|
ActionDispatcher,
|
|
@@ -10,7 +30,6 @@ import {
|
|
|
10
30
|
Container,
|
|
11
31
|
DEP_KEYS,
|
|
12
32
|
Framework,
|
|
13
|
-
History,
|
|
14
33
|
HttpClient,
|
|
15
34
|
HttpError,
|
|
16
35
|
IntentDispatcher,
|
|
@@ -18,9 +37,7 @@ import {
|
|
|
18
37
|
PrefetchedIntents,
|
|
19
38
|
Router,
|
|
20
39
|
buildUrl,
|
|
21
|
-
createPrefetchedIntentsFromDom,
|
|
22
40
|
defineRoutes,
|
|
23
|
-
deserializeServerData,
|
|
24
41
|
generateUuid,
|
|
25
42
|
getBaseUrl,
|
|
26
43
|
isCompoundAction,
|
|
@@ -34,206 +51,460 @@ import {
|
|
|
34
51
|
mapEach,
|
|
35
52
|
pipe,
|
|
36
53
|
pipeAsync,
|
|
37
|
-
registerActionHandlers,
|
|
38
|
-
registerExternalUrlHandler,
|
|
39
|
-
registerFlowActionHandler,
|
|
40
54
|
removeHost,
|
|
41
55
|
removeQueryParams,
|
|
42
56
|
removeScheme,
|
|
43
57
|
resetFilterCache,
|
|
44
58
|
shouldLog,
|
|
45
|
-
stableStringify
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
59
|
+
stableStringify
|
|
60
|
+
} from "./chunk-RVKDILGM.js";
|
|
61
|
+
import {
|
|
62
|
+
parseAcceptLanguage
|
|
63
|
+
} from "./chunk-FYP2ZYYV.js";
|
|
49
64
|
|
|
50
|
-
// ../
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
// ../server/src/adapters/shared.ts
|
|
66
|
+
var BUILD_TOOL_EXTERNALS = [
|
|
67
|
+
"vite",
|
|
68
|
+
"esbuild",
|
|
69
|
+
"rollup",
|
|
70
|
+
"fsevents",
|
|
71
|
+
"lightningcss"
|
|
72
|
+
];
|
|
73
|
+
function generateSSREntry(ctx, opts) {
|
|
74
|
+
const setupImport = ctx.setupPath ? `import _setupDefault from "./${ctx.setupPath}";` : ``;
|
|
75
|
+
const setupCall = ctx.setupPath ? `if (typeof _setupDefault === "function") await _setupDefault(app);` : ``;
|
|
76
|
+
const locales = JSON.stringify(ctx.locales);
|
|
77
|
+
const defaultLocale = JSON.stringify(ctx.defaultLocale);
|
|
78
|
+
return `
|
|
79
|
+
import { Hono } from "hono";
|
|
80
|
+
${opts.platformImport}
|
|
81
|
+
import { render, serializeServerData } from "./${ctx.ssrEntry}";
|
|
82
|
+
${setupImport}
|
|
83
|
+
|
|
84
|
+
const TEMPLATE = ${JSON.stringify(ctx.templateHtml)};
|
|
85
|
+
const LOCALES = ${locales};
|
|
86
|
+
const DEFAULT_LOCALE = ${defaultLocale};
|
|
87
|
+
|
|
88
|
+
function parseAcceptLanguage(header) {
|
|
89
|
+
if (!header) return DEFAULT_LOCALE;
|
|
90
|
+
const langs = header.split(",").map(p => {
|
|
91
|
+
const [l, q] = p.trim().split(";q=");
|
|
92
|
+
return { l: l.trim().toLowerCase(), q: q ? +q : 1 };
|
|
93
|
+
}).sort((a, b) => b.q - a.q);
|
|
94
|
+
for (const { l } of langs) {
|
|
95
|
+
const prefix = l.split("-")[0];
|
|
96
|
+
if (LOCALES.includes(prefix)) return prefix;
|
|
69
97
|
}
|
|
70
|
-
|
|
71
|
-
framework.dispose();
|
|
72
|
-
return {
|
|
73
|
-
html: result.html,
|
|
74
|
-
head: result.head,
|
|
75
|
-
css: result.css,
|
|
76
|
-
serverData
|
|
77
|
-
};
|
|
98
|
+
return DEFAULT_LOCALE;
|
|
78
99
|
}
|
|
79
100
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
bootstrap,
|
|
87
|
-
getErrorPage,
|
|
88
|
-
renderApp: (page) => renderApp(page, locale)
|
|
89
|
-
});
|
|
101
|
+
function injectSSR(t, locale, head, css, html, data) {
|
|
102
|
+
return t
|
|
103
|
+
.replace("<!--ssr-lang-->", locale)
|
|
104
|
+
.replace("<!--ssr-head-->", head + "\\n<style>" + css + "</style>")
|
|
105
|
+
.replace("<!--ssr-body-->", html)
|
|
106
|
+
.replace("<!--ssr-data-->", '<script id="serialized-server-data" type="application/json">' + data + "</script>");
|
|
90
107
|
}
|
|
91
108
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
109
|
+
const app = new Hono();
|
|
110
|
+
${setupCall}
|
|
111
|
+
|
|
112
|
+
app.get("*", async (c) => {
|
|
113
|
+
const url = c.req.path + (c.req.url.includes("?") ? "?" + c.req.url.split("?")[1] : "");
|
|
114
|
+
try {
|
|
115
|
+
const locale = parseAcceptLanguage(c.req.header("accept-language"));
|
|
116
|
+
const { html: appHtml, head, css, serverData } = await render(url, locale);
|
|
117
|
+
const serializedData = serializeServerData(serverData);
|
|
118
|
+
return c.html(injectSSR(TEMPLATE, locale, head, css, appHtml, serializedData));
|
|
119
|
+
} catch (e) {
|
|
120
|
+
console.error("[SSR Error]", e);
|
|
121
|
+
return c.text("Internal Server Error", 500);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
${opts.platformExport}
|
|
126
|
+
`;
|
|
127
|
+
}
|
|
128
|
+
async function buildBundle(ctx, opts) {
|
|
129
|
+
await ctx.vite.build({
|
|
130
|
+
root: ctx.root,
|
|
131
|
+
build: {
|
|
132
|
+
ssr: opts.entry,
|
|
133
|
+
outDir: opts.outDir,
|
|
134
|
+
emptyOutDir: true,
|
|
135
|
+
target: opts.target ?? "node18",
|
|
136
|
+
rollupOptions: {
|
|
137
|
+
output: { entryFileNames: opts.fileName ?? "index.mjs" }
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
ssr: {
|
|
141
|
+
noExternal: opts.noExternal !== false,
|
|
142
|
+
external: opts.external ?? BUILD_TOOL_EXTERNALS
|
|
143
|
+
},
|
|
144
|
+
resolve: ctx.resolvedResolve,
|
|
145
|
+
css: ctx.resolvedCss
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function copyStaticAssets(ctx, destDir, opts) {
|
|
149
|
+
const { fs, path } = ctx;
|
|
150
|
+
fs.cpSync(path.resolve(ctx.root, "dist/client"), destDir, {
|
|
151
|
+
recursive: true
|
|
152
|
+
});
|
|
153
|
+
if (opts?.excludeHtml !== false) {
|
|
154
|
+
fs.rmSync(path.join(destDir, "index.html"), { force: true });
|
|
155
|
+
}
|
|
107
156
|
}
|
|
108
157
|
|
|
109
|
-
// ../
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
158
|
+
// ../server/src/adapters/cloudflare.ts
|
|
159
|
+
function cloudflareAdapter() {
|
|
160
|
+
return {
|
|
161
|
+
name: "cloudflare",
|
|
162
|
+
async build(ctx) {
|
|
163
|
+
const { fs, path, root } = ctx;
|
|
164
|
+
const outputDir = path.resolve(root, "dist/cloudflare");
|
|
165
|
+
fs.rmSync(outputDir, { recursive: true, force: true });
|
|
166
|
+
const entrySource = generateSSREntry(ctx, {
|
|
167
|
+
platformImport: ``,
|
|
168
|
+
platformExport: `export default app;`
|
|
169
|
+
});
|
|
170
|
+
const tempEntry = path.resolve(root, ".cf-entry.tmp.mjs");
|
|
171
|
+
fs.writeFileSync(tempEntry, entrySource);
|
|
172
|
+
try {
|
|
173
|
+
await buildBundle(ctx, {
|
|
174
|
+
entry: ".cf-entry.tmp.mjs",
|
|
175
|
+
outDir: outputDir,
|
|
176
|
+
target: "es2022",
|
|
177
|
+
fileName: "_worker.js",
|
|
178
|
+
external: []
|
|
179
|
+
// CF Workers 需全部打包
|
|
180
|
+
});
|
|
181
|
+
copyStaticAssets(ctx, path.resolve(outputDir, "assets"));
|
|
182
|
+
} finally {
|
|
183
|
+
fs.rmSync(tempEntry, { force: true });
|
|
184
|
+
}
|
|
185
|
+
console.log(" Cloudflare output \u2192 dist/cloudflare/\n");
|
|
186
|
+
}
|
|
187
|
+
};
|
|
124
188
|
}
|
|
125
189
|
|
|
126
|
-
// ../server/src/
|
|
127
|
-
|
|
190
|
+
// ../server/src/adapters/netlify.ts
|
|
191
|
+
function netlifyAdapter() {
|
|
192
|
+
return {
|
|
193
|
+
name: "netlify",
|
|
194
|
+
async build(ctx) {
|
|
195
|
+
const { fs, path, root } = ctx;
|
|
196
|
+
const funcDir = path.resolve(
|
|
197
|
+
root,
|
|
198
|
+
".netlify/functions-internal/ssr"
|
|
199
|
+
);
|
|
200
|
+
fs.rmSync(path.resolve(root, ".netlify"), {
|
|
201
|
+
recursive: true,
|
|
202
|
+
force: true
|
|
203
|
+
});
|
|
204
|
+
const entrySource = generateSSREntry(ctx, {
|
|
205
|
+
platformImport: `import { handle } from "hono/netlify";`,
|
|
206
|
+
platformExport: `export default handle(app);`
|
|
207
|
+
});
|
|
208
|
+
const tempEntry = path.resolve(root, ".netlify-entry.tmp.mjs");
|
|
209
|
+
fs.writeFileSync(tempEntry, entrySource);
|
|
210
|
+
try {
|
|
211
|
+
await buildBundle(ctx, {
|
|
212
|
+
entry: ".netlify-entry.tmp.mjs",
|
|
213
|
+
outDir: funcDir,
|
|
214
|
+
target: "node18"
|
|
215
|
+
});
|
|
216
|
+
} finally {
|
|
217
|
+
fs.rmSync(tempEntry, { force: true });
|
|
218
|
+
}
|
|
219
|
+
const redirects = `/* /.netlify/functions/ssr 200
|
|
220
|
+
`;
|
|
221
|
+
fs.writeFileSync(
|
|
222
|
+
path.resolve(root, "dist/client/_redirects"),
|
|
223
|
+
redirects
|
|
224
|
+
);
|
|
225
|
+
console.log(
|
|
226
|
+
" Netlify output \u2192 .netlify/functions-internal/ssr/\n Publish dir: dist/client/\n"
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
128
231
|
|
|
129
|
-
// ../server/src/
|
|
130
|
-
function
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
232
|
+
// ../server/src/adapters/node.ts
|
|
233
|
+
function nodeAdapter() {
|
|
234
|
+
return {
|
|
235
|
+
name: "node",
|
|
236
|
+
async build(ctx) {
|
|
237
|
+
const { fs, path, root } = ctx;
|
|
238
|
+
const entrySource = generateSSREntry(ctx, {
|
|
239
|
+
platformImport: `import { serve } from "@hono/node-server";`,
|
|
240
|
+
platformExport: `
|
|
241
|
+
const port = +(process.env.PORT || 3000);
|
|
242
|
+
serve({ fetch: app.fetch, port }, (info) => {
|
|
243
|
+
console.log(\`Server running at http://localhost:\${info.port}\`);
|
|
244
|
+
});
|
|
245
|
+
`
|
|
246
|
+
});
|
|
247
|
+
const tempEntry = path.resolve(root, ".node-entry.tmp.mjs");
|
|
248
|
+
fs.writeFileSync(tempEntry, entrySource);
|
|
249
|
+
try {
|
|
250
|
+
await buildBundle(ctx, {
|
|
251
|
+
entry: ".node-entry.tmp.mjs",
|
|
252
|
+
outDir: path.resolve(root, "dist/server"),
|
|
253
|
+
target: "node18"
|
|
254
|
+
});
|
|
255
|
+
} finally {
|
|
256
|
+
fs.rmSync(tempEntry, { force: true });
|
|
257
|
+
}
|
|
258
|
+
console.log(
|
|
259
|
+
" Node output \u2192 dist/server/index.mjs\n Run: node dist/server/index.mjs\n"
|
|
260
|
+
);
|
|
145
261
|
}
|
|
146
|
-
}
|
|
147
|
-
return effectiveFallback;
|
|
262
|
+
};
|
|
148
263
|
}
|
|
149
264
|
|
|
150
|
-
// ../server/src/
|
|
151
|
-
function
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
} = options;
|
|
161
|
-
const app = new Hono();
|
|
162
|
-
async function readTemplate(url) {
|
|
163
|
-
if (!isProduction && vite) {
|
|
164
|
-
const { readFileSync: readFileSync2 } = await import(
|
|
265
|
+
// ../server/src/adapters/static.ts
|
|
266
|
+
function staticAdapter(opts = {}) {
|
|
267
|
+
return {
|
|
268
|
+
name: "static",
|
|
269
|
+
async build(ctx) {
|
|
270
|
+
const { fs, path, root, vite } = ctx;
|
|
271
|
+
const outputDir = path.resolve(root, "dist/static");
|
|
272
|
+
fs.rmSync(outputDir, { recursive: true, force: true });
|
|
273
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
274
|
+
const { pathToFileURL } = await import(
|
|
165
275
|
/* @vite-ignore */
|
|
166
|
-
"
|
|
276
|
+
"url"
|
|
167
277
|
);
|
|
168
|
-
const
|
|
278
|
+
const ssrPath = pathToFileURL(
|
|
279
|
+
path.resolve(root, "dist/server/ssr.js")
|
|
280
|
+
).href;
|
|
281
|
+
const ssrModule = await import(
|
|
169
282
|
/* @vite-ignore */
|
|
170
|
-
|
|
283
|
+
ssrPath
|
|
171
284
|
);
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
285
|
+
const routePaths = await extractRoutes(ctx, opts);
|
|
286
|
+
const allUrls = [];
|
|
287
|
+
for (const routePath of routePaths) {
|
|
288
|
+
for (const locale of ctx.locales) {
|
|
289
|
+
const url = locale === ctx.defaultLocale ? routePath : `/${locale}${routePath === "/" ? "" : routePath}`;
|
|
290
|
+
allUrls.push(url);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
console.log(
|
|
294
|
+
` Pre-rendering ${allUrls.length} pages (${routePaths.length} routes \xD7 ${ctx.locales.length} locales)...
|
|
295
|
+
`
|
|
179
296
|
);
|
|
297
|
+
for (const url of allUrls) {
|
|
298
|
+
try {
|
|
299
|
+
const locale = inferLocale(
|
|
300
|
+
url,
|
|
301
|
+
ctx.locales,
|
|
302
|
+
ctx.defaultLocale
|
|
303
|
+
);
|
|
304
|
+
const {
|
|
305
|
+
html: appHtml,
|
|
306
|
+
head,
|
|
307
|
+
css,
|
|
308
|
+
serverData
|
|
309
|
+
} = await ssrModule.render(url, locale);
|
|
310
|
+
const serializedData = ssrModule.serializeServerData(serverData);
|
|
311
|
+
const finalHtml = injectSSRForStatic(
|
|
312
|
+
ctx.templateHtml,
|
|
313
|
+
locale,
|
|
314
|
+
head,
|
|
315
|
+
css,
|
|
316
|
+
appHtml,
|
|
317
|
+
serializedData
|
|
318
|
+
);
|
|
319
|
+
const filePath = url === "/" ? path.join(outputDir, "index.html") : path.join(outputDir, url, "index.html");
|
|
320
|
+
fs.mkdirSync(path.resolve(filePath, ".."), {
|
|
321
|
+
recursive: true
|
|
322
|
+
});
|
|
323
|
+
fs.writeFileSync(filePath, finalHtml);
|
|
324
|
+
} catch (e) {
|
|
325
|
+
console.warn(` [static] Failed to render ${url}:`, e);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
ctx.copyStaticAssets(outputDir, { excludeHtml: true });
|
|
329
|
+
console.log(` Static output \u2192 dist/static/
|
|
330
|
+
`);
|
|
180
331
|
}
|
|
181
|
-
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
async function extractRoutes(ctx, opts) {
|
|
335
|
+
const routesFile = opts.routesExport ?? "src/lib/bootstrap.ts";
|
|
336
|
+
const paths = [];
|
|
337
|
+
try {
|
|
338
|
+
const { pathToFileURL } = await import(
|
|
182
339
|
/* @vite-ignore */
|
|
183
|
-
"
|
|
340
|
+
"url"
|
|
184
341
|
);
|
|
185
|
-
|
|
342
|
+
await ctx.vite.build({
|
|
343
|
+
root: ctx.root,
|
|
344
|
+
build: {
|
|
345
|
+
ssr: routesFile,
|
|
346
|
+
outDir: ctx.path.resolve(ctx.root, "dist/server"),
|
|
347
|
+
emptyOutDir: false,
|
|
348
|
+
rollupOptions: {
|
|
349
|
+
output: { entryFileNames: "_routes.mjs" }
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
resolve: ctx.resolvedResolve
|
|
353
|
+
});
|
|
354
|
+
const routesPath = pathToFileURL(
|
|
355
|
+
ctx.path.resolve(ctx.root, "dist/server/_routes.mjs")
|
|
356
|
+
).href;
|
|
357
|
+
const routesMod = await import(
|
|
186
358
|
/* @vite-ignore */
|
|
187
|
-
|
|
359
|
+
routesPath
|
|
188
360
|
);
|
|
189
|
-
|
|
361
|
+
const routes = routesMod.routes ?? routesMod.default;
|
|
362
|
+
if (Array.isArray(routes)) {
|
|
363
|
+
for (const r of routes) {
|
|
364
|
+
if (r.path && !r.path.includes(":")) {
|
|
365
|
+
paths.push(r.path);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
ctx.fs.rmSync(ctx.path.resolve(ctx.root, "dist/server/_routes.mjs"), {
|
|
370
|
+
force: true
|
|
371
|
+
});
|
|
372
|
+
} catch (e) {
|
|
373
|
+
console.warn(
|
|
374
|
+
` [static] Could not load routes from "${routesFile}". Using "/" only.`,
|
|
375
|
+
e
|
|
376
|
+
);
|
|
377
|
+
if (paths.length === 0) paths.push("/");
|
|
190
378
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
379
|
+
if (opts.dynamicRoutes) {
|
|
380
|
+
for (const r of opts.dynamicRoutes) {
|
|
381
|
+
if (!paths.includes(r)) paths.push(r);
|
|
194
382
|
}
|
|
195
|
-
const modulePath = ssrProductionModule ?? "../dist/server/ssr.js";
|
|
196
|
-
return import(modulePath);
|
|
197
383
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
384
|
+
if (paths.length === 0) paths.push("/");
|
|
385
|
+
return paths;
|
|
386
|
+
}
|
|
387
|
+
function inferLocale(url, locales, defaultLocale) {
|
|
388
|
+
const segments = url.split("/").filter(Boolean);
|
|
389
|
+
if (segments.length > 0 && locales.includes(segments[0])) {
|
|
390
|
+
return segments[0];
|
|
391
|
+
}
|
|
392
|
+
return defaultLocale;
|
|
393
|
+
}
|
|
394
|
+
function injectSSRForStatic(template, locale, head, css, html, serializedData) {
|
|
395
|
+
return template.replace("<!--ssr-lang-->", locale).replace("<!--ssr-head-->", head + "\n<style>" + css + "</style>").replace("<!--ssr-body-->", html).replace(
|
|
396
|
+
"<!--ssr-data-->",
|
|
397
|
+
'<script id="serialized-server-data" type="application/json">' + serializedData + "</script>"
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// ../server/src/adapters/vercel.ts
|
|
402
|
+
function vercelAdapter() {
|
|
403
|
+
return {
|
|
404
|
+
name: "vercel",
|
|
405
|
+
async build(ctx) {
|
|
406
|
+
const { fs, path, root } = ctx;
|
|
407
|
+
const outputDir = path.resolve(root, ".vercel/output");
|
|
408
|
+
fs.rmSync(outputDir, { recursive: true, force: true });
|
|
409
|
+
const entrySource = generateSSREntry(ctx, {
|
|
410
|
+
platformImport: `import { handle } from "hono/vercel";`,
|
|
411
|
+
platformExport: `export default handle(app);`
|
|
222
412
|
});
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
413
|
+
const tempEntry = path.resolve(root, ".vercel-entry.tmp.mjs");
|
|
414
|
+
fs.writeFileSync(tempEntry, entrySource);
|
|
415
|
+
try {
|
|
416
|
+
const funcDir = path.resolve(
|
|
417
|
+
root,
|
|
418
|
+
".vercel/output/functions/ssr.func"
|
|
419
|
+
);
|
|
420
|
+
await buildBundle(ctx, {
|
|
421
|
+
entry: ".vercel-entry.tmp.mjs",
|
|
422
|
+
outDir: funcDir,
|
|
423
|
+
target: "node18"
|
|
424
|
+
});
|
|
425
|
+
fs.writeFileSync(
|
|
426
|
+
path.resolve(funcDir, ".vc-config.json"),
|
|
427
|
+
JSON.stringify(
|
|
428
|
+
{
|
|
429
|
+
runtime: "nodejs20.x",
|
|
430
|
+
handler: "index.mjs",
|
|
431
|
+
launcherType: "Nodejs"
|
|
432
|
+
},
|
|
433
|
+
null,
|
|
434
|
+
2
|
|
435
|
+
)
|
|
436
|
+
);
|
|
437
|
+
copyStaticAssets(
|
|
438
|
+
ctx,
|
|
439
|
+
path.resolve(root, ".vercel/output/static")
|
|
440
|
+
);
|
|
441
|
+
fs.writeFileSync(
|
|
442
|
+
path.resolve(root, ".vercel/output/config.json"),
|
|
443
|
+
JSON.stringify(
|
|
444
|
+
{
|
|
445
|
+
version: 3,
|
|
446
|
+
routes: [
|
|
447
|
+
{ handle: "filesystem" },
|
|
448
|
+
{ src: "/(.*)", dest: "/ssr" }
|
|
449
|
+
]
|
|
450
|
+
},
|
|
451
|
+
null,
|
|
452
|
+
2
|
|
453
|
+
)
|
|
454
|
+
);
|
|
455
|
+
} finally {
|
|
456
|
+
fs.rmSync(tempEntry, { force: true });
|
|
227
457
|
}
|
|
228
|
-
console.
|
|
229
|
-
return c.text("Internal Server Error", 500);
|
|
458
|
+
console.log(" Vercel output \u2192 .vercel/output/\n");
|
|
230
459
|
}
|
|
231
|
-
}
|
|
232
|
-
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// ../server/src/adapters/resolve.ts
|
|
464
|
+
function resolveAdapter(value) {
|
|
465
|
+
if (typeof value !== "string") return value;
|
|
466
|
+
switch (value) {
|
|
467
|
+
case "vercel":
|
|
468
|
+
return vercelAdapter();
|
|
469
|
+
case "cloudflare":
|
|
470
|
+
return cloudflareAdapter();
|
|
471
|
+
case "netlify":
|
|
472
|
+
return netlifyAdapter();
|
|
473
|
+
case "node":
|
|
474
|
+
return nodeAdapter();
|
|
475
|
+
case "static":
|
|
476
|
+
return staticAdapter();
|
|
477
|
+
case "auto":
|
|
478
|
+
return autoAdapter();
|
|
479
|
+
default:
|
|
480
|
+
throw new Error(
|
|
481
|
+
`[finesoft] Unknown adapter: "${value}". Available: vercel, cloudflare, netlify, node, static, auto`
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// ../server/src/adapters/auto.ts
|
|
487
|
+
function autoAdapter() {
|
|
488
|
+
return {
|
|
489
|
+
name: "auto",
|
|
490
|
+
async build(ctx) {
|
|
491
|
+
const detected = detectPlatform();
|
|
492
|
+
console.log(` [auto] Detected platform: ${detected}
|
|
493
|
+
`);
|
|
494
|
+
const adapter = resolveAdapter(detected);
|
|
495
|
+
return adapter.build(ctx);
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
function detectPlatform() {
|
|
500
|
+
if (process.env.VERCEL) return "vercel";
|
|
501
|
+
if (process.env.CF_PAGES) return "cloudflare";
|
|
502
|
+
if (process.env.NETLIFY) return "netlify";
|
|
503
|
+
return "node";
|
|
233
504
|
}
|
|
234
505
|
|
|
235
506
|
// ../server/src/create-server.ts
|
|
236
|
-
import { Hono as
|
|
507
|
+
import { Hono as Hono2 } from "hono";
|
|
237
508
|
|
|
238
509
|
// ../server/src/runtime.ts
|
|
239
510
|
function detectRuntime() {
|
|
@@ -269,7 +540,7 @@ async function resolveRoot(importMetaUrl, levelsUp = 0) {
|
|
|
269
540
|
}
|
|
270
541
|
|
|
271
542
|
// ../server/src/start.ts
|
|
272
|
-
import { Hono
|
|
543
|
+
import { Hono } from "hono";
|
|
273
544
|
async function startServer(options) {
|
|
274
545
|
const {
|
|
275
546
|
app,
|
|
@@ -351,8 +622,16 @@ async function startServer(options) {
|
|
|
351
622
|
/* @vite-ignore */
|
|
352
623
|
"path"
|
|
353
624
|
);
|
|
354
|
-
const prodApp = new
|
|
355
|
-
|
|
625
|
+
const prodApp = new Hono();
|
|
626
|
+
const clientDir = resolve(root, "dist/client");
|
|
627
|
+
prodApp.use(
|
|
628
|
+
"/*",
|
|
629
|
+
serveStatic({
|
|
630
|
+
root: clientDir,
|
|
631
|
+
// 禁止目录路径自动提供 index.html,让其 fall through 到 SSR
|
|
632
|
+
rewriteRequestPath: (path) => path.endsWith("/") ? "/__nosuchfile__" : path
|
|
633
|
+
})
|
|
634
|
+
);
|
|
356
635
|
prodApp.route("/", app);
|
|
357
636
|
const { serve } = await import(
|
|
358
637
|
/* @vite-ignore */
|
|
@@ -408,7 +687,7 @@ async function createServer(config = {}) {
|
|
|
408
687
|
appType: "custom"
|
|
409
688
|
});
|
|
410
689
|
}
|
|
411
|
-
const app = new
|
|
690
|
+
const app = new Hono2();
|
|
412
691
|
if (setup) {
|
|
413
692
|
await setup(app);
|
|
414
693
|
}
|
|
@@ -433,6 +712,251 @@ async function createServer(config = {}) {
|
|
|
433
712
|
});
|
|
434
713
|
return { app, vite, runtime };
|
|
435
714
|
}
|
|
715
|
+
|
|
716
|
+
// ../server/src/vite-plugin.ts
|
|
717
|
+
function resolveSetupFn(mod) {
|
|
718
|
+
if (typeof mod.default === "function") return mod.default;
|
|
719
|
+
if (typeof mod.setup === "function") return mod.setup;
|
|
720
|
+
const first = Object.values(mod).find((v) => typeof v === "function");
|
|
721
|
+
return first ?? null;
|
|
722
|
+
}
|
|
723
|
+
function finesoftFrontViteConfig(options = {}) {
|
|
724
|
+
const ssrEntry = options.ssr?.entry ?? "src/ssr.ts";
|
|
725
|
+
let root = process.cwd();
|
|
726
|
+
let resolvedCommand;
|
|
727
|
+
let resolvedResolve;
|
|
728
|
+
let resolvedCss;
|
|
729
|
+
return {
|
|
730
|
+
name: "finesoft-front",
|
|
731
|
+
config(userConfig, env) {
|
|
732
|
+
const overrides = {
|
|
733
|
+
appType: "custom"
|
|
734
|
+
};
|
|
735
|
+
if (env.command === "build" && !process.env.__FINESOFT_SUB_BUILD__) {
|
|
736
|
+
overrides.build = {
|
|
737
|
+
outDir: userConfig.build?.outDir ?? "dist/client"
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
return overrides;
|
|
741
|
+
},
|
|
742
|
+
configResolved(config) {
|
|
743
|
+
resolvedCommand = config.command;
|
|
744
|
+
resolvedResolve = config.resolve;
|
|
745
|
+
resolvedCss = config.css;
|
|
746
|
+
root = config.root;
|
|
747
|
+
},
|
|
748
|
+
// ─── Dev ───────────────────────────────────────────────
|
|
749
|
+
configureServer(server) {
|
|
750
|
+
return async () => {
|
|
751
|
+
const { Hono: HonoClass } = await import(
|
|
752
|
+
/* @vite-ignore */
|
|
753
|
+
"hono"
|
|
754
|
+
);
|
|
755
|
+
const { createSSRApp: createSSRApp2 } = await import("./app-MYBG3TGV.js");
|
|
756
|
+
const { getRequestListener } = await import(
|
|
757
|
+
/* @vite-ignore */
|
|
758
|
+
"@hono/node-server"
|
|
759
|
+
);
|
|
760
|
+
const app = new HonoClass();
|
|
761
|
+
if (typeof options.setup === "function") {
|
|
762
|
+
await options.setup(app);
|
|
763
|
+
} else if (typeof options.setup === "string") {
|
|
764
|
+
const mod = await server.ssrLoadModule("/" + options.setup);
|
|
765
|
+
const fn = resolveSetupFn(mod);
|
|
766
|
+
if (fn) await fn(app);
|
|
767
|
+
}
|
|
768
|
+
const ssrApp = createSSRApp2({
|
|
769
|
+
root,
|
|
770
|
+
vite: server,
|
|
771
|
+
isProduction: false,
|
|
772
|
+
ssrEntryPath: "/" + ssrEntry,
|
|
773
|
+
supportedLocales: options.locales,
|
|
774
|
+
defaultLocale: options.defaultLocale
|
|
775
|
+
});
|
|
776
|
+
app.route("/", ssrApp);
|
|
777
|
+
const listener = getRequestListener(app.fetch);
|
|
778
|
+
server.middlewares.use((req, res) => {
|
|
779
|
+
listener(req, res);
|
|
780
|
+
});
|
|
781
|
+
};
|
|
782
|
+
},
|
|
783
|
+
// ─── Preview ───────────────────────────────────────────
|
|
784
|
+
configurePreviewServer(server) {
|
|
785
|
+
return async () => {
|
|
786
|
+
const { readFileSync } = await import(
|
|
787
|
+
/* @vite-ignore */
|
|
788
|
+
"fs"
|
|
789
|
+
);
|
|
790
|
+
const { resolve } = await import(
|
|
791
|
+
/* @vite-ignore */
|
|
792
|
+
"path"
|
|
793
|
+
);
|
|
794
|
+
const { pathToFileURL } = await import(
|
|
795
|
+
/* @vite-ignore */
|
|
796
|
+
"url"
|
|
797
|
+
);
|
|
798
|
+
const { Hono: HonoClass } = await import(
|
|
799
|
+
/* @vite-ignore */
|
|
800
|
+
"hono"
|
|
801
|
+
);
|
|
802
|
+
const { injectSSRContent: injectSSRContent2 } = await import(
|
|
803
|
+
/* @vite-ignore */
|
|
804
|
+
"./src-7D236CLJ.js"
|
|
805
|
+
);
|
|
806
|
+
const { parseAcceptLanguage: parseAcceptLanguage2 } = await import("./locale-YK3THSI6.js");
|
|
807
|
+
const { getRequestListener } = await import(
|
|
808
|
+
/* @vite-ignore */
|
|
809
|
+
"@hono/node-server"
|
|
810
|
+
);
|
|
811
|
+
const app = new HonoClass();
|
|
812
|
+
if (typeof options.setup === "function") {
|
|
813
|
+
await options.setup(app);
|
|
814
|
+
} else if (typeof options.setup === "string") {
|
|
815
|
+
try {
|
|
816
|
+
const setupPath = pathToFileURL(
|
|
817
|
+
resolve(root, "dist/server/setup.mjs")
|
|
818
|
+
).href;
|
|
819
|
+
const mod = await import(
|
|
820
|
+
/* @vite-ignore */
|
|
821
|
+
setupPath
|
|
822
|
+
);
|
|
823
|
+
const fn = resolveSetupFn(
|
|
824
|
+
mod
|
|
825
|
+
);
|
|
826
|
+
if (fn) await fn(app);
|
|
827
|
+
} catch {
|
|
828
|
+
console.warn(
|
|
829
|
+
"[finesoft] Could not load setup module for preview. API routes disabled."
|
|
830
|
+
);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
const templatePath = resolve(root, "dist/client/index.html");
|
|
834
|
+
const template = readFileSync(templatePath, "utf-8");
|
|
835
|
+
const ssrPath = pathToFileURL(
|
|
836
|
+
resolve(root, "dist/server/ssr.js")
|
|
837
|
+
).href;
|
|
838
|
+
const ssrModule = await import(
|
|
839
|
+
/* @vite-ignore */
|
|
840
|
+
ssrPath
|
|
841
|
+
);
|
|
842
|
+
app.get("*", async (c) => {
|
|
843
|
+
const url = c.req.path + (c.req.url.includes("?") ? "?" + c.req.url.split("?")[1] : "");
|
|
844
|
+
try {
|
|
845
|
+
const locale = parseAcceptLanguage2(
|
|
846
|
+
c.req.header("accept-language"),
|
|
847
|
+
options.locales,
|
|
848
|
+
options.defaultLocale
|
|
849
|
+
);
|
|
850
|
+
const {
|
|
851
|
+
html: appHtml,
|
|
852
|
+
head,
|
|
853
|
+
css,
|
|
854
|
+
serverData
|
|
855
|
+
} = await ssrModule.render(url, locale);
|
|
856
|
+
const serializedData = ssrModule.serializeServerData(serverData);
|
|
857
|
+
const finalHtml = injectSSRContent2({
|
|
858
|
+
template,
|
|
859
|
+
locale,
|
|
860
|
+
head,
|
|
861
|
+
css,
|
|
862
|
+
html: appHtml,
|
|
863
|
+
serializedData
|
|
864
|
+
});
|
|
865
|
+
return c.html(finalHtml);
|
|
866
|
+
} catch (e) {
|
|
867
|
+
console.error("[SSR Preview Error]", e);
|
|
868
|
+
return c.text("Internal Server Error", 500);
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
const listener = getRequestListener(app.fetch);
|
|
872
|
+
server.middlewares.use((req, res) => {
|
|
873
|
+
listener(req, res);
|
|
874
|
+
});
|
|
875
|
+
};
|
|
876
|
+
},
|
|
877
|
+
// ─── Build ─────────────────────────────────────────────
|
|
878
|
+
async closeBundle() {
|
|
879
|
+
if (process.env.__FINESOFT_SUB_BUILD__) return;
|
|
880
|
+
if (resolvedCommand !== "build") return;
|
|
881
|
+
process.env.__FINESOFT_SUB_BUILD__ = "1";
|
|
882
|
+
try {
|
|
883
|
+
const vite = await import(
|
|
884
|
+
/* @vite-ignore */
|
|
885
|
+
"vite"
|
|
886
|
+
);
|
|
887
|
+
const fs = await import(
|
|
888
|
+
/* @vite-ignore */
|
|
889
|
+
"fs"
|
|
890
|
+
);
|
|
891
|
+
const path = await import(
|
|
892
|
+
/* @vite-ignore */
|
|
893
|
+
"path"
|
|
894
|
+
);
|
|
895
|
+
console.log("\n Building SSR bundle...\n");
|
|
896
|
+
await vite.build({
|
|
897
|
+
root,
|
|
898
|
+
build: {
|
|
899
|
+
ssr: ssrEntry,
|
|
900
|
+
outDir: "dist/server"
|
|
901
|
+
},
|
|
902
|
+
resolve: resolvedResolve,
|
|
903
|
+
css: resolvedCss
|
|
904
|
+
});
|
|
905
|
+
if (typeof options.setup === "string") {
|
|
906
|
+
console.log(" Building setup module...\n");
|
|
907
|
+
await vite.build({
|
|
908
|
+
root,
|
|
909
|
+
build: {
|
|
910
|
+
ssr: options.setup,
|
|
911
|
+
outDir: "dist/server",
|
|
912
|
+
emptyOutDir: false,
|
|
913
|
+
rollupOptions: {
|
|
914
|
+
output: { entryFileNames: "setup.mjs" }
|
|
915
|
+
}
|
|
916
|
+
},
|
|
917
|
+
resolve: resolvedResolve
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
if (options.adapter) {
|
|
921
|
+
const adapter = resolveAdapter(options.adapter);
|
|
922
|
+
const locales = options.locales ?? ["zh", "en"];
|
|
923
|
+
const defaultLocale = options.defaultLocale ?? locales[0] ?? "en";
|
|
924
|
+
const templateHtml = fs.readFileSync(
|
|
925
|
+
path.resolve(root, "dist/client/index.html"),
|
|
926
|
+
"utf-8"
|
|
927
|
+
);
|
|
928
|
+
const ctx = {
|
|
929
|
+
root,
|
|
930
|
+
ssrEntry,
|
|
931
|
+
setupPath: typeof options.setup === "string" ? options.setup : void 0,
|
|
932
|
+
locales,
|
|
933
|
+
defaultLocale,
|
|
934
|
+
templateHtml,
|
|
935
|
+
resolvedResolve,
|
|
936
|
+
resolvedCss,
|
|
937
|
+
vite,
|
|
938
|
+
fs,
|
|
939
|
+
path,
|
|
940
|
+
generateSSREntry(opts) {
|
|
941
|
+
return generateSSREntry(ctx, opts);
|
|
942
|
+
},
|
|
943
|
+
buildBundle(opts) {
|
|
944
|
+
return buildBundle(ctx, opts);
|
|
945
|
+
},
|
|
946
|
+
copyStaticAssets(destDir, opts) {
|
|
947
|
+
return copyStaticAssets(ctx, destDir, opts);
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
console.log(` Running adapter: ${adapter.name}...
|
|
951
|
+
`);
|
|
952
|
+
await adapter.build(ctx);
|
|
953
|
+
}
|
|
954
|
+
} finally {
|
|
955
|
+
delete process.env.__FINESOFT_SUB_BUILD__;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
};
|
|
959
|
+
}
|
|
436
960
|
export {
|
|
437
961
|
ACTION_KINDS,
|
|
438
962
|
ActionDispatcher,
|
|
@@ -453,7 +977,9 @@ export {
|
|
|
453
977
|
PrefetchedIntents,
|
|
454
978
|
Router,
|
|
455
979
|
SSR_PLACEHOLDERS,
|
|
980
|
+
autoAdapter,
|
|
456
981
|
buildUrl,
|
|
982
|
+
cloudflareAdapter,
|
|
457
983
|
createPrefetchedIntentsFromDom,
|
|
458
984
|
createSSRApp,
|
|
459
985
|
createSSRRender,
|
|
@@ -461,6 +987,7 @@ export {
|
|
|
461
987
|
defineRoutes,
|
|
462
988
|
deserializeServerData,
|
|
463
989
|
detectRuntime,
|
|
990
|
+
finesoftFrontViteConfig,
|
|
464
991
|
generateUuid,
|
|
465
992
|
getBaseUrl,
|
|
466
993
|
injectSSRContent,
|
|
@@ -473,6 +1000,8 @@ export {
|
|
|
473
1000
|
makeExternalUrlAction,
|
|
474
1001
|
makeFlowAction,
|
|
475
1002
|
mapEach,
|
|
1003
|
+
netlifyAdapter,
|
|
1004
|
+
nodeAdapter,
|
|
476
1005
|
parseAcceptLanguage,
|
|
477
1006
|
pipe,
|
|
478
1007
|
pipeAsync,
|
|
@@ -483,6 +1012,7 @@ export {
|
|
|
483
1012
|
removeQueryParams,
|
|
484
1013
|
removeScheme,
|
|
485
1014
|
resetFilterCache,
|
|
1015
|
+
resolveAdapter,
|
|
486
1016
|
resolveRoot,
|
|
487
1017
|
serializeServerData,
|
|
488
1018
|
shouldLog,
|
|
@@ -490,6 +1020,8 @@ export {
|
|
|
490
1020
|
stableStringify,
|
|
491
1021
|
startBrowserApp,
|
|
492
1022
|
startServer,
|
|
493
|
-
|
|
1023
|
+
staticAdapter,
|
|
1024
|
+
tryScroll,
|
|
1025
|
+
vercelAdapter
|
|
494
1026
|
};
|
|
495
1027
|
//# sourceMappingURL=index.js.map
|