@bleedingdev/modern-js-server-core 3.2.0-ultramodern.99 → 3.4.0-ultramodern.0
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/cjs/adapters/node/helper/index.js +9 -5
- package/dist/cjs/adapters/node/helper/loadCache.js +9 -5
- package/dist/cjs/adapters/node/helper/loadConfig.js +9 -5
- package/dist/cjs/adapters/node/helper/loadEnv.js +9 -5
- package/dist/cjs/adapters/node/helper/loadPlugin.js +9 -5
- package/dist/cjs/adapters/node/helper/utils.js +12 -8
- package/dist/cjs/adapters/node/hono.js +9 -5
- package/dist/cjs/adapters/node/index.js +9 -5
- package/dist/cjs/adapters/node/node.js +9 -5
- package/dist/cjs/adapters/node/plugins/index.js +9 -5
- package/dist/cjs/adapters/node/plugins/nodeServer.js +12 -8
- package/dist/cjs/adapters/node/plugins/resource.js +10 -11
- package/dist/cjs/adapters/node/plugins/static.js +20 -190
- package/dist/cjs/adapters/node/plugins/staticModuleFederation.js +165 -0
- package/dist/cjs/adapters/node/plugins/staticPrecompressed.js +135 -0
- package/dist/cjs/constants.js +18 -13
- package/dist/cjs/context.js +9 -5
- package/dist/cjs/helper.js +12 -8
- package/dist/cjs/hono.js +9 -5
- package/dist/cjs/index.js +60 -32
- package/dist/cjs/plugins/compat/hooks.js +14 -10
- package/dist/cjs/plugins/compat/index.js +9 -5
- package/dist/cjs/plugins/default.js +9 -7
- package/dist/cjs/plugins/favicon.js +12 -8
- package/dist/cjs/plugins/index.js +11 -88
- package/dist/cjs/plugins/log.js +9 -5
- package/dist/cjs/plugins/middlewares.js +12 -8
- package/dist/cjs/plugins/monitors.js +9 -5
- package/dist/cjs/plugins/processedBy.js +12 -8
- package/dist/cjs/plugins/render/csrRscRender.js +9 -5
- package/dist/cjs/plugins/render/dataHandler.js +9 -5
- package/dist/cjs/plugins/render/index.js +12 -8
- package/dist/cjs/plugins/render/inject.js +12 -7
- package/dist/cjs/plugins/render/render.js +14 -6
- package/dist/cjs/plugins/render/renderRscHandler.js +9 -5
- package/dist/cjs/plugins/render/serverActionHandler.js +9 -5
- package/dist/cjs/plugins/render/ssrCache.js +9 -5
- package/dist/cjs/plugins/render/ssrRender.js +9 -5
- package/dist/cjs/plugins/render/utils.js +12 -8
- package/dist/cjs/plugins/route.js +9 -5
- package/dist/cjs/serverBase.js +9 -5
- package/dist/cjs/types/config/bffRuntime.js +18 -0
- package/dist/cjs/types/config/index.js +9 -5
- package/dist/cjs/types/config/serverTelemetry.js +18 -0
- package/dist/cjs/types/index.js +9 -5
- package/dist/cjs/types/plugins/index.js +9 -5
- package/dist/cjs/utils/entry.js +13 -9
- package/dist/cjs/utils/env.js +13 -9
- package/dist/cjs/utils/error.js +71 -5
- package/dist/cjs/utils/index.js +9 -5
- package/dist/cjs/utils/middlewareCollector.js +13 -9
- package/dist/cjs/utils/publicDir.js +9 -5
- package/dist/cjs/utils/request.js +16 -12
- package/dist/cjs/utils/serverConfig.js +9 -5
- package/dist/cjs/utils/storage.js +9 -5
- package/dist/cjs/utils/transformStream.js +13 -9
- package/dist/cjs/utils/warmup.js +12 -8
- package/dist/esm/adapters/node/plugins/resource.mjs +1 -6
- package/dist/esm/adapters/node/plugins/static.mjs +7 -181
- package/dist/esm/adapters/node/plugins/staticModuleFederation.mjs +96 -0
- package/dist/esm/adapters/node/plugins/staticPrecompressed.mjs +91 -0
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/plugins/default.mjs +0 -2
- package/dist/esm/plugins/index.mjs +0 -3
- package/dist/esm/plugins/render/inject.mjs +3 -2
- package/dist/esm/plugins/render/render.mjs +7 -3
- package/dist/esm/types/config/bffRuntime.mjs +0 -0
- package/dist/esm/types/config/serverTelemetry.mjs +0 -0
- package/dist/esm/utils/error.mjs +54 -1
- package/dist/esm-node/adapters/node/plugins/resource.mjs +1 -6
- package/dist/esm-node/adapters/node/plugins/static.mjs +7 -181
- package/dist/esm-node/adapters/node/plugins/staticModuleFederation.mjs +97 -0
- package/dist/esm-node/adapters/node/plugins/staticPrecompressed.mjs +92 -0
- package/dist/esm-node/index.mjs +1 -1
- package/dist/esm-node/plugins/default.mjs +0 -2
- package/dist/esm-node/plugins/index.mjs +0 -3
- package/dist/esm-node/plugins/render/inject.mjs +3 -2
- package/dist/esm-node/plugins/render/render.mjs +5 -1
- package/dist/esm-node/types/config/bffRuntime.mjs +1 -0
- package/dist/esm-node/types/config/serverTelemetry.mjs +1 -0
- package/dist/esm-node/utils/error.mjs +54 -1
- package/dist/types/adapters/node/plugins/staticModuleFederation.d.ts +13 -0
- package/dist/types/adapters/node/plugins/staticPrecompressed.d.ts +13 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/plugins/index.d.ts +0 -3
- package/dist/types/types/config/bff.d.ts +2 -97
- package/dist/types/types/config/bffRuntime.d.ts +105 -0
- package/dist/types/types/config/server.d.ts +3 -337
- package/dist/types/types/config/serverTelemetry.d.ts +319 -0
- package/dist/types/types/plugins/base.d.ts +7 -2
- package/dist/types/types/plugins/index.d.ts +1 -1
- package/dist/types/utils/error.d.ts +16 -0
- package/package.json +12 -12
- package/dist/cjs/adapters/node/plugins/moduleFederationCss.js +0 -172
- package/dist/cjs/plugins/contractGateAutopilot.js +0 -158
- package/dist/cjs/plugins/contractGateSnapshotStore.js +0 -239
- package/dist/cjs/plugins/mfCache.js +0 -78
- package/dist/cjs/plugins/telemetry.js +0 -1283
- package/dist/esm/adapters/node/plugins/moduleFederationCss.mjs +0 -125
- package/dist/esm/plugins/contractGateAutopilot.mjs +0 -124
- package/dist/esm/plugins/contractGateSnapshotStore.mjs +0 -180
- package/dist/esm/plugins/mfCache.mjs +0 -35
- package/dist/esm/plugins/telemetry.mjs +0 -1195
- package/dist/esm-node/adapters/node/plugins/moduleFederationCss.mjs +0 -126
- package/dist/esm-node/plugins/contractGateAutopilot.mjs +0 -125
- package/dist/esm-node/plugins/contractGateSnapshotStore.mjs +0 -182
- package/dist/esm-node/plugins/mfCache.mjs +0 -36
- package/dist/esm-node/plugins/telemetry.mjs +0 -1196
- package/dist/types/adapters/node/plugins/moduleFederationCss.d.ts +0 -33
- package/dist/types/plugins/contractGateAutopilot.d.ts +0 -35
- package/dist/types/plugins/contractGateSnapshotStore.d.ts +0 -57
- package/dist/types/plugins/mfCache.d.ts +0 -12
- package/dist/types/plugins/telemetry.d.ts +0 -309
package/dist/cjs/utils/warmup.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_require__ = {};
|
|
3
3
|
(()=>{
|
|
4
|
-
__webpack_require__.d = (exports1,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
9
13
|
};
|
|
10
14
|
})();
|
|
11
15
|
(()=>{
|
|
@@ -23,14 +27,14 @@ var __webpack_require__ = {};
|
|
|
23
27
|
})();
|
|
24
28
|
var __webpack_exports__ = {};
|
|
25
29
|
__webpack_require__.r(__webpack_exports__);
|
|
26
|
-
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
-
warmup: ()=>warmup
|
|
28
|
-
});
|
|
29
30
|
function warmup(bundles) {
|
|
30
31
|
bundles.forEach((bundle)=>{
|
|
31
32
|
bundle && import(bundle).catch((_)=>{});
|
|
32
33
|
});
|
|
33
34
|
}
|
|
35
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
36
|
+
warmup: ()=>warmup
|
|
37
|
+
});
|
|
34
38
|
exports.warmup = __webpack_exports__.warmup;
|
|
35
39
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
36
40
|
"warmup"
|
|
@@ -2,7 +2,6 @@ import { fileReader } from "@modern-js/runtime-utils/fileReader";
|
|
|
2
2
|
import { LOADABLE_STATS_FILE, MAIN_ENTRY_NAME, NESTED_ROUTE_SPEC_FILE, ROUTE_MANIFEST_FILE, SERVER_BUNDLE_DIRECTORY, compatibleRequire, fs, isProd } from "@modern-js/utils";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { uniqueKeyByRoute } from "../../../utils/index.mjs";
|
|
5
|
-
import { collectDirectRemoteModuleFederationCss } from "./moduleFederationCss.mjs";
|
|
6
5
|
async function getHtmlTemplates(pwd, routes) {
|
|
7
6
|
const htmlRoutes = routes.filter((route)=>route.entryName);
|
|
8
7
|
const htmls = await Promise.all(htmlRoutes.map(async (route)=>{
|
|
@@ -57,16 +56,12 @@ async function getServerManifest(pwd, routes, monitors) {
|
|
|
57
56
|
const routeManifest = await compatibleRequire(routesManifestUri).catch((_)=>({}));
|
|
58
57
|
const nestedRoutesJsonPath = path.join(pwd, NESTED_ROUTE_SPEC_FILE);
|
|
59
58
|
const nestedRoutesJson = await compatibleRequire(nestedRoutesJsonPath).catch((_)=>({}));
|
|
60
|
-
const moduleFederationCssAssets = await collectDirectRemoteModuleFederationCss(pwd, {
|
|
61
|
-
monitors
|
|
62
|
-
});
|
|
63
59
|
return {
|
|
64
60
|
loaderBundles,
|
|
65
61
|
renderBundles,
|
|
66
62
|
loadableStats,
|
|
67
63
|
routeManifest,
|
|
68
|
-
nestedRoutesJson
|
|
69
|
-
moduleFederationCssAssets
|
|
64
|
+
nestedRoutesJson
|
|
70
65
|
};
|
|
71
66
|
}
|
|
72
67
|
function injectServerManifest(pwd, routes, manifestPromise) {
|
|
@@ -4,6 +4,8 @@ import { getMimeType } from "hono/utils/mime";
|
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { sortRoutes } from "../../../utils/index.mjs";
|
|
6
6
|
import { getPublicDirPatterns } from "../../../utils/publicDir.mjs";
|
|
7
|
+
import { applyModuleFederationAssetHeaders, getModuleFederationAssetList, getModuleFederationRequestPath, isModuleFederationManifestRequest, patchModuleFederationManifestPublicPath, patchModuleFederationRemoteEntryPublicPath } from "./staticModuleFederation.mjs";
|
|
8
|
+
import { applyPreCompressedAssetHeaders, resolvePreCompressedAsset } from "./staticPrecompressed.mjs";
|
|
7
9
|
const serverStaticPlugin = ()=>({
|
|
8
10
|
name: '@modern-js/plugin-server-static',
|
|
9
11
|
setup (api) {
|
|
@@ -24,91 +26,6 @@ const serverStaticPlugin = ()=>({
|
|
|
24
26
|
});
|
|
25
27
|
}
|
|
26
28
|
});
|
|
27
|
-
const PRE_COMPRESSED_ASSET_EXTENSIONS = {
|
|
28
|
-
br: '.br',
|
|
29
|
-
gzip: '.gz'
|
|
30
|
-
};
|
|
31
|
-
const PRE_COMPRESSED_SUPPORTED_ENCODINGS = [
|
|
32
|
-
'br',
|
|
33
|
-
'gzip'
|
|
34
|
-
];
|
|
35
|
-
const parseAcceptEncoding = (value)=>value.split(',').map((item)=>item.trim()).filter(Boolean).map((item)=>{
|
|
36
|
-
const [rawName, ...params] = item.split(';');
|
|
37
|
-
const name = rawName.trim().toLowerCase();
|
|
38
|
-
let q = 1;
|
|
39
|
-
for (const param of params){
|
|
40
|
-
const [key, rawValue] = param.split('=').map((v)=>v.trim());
|
|
41
|
-
if ('q' !== key.toLowerCase() || null == rawValue) continue;
|
|
42
|
-
const parsedQ = Number(rawValue);
|
|
43
|
-
if (!Number.isNaN(parsedQ)) q = Math.max(0, Math.min(parsedQ, 1));
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
name,
|
|
47
|
-
q
|
|
48
|
-
};
|
|
49
|
-
});
|
|
50
|
-
const getAcceptedEncodings = (value)=>{
|
|
51
|
-
if (!value) return [];
|
|
52
|
-
const parsed = parseAcceptEncoding(value);
|
|
53
|
-
const qualityByEncoding = new Map();
|
|
54
|
-
let wildcardQuality;
|
|
55
|
-
for (const { name, q } of parsed){
|
|
56
|
-
if ('*' === name) {
|
|
57
|
-
wildcardQuality = q;
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
qualityByEncoding.set(name, q);
|
|
61
|
-
}
|
|
62
|
-
const getQuality = (encoding)=>{
|
|
63
|
-
const explicit = qualityByEncoding.get(encoding);
|
|
64
|
-
if (void 0 !== explicit) return explicit;
|
|
65
|
-
return wildcardQuality ?? 0;
|
|
66
|
-
};
|
|
67
|
-
return PRE_COMPRESSED_SUPPORTED_ENCODINGS.map((encoding)=>({
|
|
68
|
-
encoding,
|
|
69
|
-
quality: getQuality(encoding)
|
|
70
|
-
})).filter((item)=>item.quality > 0).sort((a, b)=>b.quality - a.quality).map((item)=>item.encoding);
|
|
71
|
-
};
|
|
72
|
-
const appendVaryHeader = (c, value)=>{
|
|
73
|
-
const current = c.res.headers.get('Vary');
|
|
74
|
-
if (!current) return void c.header('Vary', value);
|
|
75
|
-
const values = current.split(',').map((item)=>item.trim().toLowerCase()).filter(Boolean);
|
|
76
|
-
if (!values.includes(value.toLowerCase())) c.header('Vary', `${current}, ${value}`);
|
|
77
|
-
};
|
|
78
|
-
const resolvePreCompressedAsset = async (c, filepath)=>{
|
|
79
|
-
const brPath = `${filepath}${PRE_COMPRESSED_ASSET_EXTENSIONS.br}`;
|
|
80
|
-
const gzipPath = `${filepath}${PRE_COMPRESSED_ASSET_EXTENSIONS.gzip}`;
|
|
81
|
-
const [hasBr, hasGzip] = await Promise.all([
|
|
82
|
-
fs.pathExists(brPath),
|
|
83
|
-
fs.pathExists(gzipPath)
|
|
84
|
-
]);
|
|
85
|
-
const hasVariant = hasBr || hasGzip;
|
|
86
|
-
if (!hasVariant) return {
|
|
87
|
-
selected: null,
|
|
88
|
-
hasVariant: false
|
|
89
|
-
};
|
|
90
|
-
const acceptedEncodings = getAcceptedEncodings(c.req.header('accept-encoding'));
|
|
91
|
-
for (const encoding of acceptedEncodings){
|
|
92
|
-
if ('br' === encoding && hasBr) return {
|
|
93
|
-
selected: {
|
|
94
|
-
filepath: brPath,
|
|
95
|
-
encoding
|
|
96
|
-
},
|
|
97
|
-
hasVariant: true
|
|
98
|
-
};
|
|
99
|
-
if ('gzip' === encoding && hasGzip) return {
|
|
100
|
-
selected: {
|
|
101
|
-
filepath: gzipPath,
|
|
102
|
-
encoding
|
|
103
|
-
},
|
|
104
|
-
hasVariant: true
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
return {
|
|
108
|
-
selected: null,
|
|
109
|
-
hasVariant: true
|
|
110
|
-
};
|
|
111
|
-
};
|
|
112
29
|
function createPublicMiddleware({ pwd, routes }) {
|
|
113
30
|
return async (c, next)=>{
|
|
114
31
|
const route = matchPublicRoute(c.req, routes);
|
|
@@ -125,8 +42,7 @@ function createPublicMiddleware({ pwd, routes }) {
|
|
|
125
42
|
Object.entries(route.responseHeaders || {}).forEach(([k, v])=>{
|
|
126
43
|
c.header(k, v);
|
|
127
44
|
});
|
|
128
|
-
|
|
129
|
-
if (preCompressedAsset.selected) c.header('Content-Encoding', preCompressedAsset.selected.encoding);
|
|
45
|
+
applyPreCompressedAssetHeaders(c, preCompressedAsset);
|
|
130
46
|
c.header('Content-Length', String(data.byteLength));
|
|
131
47
|
return c.body(body, 200);
|
|
132
48
|
}
|
|
@@ -146,91 +62,6 @@ const extractPathname = (url)=>{
|
|
|
146
62
|
return url;
|
|
147
63
|
}
|
|
148
64
|
};
|
|
149
|
-
const MODULE_FEDERATION_MANIFEST_FILE = 'mf-manifest.json';
|
|
150
|
-
const MODULE_FEDERATION_OPTIONAL_FILES = [
|
|
151
|
-
'mf-stats.json'
|
|
152
|
-
];
|
|
153
|
-
const trimLeadingSlash = (value)=>value.replace(/^\/+/, '');
|
|
154
|
-
const joinModuleFederationAssetPath = (assetPath, assetName)=>{
|
|
155
|
-
if (!assetName) return '';
|
|
156
|
-
return trimLeadingSlash(path.posix.join(assetPath || '', assetName));
|
|
157
|
-
};
|
|
158
|
-
const appendModuleFederationAsset = (set, assetPath)=>{
|
|
159
|
-
if (!assetPath) return;
|
|
160
|
-
set.add(trimLeadingSlash(assetPath));
|
|
161
|
-
};
|
|
162
|
-
const appendModuleFederationAssets = (set, assets)=>{
|
|
163
|
-
assets?.js?.sync?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
164
|
-
assets?.js?.async?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
165
|
-
assets?.css?.sync?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
166
|
-
assets?.css?.async?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
167
|
-
};
|
|
168
|
-
const hasAbsoluteProtocol = (value)=>/^https?:\/\//i.test(value) || value.startsWith('//');
|
|
169
|
-
const ensureLeadingSlash = (value)=>{
|
|
170
|
-
if ('' === value) return '/';
|
|
171
|
-
return value.startsWith('/') ? value : `/${value}`;
|
|
172
|
-
};
|
|
173
|
-
const ensureTrailingSlash = (value)=>value.endsWith('/') ? value : `${value}/`;
|
|
174
|
-
const patchModuleFederationManifestPublicPath = (c, manifestBuffer, pathPrefix)=>{
|
|
175
|
-
try {
|
|
176
|
-
const manifest = JSON.parse(manifestBuffer.toString('utf-8'));
|
|
177
|
-
const publicPath = manifest.metaData?.publicPath;
|
|
178
|
-
if (!publicPath || hasAbsoluteProtocol(publicPath)) return manifestBuffer;
|
|
179
|
-
const requestURL = new URL(c.req.url);
|
|
180
|
-
const prefixPath = ensureTrailingSlash(ensureLeadingSlash(pathPrefix || '/'));
|
|
181
|
-
manifest.metaData = {
|
|
182
|
-
...manifest.metaData,
|
|
183
|
-
publicPath: `${requestURL.origin}${prefixPath}`
|
|
184
|
-
};
|
|
185
|
-
return Buffer.from(JSON.stringify(manifest), 'utf-8');
|
|
186
|
-
} catch {
|
|
187
|
-
return manifestBuffer;
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
const patchModuleFederationRemoteEntryPublicPath = (c, remoteEntryBuffer, pathPrefix)=>{
|
|
191
|
-
const requestURL = new URL(c.req.url);
|
|
192
|
-
const prefixPath = ensureTrailingSlash(ensureLeadingSlash(pathPrefix || '/'));
|
|
193
|
-
const publicPath = `${requestURL.origin}${prefixPath}`;
|
|
194
|
-
const source = remoteEntryBuffer.toString('utf-8');
|
|
195
|
-
const patched = source.replace(/__webpack_require__\.p\s*=\s*(['"`])[^'"`]*\1;/, `__webpack_require__.p = ${JSON.stringify(publicPath)};`).replace(/__rspack_require__\.p\s*=\s*(['"`])[^'"`]*\1;/, `__rspack_require__.p = ${JSON.stringify(publicPath)};`);
|
|
196
|
-
if (patched === source) return remoteEntryBuffer;
|
|
197
|
-
return Buffer.from(patched, 'utf-8');
|
|
198
|
-
};
|
|
199
|
-
const getModuleFederationAssetList = async (pwd)=>{
|
|
200
|
-
const assets = new Set();
|
|
201
|
-
const manifestPath = path.join(pwd, MODULE_FEDERATION_MANIFEST_FILE);
|
|
202
|
-
if (!await fs.pathExists(manifestPath)) return {
|
|
203
|
-
assets,
|
|
204
|
-
remoteEntry: null
|
|
205
|
-
};
|
|
206
|
-
assets.add(MODULE_FEDERATION_MANIFEST_FILE);
|
|
207
|
-
const manifestBuffer = await fileReader.readFileFromSystem(manifestPath, 'buffer');
|
|
208
|
-
if (null === manifestBuffer) return {
|
|
209
|
-
assets,
|
|
210
|
-
remoteEntry: null
|
|
211
|
-
};
|
|
212
|
-
for (const filename of MODULE_FEDERATION_OPTIONAL_FILES)if (await fs.pathExists(path.join(pwd, filename))) assets.add(filename);
|
|
213
|
-
let remoteEntryFile = null;
|
|
214
|
-
try {
|
|
215
|
-
const manifest = JSON.parse(manifestBuffer.toString('utf-8'));
|
|
216
|
-
const remoteEntry = joinModuleFederationAssetPath(manifest.metaData?.remoteEntry?.path, manifest.metaData?.remoteEntry?.name);
|
|
217
|
-
const dtsZip = joinModuleFederationAssetPath(manifest.metaData?.types?.path, manifest.metaData?.types?.zip);
|
|
218
|
-
const dtsApi = joinModuleFederationAssetPath(manifest.metaData?.types?.path, manifest.metaData?.types?.api);
|
|
219
|
-
if (remoteEntry) {
|
|
220
|
-
assets.add(remoteEntry);
|
|
221
|
-
remoteEntryFile = remoteEntry;
|
|
222
|
-
}
|
|
223
|
-
if (dtsZip) assets.add(dtsZip);
|
|
224
|
-
if (dtsApi) assets.add(dtsApi);
|
|
225
|
-
manifest.shared?.forEach((item)=>appendModuleFederationAssets(assets, item.assets));
|
|
226
|
-
manifest.remotes?.forEach((item)=>appendModuleFederationAssets(assets, item.assets));
|
|
227
|
-
manifest.exposes?.forEach((item)=>appendModuleFederationAssets(assets, item.assets));
|
|
228
|
-
} catch {}
|
|
229
|
-
return {
|
|
230
|
-
assets,
|
|
231
|
-
remoteEntry: remoteEntryFile
|
|
232
|
-
};
|
|
233
|
-
};
|
|
234
65
|
function createStaticMiddleware(options) {
|
|
235
66
|
const { pwd, routes } = options;
|
|
236
67
|
const prefix = options.output.assetPrefix || '/';
|
|
@@ -271,14 +102,10 @@ function createStaticMiddleware(options) {
|
|
|
271
102
|
return moduleFederationAssetsPromise;
|
|
272
103
|
};
|
|
273
104
|
const serveFile = async (c, filepath, moduleFederationAsset = false, moduleFederationRemoteEntry = false, requestPath = '')=>{
|
|
274
|
-
if (moduleFederationAsset)
|
|
275
|
-
c.header('Access-Control-Allow-Origin', '*');
|
|
276
|
-
c.header('Access-Control-Allow-Headers', '*');
|
|
277
|
-
c.header('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS');
|
|
278
|
-
}
|
|
105
|
+
if (moduleFederationAsset) applyModuleFederationAssetHeaders(c);
|
|
279
106
|
const mimeType = getMimeType(filepath);
|
|
280
107
|
if (mimeType) c.header('Content-Type', mimeType);
|
|
281
|
-
const shouldPatchManifest = moduleFederationAsset && requestPath
|
|
108
|
+
const shouldPatchManifest = moduleFederationAsset && isModuleFederationManifestRequest(requestPath);
|
|
282
109
|
const shouldPatchRemoteEntry = moduleFederationRemoteEntry;
|
|
283
110
|
const canUsePreCompressed = !shouldPatchManifest && !shouldPatchRemoteEntry;
|
|
284
111
|
const preCompressedAsset = canUsePreCompressed ? await resolvePreCompressedAsset(c, filepath) : {
|
|
@@ -289,8 +116,7 @@ function createStaticMiddleware(options) {
|
|
|
289
116
|
const chunk = await fileReader.readFileFromSystem(targetFilepath, 'buffer');
|
|
290
117
|
if (null === chunk) return null;
|
|
291
118
|
const responseChunk = shouldPatchManifest ? patchModuleFederationManifestPublicPath(c, chunk, pathPrefix) : shouldPatchRemoteEntry ? patchModuleFederationRemoteEntryPublicPath(c, chunk, pathPrefix) : chunk;
|
|
292
|
-
|
|
293
|
-
if (preCompressedAsset.selected) c.header('Content-Encoding', preCompressedAsset.selected.encoding);
|
|
119
|
+
applyPreCompressedAssetHeaders(c, preCompressedAsset);
|
|
294
120
|
c.header('Content-Length', String(responseChunk.byteLength));
|
|
295
121
|
const body = new Uint8Array(responseChunk.buffer, responseChunk.byteOffset, responseChunk.byteLength);
|
|
296
122
|
return c.body(body, 200);
|
|
@@ -300,7 +126,7 @@ function createStaticMiddleware(options) {
|
|
|
300
126
|
const pathname = c.req.path;
|
|
301
127
|
if (pageRoute && '' === path.extname(pathname)) return next();
|
|
302
128
|
const hit = staticPathRegExp.test(pathname);
|
|
303
|
-
const requestPath =
|
|
129
|
+
const requestPath = getModuleFederationRequestPath(pathname, pathPrefix);
|
|
304
130
|
if (requestPath.includes('..')) return next();
|
|
305
131
|
const moduleFederationAssetMeta = await getModuleFederationAssets();
|
|
306
132
|
const isModuleFederationAsset = moduleFederationAssetMeta.assets.has(requestPath);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { fileReader } from "@modern-js/runtime-utils/fileReader";
|
|
2
|
+
import { fs } from "@modern-js/utils";
|
|
3
|
+
import path from "path";
|
|
4
|
+
const MODULE_FEDERATION_MANIFEST_FILE = 'mf-manifest.json';
|
|
5
|
+
const MODULE_FEDERATION_OPTIONAL_FILES = [
|
|
6
|
+
'mf-stats.json'
|
|
7
|
+
];
|
|
8
|
+
const trimLeadingSlash = (value)=>value.replace(/^\/+/, '');
|
|
9
|
+
const getModuleFederationRequestPath = (pathname, pathPrefix)=>trimLeadingSlash(pathname.replace(pathPrefix, ()=>''));
|
|
10
|
+
const isModuleFederationManifestRequest = (requestPath)=>requestPath === MODULE_FEDERATION_MANIFEST_FILE;
|
|
11
|
+
const applyModuleFederationAssetHeaders = (c)=>{
|
|
12
|
+
c.header('Access-Control-Allow-Origin', '*');
|
|
13
|
+
c.header('Access-Control-Allow-Headers', '*');
|
|
14
|
+
c.header('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS');
|
|
15
|
+
};
|
|
16
|
+
const joinModuleFederationAssetPath = (assetPath, assetName)=>{
|
|
17
|
+
if (!assetName) return '';
|
|
18
|
+
return trimLeadingSlash(path.posix.join(assetPath || '', assetName));
|
|
19
|
+
};
|
|
20
|
+
const appendModuleFederationAsset = (set, assetPath)=>{
|
|
21
|
+
if (!assetPath) return;
|
|
22
|
+
set.add(trimLeadingSlash(assetPath));
|
|
23
|
+
};
|
|
24
|
+
const appendModuleFederationAssets = (set, assets)=>{
|
|
25
|
+
assets?.js?.sync?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
26
|
+
assets?.js?.async?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
27
|
+
assets?.css?.sync?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
28
|
+
assets?.css?.async?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
29
|
+
};
|
|
30
|
+
const hasAbsoluteProtocol = (value)=>/^https?:\/\//i.test(value) || value.startsWith('//');
|
|
31
|
+
const ensureLeadingSlash = (value)=>{
|
|
32
|
+
if ('' === value) return '/';
|
|
33
|
+
return value.startsWith('/') ? value : `/${value}`;
|
|
34
|
+
};
|
|
35
|
+
const ensureTrailingSlash = (value)=>value.endsWith('/') ? value : `${value}/`;
|
|
36
|
+
const patchModuleFederationManifestPublicPath = (c, manifestBuffer, pathPrefix)=>{
|
|
37
|
+
try {
|
|
38
|
+
const manifest = JSON.parse(manifestBuffer.toString('utf-8'));
|
|
39
|
+
const publicPath = manifest.metaData?.publicPath;
|
|
40
|
+
if (!publicPath || hasAbsoluteProtocol(publicPath)) return manifestBuffer;
|
|
41
|
+
const requestURL = new URL(c.req.url);
|
|
42
|
+
const prefixPath = ensureTrailingSlash(ensureLeadingSlash(pathPrefix || '/'));
|
|
43
|
+
manifest.metaData = {
|
|
44
|
+
...manifest.metaData,
|
|
45
|
+
publicPath: `${requestURL.origin}${prefixPath}`
|
|
46
|
+
};
|
|
47
|
+
return Buffer.from(JSON.stringify(manifest), 'utf-8');
|
|
48
|
+
} catch {
|
|
49
|
+
return manifestBuffer;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const patchModuleFederationRemoteEntryPublicPath = (c, remoteEntryBuffer, pathPrefix)=>{
|
|
53
|
+
const requestURL = new URL(c.req.url);
|
|
54
|
+
const prefixPath = ensureTrailingSlash(ensureLeadingSlash(pathPrefix || '/'));
|
|
55
|
+
const publicPath = `${requestURL.origin}${prefixPath}`;
|
|
56
|
+
const source = remoteEntryBuffer.toString('utf-8');
|
|
57
|
+
const patched = source.replace(/__webpack_require__\.p\s*=\s*(['"`])[^'"`]*\1;/, `__webpack_require__.p = ${JSON.stringify(publicPath)};`).replace(/__rspack_require__\.p\s*=\s*(['"`])[^'"`]*\1;/, `__rspack_require__.p = ${JSON.stringify(publicPath)};`);
|
|
58
|
+
if (patched === source) return remoteEntryBuffer;
|
|
59
|
+
return Buffer.from(patched, 'utf-8');
|
|
60
|
+
};
|
|
61
|
+
const getModuleFederationAssetList = async (pwd)=>{
|
|
62
|
+
const assets = new Set();
|
|
63
|
+
const manifestPath = path.join(pwd, MODULE_FEDERATION_MANIFEST_FILE);
|
|
64
|
+
if (!await fs.pathExists(manifestPath)) return {
|
|
65
|
+
assets,
|
|
66
|
+
remoteEntry: null
|
|
67
|
+
};
|
|
68
|
+
assets.add(MODULE_FEDERATION_MANIFEST_FILE);
|
|
69
|
+
const manifestBuffer = await fileReader.readFileFromSystem(manifestPath, 'buffer');
|
|
70
|
+
if (null === manifestBuffer) return {
|
|
71
|
+
assets,
|
|
72
|
+
remoteEntry: null
|
|
73
|
+
};
|
|
74
|
+
for (const filename of MODULE_FEDERATION_OPTIONAL_FILES)if (await fs.pathExists(path.join(pwd, filename))) assets.add(filename);
|
|
75
|
+
let remoteEntryFile = null;
|
|
76
|
+
try {
|
|
77
|
+
const manifest = JSON.parse(manifestBuffer.toString('utf-8'));
|
|
78
|
+
const remoteEntry = joinModuleFederationAssetPath(manifest.metaData?.remoteEntry?.path, manifest.metaData?.remoteEntry?.name);
|
|
79
|
+
const dtsZip = joinModuleFederationAssetPath(manifest.metaData?.types?.path, manifest.metaData?.types?.zip);
|
|
80
|
+
const dtsApi = joinModuleFederationAssetPath(manifest.metaData?.types?.path, manifest.metaData?.types?.api);
|
|
81
|
+
if (remoteEntry) {
|
|
82
|
+
assets.add(remoteEntry);
|
|
83
|
+
remoteEntryFile = remoteEntry;
|
|
84
|
+
}
|
|
85
|
+
if (dtsZip) assets.add(dtsZip);
|
|
86
|
+
if (dtsApi) assets.add(dtsApi);
|
|
87
|
+
manifest.shared?.forEach((item)=>appendModuleFederationAssets(assets, item.assets));
|
|
88
|
+
manifest.remotes?.forEach((item)=>appendModuleFederationAssets(assets, item.assets));
|
|
89
|
+
manifest.exposes?.forEach((item)=>appendModuleFederationAssets(assets, item.assets));
|
|
90
|
+
} catch {}
|
|
91
|
+
return {
|
|
92
|
+
assets,
|
|
93
|
+
remoteEntry: remoteEntryFile
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
export { MODULE_FEDERATION_MANIFEST_FILE, applyModuleFederationAssetHeaders, getModuleFederationAssetList, getModuleFederationRequestPath, isModuleFederationManifestRequest, patchModuleFederationManifestPublicPath, patchModuleFederationRemoteEntryPublicPath, trimLeadingSlash };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { fs } from "@modern-js/utils";
|
|
2
|
+
const PRE_COMPRESSED_ASSET_EXTENSIONS = {
|
|
3
|
+
br: '.br',
|
|
4
|
+
gzip: '.gz'
|
|
5
|
+
};
|
|
6
|
+
const PRE_COMPRESSED_SUPPORTED_ENCODINGS = [
|
|
7
|
+
'br',
|
|
8
|
+
'gzip'
|
|
9
|
+
];
|
|
10
|
+
const parseAcceptEncoding = (value)=>value.split(',').map((item)=>item.trim()).filter(Boolean).map((item)=>{
|
|
11
|
+
const [rawName, ...params] = item.split(';');
|
|
12
|
+
const name = rawName.trim().toLowerCase();
|
|
13
|
+
let q = 1;
|
|
14
|
+
for (const param of params){
|
|
15
|
+
const [key, rawValue] = param.split('=').map((v)=>v.trim());
|
|
16
|
+
if ('q' !== key.toLowerCase() || null == rawValue) continue;
|
|
17
|
+
const parsedQ = Number(rawValue);
|
|
18
|
+
if (!Number.isNaN(parsedQ)) q = Math.max(0, Math.min(parsedQ, 1));
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
name,
|
|
22
|
+
q
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
const getAcceptedEncodings = (value)=>{
|
|
26
|
+
if (!value) return [];
|
|
27
|
+
const parsed = parseAcceptEncoding(value);
|
|
28
|
+
const qualityByEncoding = new Map();
|
|
29
|
+
let wildcardQuality;
|
|
30
|
+
for (const { name, q } of parsed){
|
|
31
|
+
if ('*' === name) {
|
|
32
|
+
wildcardQuality = q;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
qualityByEncoding.set(name, q);
|
|
36
|
+
}
|
|
37
|
+
const getQuality = (encoding)=>{
|
|
38
|
+
const explicit = qualityByEncoding.get(encoding);
|
|
39
|
+
if (void 0 !== explicit) return explicit;
|
|
40
|
+
return wildcardQuality ?? 0;
|
|
41
|
+
};
|
|
42
|
+
return PRE_COMPRESSED_SUPPORTED_ENCODINGS.map((encoding)=>({
|
|
43
|
+
encoding,
|
|
44
|
+
quality: getQuality(encoding)
|
|
45
|
+
})).filter((item)=>item.quality > 0).sort((a, b)=>b.quality - a.quality).map((item)=>item.encoding);
|
|
46
|
+
};
|
|
47
|
+
const appendVaryHeader = (c, value)=>{
|
|
48
|
+
const current = c.res.headers.get('Vary');
|
|
49
|
+
if (!current) return void c.header('Vary', value);
|
|
50
|
+
const values = current.split(',').map((item)=>item.trim().toLowerCase()).filter(Boolean);
|
|
51
|
+
if (!values.includes(value.toLowerCase())) c.header('Vary', `${current}, ${value}`);
|
|
52
|
+
};
|
|
53
|
+
const resolvePreCompressedAsset = async (c, filepath)=>{
|
|
54
|
+
const brPath = `${filepath}${PRE_COMPRESSED_ASSET_EXTENSIONS.br}`;
|
|
55
|
+
const gzipPath = `${filepath}${PRE_COMPRESSED_ASSET_EXTENSIONS.gzip}`;
|
|
56
|
+
const [hasBr, hasGzip] = await Promise.all([
|
|
57
|
+
fs.pathExists(brPath),
|
|
58
|
+
fs.pathExists(gzipPath)
|
|
59
|
+
]);
|
|
60
|
+
const hasVariant = hasBr || hasGzip;
|
|
61
|
+
if (!hasVariant) return {
|
|
62
|
+
selected: null,
|
|
63
|
+
hasVariant: false
|
|
64
|
+
};
|
|
65
|
+
const acceptedEncodings = getAcceptedEncodings(c.req.header('accept-encoding'));
|
|
66
|
+
for (const encoding of acceptedEncodings){
|
|
67
|
+
if ('br' === encoding && hasBr) return {
|
|
68
|
+
selected: {
|
|
69
|
+
filepath: brPath,
|
|
70
|
+
encoding
|
|
71
|
+
},
|
|
72
|
+
hasVariant: true
|
|
73
|
+
};
|
|
74
|
+
if ('gzip' === encoding && hasGzip) return {
|
|
75
|
+
selected: {
|
|
76
|
+
filepath: gzipPath,
|
|
77
|
+
encoding
|
|
78
|
+
},
|
|
79
|
+
hasVariant: true
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
selected: null,
|
|
84
|
+
hasVariant: true
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
const applyPreCompressedAssetHeaders = (c, preCompressedAsset)=>{
|
|
88
|
+
if (preCompressedAsset.hasVariant) appendVaryHeader(c, 'Accept-Encoding');
|
|
89
|
+
if (preCompressedAsset.selected) c.header('Content-Encoding', preCompressedAsset.selected.encoding);
|
|
90
|
+
};
|
|
91
|
+
export { appendVaryHeader, applyPreCompressedAssetHeaders, resolvePreCompressedAsset };
|
package/dist/esm/index.mjs
CHANGED
|
@@ -8,5 +8,5 @@ export { AGGRED_DIR } from "./constants.mjs";
|
|
|
8
8
|
export { run, useHonoContext } from "./context.mjs";
|
|
9
9
|
export { getLoaderCtx } from "./helper.mjs";
|
|
10
10
|
export { createServerBase } from "./serverBase.mjs";
|
|
11
|
-
export { ErrorDigest, createErrorHtml, onError } from "./utils/index.mjs";
|
|
11
|
+
export { ErrorDigest, createErrorHtml, createSafeFailureHttpResult, createSafeJsonFailureResponse, getSafeFailureStatus, onError } from "./utils/index.mjs";
|
|
12
12
|
export { getPublicDirConfig, getPublicDirPatterns, getPublicDirRoutePrefixes, normalizePublicDir, normalizePublicDirPath, resolvePublicDirPaths } from "./utils/publicDir.mjs";
|
|
@@ -4,7 +4,6 @@ import { initMonitorsPlugin, injectServerTiming, injectloggerPlugin } from "./mo
|
|
|
4
4
|
import { processedByPlugin } from "./processedBy.mjs";
|
|
5
5
|
import { injectRenderHandlerPlugin } from "./render/index.mjs";
|
|
6
6
|
import { injectRoutePlugin } from "./route.mjs";
|
|
7
|
-
import { injectTelemetryPlugin } from "./telemetry.mjs";
|
|
8
7
|
function createSilenceLogger() {
|
|
9
8
|
return new Proxy({}, {
|
|
10
9
|
get: ()=>()=>{}
|
|
@@ -15,7 +14,6 @@ function createDefaultPlugins(options = {}) {
|
|
|
15
14
|
compatPlugin(),
|
|
16
15
|
logPlugin(),
|
|
17
16
|
initMonitorsPlugin(),
|
|
18
|
-
injectTelemetryPlugin(),
|
|
19
17
|
injectRenderHandlerPlugin(options),
|
|
20
18
|
injectloggerPlugin(options.logger ? options.logger : createSilenceLogger()),
|
|
21
19
|
injectServerTiming(),
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
export { compatPlugin, handleSetupResult } from "./compat/index.mjs";
|
|
2
|
-
export { ContractGateAutopilot } from "./contractGateAutopilot.mjs";
|
|
3
|
-
export { CONTRACT_GATE_SNAPSHOT_SCHEMA_VERSION, DEFAULT_CONTRACT_GATE_SNAPSHOT_PATH, createFileContractGateSnapshotStore, createHttpContractGateSnapshotStore, resolveContractGateSnapshotPath, resolveContractGateSnapshotStore } from "./contractGateSnapshotStore.mjs";
|
|
4
2
|
export { createDefaultPlugins } from "./default.mjs";
|
|
5
3
|
export { faviconPlugin } from "./favicon.mjs";
|
|
6
4
|
export { logPlugin } from "./log.mjs";
|
|
@@ -8,4 +6,3 @@ export { injectConfigMiddlewarePlugin } from "./middlewares.mjs";
|
|
|
8
6
|
export { injectServerTiming, injectloggerPlugin } from "./monitors.mjs";
|
|
9
7
|
export { processedByPlugin } from "./processedBy.mjs";
|
|
10
8
|
export { getRenderHandler, injectRenderHandlerPlugin, renderPlugin } from "./render/index.mjs";
|
|
11
|
-
export { DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT, DEFAULT_RUNTIME_STATUS_ENDPOINT, TelemetryCanaryOrchestrator, TelemetryRegistry, TelemetryStartupHealthError, createOtlpTelemetryExporter, createRuntimeFallbackSignalRuntimeState, createRuntimeSignalError, createTelemetryAwareMetrics, createVictoriaMetricsTelemetryExporter, enforceRuntimeFallbackSignalAuthToken, enforceRuntimeFallbackSignalTrustPolicy, getRuntimeSignalErrorStatusCode, hasEnabledTelemetryExporters, injectTelemetryPlugin, normalizeRuntimeFallbackSignalAuthConfig, normalizeRuntimeFallbackTrustPolicy, parseRuntimeFallbackSignalPayloadFromRawBody, resolveRuntimeFallbackSignalEndpoint } from "./telemetry.mjs";
|
|
@@ -7,10 +7,11 @@ const injectRenderHandlerPlugin = ({ staticGenerate, cacheConfig })=>({
|
|
|
7
7
|
const config = api.getServerConfig();
|
|
8
8
|
const hooks = api.getHooks();
|
|
9
9
|
if (!routes) return;
|
|
10
|
-
const onFallback = async (reason, error)=>{
|
|
10
|
+
const onFallback = async (reason, error, context)=>{
|
|
11
11
|
await hooks.fallback.call({
|
|
12
12
|
reason,
|
|
13
|
-
error
|
|
13
|
+
error,
|
|
14
|
+
context
|
|
14
15
|
});
|
|
15
16
|
};
|
|
16
17
|
const getRenderHandlerOptions = {
|
|
@@ -10,7 +10,7 @@ import { ssrRender } from "./ssrRender.mjs";
|
|
|
10
10
|
import { __webpack_require__ } from "../../rslib-runtime.mjs";
|
|
11
11
|
import * as __rspack_external__modern_js_runtime_utils_router_2aa8d96f from "@modern-js/runtime-utils/router";
|
|
12
12
|
__webpack_require__.add({
|
|
13
|
-
|
|
13
|
+
2420 (module) {
|
|
14
14
|
module.exports = __rspack_external__modern_js_runtime_utils_router_2aa8d96f;
|
|
15
15
|
}
|
|
16
16
|
});
|
|
@@ -75,9 +75,13 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
|
|
|
75
75
|
const framework = cutNameByHyphen(metaName || 'modern-js');
|
|
76
76
|
const fallbackHeader = `x-${framework}-ssr-fallback`;
|
|
77
77
|
let fallbackReason = null;
|
|
78
|
+
const fallbackContext = {
|
|
79
|
+
request: req,
|
|
80
|
+
monitors
|
|
81
|
+
};
|
|
78
82
|
const fallbackWrapper = async (reason, error)=>{
|
|
79
83
|
fallbackReason = reason;
|
|
80
|
-
return onFallback?.(reason, error);
|
|
84
|
+
return onFallback?.(reason, error, fallbackContext);
|
|
81
85
|
};
|
|
82
86
|
if (!routeInfo) return new Response(createErrorHtml(404), {
|
|
83
87
|
status: 404,
|
|
@@ -158,7 +162,7 @@ async function renderHandler(request, options, mode, fallbackWrapper, framework)
|
|
|
158
162
|
const { nestedRoutesJson } = serverManifest;
|
|
159
163
|
const routes = nestedRoutesJson?.[options.routeInfo.entryName];
|
|
160
164
|
if (routes) {
|
|
161
|
-
const { matchRoutes } = __webpack_require__(
|
|
165
|
+
const { matchRoutes } = __webpack_require__(2420);
|
|
162
166
|
const url = new URL(request.url);
|
|
163
167
|
const matchedRoutes = matchRoutes(routes, url.pathname, options.routeInfo.urlPath);
|
|
164
168
|
if (matchedRoutes) {
|
|
File without changes
|
|
File without changes
|
package/dist/esm/utils/error.mjs
CHANGED
|
@@ -3,6 +3,59 @@ const ERROR_PAGE_TEXT = {
|
|
|
3
3
|
404: 'This page could not be found.',
|
|
4
4
|
500: 'Internal Server Error.'
|
|
5
5
|
};
|
|
6
|
+
const SAFE_FAILURE_MESSAGES = {
|
|
7
|
+
500: 'Internal Server Error',
|
|
8
|
+
503: 'Service Unavailable'
|
|
9
|
+
};
|
|
10
|
+
const SAFE_FAILURE_CODES = {
|
|
11
|
+
500: 'INTERNAL_SERVER_ERROR',
|
|
12
|
+
503: 'SERVICE_UNAVAILABLE'
|
|
13
|
+
};
|
|
14
|
+
const readErrorProperty = (error, key)=>{
|
|
15
|
+
if ('object' != typeof error || null === error || !(key in error)) return;
|
|
16
|
+
return error[key];
|
|
17
|
+
};
|
|
18
|
+
const normalizeFailureStatus = (value)=>{
|
|
19
|
+
if ('number' != typeof value || !Number.isInteger(value)) return;
|
|
20
|
+
return value >= 400 && value <= 599 ? value : void 0;
|
|
21
|
+
};
|
|
22
|
+
const normalizeRetryAfter = (value)=>{
|
|
23
|
+
if ('number' == typeof value && Number.isFinite(value) && value >= 0) return String(Math.ceil(value));
|
|
24
|
+
if ('string' == typeof value) {
|
|
25
|
+
const trimmed = value.trim();
|
|
26
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
27
|
+
}
|
|
28
|
+
if (value instanceof Date) return value.toUTCString();
|
|
29
|
+
};
|
|
30
|
+
const getSafeFailureStatus = (error)=>normalizeFailureStatus(readErrorProperty(error, 'status')) ?? normalizeFailureStatus(readErrorProperty(error, 'statusCode')) ?? 500;
|
|
31
|
+
const createSafeFailureHttpResult = (error)=>{
|
|
32
|
+
const status = getSafeFailureStatus(error);
|
|
33
|
+
const retryAfter = 503 === status ? normalizeRetryAfter(readErrorProperty(error, 'retryAfter')) ?? normalizeRetryAfter(readErrorProperty(error, 'retryAfterSeconds')) ?? normalizeRetryAfter('number' == typeof readErrorProperty(error, 'retryAfterMs') ? readErrorProperty(error, 'retryAfterMs') / 1000 : void 0) : void 0;
|
|
34
|
+
return {
|
|
35
|
+
status,
|
|
36
|
+
body: {
|
|
37
|
+
success: false,
|
|
38
|
+
error: {
|
|
39
|
+
code: SAFE_FAILURE_CODES[status] ?? 'REQUEST_FAILED',
|
|
40
|
+
message: SAFE_FAILURE_MESSAGES[status] ?? 'Request failed',
|
|
41
|
+
status
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
headers: {
|
|
45
|
+
'content-type': 'application/json; charset=utf-8',
|
|
46
|
+
...retryAfter ? {
|
|
47
|
+
'Retry-After': retryAfter
|
|
48
|
+
} : {}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
const createSafeJsonFailureResponse = (error)=>{
|
|
53
|
+
const result = createSafeFailureHttpResult(error);
|
|
54
|
+
return new Response(JSON.stringify(result.body), {
|
|
55
|
+
status: result.status,
|
|
56
|
+
headers: result.headers
|
|
57
|
+
});
|
|
58
|
+
};
|
|
6
59
|
const createErrorHtml = (status)=>{
|
|
7
60
|
const text = ERROR_PAGE_TEXT[status] || '';
|
|
8
61
|
const title = `${status}: ${text}`;
|
|
@@ -50,4 +103,4 @@ function onError(digest, error, monitors, req) {
|
|
|
50
103
|
else if (req) console.error(`Server Error - ${digest}, error = ${error instanceof Error ? error.stack || error.message : error}, req.url = ${req.url}, req.headers = ${JSON.stringify(headerData)}`);
|
|
51
104
|
else console.error(`Server Error - ${digest}, error = ${error instanceof Error ? error.stack || error.message : error} `);
|
|
52
105
|
}
|
|
53
|
-
export { createErrorHtml, error_ErrorDigest as ErrorDigest, onError };
|
|
106
|
+
export { createErrorHtml, createSafeFailureHttpResult, createSafeJsonFailureResponse, error_ErrorDigest as ErrorDigest, getSafeFailureStatus, onError };
|