@modern-js/server-core 2.47.0 → 2.47.1-alpha.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 (142) hide show
  1. package/dist/cjs/base/adapters/node/bff.js +69 -0
  2. package/dist/cjs/base/adapters/node/hono.js +62 -0
  3. package/dist/cjs/base/adapters/node/index.js +32 -0
  4. package/dist/cjs/base/adapters/node/loadServer.js +56 -0
  5. package/dist/cjs/base/adapters/node/middlewares/index.js +26 -0
  6. package/dist/cjs/base/adapters/node/middlewares/mock.js +113 -0
  7. package/dist/cjs/base/adapters/node/middlewares/serverStatic.js +105 -0
  8. package/dist/cjs/base/adapters/node/middlewares/templates.js +65 -0
  9. package/dist/cjs/base/adapters/node/node.js +121 -0
  10. package/dist/cjs/base/adapters/node/polyfills/index.js +24 -0
  11. package/dist/cjs/base/adapters/node/polyfills/install.js +57 -0
  12. package/dist/cjs/base/adapters/node/polyfills/stream.js +159 -0
  13. package/dist/cjs/base/constants.js +55 -0
  14. package/dist/cjs/base/index.js +73 -0
  15. package/dist/cjs/base/middlewares/customServer/base.js +115 -0
  16. package/dist/cjs/base/middlewares/customServer/context.js +78 -0
  17. package/dist/cjs/base/middlewares/customServer/index.js +138 -0
  18. package/dist/cjs/base/middlewares/customServer/routerApi.js +48 -0
  19. package/dist/cjs/base/middlewares/customServer/template.js +60 -0
  20. package/dist/cjs/base/middlewares/dataHandler.js +69 -0
  21. package/dist/cjs/base/middlewares/faviconFallback.js +34 -0
  22. package/dist/cjs/base/middlewares/index.js +28 -0
  23. package/dist/cjs/base/middlewares/monitor.js +75 -0
  24. package/dist/cjs/base/middlewares/renderHandler/index.js +92 -0
  25. package/dist/cjs/base/middlewares/renderHandler/render.js +90 -0
  26. package/dist/cjs/base/middlewares/renderHandler/serverTiming.js +43 -0
  27. package/dist/cjs/base/middlewares/renderHandler/ssrCache.js +173 -0
  28. package/dist/cjs/base/middlewares/renderHandler/ssrRender.js +183 -0
  29. package/dist/cjs/base/serverBase.js +167 -0
  30. package/dist/cjs/base/utils/debug.js +29 -0
  31. package/dist/cjs/base/utils/entry.js +30 -0
  32. package/dist/cjs/base/utils/env.js +45 -0
  33. package/dist/cjs/base/utils/error.js +65 -0
  34. package/dist/cjs/base/utils/index.js +40 -0
  35. package/dist/cjs/base/utils/middlewareCollector.js +54 -0
  36. package/dist/cjs/base/utils/path.js +46 -0
  37. package/dist/cjs/base/utils/request.js +65 -0
  38. package/dist/cjs/base/utils/serverConfig.js +71 -0
  39. package/dist/cjs/base/utils/transformStream.js +38 -0
  40. package/dist/cjs/base/utils/warmup.js +43 -0
  41. package/dist/cjs/core/hono.js +16 -0
  42. package/dist/cjs/core/index.js +24 -0
  43. package/dist/cjs/{loadPlugins.js → core/loadPlugins.js} +1 -1
  44. package/dist/cjs/{plugin.js → core/plugin.js} +1 -3
  45. package/dist/cjs/core/render.js +16 -0
  46. package/dist/cjs/core/server.js +22 -0
  47. package/dist/cjs/index.js +6 -4
  48. package/dist/esm/base/adapters/node/bff.js +45 -0
  49. package/dist/esm/base/adapters/node/hono.js +37 -0
  50. package/dist/esm/base/adapters/node/index.js +6 -0
  51. package/dist/esm/base/adapters/node/loadServer.js +22 -0
  52. package/dist/esm/base/adapters/node/middlewares/index.js +3 -0
  53. package/dist/esm/base/adapters/node/middlewares/mock.js +79 -0
  54. package/dist/esm/base/adapters/node/middlewares/serverStatic.js +71 -0
  55. package/dist/esm/base/adapters/node/middlewares/templates.js +31 -0
  56. package/dist/esm/base/adapters/node/node.js +95 -0
  57. package/dist/esm/base/adapters/node/polyfills/index.js +2 -0
  58. package/dist/esm/base/adapters/node/polyfills/install.js +33 -0
  59. package/dist/esm/base/adapters/node/polyfills/stream.js +132 -0
  60. package/dist/esm/base/constants.js +29 -0
  61. package/dist/esm/base/index.js +32 -0
  62. package/dist/esm/base/middlewares/customServer/base.js +91 -0
  63. package/dist/esm/base/middlewares/customServer/context.js +51 -0
  64. package/dist/esm/base/middlewares/customServer/index.js +114 -0
  65. package/dist/esm/base/middlewares/customServer/routerApi.js +24 -0
  66. package/dist/esm/base/middlewares/customServer/template.js +36 -0
  67. package/dist/esm/base/middlewares/dataHandler.js +35 -0
  68. package/dist/esm/base/middlewares/faviconFallback.js +10 -0
  69. package/dist/esm/base/middlewares/index.js +4 -0
  70. package/dist/esm/base/middlewares/monitor.js +49 -0
  71. package/dist/esm/base/middlewares/renderHandler/index.js +67 -0
  72. package/dist/esm/base/middlewares/renderHandler/render.js +66 -0
  73. package/dist/esm/base/middlewares/renderHandler/serverTiming.js +19 -0
  74. package/dist/esm/base/middlewares/renderHandler/ssrCache.js +149 -0
  75. package/dist/esm/base/middlewares/renderHandler/ssrRender.js +149 -0
  76. package/dist/esm/base/serverBase.js +143 -0
  77. package/dist/esm/base/utils/debug.js +5 -0
  78. package/dist/esm/base/utils/entry.js +6 -0
  79. package/dist/esm/base/utils/env.js +20 -0
  80. package/dist/esm/base/utils/error.js +41 -0
  81. package/dist/esm/base/utils/index.js +10 -0
  82. package/dist/esm/base/utils/middlewareCollector.js +29 -0
  83. package/dist/esm/base/utils/path.js +12 -0
  84. package/dist/esm/base/utils/request.js +38 -0
  85. package/dist/esm/base/utils/serverConfig.js +35 -0
  86. package/dist/esm/base/utils/transformStream.js +14 -0
  87. package/dist/esm/base/utils/warmup.js +9 -0
  88. package/dist/esm/core/hono.js +0 -0
  89. package/dist/esm/core/index.js +2 -0
  90. package/dist/esm/{loadPlugins.js → core/loadPlugins.js} +1 -1
  91. package/dist/esm/{plugin.js → core/plugin.js} +1 -3
  92. package/dist/esm/core/render.js +0 -0
  93. package/dist/esm/core/server.js +1 -0
  94. package/dist/esm/index.js +3 -2
  95. package/dist/types/base/adapters/node/bff.d.ts +4 -0
  96. package/dist/types/base/adapters/node/hono.d.ts +30 -0
  97. package/dist/types/base/adapters/node/index.d.ts +6 -0
  98. package/dist/types/base/adapters/node/loadServer.d.ts +3 -0
  99. package/dist/types/base/adapters/node/middlewares/index.d.ts +3 -0
  100. package/dist/types/base/adapters/node/middlewares/mock.d.ts +5 -0
  101. package/dist/types/base/adapters/node/middlewares/serverStatic.d.ts +9 -0
  102. package/dist/types/base/adapters/node/middlewares/templates.d.ts +3 -0
  103. package/dist/types/base/adapters/node/node.d.ts +12 -0
  104. package/dist/types/base/adapters/node/polyfills/index.d.ts +2 -0
  105. package/dist/types/base/adapters/node/polyfills/install.d.ts +1 -0
  106. package/dist/types/base/adapters/node/polyfills/stream.d.ts +18 -0
  107. package/dist/types/base/constants.d.ts +23 -0
  108. package/dist/types/base/index.d.ts +9 -0
  109. package/dist/types/base/middlewares/customServer/base.d.ts +3 -0
  110. package/dist/types/base/middlewares/customServer/context.d.ts +7 -0
  111. package/dist/types/base/middlewares/customServer/index.d.ts +13 -0
  112. package/dist/types/base/middlewares/customServer/routerApi.d.ts +9 -0
  113. package/dist/types/base/middlewares/customServer/template.d.ts +11 -0
  114. package/dist/types/base/middlewares/dataHandler.d.ts +3 -0
  115. package/dist/types/base/middlewares/faviconFallback.d.ts +2 -0
  116. package/dist/types/base/middlewares/index.d.ts +4 -0
  117. package/dist/types/base/middlewares/monitor.d.ts +7 -0
  118. package/dist/types/base/middlewares/renderHandler/index.d.ts +9 -0
  119. package/dist/types/base/middlewares/renderHandler/render.d.ts +12 -0
  120. package/dist/types/base/middlewares/renderHandler/serverTiming.d.ts +7 -0
  121. package/dist/types/base/middlewares/renderHandler/ssrCache.d.ts +17 -0
  122. package/dist/types/base/middlewares/renderHandler/ssrRender.d.ts +18 -0
  123. package/dist/types/base/serverBase.d.ts +49 -0
  124. package/dist/types/base/utils/debug.d.ts +1 -0
  125. package/dist/types/base/utils/entry.d.ts +2 -0
  126. package/dist/types/base/utils/env.d.ts +2 -0
  127. package/dist/types/base/utils/error.d.ts +1 -0
  128. package/dist/types/base/utils/index.d.ts +10 -0
  129. package/dist/types/base/utils/middlewareCollector.d.ts +12 -0
  130. package/dist/types/base/utils/path.d.ts +3 -0
  131. package/dist/types/base/utils/request.d.ts +12 -0
  132. package/dist/types/base/utils/serverConfig.d.ts +14 -0
  133. package/dist/types/base/utils/transformStream.d.ts +2 -0
  134. package/dist/types/base/utils/warmup.d.ts +1 -0
  135. package/dist/types/core/hono.d.ts +1 -0
  136. package/dist/types/core/index.d.ts +2 -0
  137. package/dist/types/{loadPlugins.d.ts → core/loadPlugins.d.ts} +1 -1
  138. package/dist/types/{plugin.d.ts → core/plugin.d.ts} +32 -35
  139. package/dist/types/core/render.d.ts +11 -0
  140. package/dist/types/core/server.d.ts +71 -0
  141. package/dist/types/index.d.ts +3 -2
  142. package/package.json +25 -2
@@ -0,0 +1,114 @@
1
+ import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
+ import { time } from "@modern-js/runtime-utils/time";
3
+ import { createTransformStream } from "../../utils";
4
+ import { ServerReportTimings } from "../../constants";
5
+ import { createAfterMatchCtx, createAfterRenderCtx, createCustomMiddlewaresCtx, createAfterStreamingRenderContext } from "./context";
6
+ const noop = () => {
7
+ };
8
+ class CustomServer {
9
+ getHookMiddleware(entryName, routes) {
10
+ return async (c, next) => {
11
+ const routeInfo = routes.find((route) => route.entryName === entryName);
12
+ const logger = c.get("logger");
13
+ const reporter = c.get("reporter");
14
+ const metrics = c.get("metrics");
15
+ const afterMatchCtx = createAfterMatchCtx(c, entryName, logger, metrics);
16
+ const getCost = time();
17
+ await this.runner.afterMatch(afterMatchCtx, {
18
+ onLast: noop
19
+ });
20
+ const cost = getCost();
21
+ cost && reporter.reportTiming(ServerReportTimings.SERVER_HOOK_AFTER_MATCH, cost);
22
+ const {
23
+ // current,
24
+ url,
25
+ status
26
+ } = afterMatchCtx.router;
27
+ if (url) {
28
+ return c.redirect(url, status);
29
+ }
30
+ const { current } = afterMatchCtx.router;
31
+ if (current !== entryName) {
32
+ const rewriteRoute = routes.find((route) => route.entryName === current);
33
+ if (rewriteRoute) {
34
+ return this.serverBase.request(rewriteRoute.urlPath);
35
+ }
36
+ }
37
+ if (c.finalized) {
38
+ return void 0;
39
+ }
40
+ await next();
41
+ if (c.finalized && !c.res.body) {
42
+ return void 0;
43
+ }
44
+ if (routeInfo.isStream) {
45
+ var _c_res_body;
46
+ const afterStreamingRenderContext = createAfterStreamingRenderContext(c, logger, routeInfo, metrics);
47
+ const injectStream = createTransformStream((chunk) => {
48
+ const context = afterStreamingRenderContext(chunk);
49
+ return this.runner.afterStreamingRender(context, {
50
+ onLast: ({ chunk: chunk2 }) => chunk2
51
+ });
52
+ });
53
+ (_c_res_body = c.res.body) === null || _c_res_body === void 0 ? void 0 : _c_res_body.pipeThrough(injectStream);
54
+ const { headers, status: status2, statusText } = c.res;
55
+ c.res = c.body(injectStream.readable, {
56
+ headers,
57
+ status: status2,
58
+ statusText
59
+ });
60
+ } else {
61
+ const afterRenderCtx = await createAfterRenderCtx(c, logger, metrics);
62
+ const getCost2 = time();
63
+ await this.runner.afterRender(afterRenderCtx, {
64
+ onLast: noop
65
+ });
66
+ const cost2 = getCost2();
67
+ cost2 && reporter.reportTiming(ServerReportTimings.SERVER_HOOK_AFTER_RENDER, cost2);
68
+ if (afterRenderCtx.response.private_overrided) {
69
+ return void 0;
70
+ }
71
+ const newBody = afterRenderCtx.template.get();
72
+ c.res = c.body(newBody);
73
+ }
74
+ };
75
+ }
76
+ getServerMiddleware() {
77
+ return async (c, next) => {
78
+ const serverMiddleware = await this.serverMiddlewarePromise;
79
+ if (!serverMiddleware) {
80
+ return next();
81
+ }
82
+ const reporter = c.get("reporter");
83
+ const logger = c.get("logger");
84
+ const metrics = c.get("metrics");
85
+ const customMiddlewareCtx = createCustomMiddlewaresCtx(c, logger, metrics);
86
+ const getCost = time();
87
+ await serverMiddleware(customMiddlewareCtx);
88
+ const cost = getCost();
89
+ cost && reporter.reportTiming(ServerReportTimings.SERVER_MIDDLEWARE, cost);
90
+ if (!c.finalized) {
91
+ return next();
92
+ }
93
+ };
94
+ }
95
+ constructor(runner, serverBase, pwd) {
96
+ _define_property(this, "runner", void 0);
97
+ _define_property(this, "serverMiddlewarePromise", void 0);
98
+ _define_property(this, "serverBase", void 0);
99
+ this.runner = runner;
100
+ this.serverBase = serverBase;
101
+ const webExtension = [];
102
+ this.serverMiddlewarePromise = runner.prepareWebServer({
103
+ pwd,
104
+ config: {
105
+ middleware: webExtension
106
+ }
107
+ }, {
108
+ onLast: () => null
109
+ });
110
+ }
111
+ }
112
+ export {
113
+ CustomServer
114
+ };
@@ -0,0 +1,24 @@
1
+ import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
+ class RouterAPI {
3
+ redirect(url, status = 302) {
4
+ this.url = url;
5
+ this.status = status;
6
+ }
7
+ rewrite(entryName) {
8
+ this.current = entryName;
9
+ }
10
+ use(entryName) {
11
+ this.rewrite(entryName);
12
+ }
13
+ constructor(entryName) {
14
+ _define_property(this, "current", void 0);
15
+ _define_property(this, "status", void 0);
16
+ _define_property(this, "url", void 0);
17
+ this.current = entryName;
18
+ this.status = 200;
19
+ this.url = "";
20
+ }
21
+ }
22
+ export {
23
+ RouterAPI
24
+ };
@@ -0,0 +1,36 @@
1
+ import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
+ import { REPLACE_REG } from "../../constants";
3
+ class TemplateApi {
4
+ set(content) {
5
+ this.body = content;
6
+ }
7
+ get() {
8
+ return this.body;
9
+ }
10
+ prependHead(fragment) {
11
+ const { head } = REPLACE_REG.before;
12
+ this.replaceBody(new RegExp(head), (beforeHead) => `${beforeHead}${fragment}`);
13
+ }
14
+ appendHead(fragment) {
15
+ const { head } = REPLACE_REG.after;
16
+ this.replaceBody(head, () => `${fragment}${head}`);
17
+ }
18
+ prependBody(fragment) {
19
+ const { body } = REPLACE_REG.before;
20
+ this.replaceBody(new RegExp(body), (beforeBody) => `${beforeBody}${fragment}`);
21
+ }
22
+ appendBody(fragment) {
23
+ const { body } = REPLACE_REG.after;
24
+ this.replaceBody(body, () => `${fragment}${body}`);
25
+ }
26
+ replaceBody(searchValue, replaceCb) {
27
+ this.body = this.body.replace(searchValue, replaceCb);
28
+ }
29
+ constructor(body) {
30
+ _define_property(this, "body", void 0);
31
+ this.body = body;
32
+ }
33
+ }
34
+ export {
35
+ TemplateApi
36
+ };
@@ -0,0 +1,35 @@
1
+ import { MAIN_ENTRY_NAME, SERVER_BUNDLE_DIRECTORY } from "@modern-js/utils";
2
+ import { getPathModule, sortRoutes } from "../utils";
3
+ const bindDataHandlers = async (server, routes, distDir) => {
4
+ const path = await getPathModule();
5
+ routes.sort(sortRoutes).forEach((route) => {
6
+ const bundlePath = path.join(distDir, SERVER_BUNDLE_DIRECTORY, `${route.entryName || MAIN_ENTRY_NAME}-server-loaders.js`);
7
+ server.all(`${route.urlPath === "/" ? "*" : `${route.urlPath}/*`}`, createDataHandler(routes, bundlePath));
8
+ });
9
+ };
10
+ const createDataHandler = (serverRoutes, buildModulePath) => {
11
+ return async (context, next) => {
12
+ let buildModule;
13
+ try {
14
+ buildModule = await import(buildModulePath);
15
+ } catch (_) {
16
+ return next();
17
+ }
18
+ const { routes, handleRequest } = buildModule;
19
+ const logger = context.get("logger");
20
+ const reporter = context.get("reporter");
21
+ const response = await handleRequest({
22
+ request: context.req.raw,
23
+ serverRoutes,
24
+ context: {
25
+ logger,
26
+ reporter
27
+ },
28
+ routes
29
+ });
30
+ return response ? response : next();
31
+ };
32
+ };
33
+ export {
34
+ bindDataHandlers
35
+ };
@@ -0,0 +1,10 @@
1
+ const favionFallbackMiddleware = async (c, next) => {
2
+ if (c.req.path === "/favicon.ico") {
3
+ return c.body(null, 204);
4
+ } else {
5
+ return next();
6
+ }
7
+ };
8
+ export {
9
+ favionFallbackMiddleware
10
+ };
@@ -0,0 +1,4 @@
1
+ export * from "./faviconFallback";
2
+ export * from "./dataHandler";
3
+ export * from "./monitor";
4
+ export * from "./renderHandler";
@@ -0,0 +1,49 @@
1
+ import { time } from "@modern-js/runtime-utils/time";
2
+ import { ServerReportTimings } from "../constants";
3
+ const defaultReporter = {
4
+ init() {
5
+ },
6
+ reportError() {
7
+ },
8
+ reportTiming() {
9
+ },
10
+ reportInfo() {
11
+ },
12
+ reportWarn() {
13
+ }
14
+ };
15
+ function injectReporter() {
16
+ return async (c, next) => {
17
+ const reporter = c.get("reporter");
18
+ if (!reporter) {
19
+ c.set("reporter", defaultReporter);
20
+ }
21
+ await next();
22
+ };
23
+ }
24
+ function initReporter(entryName) {
25
+ return async (c, next) => {
26
+ const reporter = c.get("reporter");
27
+ await reporter.init({
28
+ entryName
29
+ });
30
+ const getCost = time();
31
+ await next();
32
+ const cost = getCost();
33
+ reporter.reportTiming(ServerReportTimings.SERVER_HANDLE_REQUEST, cost);
34
+ };
35
+ }
36
+ function injectLogger(inputLogger) {
37
+ return async (c, next) => {
38
+ const logger = c.get("logger");
39
+ if (!logger && inputLogger) {
40
+ c.set("logger", inputLogger);
41
+ }
42
+ await next();
43
+ };
44
+ }
45
+ export {
46
+ initReporter,
47
+ injectLogger,
48
+ injectReporter
49
+ };
@@ -0,0 +1,67 @@
1
+ import { warmup, checkIsProd, sortRoutes, getPathModule } from "../../utils";
2
+ import { initReporter } from "../monitor";
3
+ import { CustomServer } from "../customServer";
4
+ import { ssrCache } from "./ssrCache";
5
+ import { createRender } from "./render";
6
+ function createRenderHandler(render) {
7
+ return async (c, _) => {
8
+ var _c_env_node;
9
+ const logger = c.get("logger");
10
+ const reporter = c.get("reporter");
11
+ const request = c.req.raw;
12
+ const nodeReq = (_c_env_node = c.env.node) === null || _c_env_node === void 0 ? void 0 : _c_env_node.req;
13
+ const templates = c.get("templates");
14
+ const res = await render(request, {
15
+ logger,
16
+ nodeReq,
17
+ reporter,
18
+ tpls: templates || {}
19
+ });
20
+ return res;
21
+ };
22
+ }
23
+ function getRenderHandler(options) {
24
+ const { routes, pwd, config } = options;
25
+ if (routes && routes.length > 0) {
26
+ var _config_server, _options_config_security;
27
+ const ssrConfig = (_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.ssr;
28
+ const forceCSR = typeof ssrConfig === "object" ? ssrConfig.forceCSR : false;
29
+ const render = createRender({
30
+ routes,
31
+ pwd,
32
+ staticGenerate: options.staticGenerate,
33
+ metaName: options.metaName || "modern-js",
34
+ forceCSR,
35
+ nonce: (_options_config_security = options.config.security) === null || _options_config_security === void 0 ? void 0 : _options_config_security.nonce
36
+ });
37
+ return render;
38
+ }
39
+ return null;
40
+ }
41
+ async function bindRenderHandler(server, options) {
42
+ const { routes, pwd } = options;
43
+ const path = await getPathModule();
44
+ const { runner } = server;
45
+ if (routes && routes.length > 0) {
46
+ const customServer = new CustomServer(runner, server, pwd);
47
+ const ssrBundles = routes.filter((route) => route.isSSR && route.bundle).map((route) => path.join(pwd, route.bundle));
48
+ warmup(ssrBundles);
49
+ await ssrCache.loadCacheMod(checkIsProd() ? pwd : void 0);
50
+ const pageRoutes = routes.filter((route) => !route.isApi).sort(sortRoutes);
51
+ for (const route of pageRoutes) {
52
+ const { urlPath: originUrlPath, entryName } = route;
53
+ const urlPath = originUrlPath.endsWith("/") ? `${originUrlPath}*` : `${originUrlPath}/*`;
54
+ const customServerHookMiddleware = customServer.getHookMiddleware(entryName || "main", routes);
55
+ server.use(urlPath, initReporter(entryName));
56
+ server.use(urlPath, customServerHookMiddleware);
57
+ const customServerMiddleware = customServer.getServerMiddleware();
58
+ server.use(urlPath, customServerMiddleware);
59
+ }
60
+ const render = getRenderHandler(options);
61
+ render && server.get("*", createRenderHandler(render));
62
+ }
63
+ }
64
+ export {
65
+ bindRenderHandler,
66
+ getRenderHandler
67
+ };
@@ -0,0 +1,66 @@
1
+ import { cutNameByHyphen } from "@modern-js/utils";
2
+ import { parseQuery } from "../../utils/request";
3
+ import { createErrorHtml, sortRoutes } from "../../utils";
4
+ import { ssrRender } from "./ssrRender";
5
+ function createRender({ routes, pwd, metaName, staticGenerate, forceCSR, nonce }) {
6
+ return async (req, { logger, nodeReq, reporter, tpls }) => {
7
+ const routeInfo = matchRoute(req, routes);
8
+ if (!routeInfo) {
9
+ return new Response(createErrorHtml(404), {
10
+ status: 404,
11
+ headers: {
12
+ "content-type": "text/html; charset=UTF-8"
13
+ }
14
+ });
15
+ }
16
+ const html = tpls[routeInfo.entryName];
17
+ if (!html) {
18
+ throw new Error(`Can't found entry ${routeInfo.entryName} html `);
19
+ }
20
+ const renderMode = getRenderMode(req, metaName || "modern-js", routeInfo.isSSR, forceCSR);
21
+ return renderMode === "csr" ? csrRender(html) : ssrRender(req, {
22
+ pwd,
23
+ mode: "string",
24
+ html,
25
+ routeInfo,
26
+ staticGenerate: staticGenerate || false,
27
+ metaName: metaName || "modern-js",
28
+ nonce,
29
+ logger,
30
+ nodeReq,
31
+ reporter
32
+ });
33
+ };
34
+ }
35
+ function matchRoute(req, routes) {
36
+ const sorted = routes.sort(sortRoutes);
37
+ for (const route of sorted) {
38
+ const reg = new RegExp(route.urlPath);
39
+ if (reg.test(req.url)) {
40
+ return route;
41
+ }
42
+ }
43
+ return void 0;
44
+ }
45
+ function getRenderMode(req, framework, isSSR, forceCSR) {
46
+ const query = parseQuery(req);
47
+ if (isSSR) {
48
+ if (forceCSR && (query.csr || req.headers.get(`x-${cutNameByHyphen(framework)}-ssr-fallback`))) {
49
+ return "csr";
50
+ }
51
+ return "ssr";
52
+ } else {
53
+ return "csr";
54
+ }
55
+ }
56
+ function csrRender(html) {
57
+ return new Response(html, {
58
+ status: 200,
59
+ headers: new Headers({
60
+ "content-type": "text/html; charset=UTF-8"
61
+ })
62
+ });
63
+ }
64
+ export {
65
+ createRender
66
+ };
@@ -0,0 +1,19 @@
1
+ import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
+ const SERVER_TIMING = "Server-Timing";
3
+ class ServerTiming {
4
+ addServeTiming(name, dur, desc) {
5
+ const _name = `bd-${this.meta}-${name}`;
6
+ const value = `${_name};${desc ? `decs="${desc}";` : ""} dur=${dur}`;
7
+ this.headers.append(SERVER_TIMING, value);
8
+ return this;
9
+ }
10
+ constructor(headers, meta) {
11
+ _define_property(this, "headers", void 0);
12
+ _define_property(this, "meta", void 0);
13
+ this.meta = meta;
14
+ this.headers = headers;
15
+ }
16
+ }
17
+ export {
18
+ ServerTiming
19
+ };
@@ -0,0 +1,149 @@
1
+ import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
+ import { Readable } from "stream";
3
+ import { SERVER_DIR, requireExistModule } from "@modern-js/utils";
4
+ import { createMemoryStorage } from "@modern-js/runtime-utils/storer";
5
+ import { createReadableStreamFromReadable } from "../../adapters/node/polyfills/stream";
6
+ import { createTransformStream, getPathModule, getPathname } from "../../utils";
7
+ class CacheManager {
8
+ async getCacheResult(req, cacheControl, render, ssrContext) {
9
+ const key = this.computedKey(req, cacheControl);
10
+ const value = await this.container.get(key);
11
+ const { maxAge, staleWhileRevalidate } = cacheControl;
12
+ const ttl = maxAge + staleWhileRevalidate;
13
+ if (value) {
14
+ const cache = JSON.parse(value);
15
+ const interval = Date.now() - cache.cursor;
16
+ if (interval <= maxAge) {
17
+ return cache.val;
18
+ } else if (interval <= staleWhileRevalidate + maxAge) {
19
+ this.processCache(key, render, ssrContext, ttl);
20
+ return cache.val;
21
+ } else {
22
+ return this.processCache(key, render, ssrContext, ttl);
23
+ }
24
+ } else {
25
+ return this.processCache(key, render, ssrContext, ttl);
26
+ }
27
+ }
28
+ async processCache(key, render, ssrContext, ttl) {
29
+ const renderResult = await render(ssrContext);
30
+ if (!renderResult) {
31
+ return "";
32
+ } else if (typeof renderResult === "string") {
33
+ const current = Date.now();
34
+ const cache = {
35
+ val: renderResult,
36
+ cursor: current
37
+ };
38
+ await this.container.set(key, JSON.stringify(cache), {
39
+ ttl
40
+ });
41
+ return renderResult;
42
+ } else {
43
+ const body = (
44
+ // TODO: remove node:stream, move it to ssr entry.
45
+ renderResult instanceof Readable ? createReadableStreamFromReadable(renderResult) : renderResult
46
+ );
47
+ let html = "";
48
+ const stream = createTransformStream((chunk) => {
49
+ html += chunk;
50
+ return chunk;
51
+ });
52
+ stream.readable.getReader().closed.then(() => {
53
+ const current = Date.now();
54
+ const cache = {
55
+ val: html,
56
+ cursor: current
57
+ };
58
+ this.container.set(key, JSON.stringify(cache), {
59
+ ttl
60
+ });
61
+ });
62
+ body.pipeThrough(stream);
63
+ return stream.readable;
64
+ }
65
+ }
66
+ computedKey(req, cacheControl) {
67
+ const pathname = getPathname(req);
68
+ const { customKey } = cacheControl;
69
+ const defaultKey = pathname.replace(/.+\/+$/, "");
70
+ if (customKey) {
71
+ if (typeof customKey === "string") {
72
+ return customKey;
73
+ } else {
74
+ return customKey(defaultKey);
75
+ }
76
+ } else {
77
+ return defaultKey;
78
+ }
79
+ }
80
+ constructor(container) {
81
+ _define_property(this, "container", void 0);
82
+ this.container = container;
83
+ }
84
+ }
85
+ const CACHE_FILENAME = "cache";
86
+ class ServerCache {
87
+ async loadCacheMod(pwd = process.cwd()) {
88
+ const path = await getPathModule();
89
+ const serverCacheFilepath = path.resolve(pwd, SERVER_DIR, CACHE_FILENAME);
90
+ const mod = requireExistModule(serverCacheFilepath, {
91
+ interop: false
92
+ });
93
+ this.cacheOption = mod === null || mod === void 0 ? void 0 : mod.cacheOption;
94
+ if (this.cacheOption && !(mod === null || mod === void 0 ? void 0 : mod.customContainer)) {
95
+ const cacheStorage = createMemoryStorage("__ssr__cache");
96
+ this.customContainer = cacheStorage;
97
+ } else {
98
+ this.customContainer = mod === null || mod === void 0 ? void 0 : mod.customContainer;
99
+ }
100
+ if (this.customContainer) {
101
+ this.cacheManger = new CacheManager(this.customContainer);
102
+ }
103
+ }
104
+ matchCacheControl(req) {
105
+ const { cacheOption } = this;
106
+ if (!cacheOption || !req) {
107
+ return void 0;
108
+ } else if (isCacheControl(cacheOption)) {
109
+ return cacheOption;
110
+ } else if (isCacheOptionProvider(cacheOption)) {
111
+ return cacheOption(req);
112
+ } else {
113
+ const url = req.url;
114
+ const options = Object.entries(cacheOption);
115
+ for (const [key, option] of options) {
116
+ if (key === "*" || new RegExp(key).test(url)) {
117
+ if (typeof option === "function") {
118
+ return option(req);
119
+ } else {
120
+ return option;
121
+ }
122
+ }
123
+ }
124
+ return void 0;
125
+ }
126
+ function isCacheOptionProvider(option) {
127
+ return typeof option === "function";
128
+ }
129
+ function isCacheControl(option) {
130
+ return typeof option === "object" && option !== null && "maxAge" in option;
131
+ }
132
+ }
133
+ getCache(req, cacheControl, render, ssrContext) {
134
+ if (this.cacheManger) {
135
+ return this.cacheManger.getCacheResult(req, cacheControl, render, ssrContext);
136
+ } else {
137
+ return render(ssrContext);
138
+ }
139
+ }
140
+ constructor() {
141
+ _define_property(this, "customContainer", void 0);
142
+ _define_property(this, "cacheOption", void 0);
143
+ _define_property(this, "cacheManger", void 0);
144
+ }
145
+ }
146
+ const ssrCache = new ServerCache();
147
+ export {
148
+ ssrCache
149
+ };