@finesoft/front 0.1.32 → 0.1.33
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/index.cjs +207 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -6
- package/dist/index.d.ts +75 -6
- package/dist/index.js +205 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1358,6 +1358,7 @@ __export(index_exports, {
|
|
|
1358
1358
|
deserializeServerData: () => deserializeServerData,
|
|
1359
1359
|
detectRuntime: () => detectRuntime,
|
|
1360
1360
|
finesoftFrontViteConfig: () => finesoftFrontViteConfig,
|
|
1361
|
+
generateProxyCode: () => generateProxyCode,
|
|
1361
1362
|
generateUuid: () => generateUuid,
|
|
1362
1363
|
getBaseUrl: () => getBaseUrl,
|
|
1363
1364
|
injectCSRShell: () => injectCSRShell,
|
|
@@ -1379,6 +1380,7 @@ __export(index_exports, {
|
|
|
1379
1380
|
registerActionHandlers: () => registerActionHandlers,
|
|
1380
1381
|
registerExternalUrlHandler: () => registerExternalUrlHandler,
|
|
1381
1382
|
registerFlowActionHandler: () => registerFlowActionHandler,
|
|
1383
|
+
registerProxyRoutes: () => registerProxyRoutes,
|
|
1382
1384
|
removeHost: () => removeHost,
|
|
1383
1385
|
removeQueryParams: () => removeQueryParams,
|
|
1384
1386
|
removeScheme: () => removeScheme,
|
|
@@ -1732,6 +1734,120 @@ init_src();
|
|
|
1732
1734
|
// src/index.ts
|
|
1733
1735
|
init_src2();
|
|
1734
1736
|
|
|
1737
|
+
// ../server/src/proxy.ts
|
|
1738
|
+
function sanitizeProxyPath(raw) {
|
|
1739
|
+
if (raw.startsWith("//")) return null;
|
|
1740
|
+
return raw.startsWith("/") ? raw : `/${raw}`;
|
|
1741
|
+
}
|
|
1742
|
+
function validateConfig(config) {
|
|
1743
|
+
if (!config.prefix.startsWith("/")) {
|
|
1744
|
+
throw new Error(
|
|
1745
|
+
`[proxy] prefix must start with "/": "${config.prefix}"`
|
|
1746
|
+
);
|
|
1747
|
+
}
|
|
1748
|
+
if (!config.target.startsWith("https://")) {
|
|
1749
|
+
throw new Error(`[proxy] target must use HTTPS: "${config.target}"`);
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
function registerProxyRoutes(app, configs) {
|
|
1753
|
+
for (const config of configs) {
|
|
1754
|
+
validateConfig(config);
|
|
1755
|
+
const methods = config.methods ?? ["all"];
|
|
1756
|
+
const pattern = `${config.prefix}/*`;
|
|
1757
|
+
const handler = async (c) => {
|
|
1758
|
+
const subPath = sanitizeProxyPath(
|
|
1759
|
+
c.req.path.replace(config.prefix, "")
|
|
1760
|
+
);
|
|
1761
|
+
if (!subPath) return c.text("Invalid path", 400);
|
|
1762
|
+
const targetUrl = new URL(subPath, config.target);
|
|
1763
|
+
const reqUrl = new URL(c.req.url);
|
|
1764
|
+
reqUrl.searchParams.forEach(
|
|
1765
|
+
(v, k) => targetUrl.searchParams.set(k, v)
|
|
1766
|
+
);
|
|
1767
|
+
const headers = { ...config.headers };
|
|
1768
|
+
if (config.auth) {
|
|
1769
|
+
const token = process.env[config.auth.envKey] ?? "";
|
|
1770
|
+
if (token) {
|
|
1771
|
+
headers.Authorization = config.auth.type === "bearer" ? `Bearer ${token}` : `Basic ${token}`;
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
try {
|
|
1775
|
+
const resp = await fetch(targetUrl.toString(), {
|
|
1776
|
+
headers,
|
|
1777
|
+
redirect: config.followRedirects ? "follow" : "manual"
|
|
1778
|
+
});
|
|
1779
|
+
const body = await resp.text();
|
|
1780
|
+
const respHeaders = {
|
|
1781
|
+
"Content-Type": resp.headers.get("Content-Type") ?? "application/json"
|
|
1782
|
+
};
|
|
1783
|
+
if (config.cache) {
|
|
1784
|
+
respHeaders["Cache-Control"] = config.cache;
|
|
1785
|
+
}
|
|
1786
|
+
return c.newResponse(body, resp.status, respHeaders);
|
|
1787
|
+
} catch (e) {
|
|
1788
|
+
console.error(`[Proxy ${config.prefix}]`, e);
|
|
1789
|
+
return c.json({ error: "Proxy request failed" }, 502);
|
|
1790
|
+
}
|
|
1791
|
+
};
|
|
1792
|
+
for (const method of methods) {
|
|
1793
|
+
app[method](pattern, handler);
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
function generateProxyCode(configs) {
|
|
1798
|
+
if (!configs || configs.length === 0) return "";
|
|
1799
|
+
for (const config of configs) {
|
|
1800
|
+
validateConfig(config);
|
|
1801
|
+
}
|
|
1802
|
+
const blocks = [];
|
|
1803
|
+
blocks.push(`
|
|
1804
|
+
// \u2500\u2500\u2500 \u6846\u67B6\u58F0\u660E\u5F0F\u4EE3\u7406\u8DEF\u7531 \u2500\u2500\u2500
|
|
1805
|
+
function _sanitizeProxyPath(raw) {
|
|
1806
|
+
if (raw.startsWith("//")) return null;
|
|
1807
|
+
return raw.startsWith("/") ? raw : "/" + raw;
|
|
1808
|
+
}
|
|
1809
|
+
`);
|
|
1810
|
+
for (const config of configs) {
|
|
1811
|
+
const methods = config.methods ?? ["all"];
|
|
1812
|
+
const pattern = `"${config.prefix}/*"`;
|
|
1813
|
+
const headersJson = JSON.stringify(config.headers ?? {});
|
|
1814
|
+
const cacheStr = config.cache ? JSON.stringify(config.cache) : "null";
|
|
1815
|
+
const redirect = config.followRedirects ? '"follow"' : '"manual"';
|
|
1816
|
+
let authCode = "";
|
|
1817
|
+
if (config.auth) {
|
|
1818
|
+
const envKey = JSON.stringify(config.auth.envKey);
|
|
1819
|
+
const prefix = config.auth.type === "bearer" ? "Bearer " : "Basic ";
|
|
1820
|
+
authCode = `
|
|
1821
|
+
const _token = (typeof process !== "undefined" && process.env && process.env[${envKey}]) || "";
|
|
1822
|
+
if (_token) _headers.Authorization = "${prefix}" + _token;`;
|
|
1823
|
+
}
|
|
1824
|
+
const handlerCode = `async (c) => {
|
|
1825
|
+
const _sub = _sanitizeProxyPath(c.req.path.replace(${JSON.stringify(
|
|
1826
|
+
config.prefix
|
|
1827
|
+
)}, ""));
|
|
1828
|
+
if (!_sub) return c.text("Invalid path", 400);
|
|
1829
|
+
const _target = new URL(_sub, ${JSON.stringify(config.target)});
|
|
1830
|
+
const _reqUrl = new URL(c.req.url);
|
|
1831
|
+
_reqUrl.searchParams.forEach((v, k) => _target.searchParams.set(k, v));
|
|
1832
|
+
const _headers = ${headersJson};${authCode}
|
|
1833
|
+
try {
|
|
1834
|
+
const _resp = await fetch(_target.toString(), { headers: _headers, redirect: ${redirect} });
|
|
1835
|
+
const _body = await _resp.text();
|
|
1836
|
+
const _rh = { "Content-Type": _resp.headers.get("Content-Type") || "application/json" };
|
|
1837
|
+
if (${cacheStr}) _rh["Cache-Control"] = ${cacheStr};
|
|
1838
|
+
return c.newResponse(_body, _resp.status, _rh);
|
|
1839
|
+
} catch (_e) {
|
|
1840
|
+
console.error("[Proxy ${config.prefix}]", _e);
|
|
1841
|
+
return c.json({ error: "Proxy request failed" }, 502);
|
|
1842
|
+
}
|
|
1843
|
+
}`;
|
|
1844
|
+
for (const method of methods) {
|
|
1845
|
+
blocks.push(`app.${method}(${pattern}, ${handlerCode});`);
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
return blocks.join("\n");
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1735
1851
|
// ../server/src/adapters/shared.ts
|
|
1736
1852
|
var BUILD_TOOL_EXTERNALS = [
|
|
1737
1853
|
"vite",
|
|
@@ -1814,6 +1930,7 @@ function matchRenderMode(url) {
|
|
|
1814
1930
|
}
|
|
1815
1931
|
|
|
1816
1932
|
const app = new Hono();
|
|
1933
|
+
${generateProxyCode(ctx.proxies ?? [])}
|
|
1817
1934
|
${setupCall}
|
|
1818
1935
|
${opts.platformMiddleware ?? ""}
|
|
1819
1936
|
|
|
@@ -2673,6 +2790,7 @@ async function createServer(config = {}) {
|
|
|
2673
2790
|
defaultLocale,
|
|
2674
2791
|
port = Number(process.env.PORT) || 3e3,
|
|
2675
2792
|
setup,
|
|
2793
|
+
proxies,
|
|
2676
2794
|
ssr
|
|
2677
2795
|
} = config;
|
|
2678
2796
|
const root = rootOverride ?? process.cwd();
|
|
@@ -2709,6 +2827,9 @@ async function createServer(config = {}) {
|
|
|
2709
2827
|
});
|
|
2710
2828
|
}
|
|
2711
2829
|
const app = new import_hono3.Hono();
|
|
2830
|
+
if (proxies?.length) {
|
|
2831
|
+
registerProxyRoutes(app, proxies);
|
|
2832
|
+
}
|
|
2712
2833
|
if (setup) {
|
|
2713
2834
|
await setup(app);
|
|
2714
2835
|
}
|
|
@@ -2765,6 +2886,7 @@ function finesoftFrontViteConfig(options = {}) {
|
|
|
2765
2886
|
let resolvedCommand;
|
|
2766
2887
|
let resolvedResolve;
|
|
2767
2888
|
let resolvedCss;
|
|
2889
|
+
const CSS_EXTENSIONS = /\.(css|scss|less|sass|styl|stylus|pcss|postcss)($|\?)/;
|
|
2768
2890
|
return {
|
|
2769
2891
|
name: "finesoft-front",
|
|
2770
2892
|
config(userConfig, env) {
|
|
@@ -2784,6 +2906,82 @@ function finesoftFrontViteConfig(options = {}) {
|
|
|
2784
2906
|
resolvedCss = config.css;
|
|
2785
2907
|
root = config.root;
|
|
2786
2908
|
},
|
|
2909
|
+
/**
|
|
2910
|
+
* Dev 模式 CSS 内联 — 消除 SSR 首屏布局抖动
|
|
2911
|
+
*
|
|
2912
|
+
* Vite dev 模式下,global.scss 等非组件 CSS 通过 JS 模块系统异步加载,
|
|
2913
|
+
* 导致 SSR HTML 初次渲染缺少布局关键样式(box-sizing、flex 布局、padding-top 等)。
|
|
2914
|
+
*
|
|
2915
|
+
* 此 hook 在 HTML 模板变换阶段(SSR 渲染之前):
|
|
2916
|
+
* 1. 找到浏览器入口脚本(排除 /@vite/client 等内部脚本)
|
|
2917
|
+
* 2. 编译入口脚本,填充 Vite 模块图
|
|
2918
|
+
* 3. 遍历模块图收集所有 CSS 依赖(排除 .svelte 组件 CSS,由 SSR 渲染自行处理)
|
|
2919
|
+
* 4. 通过 ssrLoadModule 获取编译后 CSS(SCSS→CSS)
|
|
2920
|
+
* 5. 注入 <style data-vite-dev-id> 标签到 <head>
|
|
2921
|
+
*
|
|
2922
|
+
* data-vite-dev-id 确保 Vite HMR 客户端复用已有标签,避免重复注入。
|
|
2923
|
+
*/
|
|
2924
|
+
transformIndexHtml: {
|
|
2925
|
+
order: "pre",
|
|
2926
|
+
async handler(html, ctx) {
|
|
2927
|
+
const server = ctx.server;
|
|
2928
|
+
if (!server) return;
|
|
2929
|
+
const urlPath = (ctx.originalUrl || ctx.path || "").split(
|
|
2930
|
+
"?"
|
|
2931
|
+
)[0];
|
|
2932
|
+
if (/\.\w+$/.test(urlPath) && !urlPath.endsWith(".html")) {
|
|
2933
|
+
return;
|
|
2934
|
+
}
|
|
2935
|
+
const scripts = [
|
|
2936
|
+
...html.matchAll(
|
|
2937
|
+
/<script\b[^>]*\bsrc=["']([^"']+)["'][^>]*>/g
|
|
2938
|
+
)
|
|
2939
|
+
];
|
|
2940
|
+
const appEntry = scripts.find((m) => !m[1].startsWith("/@"));
|
|
2941
|
+
if (!appEntry) return;
|
|
2942
|
+
const browserEntry = appEntry[1];
|
|
2943
|
+
try {
|
|
2944
|
+
await server.transformRequest(browserEntry);
|
|
2945
|
+
} catch {
|
|
2946
|
+
return;
|
|
2947
|
+
}
|
|
2948
|
+
const cssUrls = [];
|
|
2949
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2950
|
+
function walk(mod) {
|
|
2951
|
+
if (!mod?.url || visited.has(mod.url)) return;
|
|
2952
|
+
visited.add(mod.url);
|
|
2953
|
+
if (CSS_EXTENSIONS.test(mod.url) && !mod.url.includes(".svelte")) {
|
|
2954
|
+
cssUrls.push(mod.url);
|
|
2955
|
+
}
|
|
2956
|
+
if (mod.importedModules) {
|
|
2957
|
+
for (const imported of mod.importedModules) {
|
|
2958
|
+
walk(imported);
|
|
2959
|
+
}
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
const mg = server.moduleGraph;
|
|
2963
|
+
const browserMod = await mg.getModuleByUrl(browserEntry);
|
|
2964
|
+
if (browserMod) walk(browserMod);
|
|
2965
|
+
if (cssUrls.length === 0) return;
|
|
2966
|
+
const tags = [];
|
|
2967
|
+
for (const url of cssUrls) {
|
|
2968
|
+
try {
|
|
2969
|
+
const mod = await server.ssrLoadModule(url);
|
|
2970
|
+
const css = mod?.default;
|
|
2971
|
+
if (typeof css === "string" && css.length > 0) {
|
|
2972
|
+
tags.push({
|
|
2973
|
+
tag: "style",
|
|
2974
|
+
attrs: { "data-vite-dev-id": url },
|
|
2975
|
+
children: css,
|
|
2976
|
+
injectTo: "head"
|
|
2977
|
+
});
|
|
2978
|
+
}
|
|
2979
|
+
} catch {
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
return tags;
|
|
2983
|
+
}
|
|
2984
|
+
},
|
|
2787
2985
|
// ─── Dev ───────────────────────────────────────────────
|
|
2788
2986
|
configureServer(server) {
|
|
2789
2987
|
return async () => {
|
|
@@ -2797,6 +2995,9 @@ function finesoftFrontViteConfig(options = {}) {
|
|
|
2797
2995
|
"@hono/node-server"
|
|
2798
2996
|
);
|
|
2799
2997
|
const app = new HonoClass();
|
|
2998
|
+
if (options.proxies?.length) {
|
|
2999
|
+
registerProxyRoutes(app, options.proxies);
|
|
3000
|
+
}
|
|
2800
3001
|
if (typeof options.setup === "function") {
|
|
2801
3002
|
await options.setup(app);
|
|
2802
3003
|
} else if (typeof options.setup === "string") {
|
|
@@ -2847,6 +3048,9 @@ function finesoftFrontViteConfig(options = {}) {
|
|
|
2847
3048
|
);
|
|
2848
3049
|
const app = new HonoClass();
|
|
2849
3050
|
const isrCache = /* @__PURE__ */ new Map();
|
|
3051
|
+
if (options.proxies?.length) {
|
|
3052
|
+
registerProxyRoutes(app, options.proxies);
|
|
3053
|
+
}
|
|
2850
3054
|
if (typeof options.setup === "function") {
|
|
2851
3055
|
await options.setup(app);
|
|
2852
3056
|
} else if (typeof options.setup === "string") {
|
|
@@ -3001,6 +3205,7 @@ function finesoftFrontViteConfig(options = {}) {
|
|
|
3001
3205
|
defaultLocale,
|
|
3002
3206
|
templateHtml,
|
|
3003
3207
|
renderModes: options.renderModes,
|
|
3208
|
+
proxies: options.proxies,
|
|
3004
3209
|
resolvedResolve,
|
|
3005
3210
|
resolvedCss,
|
|
3006
3211
|
vite,
|
|
@@ -3058,6 +3263,7 @@ function finesoftFrontViteConfig(options = {}) {
|
|
|
3058
3263
|
deserializeServerData,
|
|
3059
3264
|
detectRuntime,
|
|
3060
3265
|
finesoftFrontViteConfig,
|
|
3266
|
+
generateProxyCode,
|
|
3061
3267
|
generateUuid,
|
|
3062
3268
|
getBaseUrl,
|
|
3063
3269
|
injectCSRShell,
|
|
@@ -3079,6 +3285,7 @@ function finesoftFrontViteConfig(options = {}) {
|
|
|
3079
3285
|
registerActionHandlers,
|
|
3080
3286
|
registerExternalUrlHandler,
|
|
3081
3287
|
registerFlowActionHandler,
|
|
3288
|
+
registerProxyRoutes,
|
|
3082
3289
|
removeHost,
|
|
3083
3290
|
removeQueryParams,
|
|
3084
3291
|
removeScheme,
|