@bleedingdev/modern-js-server-core 3.2.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/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/cjs/adapters/node/helper/index.js +55 -0
- package/dist/cjs/adapters/node/helper/loadCache.js +58 -0
- package/dist/cjs/adapters/node/helper/loadConfig.js +78 -0
- package/dist/cjs/adapters/node/helper/loadEnv.js +66 -0
- package/dist/cjs/adapters/node/helper/loadPlugin.js +47 -0
- package/dist/cjs/adapters/node/helper/utils.js +39 -0
- package/dist/cjs/adapters/node/hono.js +95 -0
- package/dist/cjs/adapters/node/index.js +87 -0
- package/dist/cjs/adapters/node/node.js +180 -0
- package/dist/cjs/adapters/node/plugins/index.js +72 -0
- package/dist/cjs/adapters/node/plugins/nodeServer.js +43 -0
- package/dist/cjs/adapters/node/plugins/resource.js +206 -0
- package/dist/cjs/adapters/node/plugins/static.js +379 -0
- package/dist/cjs/constants.js +77 -0
- package/dist/cjs/context.js +41 -0
- package/dist/cjs/helper.js +45 -0
- package/dist/cjs/hono.js +46 -0
- package/dist/cjs/index.js +247 -0
- package/dist/cjs/plugins/compat/hooks.js +80 -0
- package/dist/cjs/plugins/compat/index.js +64 -0
- package/dist/cjs/plugins/contractGateAutopilot.js +158 -0
- package/dist/cjs/plugins/contractGateSnapshotStore.js +239 -0
- package/dist/cjs/plugins/default.js +61 -0
- package/dist/cjs/plugins/favicon.js +48 -0
- package/dist/cjs/plugins/index.js +157 -0
- package/dist/cjs/plugins/log.js +92 -0
- package/dist/cjs/plugins/mfCache.js +78 -0
- package/dist/cjs/plugins/middlewares.js +49 -0
- package/dist/cjs/plugins/monitors.js +192 -0
- package/dist/cjs/plugins/processedBy.js +50 -0
- package/dist/cjs/plugins/render/csrRscRender.js +74 -0
- package/dist/cjs/plugins/render/dataHandler.js +53 -0
- package/dist/cjs/plugins/render/index.js +158 -0
- package/dist/cjs/plugins/render/inject.js +92 -0
- package/dist/cjs/plugins/render/render.js +273 -0
- package/dist/cjs/plugins/render/renderRscHandler.js +72 -0
- package/dist/cjs/plugins/render/serverActionHandler.js +47 -0
- package/dist/cjs/plugins/render/ssrCache.js +198 -0
- package/dist/cjs/plugins/render/ssrRender.js +96 -0
- package/dist/cjs/plugins/render/utils.js +49 -0
- package/dist/cjs/plugins/route.js +68 -0
- package/dist/cjs/plugins/telemetry.js +1283 -0
- package/dist/cjs/serverBase.js +176 -0
- package/dist/cjs/types/config/bff.js +18 -0
- package/dist/cjs/types/config/dev.js +18 -0
- package/dist/cjs/types/config/html.js +18 -0
- package/dist/cjs/types/config/index.js +93 -0
- package/dist/cjs/types/config/output.js +18 -0
- package/dist/cjs/types/config/security.js +18 -0
- package/dist/cjs/types/config/server.js +18 -0
- package/dist/cjs/types/config/share.js +18 -0
- package/dist/cjs/types/config/source.js +18 -0
- package/dist/cjs/types/config/tools.js +18 -0
- package/dist/cjs/types/index.js +79 -0
- package/dist/cjs/types/plugins/base.js +18 -0
- package/dist/cjs/types/plugins/index.js +58 -0
- package/dist/cjs/types/plugins/plugin.js +18 -0
- package/dist/cjs/types/render.js +18 -0
- package/dist/cjs/types/requestHandler.js +18 -0
- package/dist/cjs/types/server.js +18 -0
- package/dist/cjs/utils/entry.js +40 -0
- package/dist/cjs/utils/env.js +51 -0
- package/dist/cjs/utils/error.js +93 -0
- package/dist/cjs/utils/index.js +114 -0
- package/dist/cjs/utils/middlewareCollector.js +63 -0
- package/dist/cjs/utils/publicDir.js +92 -0
- package/dist/cjs/utils/request.js +86 -0
- package/dist/cjs/utils/serverConfig.js +43 -0
- package/dist/cjs/utils/storage.js +69 -0
- package/dist/cjs/utils/transformStream.js +65 -0
- package/dist/cjs/utils/warmup.js +40 -0
- package/dist/esm/adapters/node/helper/index.mjs +5 -0
- package/dist/esm/adapters/node/helper/loadCache.mjs +14 -0
- package/dist/esm/adapters/node/helper/loadConfig.mjs +31 -0
- package/dist/esm/adapters/node/helper/loadEnv.mjs +22 -0
- package/dist/esm/adapters/node/helper/loadPlugin.mjs +13 -0
- package/dist/esm/adapters/node/helper/utils.mjs +5 -0
- package/dist/esm/adapters/node/hono.mjs +55 -0
- package/dist/esm/adapters/node/index.mjs +4 -0
- package/dist/esm/adapters/node/node.mjs +130 -0
- package/dist/esm/adapters/node/plugins/index.mjs +3 -0
- package/dist/esm/adapters/node/plugins/nodeServer.mjs +9 -0
- package/dist/esm/adapters/node/plugins/resource.mjs +138 -0
- package/dist/esm/adapters/node/plugins/static.mjs +329 -0
- package/dist/esm/constants.mjs +28 -0
- package/dist/esm/context.mjs +4 -0
- package/dist/esm/helper.mjs +11 -0
- package/dist/esm/hono.mjs +2 -0
- package/dist/esm/index.mjs +12 -0
- package/dist/esm/plugins/compat/hooks.mjs +40 -0
- package/dist/esm/plugins/compat/index.mjs +27 -0
- package/dist/esm/plugins/contractGateAutopilot.mjs +124 -0
- package/dist/esm/plugins/contractGateSnapshotStore.mjs +180 -0
- package/dist/esm/plugins/default.mjs +27 -0
- package/dist/esm/plugins/favicon.mjs +14 -0
- package/dist/esm/plugins/index.mjs +11 -0
- package/dist/esm/plugins/log.mjs +58 -0
- package/dist/esm/plugins/mfCache.mjs +35 -0
- package/dist/esm/plugins/middlewares.mjs +15 -0
- package/dist/esm/plugins/monitors.mjs +149 -0
- package/dist/esm/plugins/processedBy.mjs +16 -0
- package/dist/esm/plugins/render/csrRscRender.mjs +40 -0
- package/dist/esm/plugins/render/dataHandler.mjs +19 -0
- package/dist/esm/plugins/render/index.mjs +84 -0
- package/dist/esm/plugins/render/inject.mjs +55 -0
- package/dist/esm/plugins/render/render.mjs +230 -0
- package/dist/esm/plugins/render/renderRscHandler.mjs +38 -0
- package/dist/esm/plugins/render/serverActionHandler.mjs +13 -0
- package/dist/esm/plugins/render/ssrCache.mjs +158 -0
- package/dist/esm/plugins/render/ssrRender.mjs +62 -0
- package/dist/esm/plugins/render/utils.mjs +15 -0
- package/dist/esm/plugins/route.mjs +34 -0
- package/dist/esm/plugins/telemetry.mjs +1195 -0
- package/dist/esm/rslib-runtime.mjs +18 -0
- package/dist/esm/serverBase.mjs +139 -0
- package/dist/esm/types/config/bff.mjs +0 -0
- package/dist/esm/types/config/dev.mjs +0 -0
- package/dist/esm/types/config/html.mjs +0 -0
- package/dist/esm/types/config/index.mjs +6 -0
- package/dist/esm/types/config/output.mjs +0 -0
- package/dist/esm/types/config/security.mjs +0 -0
- package/dist/esm/types/config/server.mjs +0 -0
- package/dist/esm/types/config/share.mjs +0 -0
- package/dist/esm/types/config/source.mjs +0 -0
- package/dist/esm/types/config/tools.mjs +0 -0
- package/dist/esm/types/index.mjs +4 -0
- package/dist/esm/types/plugins/base.mjs +0 -0
- package/dist/esm/types/plugins/index.mjs +1 -0
- package/dist/esm/types/plugins/plugin.mjs +0 -0
- package/dist/esm/types/render.mjs +0 -0
- package/dist/esm/types/requestHandler.mjs +0 -0
- package/dist/esm/types/server.mjs +0 -0
- package/dist/esm/utils/entry.mjs +3 -0
- package/dist/esm/utils/env.mjs +14 -0
- package/dist/esm/utils/error.mjs +53 -0
- package/dist/esm/utils/index.mjs +9 -0
- package/dist/esm/utils/middlewareCollector.mjs +26 -0
- package/dist/esm/utils/publicDir.mjs +33 -0
- package/dist/esm/utils/request.mjs +40 -0
- package/dist/esm/utils/serverConfig.mjs +9 -0
- package/dist/esm/utils/storage.mjs +35 -0
- package/dist/esm/utils/transformStream.mjs +28 -0
- package/dist/esm/utils/warmup.mjs +6 -0
- package/dist/esm-node/adapters/node/helper/index.mjs +6 -0
- package/dist/esm-node/adapters/node/helper/loadCache.mjs +15 -0
- package/dist/esm-node/adapters/node/helper/loadConfig.mjs +32 -0
- package/dist/esm-node/adapters/node/helper/loadEnv.mjs +23 -0
- package/dist/esm-node/adapters/node/helper/loadPlugin.mjs +14 -0
- package/dist/esm-node/adapters/node/helper/utils.mjs +6 -0
- package/dist/esm-node/adapters/node/hono.mjs +56 -0
- package/dist/esm-node/adapters/node/index.mjs +5 -0
- package/dist/esm-node/adapters/node/node.mjs +131 -0
- package/dist/esm-node/adapters/node/plugins/index.mjs +4 -0
- package/dist/esm-node/adapters/node/plugins/nodeServer.mjs +10 -0
- package/dist/esm-node/adapters/node/plugins/resource.mjs +139 -0
- package/dist/esm-node/adapters/node/plugins/static.mjs +330 -0
- package/dist/esm-node/constants.mjs +29 -0
- package/dist/esm-node/context.mjs +5 -0
- package/dist/esm-node/helper.mjs +12 -0
- package/dist/esm-node/hono.mjs +3 -0
- package/dist/esm-node/index.mjs +13 -0
- package/dist/esm-node/plugins/compat/hooks.mjs +41 -0
- package/dist/esm-node/plugins/compat/index.mjs +28 -0
- package/dist/esm-node/plugins/contractGateAutopilot.mjs +125 -0
- package/dist/esm-node/plugins/contractGateSnapshotStore.mjs +182 -0
- package/dist/esm-node/plugins/default.mjs +28 -0
- package/dist/esm-node/plugins/favicon.mjs +15 -0
- package/dist/esm-node/plugins/index.mjs +12 -0
- package/dist/esm-node/plugins/log.mjs +59 -0
- package/dist/esm-node/plugins/mfCache.mjs +36 -0
- package/dist/esm-node/plugins/middlewares.mjs +16 -0
- package/dist/esm-node/plugins/monitors.mjs +150 -0
- package/dist/esm-node/plugins/processedBy.mjs +17 -0
- package/dist/esm-node/plugins/render/csrRscRender.mjs +41 -0
- package/dist/esm-node/plugins/render/dataHandler.mjs +20 -0
- package/dist/esm-node/plugins/render/index.mjs +85 -0
- package/dist/esm-node/plugins/render/inject.mjs +56 -0
- package/dist/esm-node/plugins/render/render.mjs +231 -0
- package/dist/esm-node/plugins/render/renderRscHandler.mjs +39 -0
- package/dist/esm-node/plugins/render/serverActionHandler.mjs +14 -0
- package/dist/esm-node/plugins/render/ssrCache.mjs +159 -0
- package/dist/esm-node/plugins/render/ssrRender.mjs +63 -0
- package/dist/esm-node/plugins/render/utils.mjs +16 -0
- package/dist/esm-node/plugins/route.mjs +35 -0
- package/dist/esm-node/plugins/telemetry.mjs +1196 -0
- package/dist/esm-node/rslib-runtime.mjs +19 -0
- package/dist/esm-node/serverBase.mjs +140 -0
- package/dist/esm-node/types/config/bff.mjs +1 -0
- package/dist/esm-node/types/config/dev.mjs +1 -0
- package/dist/esm-node/types/config/html.mjs +1 -0
- package/dist/esm-node/types/config/index.mjs +7 -0
- package/dist/esm-node/types/config/output.mjs +1 -0
- package/dist/esm-node/types/config/security.mjs +1 -0
- package/dist/esm-node/types/config/server.mjs +1 -0
- package/dist/esm-node/types/config/share.mjs +1 -0
- package/dist/esm-node/types/config/source.mjs +1 -0
- package/dist/esm-node/types/config/tools.mjs +1 -0
- package/dist/esm-node/types/index.mjs +5 -0
- package/dist/esm-node/types/plugins/base.mjs +1 -0
- package/dist/esm-node/types/plugins/index.mjs +2 -0
- package/dist/esm-node/types/plugins/plugin.mjs +1 -0
- package/dist/esm-node/types/render.mjs +1 -0
- package/dist/esm-node/types/requestHandler.mjs +1 -0
- package/dist/esm-node/types/server.mjs +1 -0
- package/dist/esm-node/utils/entry.mjs +4 -0
- package/dist/esm-node/utils/env.mjs +15 -0
- package/dist/esm-node/utils/error.mjs +54 -0
- package/dist/esm-node/utils/index.mjs +10 -0
- package/dist/esm-node/utils/middlewareCollector.mjs +27 -0
- package/dist/esm-node/utils/publicDir.mjs +34 -0
- package/dist/esm-node/utils/request.mjs +41 -0
- package/dist/esm-node/utils/serverConfig.mjs +10 -0
- package/dist/esm-node/utils/storage.mjs +36 -0
- package/dist/esm-node/utils/transformStream.mjs +29 -0
- package/dist/esm-node/utils/warmup.mjs +7 -0
- package/dist/types/adapters/node/helper/index.d.ts +6 -0
- package/dist/types/adapters/node/helper/loadCache.d.ts +2 -0
- package/dist/types/adapters/node/helper/loadConfig.d.ts +3 -0
- package/dist/types/adapters/node/helper/loadEnv.d.ts +3 -0
- package/dist/types/adapters/node/helper/loadPlugin.d.ts +3 -0
- package/dist/types/adapters/node/helper/utils.d.ts +21 -0
- package/dist/types/adapters/node/hono.d.ts +19 -0
- package/dist/types/adapters/node/index.d.ts +5 -0
- package/dist/types/adapters/node/node.d.ts +17 -0
- package/dist/types/adapters/node/plugins/index.d.ts +3 -0
- package/dist/types/adapters/node/plugins/nodeServer.d.ts +6 -0
- package/dist/types/adapters/node/plugins/resource.d.ts +11 -0
- package/dist/types/adapters/node/plugins/static.d.ts +25 -0
- package/dist/types/constants.d.ts +26 -0
- package/dist/types/context.d.ts +3 -0
- package/dist/types/helper.d.ts +10 -0
- package/dist/types/hono.d.ts +3 -0
- package/dist/types/index.d.ts +14 -0
- package/dist/types/plugins/compat/hooks.d.ts +8 -0
- package/dist/types/plugins/compat/index.d.ts +3 -0
- package/dist/types/plugins/contractGateAutopilot.d.ts +35 -0
- package/dist/types/plugins/contractGateSnapshotStore.d.ts +57 -0
- package/dist/types/plugins/default.d.ts +7 -0
- package/dist/types/plugins/favicon.d.ts +2 -0
- package/dist/types/plugins/index.d.ts +11 -0
- package/dist/types/plugins/log.d.ts +2 -0
- package/dist/types/plugins/mfCache.d.ts +12 -0
- package/dist/types/plugins/middlewares.d.ts +2 -0
- package/dist/types/plugins/monitors.d.ts +6 -0
- package/dist/types/plugins/processedBy.d.ts +2 -0
- package/dist/types/plugins/render/csrRscRender.d.ts +2 -0
- package/dist/types/plugins/render/dataHandler.d.ts +5 -0
- package/dist/types/plugins/render/index.d.ts +3 -0
- package/dist/types/plugins/render/inject.d.ts +7 -0
- package/dist/types/plugins/render/render.d.ts +16 -0
- package/dist/types/plugins/render/renderRscHandler.d.ts +2 -0
- package/dist/types/plugins/render/serverActionHandler.d.ts +2 -0
- package/dist/types/plugins/render/ssrCache.d.ts +18 -0
- package/dist/types/plugins/render/ssrRender.d.ts +26 -0
- package/dist/types/plugins/render/utils.d.ts +3 -0
- package/dist/types/plugins/route.d.ts +2 -0
- package/dist/types/plugins/telemetry.d.ts +309 -0
- package/dist/types/serverBase.d.ts +38 -0
- package/dist/types/types/config/bff.d.ts +142 -0
- package/dist/types/types/config/dev.d.ts +4 -0
- package/dist/types/types/config/html.d.ts +15 -0
- package/dist/types/types/config/index.d.ts +35 -0
- package/dist/types/types/config/output.d.ts +20 -0
- package/dist/types/types/config/security.d.ts +4 -0
- package/dist/types/types/config/server.d.ts +402 -0
- package/dist/types/types/config/share.d.ts +3 -0
- package/dist/types/types/config/source.d.ts +7 -0
- package/dist/types/types/config/tools.d.ts +2 -0
- package/dist/types/types/index.d.ts +4 -0
- package/dist/types/types/plugins/base.d.ts +57 -0
- package/dist/types/types/plugins/index.d.ts +2 -0
- package/dist/types/types/plugins/plugin.d.ts +31 -0
- package/dist/types/types/render.d.ts +24 -0
- package/dist/types/types/requestHandler.d.ts +48 -0
- package/dist/types/types/server.d.ts +67 -0
- package/dist/types/utils/entry.d.ts +3 -0
- package/dist/types/utils/env.d.ts +2 -0
- package/dist/types/utils/error.d.ts +8 -0
- package/dist/types/utils/index.d.ts +9 -0
- package/dist/types/utils/middlewareCollector.d.ts +12 -0
- package/dist/types/utils/publicDir.d.ts +40 -0
- package/dist/types/utils/request.d.ts +17 -0
- package/dist/types/utils/serverConfig.d.ts +8 -0
- package/dist/types/utils/storage.d.ts +5 -0
- package/dist/types/utils/transformStream.d.ts +5 -0
- package/dist/types/utils/warmup.d.ts +1 -0
- package/package.json +103 -0
- package/rslib.config.mts +4 -0
- package/rstest.config.mts +7 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { ServerResponse } from "node:http";
|
|
3
|
+
import { Readable, Writable } from "node:stream";
|
|
4
|
+
import cloneable_readable from "cloneable-readable";
|
|
5
|
+
import { isResFinalized } from "./helper/index.mjs";
|
|
6
|
+
const createWebRequest = (req, res, body)=>{
|
|
7
|
+
const headerRecord = [];
|
|
8
|
+
for (const [key, value] of Object.entries(req.headers))if (!key.startsWith(':')) {
|
|
9
|
+
if (Array.isArray(value)) {
|
|
10
|
+
for (const item of value)if (void 0 !== item) headerRecord.push([
|
|
11
|
+
key,
|
|
12
|
+
item
|
|
13
|
+
]);
|
|
14
|
+
} else if (void 0 !== value) {
|
|
15
|
+
if ('string' == typeof value) headerRecord.push([
|
|
16
|
+
key,
|
|
17
|
+
value
|
|
18
|
+
]);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const { method } = req;
|
|
22
|
+
const controller = new AbortController();
|
|
23
|
+
const init = {
|
|
24
|
+
method,
|
|
25
|
+
headers: headerRecord,
|
|
26
|
+
signal: controller.signal
|
|
27
|
+
};
|
|
28
|
+
res.on('close', ()=>controller.abort('res closed'));
|
|
29
|
+
const url = `http://${req.headers.host}${req.url}`;
|
|
30
|
+
const needsRequestBody = body || !('GET' === method || 'HEAD' === method);
|
|
31
|
+
const cloneableReq = needsRequestBody ? cloneable_readable(req) : null;
|
|
32
|
+
if (needsRequestBody) {
|
|
33
|
+
if (body) init.body = body;
|
|
34
|
+
else {
|
|
35
|
+
const stream = cloneableReq.clone();
|
|
36
|
+
init.body = Readable.toWeb(stream);
|
|
37
|
+
}
|
|
38
|
+
init.duplex = 'half';
|
|
39
|
+
}
|
|
40
|
+
const originalRequest = new Request(url, init);
|
|
41
|
+
if (needsRequestBody) {
|
|
42
|
+
const interceptedMethods = [
|
|
43
|
+
'json',
|
|
44
|
+
'text',
|
|
45
|
+
'blob',
|
|
46
|
+
'arrayBuffer',
|
|
47
|
+
'formData'
|
|
48
|
+
];
|
|
49
|
+
return new Proxy(originalRequest, {
|
|
50
|
+
get (target, prop) {
|
|
51
|
+
if (interceptedMethods.includes(prop)) return (...args)=>{
|
|
52
|
+
cloneableReq.resume();
|
|
53
|
+
return target[prop].call(target, ...args);
|
|
54
|
+
};
|
|
55
|
+
const value = target[prop];
|
|
56
|
+
if ('body' === prop) {
|
|
57
|
+
cloneableReq.resume();
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
if ('function' == typeof value) return (...args)=>value.apply(target, args);
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return originalRequest;
|
|
66
|
+
};
|
|
67
|
+
const sendResponse = async (response, res)=>{
|
|
68
|
+
res.statusMessage = response.statusText;
|
|
69
|
+
res.statusCode = response.status;
|
|
70
|
+
const cookies = [];
|
|
71
|
+
for (const [key, value] of response.headers.entries())if ('set-cookie' === key) cookies.push(value);
|
|
72
|
+
else res.setHeader(key, value);
|
|
73
|
+
if (cookies.length > 0) res.setHeader('set-cookie', cookies);
|
|
74
|
+
if (response.headers.get('Content-Type')?.match(/text\/event-stream/i) && res instanceof ServerResponse) res.flushHeaders();
|
|
75
|
+
if (response.body) {
|
|
76
|
+
const writable = Writable.toWeb(res);
|
|
77
|
+
await response.body.pipeTo(writable);
|
|
78
|
+
} else res.end();
|
|
79
|
+
};
|
|
80
|
+
const handleResponseError = (e, res)=>{
|
|
81
|
+
const err = e instanceof Error ? e : new Error('unknown error', {
|
|
82
|
+
cause: e
|
|
83
|
+
});
|
|
84
|
+
if ('ABORT_ERR' === err.code || 'ERR_STREAM_PREMATURE_CLOSE' === err.code) console.info('The user aborted a request.');
|
|
85
|
+
else {
|
|
86
|
+
console.error(e);
|
|
87
|
+
if (!res.headersSent) {
|
|
88
|
+
res.statusCode = 500;
|
|
89
|
+
res.setHeader('Content-Type', 'text/plain');
|
|
90
|
+
}
|
|
91
|
+
res.end(`Error: ${err.message}`);
|
|
92
|
+
res.destroy(err);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const getRequestListener = (handler)=>async (req, res)=>{
|
|
96
|
+
try {
|
|
97
|
+
const request = createWebRequest(req, res);
|
|
98
|
+
const response = await handler(request, {
|
|
99
|
+
node: {
|
|
100
|
+
req,
|
|
101
|
+
res
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
if (!response.res && !isResFinalized(res)) await sendResponse(response, res);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
return handleResponseError(error, res);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const createNodeServer = async (requestHandler, httpsOptions, http2)=>{
|
|
110
|
+
const requestListener = getRequestListener(requestHandler);
|
|
111
|
+
let nodeServer;
|
|
112
|
+
if (httpsOptions) if (http2) {
|
|
113
|
+
const { createSecureServer } = await import("node:http2");
|
|
114
|
+
nodeServer = createSecureServer({
|
|
115
|
+
allowHTTP1: true,
|
|
116
|
+
maxSessionMemory: 1024,
|
|
117
|
+
...httpsOptions
|
|
118
|
+
}, (req, res)=>requestListener(req, res));
|
|
119
|
+
} else {
|
|
120
|
+
const { createServer } = await import("node:https");
|
|
121
|
+
nodeServer = createServer(httpsOptions, requestListener);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
const { createServer } = await import("node:http");
|
|
125
|
+
nodeServer = createServer(requestListener);
|
|
126
|
+
}
|
|
127
|
+
nodeServer.getRequestListener = ()=>requestListener;
|
|
128
|
+
nodeServer.getRequestHandler = ()=>requestHandler;
|
|
129
|
+
return nodeServer;
|
|
130
|
+
};
|
|
131
|
+
export { createNodeServer, createWebRequest, sendResponse };
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { fileReader } from "@modern-js/runtime-utils/fileReader";
|
|
3
|
+
import { LOADABLE_STATS_FILE, MAIN_ENTRY_NAME, NESTED_ROUTE_SPEC_FILE, ROUTE_MANIFEST_FILE, SERVER_BUNDLE_DIRECTORY, compatibleRequire, fs, isProd } from "@modern-js/utils";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { uniqueKeyByRoute } from "../../../utils/index.mjs";
|
|
6
|
+
async function getHtmlTemplates(pwd, routes) {
|
|
7
|
+
const htmlRoutes = routes.filter((route)=>route.entryName);
|
|
8
|
+
const htmls = await Promise.all(htmlRoutes.map(async (route)=>{
|
|
9
|
+
let html;
|
|
10
|
+
try {
|
|
11
|
+
const htmlPath = path.join(pwd, route.entryPath);
|
|
12
|
+
html = (await fileReader.readFile(htmlPath, 'utf-8'))?.toString();
|
|
13
|
+
} catch (e) {}
|
|
14
|
+
return [
|
|
15
|
+
uniqueKeyByRoute(route),
|
|
16
|
+
html
|
|
17
|
+
];
|
|
18
|
+
}) || []);
|
|
19
|
+
const templates = Object.fromEntries(htmls);
|
|
20
|
+
return templates;
|
|
21
|
+
}
|
|
22
|
+
function injectTemplates(pwd, routes, htmlTemplatePromise) {
|
|
23
|
+
return async (c, next)=>{
|
|
24
|
+
if (routes && !c.get('templates')) {
|
|
25
|
+
const templates = await (htmlTemplatePromise || getHtmlTemplates(pwd, routes));
|
|
26
|
+
c.set('templates', templates);
|
|
27
|
+
}
|
|
28
|
+
await next();
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const loadBundle = async (filepath, monitors)=>{
|
|
32
|
+
if (!await fs.pathExists(filepath)) return;
|
|
33
|
+
try {
|
|
34
|
+
const module = await compatibleRequire(filepath, false);
|
|
35
|
+
return module;
|
|
36
|
+
} catch (e) {
|
|
37
|
+
if (monitors) monitors.error(`Load ${filepath} bundle failed, error = %s`, e instanceof Error ? e.stack || e.message : e);
|
|
38
|
+
else console.error(`Load ${filepath} bundle failed, error = ${e instanceof Error ? e.stack || e.message : e}`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
async function getServerManifest(pwd, routes, monitors) {
|
|
43
|
+
const loaderBundles = {};
|
|
44
|
+
const renderBundles = {};
|
|
45
|
+
await Promise.all(routes.filter((route)=>Boolean(route.bundle)).map(async (route)=>{
|
|
46
|
+
const entryName = route.entryName || MAIN_ENTRY_NAME;
|
|
47
|
+
const renderBundlePath = path.join(pwd, route.bundle || '');
|
|
48
|
+
const loaderBundlePath = path.join(pwd, SERVER_BUNDLE_DIRECTORY, `${entryName}-server-loaders.js`);
|
|
49
|
+
const renderBundle = await loadBundle(renderBundlePath, monitors);
|
|
50
|
+
const loaderBundle = await loadBundle(loaderBundlePath, monitors);
|
|
51
|
+
renderBundle && (renderBundles[entryName] = renderBundle);
|
|
52
|
+
loaderBundle && (loaderBundles[entryName] = loaderBundle?.loadModules ? await loaderBundle?.loadModules() : loaderBundle);
|
|
53
|
+
}));
|
|
54
|
+
const loadableUri = path.join(pwd, LOADABLE_STATS_FILE);
|
|
55
|
+
const loadableStats = await compatibleRequire(loadableUri).catch((_)=>({}));
|
|
56
|
+
const routesManifestUri = path.join(pwd, ROUTE_MANIFEST_FILE);
|
|
57
|
+
const routeManifest = await compatibleRequire(routesManifestUri).catch((_)=>({}));
|
|
58
|
+
const nestedRoutesJsonPath = path.join(pwd, NESTED_ROUTE_SPEC_FILE);
|
|
59
|
+
const nestedRoutesJson = await compatibleRequire(nestedRoutesJsonPath).catch((_)=>({}));
|
|
60
|
+
return {
|
|
61
|
+
loaderBundles,
|
|
62
|
+
renderBundles,
|
|
63
|
+
loadableStats,
|
|
64
|
+
routeManifest,
|
|
65
|
+
nestedRoutesJson
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function injectServerManifest(pwd, routes, manifestPromise) {
|
|
69
|
+
return async (c, next)=>{
|
|
70
|
+
if (routes && !c.get('serverManifest')) {
|
|
71
|
+
const monitors = c.get('monitors');
|
|
72
|
+
const serverManifest = await (manifestPromise || getServerManifest(pwd, routes, monitors));
|
|
73
|
+
c.set('serverManifest', serverManifest);
|
|
74
|
+
}
|
|
75
|
+
await next();
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async function getRscServerManifest(pwd) {
|
|
79
|
+
const rscServerManifest = await compatibleRequire(path.join(pwd, 'bundles', 'react-server-manifest.json')).catch((_)=>void 0);
|
|
80
|
+
return rscServerManifest;
|
|
81
|
+
}
|
|
82
|
+
async function getClientManifest(pwd) {
|
|
83
|
+
const rscClientManifest = await compatibleRequire(path.join(pwd, 'react-client-manifest.json')).catch((_)=>void 0);
|
|
84
|
+
return rscClientManifest;
|
|
85
|
+
}
|
|
86
|
+
async function getRscSSRManifest(pwd) {
|
|
87
|
+
const rscSSRManifest = await compatibleRequire(path.join(pwd, 'react-ssr-manifest.json')).catch((_)=>void 0);
|
|
88
|
+
return rscSSRManifest;
|
|
89
|
+
}
|
|
90
|
+
const injectRscManifestPlugin = (enableRsc)=>({
|
|
91
|
+
name: '@modern-js/plugin-inject-rsc-manifest',
|
|
92
|
+
setup (api) {
|
|
93
|
+
api.onPrepare(()=>{
|
|
94
|
+
const { middlewares, distDirectory: pwd } = api.getServerContext();
|
|
95
|
+
if (!enableRsc) return;
|
|
96
|
+
middlewares.push({
|
|
97
|
+
name: 'inject-rsc-manifest',
|
|
98
|
+
handler: async (c, next)=>{
|
|
99
|
+
if (!c.get('rscServerManifest')) {
|
|
100
|
+
const rscServerManifest = await getRscServerManifest(pwd);
|
|
101
|
+
c.set('rscServerManifest', rscServerManifest);
|
|
102
|
+
}
|
|
103
|
+
if (!c.get('rscClientManifest')) {
|
|
104
|
+
const rscClientManifest = await getClientManifest(pwd);
|
|
105
|
+
c.set('rscClientManifest', rscClientManifest);
|
|
106
|
+
}
|
|
107
|
+
if (!c.get('rscSSRManifest')) {
|
|
108
|
+
const rscSSRManifest = await getRscSSRManifest(pwd);
|
|
109
|
+
c.set('rscSSRManifest', rscSSRManifest);
|
|
110
|
+
}
|
|
111
|
+
await next();
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
const injectResourcePlugin = ()=>({
|
|
118
|
+
name: '@modern-js/plugin-inject-resource',
|
|
119
|
+
setup (api) {
|
|
120
|
+
api.onPrepare(()=>{
|
|
121
|
+
const { middlewares, routes, distDirectory: pwd } = api.getServerContext();
|
|
122
|
+
let htmlTemplatePromise;
|
|
123
|
+
let manifestPromise;
|
|
124
|
+
if (isProd()) {
|
|
125
|
+
manifestPromise = getServerManifest(pwd, routes || [], void 0);
|
|
126
|
+
htmlTemplatePromise = getHtmlTemplates(pwd, routes || []);
|
|
127
|
+
}
|
|
128
|
+
middlewares.push({
|
|
129
|
+
name: 'inject-server-manifest',
|
|
130
|
+
handler: injectServerManifest(pwd, routes, manifestPromise)
|
|
131
|
+
});
|
|
132
|
+
middlewares.push({
|
|
133
|
+
name: 'inject-html',
|
|
134
|
+
handler: injectTemplates(pwd, routes, htmlTemplatePromise)
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
export { getClientManifest, getHtmlTemplates, getRscSSRManifest, getRscServerManifest, getServerManifest, injectResourcePlugin, injectRscManifestPlugin, injectServerManifest, injectTemplates };
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { fileReader } from "@modern-js/runtime-utils/fileReader";
|
|
3
|
+
import { fs } from "@modern-js/utils";
|
|
4
|
+
import { getMimeType } from "hono/utils/mime";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { sortRoutes } from "../../../utils/index.mjs";
|
|
7
|
+
import { getPublicDirPatterns } from "../../../utils/publicDir.mjs";
|
|
8
|
+
const serverStaticPlugin = ()=>({
|
|
9
|
+
name: '@modern-js/plugin-server-static',
|
|
10
|
+
setup (api) {
|
|
11
|
+
api.onPrepare(()=>{
|
|
12
|
+
const { middlewares, distDirectory: pwd, routes } = api.getServerContext();
|
|
13
|
+
const config = api.getServerConfig();
|
|
14
|
+
const serverStaticMiddleware = createStaticMiddleware({
|
|
15
|
+
pwd: pwd,
|
|
16
|
+
routes,
|
|
17
|
+
output: config.output || {},
|
|
18
|
+
html: config.html || {},
|
|
19
|
+
server: config.server || {}
|
|
20
|
+
});
|
|
21
|
+
middlewares.push({
|
|
22
|
+
name: 'server-static',
|
|
23
|
+
handler: serverStaticMiddleware
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
const PRE_COMPRESSED_ASSET_EXTENSIONS = {
|
|
29
|
+
br: '.br',
|
|
30
|
+
gzip: '.gz'
|
|
31
|
+
};
|
|
32
|
+
const PRE_COMPRESSED_SUPPORTED_ENCODINGS = [
|
|
33
|
+
'br',
|
|
34
|
+
'gzip'
|
|
35
|
+
];
|
|
36
|
+
const parseAcceptEncoding = (value)=>value.split(',').map((item)=>item.trim()).filter(Boolean).map((item)=>{
|
|
37
|
+
const [rawName, ...params] = item.split(';');
|
|
38
|
+
const name = rawName.trim().toLowerCase();
|
|
39
|
+
let q = 1;
|
|
40
|
+
for (const param of params){
|
|
41
|
+
const [key, rawValue] = param.split('=').map((v)=>v.trim());
|
|
42
|
+
if ('q' !== key.toLowerCase() || null == rawValue) continue;
|
|
43
|
+
const parsedQ = Number(rawValue);
|
|
44
|
+
if (!Number.isNaN(parsedQ)) q = Math.max(0, Math.min(parsedQ, 1));
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
name,
|
|
48
|
+
q
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
const getAcceptedEncodings = (value)=>{
|
|
52
|
+
if (!value) return [];
|
|
53
|
+
const parsed = parseAcceptEncoding(value);
|
|
54
|
+
const qualityByEncoding = new Map();
|
|
55
|
+
let wildcardQuality;
|
|
56
|
+
for (const { name, q } of parsed){
|
|
57
|
+
if ('*' === name) {
|
|
58
|
+
wildcardQuality = q;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
qualityByEncoding.set(name, q);
|
|
62
|
+
}
|
|
63
|
+
const getQuality = (encoding)=>{
|
|
64
|
+
const explicit = qualityByEncoding.get(encoding);
|
|
65
|
+
if (void 0 !== explicit) return explicit;
|
|
66
|
+
return wildcardQuality ?? 0;
|
|
67
|
+
};
|
|
68
|
+
return PRE_COMPRESSED_SUPPORTED_ENCODINGS.map((encoding)=>({
|
|
69
|
+
encoding,
|
|
70
|
+
quality: getQuality(encoding)
|
|
71
|
+
})).filter((item)=>item.quality > 0).sort((a, b)=>b.quality - a.quality).map((item)=>item.encoding);
|
|
72
|
+
};
|
|
73
|
+
const appendVaryHeader = (c, value)=>{
|
|
74
|
+
const current = c.res.headers.get('Vary');
|
|
75
|
+
if (!current) return void c.header('Vary', value);
|
|
76
|
+
const values = current.split(',').map((item)=>item.trim().toLowerCase()).filter(Boolean);
|
|
77
|
+
if (!values.includes(value.toLowerCase())) c.header('Vary', `${current}, ${value}`);
|
|
78
|
+
};
|
|
79
|
+
const resolvePreCompressedAsset = async (c, filepath)=>{
|
|
80
|
+
const brPath = `${filepath}${PRE_COMPRESSED_ASSET_EXTENSIONS.br}`;
|
|
81
|
+
const gzipPath = `${filepath}${PRE_COMPRESSED_ASSET_EXTENSIONS.gzip}`;
|
|
82
|
+
const [hasBr, hasGzip] = await Promise.all([
|
|
83
|
+
fs.pathExists(brPath),
|
|
84
|
+
fs.pathExists(gzipPath)
|
|
85
|
+
]);
|
|
86
|
+
const hasVariant = hasBr || hasGzip;
|
|
87
|
+
if (!hasVariant) return {
|
|
88
|
+
selected: null,
|
|
89
|
+
hasVariant: false
|
|
90
|
+
};
|
|
91
|
+
const acceptedEncodings = getAcceptedEncodings(c.req.header('accept-encoding'));
|
|
92
|
+
for (const encoding of acceptedEncodings){
|
|
93
|
+
if ('br' === encoding && hasBr) return {
|
|
94
|
+
selected: {
|
|
95
|
+
filepath: brPath,
|
|
96
|
+
encoding
|
|
97
|
+
},
|
|
98
|
+
hasVariant: true
|
|
99
|
+
};
|
|
100
|
+
if ('gzip' === encoding && hasGzip) return {
|
|
101
|
+
selected: {
|
|
102
|
+
filepath: gzipPath,
|
|
103
|
+
encoding
|
|
104
|
+
},
|
|
105
|
+
hasVariant: true
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
selected: null,
|
|
110
|
+
hasVariant: true
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
function createPublicMiddleware({ pwd, routes }) {
|
|
114
|
+
return async (c, next)=>{
|
|
115
|
+
const route = matchPublicRoute(c.req, routes);
|
|
116
|
+
if (route) {
|
|
117
|
+
const { entryPath } = route;
|
|
118
|
+
const originFilename = path.join(pwd, entryPath);
|
|
119
|
+
const preCompressedAsset = await resolvePreCompressedAsset(c, originFilename);
|
|
120
|
+
const filename = preCompressedAsset.selected?.filepath ?? originFilename;
|
|
121
|
+
const data = await fileReader.readFile(filename, 'buffer');
|
|
122
|
+
const mimeType = getMimeType(originFilename);
|
|
123
|
+
if (null !== data) {
|
|
124
|
+
const body = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
125
|
+
if (mimeType) c.header('Content-Type', mimeType);
|
|
126
|
+
Object.entries(route.responseHeaders || {}).forEach(([k, v])=>{
|
|
127
|
+
c.header(k, v);
|
|
128
|
+
});
|
|
129
|
+
if (preCompressedAsset.hasVariant) appendVaryHeader(c, 'Accept-Encoding');
|
|
130
|
+
if (preCompressedAsset.selected) c.header('Content-Encoding', preCompressedAsset.selected.encoding);
|
|
131
|
+
c.header('Content-Length', String(data.byteLength));
|
|
132
|
+
return c.body(body, 200);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return await next();
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function matchPublicRoute(req, routes) {
|
|
139
|
+
for (const route of routes.sort(sortRoutes))if (!route.isSSR && route.entryPath.startsWith('public') && req.path.startsWith(route.urlPath)) return route;
|
|
140
|
+
}
|
|
141
|
+
const extractPathname = (url)=>{
|
|
142
|
+
try {
|
|
143
|
+
if (url.includes('://')) return new URL(url).pathname || '/';
|
|
144
|
+
if (url.startsWith('//')) return new URL(`http:${url}`).pathname || '/';
|
|
145
|
+
return url;
|
|
146
|
+
} catch (e) {
|
|
147
|
+
return url;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const MODULE_FEDERATION_MANIFEST_FILE = 'mf-manifest.json';
|
|
151
|
+
const MODULE_FEDERATION_OPTIONAL_FILES = [
|
|
152
|
+
'mf-stats.json'
|
|
153
|
+
];
|
|
154
|
+
const trimLeadingSlash = (value)=>value.replace(/^\/+/, '');
|
|
155
|
+
const joinModuleFederationAssetPath = (assetPath, assetName)=>{
|
|
156
|
+
if (!assetName) return '';
|
|
157
|
+
return trimLeadingSlash(path.posix.join(assetPath || '', assetName));
|
|
158
|
+
};
|
|
159
|
+
const appendModuleFederationAsset = (set, assetPath)=>{
|
|
160
|
+
if (!assetPath) return;
|
|
161
|
+
set.add(trimLeadingSlash(assetPath));
|
|
162
|
+
};
|
|
163
|
+
const appendModuleFederationAssets = (set, assets)=>{
|
|
164
|
+
assets?.js?.sync?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
165
|
+
assets?.js?.async?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
166
|
+
assets?.css?.sync?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
167
|
+
assets?.css?.async?.forEach((asset)=>appendModuleFederationAsset(set, asset));
|
|
168
|
+
};
|
|
169
|
+
const hasAbsoluteProtocol = (value)=>/^https?:\/\//i.test(value) || value.startsWith('//');
|
|
170
|
+
const ensureLeadingSlash = (value)=>{
|
|
171
|
+
if ('' === value) return '/';
|
|
172
|
+
return value.startsWith('/') ? value : `/${value}`;
|
|
173
|
+
};
|
|
174
|
+
const ensureTrailingSlash = (value)=>value.endsWith('/') ? value : `${value}/`;
|
|
175
|
+
const patchModuleFederationManifestPublicPath = (c, manifestBuffer, pathPrefix)=>{
|
|
176
|
+
try {
|
|
177
|
+
const manifest = JSON.parse(manifestBuffer.toString('utf-8'));
|
|
178
|
+
const publicPath = manifest.metaData?.publicPath;
|
|
179
|
+
if (!publicPath || hasAbsoluteProtocol(publicPath)) return manifestBuffer;
|
|
180
|
+
const requestURL = new URL(c.req.url);
|
|
181
|
+
const prefixPath = ensureTrailingSlash(ensureLeadingSlash(pathPrefix || '/'));
|
|
182
|
+
manifest.metaData = {
|
|
183
|
+
...manifest.metaData,
|
|
184
|
+
publicPath: `${requestURL.origin}${prefixPath}`
|
|
185
|
+
};
|
|
186
|
+
return Buffer.from(JSON.stringify(manifest), 'utf-8');
|
|
187
|
+
} catch {
|
|
188
|
+
return manifestBuffer;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
const patchModuleFederationRemoteEntryPublicPath = (c, remoteEntryBuffer, pathPrefix)=>{
|
|
192
|
+
const requestURL = new URL(c.req.url);
|
|
193
|
+
const prefixPath = ensureTrailingSlash(ensureLeadingSlash(pathPrefix || '/'));
|
|
194
|
+
const publicPath = `${requestURL.origin}${prefixPath}`;
|
|
195
|
+
const source = remoteEntryBuffer.toString('utf-8');
|
|
196
|
+
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)};`);
|
|
197
|
+
if (patched === source) return remoteEntryBuffer;
|
|
198
|
+
return Buffer.from(patched, 'utf-8');
|
|
199
|
+
};
|
|
200
|
+
const getModuleFederationAssetList = async (pwd)=>{
|
|
201
|
+
const assets = new Set();
|
|
202
|
+
const manifestPath = path.join(pwd, MODULE_FEDERATION_MANIFEST_FILE);
|
|
203
|
+
if (!await fs.pathExists(manifestPath)) return {
|
|
204
|
+
assets,
|
|
205
|
+
remoteEntry: null
|
|
206
|
+
};
|
|
207
|
+
assets.add(MODULE_FEDERATION_MANIFEST_FILE);
|
|
208
|
+
const manifestBuffer = await fileReader.readFileFromSystem(manifestPath, 'buffer');
|
|
209
|
+
if (null === manifestBuffer) return {
|
|
210
|
+
assets,
|
|
211
|
+
remoteEntry: null
|
|
212
|
+
};
|
|
213
|
+
for (const filename of MODULE_FEDERATION_OPTIONAL_FILES)if (await fs.pathExists(path.join(pwd, filename))) assets.add(filename);
|
|
214
|
+
let remoteEntryFile = null;
|
|
215
|
+
try {
|
|
216
|
+
const manifest = JSON.parse(manifestBuffer.toString('utf-8'));
|
|
217
|
+
const remoteEntry = joinModuleFederationAssetPath(manifest.metaData?.remoteEntry?.path, manifest.metaData?.remoteEntry?.name);
|
|
218
|
+
const dtsZip = joinModuleFederationAssetPath(manifest.metaData?.types?.path, manifest.metaData?.types?.zip);
|
|
219
|
+
const dtsApi = joinModuleFederationAssetPath(manifest.metaData?.types?.path, manifest.metaData?.types?.api);
|
|
220
|
+
if (remoteEntry) {
|
|
221
|
+
assets.add(remoteEntry);
|
|
222
|
+
remoteEntryFile = remoteEntry;
|
|
223
|
+
}
|
|
224
|
+
if (dtsZip) assets.add(dtsZip);
|
|
225
|
+
if (dtsApi) assets.add(dtsApi);
|
|
226
|
+
manifest.shared?.forEach((item)=>appendModuleFederationAssets(assets, item.assets));
|
|
227
|
+
manifest.remotes?.forEach((item)=>appendModuleFederationAssets(assets, item.assets));
|
|
228
|
+
manifest.exposes?.forEach((item)=>appendModuleFederationAssets(assets, item.assets));
|
|
229
|
+
} catch {}
|
|
230
|
+
return {
|
|
231
|
+
assets,
|
|
232
|
+
remoteEntry: remoteEntryFile
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
function createStaticMiddleware(options) {
|
|
236
|
+
const { pwd, routes } = options;
|
|
237
|
+
const prefix = options.output.assetPrefix || '/';
|
|
238
|
+
const pathPrefix = extractPathname(prefix);
|
|
239
|
+
const { distPath: { css: cssPath, js: jsPath, media: mediaPath } = {} } = options.output;
|
|
240
|
+
const { favicon } = options.html;
|
|
241
|
+
const { publicDir } = options.server;
|
|
242
|
+
const favicons = prepareFavicons(favicon);
|
|
243
|
+
const staticFiles = [
|
|
244
|
+
cssPath,
|
|
245
|
+
jsPath,
|
|
246
|
+
mediaPath
|
|
247
|
+
].filter((v)=>Boolean(v));
|
|
248
|
+
const publicDirPatterns = getPublicDirPatterns(publicDir);
|
|
249
|
+
const staticReg = [
|
|
250
|
+
'static/',
|
|
251
|
+
'upload/',
|
|
252
|
+
...staticFiles,
|
|
253
|
+
...publicDirPatterns
|
|
254
|
+
];
|
|
255
|
+
const iconReg = [
|
|
256
|
+
'favicon.ico',
|
|
257
|
+
'icon.png',
|
|
258
|
+
...favicons
|
|
259
|
+
];
|
|
260
|
+
const regPrefix = pathPrefix.endsWith('/') ? pathPrefix : `${pathPrefix}/`;
|
|
261
|
+
const staticPathRegExp = new RegExp(`^${regPrefix}(${[
|
|
262
|
+
...staticReg,
|
|
263
|
+
...iconReg
|
|
264
|
+
].join('|')})`);
|
|
265
|
+
const publicMiddleware = createPublicMiddleware({
|
|
266
|
+
pwd,
|
|
267
|
+
routes: routes || []
|
|
268
|
+
});
|
|
269
|
+
let moduleFederationAssetsPromise = null;
|
|
270
|
+
const getModuleFederationAssets = async ()=>{
|
|
271
|
+
if (!moduleFederationAssetsPromise) moduleFederationAssetsPromise = getModuleFederationAssetList(pwd);
|
|
272
|
+
return moduleFederationAssetsPromise;
|
|
273
|
+
};
|
|
274
|
+
const serveFile = async (c, filepath, moduleFederationAsset = false, moduleFederationRemoteEntry = false, requestPath = '')=>{
|
|
275
|
+
if (moduleFederationAsset) {
|
|
276
|
+
c.header('Access-Control-Allow-Origin', '*');
|
|
277
|
+
c.header('Access-Control-Allow-Headers', '*');
|
|
278
|
+
c.header('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS');
|
|
279
|
+
}
|
|
280
|
+
const mimeType = getMimeType(filepath);
|
|
281
|
+
if (mimeType) c.header('Content-Type', mimeType);
|
|
282
|
+
const shouldPatchManifest = moduleFederationAsset && requestPath === MODULE_FEDERATION_MANIFEST_FILE;
|
|
283
|
+
const shouldPatchRemoteEntry = moduleFederationRemoteEntry;
|
|
284
|
+
const canUsePreCompressed = !shouldPatchManifest && !shouldPatchRemoteEntry;
|
|
285
|
+
const preCompressedAsset = canUsePreCompressed ? await resolvePreCompressedAsset(c, filepath) : {
|
|
286
|
+
selected: null,
|
|
287
|
+
hasVariant: false
|
|
288
|
+
};
|
|
289
|
+
const targetFilepath = preCompressedAsset.selected?.filepath ?? filepath;
|
|
290
|
+
const chunk = await fileReader.readFileFromSystem(targetFilepath, 'buffer');
|
|
291
|
+
if (null === chunk) return null;
|
|
292
|
+
const responseChunk = shouldPatchManifest ? patchModuleFederationManifestPublicPath(c, chunk, pathPrefix) : shouldPatchRemoteEntry ? patchModuleFederationRemoteEntryPublicPath(c, chunk, pathPrefix) : chunk;
|
|
293
|
+
if (preCompressedAsset.hasVariant) appendVaryHeader(c, 'Accept-Encoding');
|
|
294
|
+
if (preCompressedAsset.selected) c.header('Content-Encoding', preCompressedAsset.selected.encoding);
|
|
295
|
+
c.header('Content-Length', String(responseChunk.byteLength));
|
|
296
|
+
const body = new Uint8Array(responseChunk.buffer, responseChunk.byteOffset, responseChunk.byteLength);
|
|
297
|
+
return c.body(body, 200);
|
|
298
|
+
};
|
|
299
|
+
return async (c, next)=>{
|
|
300
|
+
const pageRoute = c.get('route');
|
|
301
|
+
const pathname = c.req.path;
|
|
302
|
+
if (pageRoute && '' === path.extname(pathname)) return next();
|
|
303
|
+
const hit = staticPathRegExp.test(pathname);
|
|
304
|
+
const requestPath = trimLeadingSlash(pathname.replace(pathPrefix, ()=>''));
|
|
305
|
+
if (requestPath.includes('..')) return next();
|
|
306
|
+
const moduleFederationAssetMeta = await getModuleFederationAssets();
|
|
307
|
+
const isModuleFederationAsset = moduleFederationAssetMeta.assets.has(requestPath);
|
|
308
|
+
const isModuleFederationRemoteEntry = moduleFederationAssetMeta.remoteEntry === requestPath;
|
|
309
|
+
const serveByPath = async (filepath, moduleFederationAsset = false, moduleFederationRemoteEntry = false)=>{
|
|
310
|
+
if (!await fs.pathExists(filepath)) return null;
|
|
311
|
+
return serveFile(c, filepath, moduleFederationAsset, moduleFederationRemoteEntry, requestPath);
|
|
312
|
+
};
|
|
313
|
+
if (hit) {
|
|
314
|
+
const response = await serveByPath(path.join(pwd, requestPath), isModuleFederationAsset, isModuleFederationRemoteEntry);
|
|
315
|
+
if (null !== response) return response;
|
|
316
|
+
return next();
|
|
317
|
+
}
|
|
318
|
+
if (isModuleFederationAsset) {
|
|
319
|
+
const response = await serveByPath(path.join(pwd, requestPath), true, isModuleFederationRemoteEntry);
|
|
320
|
+
if (null !== response) return response;
|
|
321
|
+
}
|
|
322
|
+
return publicMiddleware(c, next);
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
const prepareFavicons = (favicon)=>{
|
|
326
|
+
const faviconNames = [];
|
|
327
|
+
if (favicon && 'string' == typeof favicon) faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
|
|
328
|
+
return faviconNames;
|
|
329
|
+
};
|
|
330
|
+
export { createPublicMiddleware, createStaticMiddleware, serverStaticPlugin };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
const AGGRED_DIR = {
|
|
3
|
+
mock: 'config/mock',
|
|
4
|
+
server: 'server',
|
|
5
|
+
api: 'api',
|
|
6
|
+
shared: 'shared',
|
|
7
|
+
lambda: 'lambda'
|
|
8
|
+
};
|
|
9
|
+
const REPLACE_REG = {
|
|
10
|
+
before: {
|
|
11
|
+
head: '<head\\b[^>]*>',
|
|
12
|
+
body: '<body\\b[^>]*>'
|
|
13
|
+
},
|
|
14
|
+
after: {
|
|
15
|
+
head: '</head>',
|
|
16
|
+
body: '</body>'
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var constants_ServerTimings = /*#__PURE__*/ function(ServerTimings) {
|
|
20
|
+
ServerTimings["SERVER_HANDLE_REQUEST"] = "server-handle-request";
|
|
21
|
+
ServerTimings["SERVER_MIDDLEWARE"] = "server-middleware";
|
|
22
|
+
ServerTimings["SERVER_HOOK_AFTER_RENDER"] = "server-hook-after-render";
|
|
23
|
+
ServerTimings["SERVER_HOOK_AFTER_MATCH"] = "server-hook-after-match";
|
|
24
|
+
return ServerTimings;
|
|
25
|
+
}({});
|
|
26
|
+
const SERVER_TIMING = 'Server-Timing';
|
|
27
|
+
const X_RENDER_CACHE = 'x-render-cache';
|
|
28
|
+
const X_MODERNJS_RENDER = 'x-modernjs-render';
|
|
29
|
+
export { AGGRED_DIR, REPLACE_REG, SERVER_TIMING, X_MODERNJS_RENDER, X_RENDER_CACHE, constants_ServerTimings as ServerTimings };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { createStorage } from "./utils/storage.mjs";
|
|
3
|
+
const kHonoContextStorage = Symbol.for('modernjs.server-core.honoContextStorage');
|
|
4
|
+
const { run: run, useContext: useHonoContext } = createStorage(kHonoContextStorage);
|
|
5
|
+
export { run, useHonoContext };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
const LOADER_CONTEXT = 'loaderContext';
|
|
3
|
+
function getLoaderCtx(c) {
|
|
4
|
+
const loaderContext = c.get(LOADER_CONTEXT);
|
|
5
|
+
if (loaderContext) return loaderContext;
|
|
6
|
+
{
|
|
7
|
+
const loaderContext = new Map();
|
|
8
|
+
c.set(LOADER_CONTEXT, loaderContext);
|
|
9
|
+
return loaderContext;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export { getLoaderCtx };
|