@modern-js/server-core 2.54.6 → 2.56.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 (69) hide show
  1. package/dist/cjs/adapters/node/plugins/resource.js +1 -1
  2. package/dist/cjs/constants.js +12 -9
  3. package/dist/cjs/index.js +3 -1
  4. package/dist/cjs/plugins/customServer/index.js +5 -5
  5. package/dist/cjs/plugins/index.js +7 -3
  6. package/dist/cjs/plugins/log.js +3 -3
  7. package/dist/cjs/plugins/monitors.js +183 -0
  8. package/dist/cjs/plugins/render/dataHandler.js +3 -2
  9. package/dist/cjs/plugins/render/index.js +6 -4
  10. package/dist/cjs/plugins/render/render.js +32 -15
  11. package/dist/cjs/plugins/render/ssrCache.js +72 -83
  12. package/dist/cjs/plugins/render/ssrRender.js +40 -145
  13. package/dist/cjs/types/requestHandler.js +16 -0
  14. package/dist/cjs/utils/error.js +3 -3
  15. package/dist/cjs/utils/transformStream.js +1 -1
  16. package/dist/esm/adapters/node/plugins/resource.js +1 -1
  17. package/dist/esm/constants.js +10 -8
  18. package/dist/esm/index.js +1 -0
  19. package/dist/esm/plugins/customServer/index.js +8 -8
  20. package/dist/esm/plugins/index.js +4 -2
  21. package/dist/esm/plugins/log.js +4 -4
  22. package/dist/esm/plugins/monitors.js +261 -0
  23. package/dist/esm/plugins/render/dataHandler.js +4 -3
  24. package/dist/esm/plugins/render/index.js +6 -4
  25. package/dist/esm/plugins/render/render.js +51 -24
  26. package/dist/esm/plugins/render/ssrCache.js +101 -131
  27. package/dist/esm/plugins/render/ssrRender.js +55 -175
  28. package/dist/esm/types/requestHandler.js +0 -0
  29. package/dist/esm/utils/error.js +3 -3
  30. package/dist/esm/utils/transformStream.js +16 -2
  31. package/dist/esm-node/adapters/node/plugins/resource.js +1 -1
  32. package/dist/esm-node/constants.js +10 -8
  33. package/dist/esm-node/index.js +1 -0
  34. package/dist/esm-node/plugins/customServer/index.js +6 -6
  35. package/dist/esm-node/plugins/index.js +4 -2
  36. package/dist/esm-node/plugins/log.js +3 -3
  37. package/dist/esm-node/plugins/monitors.js +156 -0
  38. package/dist/esm-node/plugins/render/dataHandler.js +3 -2
  39. package/dist/esm-node/plugins/render/index.js +5 -3
  40. package/dist/esm-node/plugins/render/render.js +33 -16
  41. package/dist/esm-node/plugins/render/ssrCache.js +73 -74
  42. package/dist/esm-node/plugins/render/ssrRender.js +43 -137
  43. package/dist/esm-node/types/requestHandler.js +0 -0
  44. package/dist/esm-node/utils/error.js +3 -3
  45. package/dist/esm-node/utils/transformStream.js +1 -1
  46. package/dist/types/constants.d.ts +2 -1
  47. package/dist/types/index.d.ts +1 -0
  48. package/dist/types/plugins/index.d.ts +1 -1
  49. package/dist/types/plugins/monitors.d.ts +6 -0
  50. package/dist/types/plugins/render/dataHandler.d.ts +1 -1
  51. package/dist/types/plugins/render/render.d.ts +3 -2
  52. package/dist/types/plugins/render/ssrCache.d.ts +7 -11
  53. package/dist/types/plugins/render/ssrRender.d.ts +10 -10
  54. package/dist/types/types/config/html.d.ts +11 -0
  55. package/dist/types/types/config/output.d.ts +8 -0
  56. package/dist/types/types/render.d.ts +7 -4
  57. package/dist/types/types/requestHandler.d.ts +41 -0
  58. package/dist/types/types/server.d.ts +13 -4
  59. package/dist/types/utils/error.d.ts +2 -2
  60. package/dist/types/utils/transformStream.d.ts +1 -1
  61. package/package.json +7 -8
  62. package/dist/cjs/plugins/monitor.js +0 -87
  63. package/dist/cjs/plugins/render/serverTiming.js +0 -40
  64. package/dist/esm/plugins/monitor.js +0 -120
  65. package/dist/esm/plugins/render/serverTiming.js +0 -21
  66. package/dist/esm-node/plugins/monitor.js +0 -62
  67. package/dist/esm-node/plugins/render/serverTiming.js +0 -16
  68. package/dist/types/plugins/monitor.d.ts +0 -9
  69. package/dist/types/plugins/render/serverTiming.d.ts +0 -7
@@ -15,19 +15,21 @@ const REPLACE_REG = {
15
15
  body: "</body>"
16
16
  }
17
17
  };
18
- var ServerReportTimings;
19
- (function(ServerReportTimings2) {
20
- ServerReportTimings2["SERVER_HANDLE_REQUEST"] = "server-handle-request";
21
- ServerReportTimings2["SERVER_MIDDLEWARE"] = "server-middleware";
22
- ServerReportTimings2["SERVER_HOOK_AFTER_RENDER"] = "server-hook-after-render";
23
- ServerReportTimings2["SERVER_HOOK_AFTER_MATCH"] = "server-hook-after-match";
24
- })(ServerReportTimings || (ServerReportTimings = {}));
18
+ var ServerTimings;
19
+ (function(ServerTimings2) {
20
+ ServerTimings2["SERVER_HANDLE_REQUEST"] = "server-handle-request";
21
+ ServerTimings2["SERVER_MIDDLEWARE"] = "server-middleware";
22
+ ServerTimings2["SERVER_HOOK_AFTER_RENDER"] = "server-hook-after-render";
23
+ ServerTimings2["SERVER_HOOK_AFTER_MATCH"] = "server-hook-after-match";
24
+ })(ServerTimings || (ServerTimings = {}));
25
+ const SERVER_TIMING = "Server-Timing";
25
26
  const X_RENDER_CACHE = "x-render-cache";
26
27
  const X_MODERNJS_RENDER = "x-modernjs-render";
27
28
  export {
28
29
  AGGRED_DIR,
29
30
  REPLACE_REG,
30
- ServerReportTimings,
31
+ SERVER_TIMING,
32
+ ServerTimings,
31
33
  X_MODERNJS_RENDER,
32
34
  X_RENDER_CACHE
33
35
  };
@@ -7,6 +7,7 @@ export * from "./types/plugin";
7
7
  export * from "./types/render";
8
8
  export * from "@modern-js/plugin";
9
9
  export * from "./types/config";
10
+ export * from "./types/requestHandler";
10
11
  export {
11
12
  AGGRED_DIR,
12
13
  ErrorDigest,
@@ -1,6 +1,6 @@
1
1
  import { time } from "@modern-js/runtime-utils/time";
2
2
  import { transformResponse } from "../../utils";
3
- import { ServerReportTimings } from "../../constants";
3
+ import { ServerTimings } from "../../constants";
4
4
  import { getLoaderCtx } from "./loader";
5
5
  import { getAfterMatchCtx, getAfterRenderCtx, createCustomMiddlewaresCtx, createAfterStreamingRenderContext } from "./context";
6
6
  import { createBaseHookContext } from "./base";
@@ -15,7 +15,7 @@ class CustomServer {
15
15
  getHookMiddleware(entryName, routes) {
16
16
  return async (c, next) => {
17
17
  const routeInfo = routes.find((route) => route.entryName === entryName);
18
- const reporter = c.get("reporter");
18
+ const monitors = c.get("monitors");
19
19
  const baseHookCtx = createBaseHookContext(c);
20
20
  const afterMatchCtx = getAfterMatchCtx(entryName, baseHookCtx);
21
21
  const getCost = time();
@@ -23,7 +23,7 @@ class CustomServer {
23
23
  onLast: noop
24
24
  });
25
25
  const cost = getCost();
26
- cost && (reporter === null || reporter === void 0 ? void 0 : reporter.reportTiming(ServerReportTimings.SERVER_HOOK_AFTER_MATCH, cost));
26
+ cost && (monitors === null || monitors === void 0 ? void 0 : monitors.timing(ServerTimings.SERVER_HOOK_AFTER_MATCH, cost));
27
27
  const { url, status } = afterMatchCtx.router;
28
28
  if (url) {
29
29
  return c.redirect(url, status);
@@ -63,7 +63,7 @@ class CustomServer {
63
63
  onLast: noop
64
64
  });
65
65
  const cost2 = getCost2();
66
- cost2 && (reporter === null || reporter === void 0 ? void 0 : reporter.reportTiming(ServerReportTimings.SERVER_HOOK_AFTER_RENDER, cost2));
66
+ cost2 && (monitors === null || monitors === void 0 ? void 0 : monitors.timing(ServerTimings.SERVER_HOOK_AFTER_RENDER, cost2));
67
67
  if (afterRenderCtx.response.private_overrided) {
68
68
  return void 0;
69
69
  }
@@ -82,7 +82,7 @@ class CustomServer {
82
82
  }
83
83
  return async (c, next) => {
84
84
  var _c_env_node_res, _c_env_node, _c_env;
85
- const reporter = c.get("reporter");
85
+ const monitors = c.get("monitors");
86
86
  const locals = {};
87
87
  const resArgs = {
88
88
  headers: new Headers()
@@ -91,7 +91,7 @@ class CustomServer {
91
91
  const getCost = time();
92
92
  await serverMiddleware(customMiddlewareCtx);
93
93
  const cost = getCost();
94
- cost && (reporter === null || reporter === void 0 ? void 0 : reporter.reportTiming(ServerReportTimings.SERVER_MIDDLEWARE, cost));
94
+ cost && (monitors === null || monitors === void 0 ? void 0 : monitors.timing(ServerTimings.SERVER_MIDDLEWARE, cost));
95
95
  c.set("locals", locals);
96
96
  if (isRedirect(resArgs.headers, resArgs.status)) {
97
97
  return c.redirect(resArgs.headers.get("Location") || "", resArgs.status || 302);
@@ -3,13 +3,15 @@ import { faviconPlugin } from "./favicon";
3
3
  import { processedByPlugin } from "./processedBy";
4
4
  import { getLoaderCtx } from "./customServer";
5
5
  import { logPlugin } from "./log";
6
- import { monitorPlugin } from "./monitor";
6
+ import { initMonitorsPlugin, injectServerTiming, injectloggerPluigin } from "./monitors";
7
7
  export {
8
8
  faviconPlugin,
9
9
  getLoaderCtx,
10
10
  getRenderHandler,
11
+ initMonitorsPlugin,
12
+ injectServerTiming,
13
+ injectloggerPluigin,
11
14
  logPlugin,
12
- monitorPlugin,
13
15
  processedByPlugin,
14
16
  renderPlugin
15
17
  };
@@ -39,13 +39,13 @@ function log(fn, prefix, method, path, status = 0, elapsed) {
39
39
  function logHandler() {
40
40
  return async function logger(c, next) {
41
41
  const { method } = c.req;
42
- const logger2 = c.get("logger");
43
- if (!logger2) {
42
+ const monitors = c.get("monitors");
43
+ if (!monitors) {
44
44
  await next();
45
45
  return;
46
46
  }
47
47
  const path = getPathname(c.req.raw);
48
- const logFn = logger2.debug;
48
+ const logFn = monitors.debug;
49
49
  log(logFn, "<--", method, path);
50
50
  const start = Date.now();
51
51
  await next();
@@ -0,0 +1,156 @@
1
+ import { time } from "@modern-js/runtime-utils/time";
2
+ import { SERVER_TIMING, ServerTimings } from "../constants";
3
+ function createMonitors() {
4
+ const coreMonitors = [];
5
+ const log = (level, message, args) => {
6
+ const event = {
7
+ type: "log",
8
+ payload: {
9
+ level,
10
+ message,
11
+ args
12
+ }
13
+ };
14
+ coreMonitors.forEach((monitor) => monitor(event));
15
+ };
16
+ const mointors = {
17
+ push(monitor) {
18
+ coreMonitors.push(monitor);
19
+ },
20
+ error(message, ...args) {
21
+ log("error", message, args);
22
+ },
23
+ warn(message, ...args) {
24
+ log("warn", message, args);
25
+ },
26
+ debug(message, ...args) {
27
+ log("debug", message, args);
28
+ },
29
+ info(message, ...args) {
30
+ log("info", message, args);
31
+ },
32
+ timing(name, dur, desc) {
33
+ const event = {
34
+ type: "timing",
35
+ payload: {
36
+ name,
37
+ dur,
38
+ desc
39
+ }
40
+ };
41
+ coreMonitors.forEach((monitor) => monitor(event));
42
+ }
43
+ };
44
+ return mointors;
45
+ }
46
+ const initMonitorsPlugin = () => ({
47
+ name: "@modern-js/init-mointor",
48
+ setup(api) {
49
+ return {
50
+ prepare() {
51
+ const { middlewares } = api.useAppContext();
52
+ middlewares.push({
53
+ name: "init-monitor",
54
+ handler: async (c, next) => {
55
+ if (!c.get("monitors")) {
56
+ const monitors = createMonitors();
57
+ c.set("monitors", monitors);
58
+ }
59
+ return next();
60
+ },
61
+ order: "pre"
62
+ });
63
+ }
64
+ };
65
+ }
66
+ });
67
+ const injectloggerPluigin = (logger) => ({
68
+ name: "@modern-js/inject-logger",
69
+ setup(api) {
70
+ return {
71
+ prepare() {
72
+ const { middlewares } = api.useAppContext();
73
+ middlewares.push({
74
+ name: "inject-logger",
75
+ handler: async (c, next) => {
76
+ if (!c.get("logger")) {
77
+ c.set("logger", logger);
78
+ }
79
+ const pathname = c.req.path;
80
+ const loggerMonitor = (event) => {
81
+ if (event.type === "log") {
82
+ const { level, message, args } = event.payload;
83
+ logger[level](message, ...args || []);
84
+ }
85
+ if (event.type === "timing") {
86
+ const { name, dur, desc } = event.payload;
87
+ if (desc) {
88
+ logger.debug(`%s Debug - ${name}, cost: %s, req.url = %s `, desc, dur, pathname);
89
+ } else {
90
+ logger.debug(`Debug - ${name}, cost: %s, req.url = %s`, dur, pathname);
91
+ }
92
+ }
93
+ };
94
+ const monitors = c.get("monitors");
95
+ monitors === null || monitors === void 0 ? void 0 : monitors.push(loggerMonitor);
96
+ return next();
97
+ }
98
+ });
99
+ }
100
+ };
101
+ }
102
+ });
103
+ const injectServerTiming = (metaName = "modern-js") => ({
104
+ name: "@modern-js/inject-server-timing",
105
+ setup(api) {
106
+ return {
107
+ prepare() {
108
+ const { middlewares } = api.useAppContext();
109
+ middlewares.push({
110
+ name: "inject-server-timing",
111
+ handler: async (c, next) => {
112
+ const serverTimings = [];
113
+ const timingMonitor = (event) => {
114
+ if (event.type === "timing") {
115
+ serverTimings.push(event.payload);
116
+ }
117
+ };
118
+ const monitors = c.get("monitors");
119
+ monitors === null || monitors === void 0 ? void 0 : monitors.push(timingMonitor);
120
+ await next();
121
+ serverTimings.forEach((serverTiming) => {
122
+ const { name, desc, dur } = serverTiming;
123
+ const _name = `bd-${metaName}-${name}`;
124
+ const value = `${_name};${desc ? `decs="${desc}";` : ""} dur=${dur}`;
125
+ c.header(SERVER_TIMING, value, {
126
+ append: true
127
+ });
128
+ });
129
+ }
130
+ });
131
+ }
132
+ };
133
+ }
134
+ });
135
+ function initReporter(entryName) {
136
+ return async (c, next) => {
137
+ const reporter = c.get("reporter");
138
+ if (!reporter) {
139
+ await next();
140
+ return;
141
+ }
142
+ await reporter.init({
143
+ entryName
144
+ });
145
+ const getCost = time();
146
+ await next();
147
+ const cost = getCost();
148
+ reporter.reportTiming(ServerTimings.SERVER_HANDLE_REQUEST, cost);
149
+ };
150
+ }
151
+ export {
152
+ initMonitorsPlugin,
153
+ initReporter,
154
+ injectServerTiming,
155
+ injectloggerPluigin
156
+ };
@@ -1,5 +1,5 @@
1
1
  import { MAIN_ENTRY_NAME } from "@modern-js/utils/universal/constants";
2
- const dataHandler = async (request, { routeInfo, serverRoutes, reporter, logger, serverManifest }) => {
2
+ const dataHandler = async (request, { routeInfo, serverRoutes, reporter, onError, onTiming, serverManifest }) => {
3
3
  var _serverManifest_loaderBundles;
4
4
  const serverLoaderModule = serverManifest === null || serverManifest === void 0 ? void 0 : (_serverManifest_loaderBundles = serverManifest.loaderBundles) === null || _serverManifest_loaderBundles === void 0 ? void 0 : _serverManifest_loaderBundles[routeInfo.entryName || MAIN_ENTRY_NAME];
5
5
  if (!serverLoaderModule) {
@@ -10,9 +10,10 @@ const dataHandler = async (request, { routeInfo, serverRoutes, reporter, logger,
10
10
  request,
11
11
  serverRoutes,
12
12
  context: {
13
- logger,
14
13
  reporter
15
14
  },
15
+ onTiming,
16
+ onError,
16
17
  routes
17
18
  });
18
19
  return response;
@@ -1,5 +1,5 @@
1
1
  import { MAIN_ENTRY_NAME } from "@modern-js/utils/universal/constants";
2
- import { initReporter } from "../monitor";
2
+ import { initReporter } from "../monitors";
3
3
  import { sortRoutes } from "../../utils";
4
4
  import { getLoaderCtx, CustomServer, getServerMidFromUnstableMid } from "../customServer";
5
5
  import { createRender } from "./render";
@@ -64,6 +64,7 @@ function createRenderHandler(render) {
64
64
  var _c_env_node;
65
65
  const logger = c.get("logger");
66
66
  const reporter = c.get("reporter");
67
+ const monitors = c.get("monitors");
67
68
  const templates = c.get("templates") || {};
68
69
  const serverManifest = c.get("serverManifest") || {};
69
70
  const locals = c.get("locals");
@@ -72,8 +73,9 @@ function createRenderHandler(render) {
72
73
  const request = c.req.raw;
73
74
  const nodeReq = (_c_env_node = c.env.node) === null || _c_env_node === void 0 ? void 0 : _c_env_node.req;
74
75
  const res = await render(request, {
75
- logger,
76
76
  nodeReq,
77
+ monitors,
78
+ logger,
77
79
  reporter,
78
80
  templates,
79
81
  metrics,
@@ -96,7 +98,7 @@ async function getRenderHandler({ pwd, routes, config, cacheConfig, metaName, st
96
98
  const render = createRender({
97
99
  routes,
98
100
  pwd,
99
- // TODO: need static Genrate
101
+ config,
100
102
  staticGenerate,
101
103
  cacheConfig,
102
104
  forceCSR,
@@ -1,6 +1,6 @@
1
1
  import { cutNameByHyphen } from "@modern-js/utils/universal";
2
2
  import { TrieRouter } from "hono/router/trie-router";
3
- import { parseQuery, getPathname, createErrorHtml, sortRoutes, transformResponse, onError as onErrorFn, ErrorDigest } from "../../utils";
3
+ import { parseQuery, getPathname, createErrorHtml, sortRoutes, transformResponse, onError as onErrorFn, ErrorDigest, parseHeaders } from "../../utils";
4
4
  import { REPLACE_REG, X_MODERNJS_RENDER } from "../../constants";
5
5
  import { dataHandler } from "./dataHandler";
6
6
  import { ssrRender } from "./ssrRender";
@@ -33,9 +33,17 @@ function matchRoute(router, request) {
33
33
  const result = matched[0][0];
34
34
  return result || [];
35
35
  }
36
- async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig, forceCSR, nonce, onFallback: onFallbackFn }) {
36
+ function getHeadersWithoutCookie(headers) {
37
+ const _headers = {
38
+ ...headers,
39
+ cookie: void 0
40
+ };
41
+ delete _headers.cookie;
42
+ return _headers;
43
+ }
44
+ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig, forceCSR, config, onFallback: onFallbackFn }) {
37
45
  const router = getRouter(routes);
38
- return async (req, { logger, nodeReq, reporter, templates, serverManifest, locals, metrics, loaderContext }) => {
46
+ return async (req, { logger, reporter, metrics, monitors, nodeReq, templates, serverManifest, locals, loaderContext }) => {
39
47
  const [routeInfo, params] = matchRoute(router, req);
40
48
  const onFallback = async (reason, error) => {
41
49
  return onFallbackFn === null || onFallbackFn === void 0 ? void 0 : onFallbackFn(reason, {
@@ -62,8 +70,16 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
62
70
  });
63
71
  }
64
72
  const renderMode = await getRenderMode(req, metaName || "modern-js", routeInfo.isSSR, forceCSR, nodeReq, onFallback);
65
- const onError = async (e) => {
66
- onErrorFn(ErrorDigest.ERENDER, e, logger, req);
73
+ const pathname = getPathname(req);
74
+ const headerData = parseHeaders(req);
75
+ const onError = (e) => {
76
+ monitors === null || monitors === void 0 ? void 0 : monitors.error(`SSR Error - ${e instanceof Error ? e.name : e}, error = %s, req.url = %s, req.headers = %o`, e instanceof Error ? e.stack || e.message : e, pathname, getHeadersWithoutCookie(headerData));
77
+ };
78
+ const onTiming = (name, dur) => {
79
+ monitors === null || monitors === void 0 ? void 0 : monitors.timing(name, dur, "SSR");
80
+ };
81
+ const onBoundError = async (e) => {
82
+ onErrorFn(ErrorDigest.ERENDER, e, monitors, req);
67
83
  await (onFallback === null || onFallback === void 0 ? void 0 : onFallback("error", e));
68
84
  };
69
85
  const renderOptions = {
@@ -71,32 +87,33 @@ async function createRender({ routes, pwd, metaName, staticGenerate, cacheConfig
71
87
  html,
72
88
  routeInfo,
73
89
  staticGenerate: staticGenerate || false,
74
- metaName: metaName || "modern-js",
75
- nonce,
76
- logger,
90
+ config,
77
91
  nodeReq,
78
92
  cacheConfig,
79
93
  reporter,
80
94
  serverRoutes: routes,
81
95
  params,
96
+ logger,
97
+ metrics,
82
98
  locals,
83
99
  serverManifest,
84
- metrics,
85
- loaderContext: loaderContext || /* @__PURE__ */ new Map()
100
+ loaderContext: loaderContext || /* @__PURE__ */ new Map(),
101
+ onError,
102
+ onTiming
86
103
  };
104
+ let response;
87
105
  switch (renderMode) {
88
106
  case "data":
89
- let response = await dataHandler(req, renderOptions);
90
- if (!response) {
91
- response = await renderHandler(req, renderOptions, "ssr", onError);
92
- }
93
- return response;
107
+ response = await dataHandler(req, renderOptions) || await renderHandler(req, renderOptions, "ssr", onBoundError);
108
+ break;
94
109
  case "ssr":
95
110
  case "csr":
96
- return renderHandler(req, renderOptions, renderMode, onError);
111
+ response = await renderHandler(req, renderOptions, renderMode, onBoundError);
112
+ break;
97
113
  default:
98
114
  throw new Error(`Unknown render mode: ${renderMode}`);
99
115
  }
116
+ return response;
100
117
  };
101
118
  }
102
119
  async function renderHandler(request, options, mode, onError) {
@@ -1,70 +1,40 @@
1
1
  import { createMemoryStorage } from "@modern-js/runtime-utils/storer";
2
- import { createTransformStream, getPathname, getRuntimeEnv } from "../../utils";
3
- async function processCache(key, render, ssrContext, ttl, container, status) {
4
- const renderResult = await render(ssrContext);
5
- if (!renderResult) {
6
- return {
7
- data: ""
8
- };
9
- } else if (typeof renderResult === "string") {
10
- const current = Date.now();
11
- const cache = {
12
- val: renderResult,
13
- cursor: current
14
- };
15
- await container.set(key, JSON.stringify(cache), {
16
- ttl
17
- });
18
- return {
19
- data: renderResult,
20
- status
21
- };
22
- } else {
23
- const { Readable } = await import("stream").catch((_) => ({
24
- Readable: void 0
25
- }));
26
- const runtimeEnv = getRuntimeEnv();
27
- const streamModule = "../../adapters/node/polyfills/stream";
28
- const { createReadableStreamFromReadable } = runtimeEnv === "node" ? await import(streamModule).catch((_) => ({
29
- createReadableStreamFromReadable: void 0
30
- })) : {
31
- createReadableStreamFromReadable: void 0
32
- };
33
- const body = (
34
- // TODO: remove node:stream, move it to ssr entry.
35
- Readable && renderResult instanceof Readable ? createReadableStreamFromReadable === null || createReadableStreamFromReadable === void 0 ? void 0 : createReadableStreamFromReadable(renderResult) : renderResult
36
- );
2
+ import { X_RENDER_CACHE } from "../../constants";
3
+ import { createTransformStream, getPathname } from "../../utils";
4
+ async function processCache({ request, key, requestHandler, requestHandlerOptions, ttl, container, cacheStatus }) {
5
+ const response = await requestHandler(request, requestHandlerOptions);
6
+ const decoder = new TextDecoder();
7
+ if (response.body) {
8
+ const stream = createTransformStream();
9
+ const reader = response.body.getReader();
10
+ const writer = stream.writable.getWriter();
37
11
  let html = "";
38
- const stream = createTransformStream((chunk) => {
39
- html += chunk;
40
- return chunk;
12
+ const push = () => reader.read().then(({ done, value }) => {
13
+ if (done) {
14
+ const current = Date.now();
15
+ const cache = {
16
+ val: html,
17
+ cursor: current
18
+ };
19
+ container.set(key, JSON.stringify(cache), {
20
+ ttl
21
+ });
22
+ writer.close();
23
+ return;
24
+ }
25
+ const content = decoder.decode(value);
26
+ html += content;
27
+ writer.write(value);
28
+ push();
41
29
  });
42
- const reader = body.getReader();
43
- const writer = stream.writable.getWriter();
44
- const push = () => {
45
- reader.read().then(({ done, value }) => {
46
- if (done) {
47
- const current = Date.now();
48
- const cache = {
49
- val: html,
50
- cursor: current
51
- };
52
- container.set(key, JSON.stringify(cache), {
53
- ttl
54
- });
55
- writer.close();
56
- return;
57
- }
58
- writer.write(value);
59
- push();
60
- });
61
- };
62
30
  push();
63
- return {
64
- data: stream.readable,
65
- status
66
- };
31
+ cacheStatus && response.headers.set(X_RENDER_CACHE, cacheStatus);
32
+ return new Response(stream.readable, {
33
+ status: response.status,
34
+ headers: response.headers
35
+ });
67
36
  }
37
+ return response;
68
38
  }
69
39
  const CACHE_NAMESPACE = "__ssr__cache";
70
40
  const storage = createMemoryStorage(CACHE_NAMESPACE);
@@ -111,7 +81,7 @@ function matchCacheControl(cacheOption, req) {
111
81
  }
112
82
  }
113
83
  async function getCacheResult(request, options) {
114
- const { cacheControl, render, ssrContext, container = storage } = options;
84
+ const { cacheControl, container = storage, requestHandler, requestHandlerOptions } = options;
115
85
  const key = computedKey(request, cacheControl);
116
86
  const value = await container.get(key);
117
87
  const { maxAge, staleWhileRevalidate } = cacheControl;
@@ -120,21 +90,50 @@ async function getCacheResult(request, options) {
120
90
  const cache = JSON.parse(value);
121
91
  const interval = Date.now() - cache.cursor;
122
92
  if (interval <= maxAge) {
123
- return {
124
- data: cache.val,
125
- status: "hit"
126
- };
93
+ const cacheStatus = "hit";
94
+ return new Response(cache.val, {
95
+ headers: {
96
+ [X_RENDER_CACHE]: cacheStatus
97
+ }
98
+ });
127
99
  } else if (interval <= staleWhileRevalidate + maxAge) {
128
- processCache(key, render, ssrContext, ttl, container);
129
- return {
130
- data: cache.val,
131
- status: "stale"
132
- };
100
+ processCache({
101
+ key,
102
+ request,
103
+ requestHandler,
104
+ requestHandlerOptions,
105
+ ttl,
106
+ container
107
+ }).then(async (response) => {
108
+ await response.text();
109
+ });
110
+ const cacheStatus = "stale";
111
+ return new Response(cache.val, {
112
+ headers: {
113
+ [X_RENDER_CACHE]: cacheStatus
114
+ }
115
+ });
133
116
  } else {
134
- return processCache(key, render, ssrContext, ttl, container, "expired");
117
+ return processCache({
118
+ key,
119
+ request,
120
+ requestHandler,
121
+ requestHandlerOptions,
122
+ ttl,
123
+ container,
124
+ cacheStatus: "expired"
125
+ });
135
126
  }
136
127
  } else {
137
- return processCache(key, render, ssrContext, ttl, container, "miss");
128
+ return processCache({
129
+ key,
130
+ request,
131
+ requestHandler,
132
+ requestHandlerOptions,
133
+ ttl,
134
+ container,
135
+ cacheStatus: "miss"
136
+ });
138
137
  }
139
138
  }
140
139
  export {