@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.
Files changed (113) hide show
  1. package/dist/cjs/adapters/node/helper/index.js +9 -5
  2. package/dist/cjs/adapters/node/helper/loadCache.js +9 -5
  3. package/dist/cjs/adapters/node/helper/loadConfig.js +9 -5
  4. package/dist/cjs/adapters/node/helper/loadEnv.js +9 -5
  5. package/dist/cjs/adapters/node/helper/loadPlugin.js +9 -5
  6. package/dist/cjs/adapters/node/helper/utils.js +12 -8
  7. package/dist/cjs/adapters/node/hono.js +9 -5
  8. package/dist/cjs/adapters/node/index.js +9 -5
  9. package/dist/cjs/adapters/node/node.js +9 -5
  10. package/dist/cjs/adapters/node/plugins/index.js +9 -5
  11. package/dist/cjs/adapters/node/plugins/nodeServer.js +12 -8
  12. package/dist/cjs/adapters/node/plugins/resource.js +10 -11
  13. package/dist/cjs/adapters/node/plugins/static.js +20 -190
  14. package/dist/cjs/adapters/node/plugins/staticModuleFederation.js +165 -0
  15. package/dist/cjs/adapters/node/plugins/staticPrecompressed.js +135 -0
  16. package/dist/cjs/constants.js +18 -13
  17. package/dist/cjs/context.js +9 -5
  18. package/dist/cjs/helper.js +12 -8
  19. package/dist/cjs/hono.js +9 -5
  20. package/dist/cjs/index.js +60 -32
  21. package/dist/cjs/plugins/compat/hooks.js +14 -10
  22. package/dist/cjs/plugins/compat/index.js +9 -5
  23. package/dist/cjs/plugins/default.js +9 -7
  24. package/dist/cjs/plugins/favicon.js +12 -8
  25. package/dist/cjs/plugins/index.js +11 -88
  26. package/dist/cjs/plugins/log.js +9 -5
  27. package/dist/cjs/plugins/middlewares.js +12 -8
  28. package/dist/cjs/plugins/monitors.js +9 -5
  29. package/dist/cjs/plugins/processedBy.js +12 -8
  30. package/dist/cjs/plugins/render/csrRscRender.js +9 -5
  31. package/dist/cjs/plugins/render/dataHandler.js +9 -5
  32. package/dist/cjs/plugins/render/index.js +12 -8
  33. package/dist/cjs/plugins/render/inject.js +12 -7
  34. package/dist/cjs/plugins/render/render.js +14 -6
  35. package/dist/cjs/plugins/render/renderRscHandler.js +9 -5
  36. package/dist/cjs/plugins/render/serverActionHandler.js +9 -5
  37. package/dist/cjs/plugins/render/ssrCache.js +9 -5
  38. package/dist/cjs/plugins/render/ssrRender.js +9 -5
  39. package/dist/cjs/plugins/render/utils.js +12 -8
  40. package/dist/cjs/plugins/route.js +9 -5
  41. package/dist/cjs/serverBase.js +9 -5
  42. package/dist/cjs/types/config/bffRuntime.js +18 -0
  43. package/dist/cjs/types/config/index.js +9 -5
  44. package/dist/cjs/types/config/serverTelemetry.js +18 -0
  45. package/dist/cjs/types/index.js +9 -5
  46. package/dist/cjs/types/plugins/index.js +9 -5
  47. package/dist/cjs/utils/entry.js +13 -9
  48. package/dist/cjs/utils/env.js +13 -9
  49. package/dist/cjs/utils/error.js +71 -5
  50. package/dist/cjs/utils/index.js +9 -5
  51. package/dist/cjs/utils/middlewareCollector.js +13 -9
  52. package/dist/cjs/utils/publicDir.js +9 -5
  53. package/dist/cjs/utils/request.js +16 -12
  54. package/dist/cjs/utils/serverConfig.js +9 -5
  55. package/dist/cjs/utils/storage.js +9 -5
  56. package/dist/cjs/utils/transformStream.js +13 -9
  57. package/dist/cjs/utils/warmup.js +12 -8
  58. package/dist/esm/adapters/node/plugins/resource.mjs +1 -6
  59. package/dist/esm/adapters/node/plugins/static.mjs +7 -181
  60. package/dist/esm/adapters/node/plugins/staticModuleFederation.mjs +96 -0
  61. package/dist/esm/adapters/node/plugins/staticPrecompressed.mjs +91 -0
  62. package/dist/esm/index.mjs +1 -1
  63. package/dist/esm/plugins/default.mjs +0 -2
  64. package/dist/esm/plugins/index.mjs +0 -3
  65. package/dist/esm/plugins/render/inject.mjs +3 -2
  66. package/dist/esm/plugins/render/render.mjs +7 -3
  67. package/dist/esm/types/config/bffRuntime.mjs +0 -0
  68. package/dist/esm/types/config/serverTelemetry.mjs +0 -0
  69. package/dist/esm/utils/error.mjs +54 -1
  70. package/dist/esm-node/adapters/node/plugins/resource.mjs +1 -6
  71. package/dist/esm-node/adapters/node/plugins/static.mjs +7 -181
  72. package/dist/esm-node/adapters/node/plugins/staticModuleFederation.mjs +97 -0
  73. package/dist/esm-node/adapters/node/plugins/staticPrecompressed.mjs +92 -0
  74. package/dist/esm-node/index.mjs +1 -1
  75. package/dist/esm-node/plugins/default.mjs +0 -2
  76. package/dist/esm-node/plugins/index.mjs +0 -3
  77. package/dist/esm-node/plugins/render/inject.mjs +3 -2
  78. package/dist/esm-node/plugins/render/render.mjs +5 -1
  79. package/dist/esm-node/types/config/bffRuntime.mjs +1 -0
  80. package/dist/esm-node/types/config/serverTelemetry.mjs +1 -0
  81. package/dist/esm-node/utils/error.mjs +54 -1
  82. package/dist/types/adapters/node/plugins/staticModuleFederation.d.ts +13 -0
  83. package/dist/types/adapters/node/plugins/staticPrecompressed.d.ts +13 -0
  84. package/dist/types/index.d.ts +2 -1
  85. package/dist/types/plugins/index.d.ts +0 -3
  86. package/dist/types/types/config/bff.d.ts +2 -97
  87. package/dist/types/types/config/bffRuntime.d.ts +105 -0
  88. package/dist/types/types/config/server.d.ts +3 -337
  89. package/dist/types/types/config/serverTelemetry.d.ts +319 -0
  90. package/dist/types/types/plugins/base.d.ts +7 -2
  91. package/dist/types/types/plugins/index.d.ts +1 -1
  92. package/dist/types/utils/error.d.ts +16 -0
  93. package/package.json +12 -12
  94. package/dist/cjs/adapters/node/plugins/moduleFederationCss.js +0 -172
  95. package/dist/cjs/plugins/contractGateAutopilot.js +0 -158
  96. package/dist/cjs/plugins/contractGateSnapshotStore.js +0 -239
  97. package/dist/cjs/plugins/mfCache.js +0 -78
  98. package/dist/cjs/plugins/telemetry.js +0 -1283
  99. package/dist/esm/adapters/node/plugins/moduleFederationCss.mjs +0 -125
  100. package/dist/esm/plugins/contractGateAutopilot.mjs +0 -124
  101. package/dist/esm/plugins/contractGateSnapshotStore.mjs +0 -180
  102. package/dist/esm/plugins/mfCache.mjs +0 -35
  103. package/dist/esm/plugins/telemetry.mjs +0 -1195
  104. package/dist/esm-node/adapters/node/plugins/moduleFederationCss.mjs +0 -126
  105. package/dist/esm-node/plugins/contractGateAutopilot.mjs +0 -125
  106. package/dist/esm-node/plugins/contractGateSnapshotStore.mjs +0 -182
  107. package/dist/esm-node/plugins/mfCache.mjs +0 -36
  108. package/dist/esm-node/plugins/telemetry.mjs +0 -1196
  109. package/dist/types/adapters/node/plugins/moduleFederationCss.d.ts +0 -33
  110. package/dist/types/plugins/contractGateAutopilot.d.ts +0 -35
  111. package/dist/types/plugins/contractGateSnapshotStore.d.ts +0 -57
  112. package/dist/types/plugins/mfCache.d.ts +0 -12
  113. package/dist/types/plugins/telemetry.d.ts +0 -309
@@ -1,11 +1,15 @@
1
1
  "use strict";
2
2
  var __webpack_require__ = {};
3
3
  (()=>{
4
- __webpack_require__.d = (exports1, definition)=>{
5
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
- enumerable: true,
7
- get: definition[key]
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
- if (preCompressedAsset.hasVariant) appendVaryHeader(c, 'Accept-Encoding');
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 === MODULE_FEDERATION_MANIFEST_FILE;
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
- if (preCompressedAsset.hasVariant) appendVaryHeader(c, 'Accept-Encoding');
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 = trimLeadingSlash(pathname.replace(pathPrefix, ()=>''));
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 };
@@ -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
- "@modern-js/runtime-utils/router" (module) {
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__("@modern-js/runtime-utils/router");
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
@@ -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 };