@modern-js/server-core 2.49.4-alpha.1 → 2.49.4

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 (35) hide show
  1. package/dist/cjs/base/adapters/node/middlewares/serverPublic.js +4 -1
  2. package/dist/cjs/base/adapters/node/middlewares/serverStatic.js +1 -2
  3. package/dist/cjs/base/adapters/node/node.js +19 -2
  4. package/dist/cjs/base/adapters/node/polyfills/stream.js +18 -11
  5. package/dist/cjs/base/middlewares/customServer/base.js +14 -4
  6. package/dist/cjs/base/middlewares/customServer/context.js +2 -2
  7. package/dist/cjs/base/middlewares/customServer/index.js +15 -1
  8. package/dist/cjs/base/middlewares/renderHandler/index.js +6 -1
  9. package/dist/cjs/base/middlewares/renderHandler/render.js +29 -12
  10. package/dist/cjs/base/middlewares/renderHandler/ssrRender.js +2 -2
  11. package/dist/esm/base/adapters/node/middlewares/serverPublic.js +6 -1
  12. package/dist/esm/base/adapters/node/middlewares/serverStatic.js +1 -2
  13. package/dist/esm/base/adapters/node/node.js +50 -11
  14. package/dist/esm/base/adapters/node/polyfills/stream.js +56 -32
  15. package/dist/esm/base/middlewares/customServer/base.js +14 -4
  16. package/dist/esm/base/middlewares/customServer/context.js +2 -2
  17. package/dist/esm/base/middlewares/customServer/index.js +19 -2
  18. package/dist/esm/base/middlewares/renderHandler/index.js +7 -2
  19. package/dist/esm/base/middlewares/renderHandler/render.js +52 -33
  20. package/dist/esm/base/middlewares/renderHandler/ssrRender.js +3 -3
  21. package/dist/esm-node/base/adapters/node/middlewares/serverPublic.js +4 -1
  22. package/dist/esm-node/base/adapters/node/middlewares/serverStatic.js +1 -2
  23. package/dist/esm-node/base/adapters/node/node.js +10 -3
  24. package/dist/esm-node/base/adapters/node/polyfills/stream.js +18 -11
  25. package/dist/esm-node/base/middlewares/customServer/base.js +14 -4
  26. package/dist/esm-node/base/middlewares/customServer/context.js +2 -2
  27. package/dist/esm-node/base/middlewares/customServer/index.js +15 -1
  28. package/dist/esm-node/base/middlewares/renderHandler/index.js +6 -1
  29. package/dist/esm-node/base/middlewares/renderHandler/render.js +29 -12
  30. package/dist/esm-node/base/middlewares/renderHandler/ssrRender.js +2 -2
  31. package/dist/types/base/adapters/node/node.d.ts +4 -2
  32. package/dist/types/base/middlewares/customServer/base.d.ts +5 -1
  33. package/dist/types/base/middlewares/customServer/context.d.ts +2 -1
  34. package/dist/types/base/middlewares/renderHandler/ssrRender.d.ts +3 -1
  35. package/package.json +7 -7
@@ -161,7 +161,7 @@ var CustomServer = /* @__PURE__ */ function() {
161
161
  var _this = this;
162
162
  return function() {
163
163
  var _ref = _async_to_generator(function(c, next) {
164
- var _c_env, serverMiddleware, reporter, locals, customMiddlewareCtx, getCost, cost;
164
+ var _c_env, serverMiddleware, reporter, locals, resArgs, customMiddlewareCtx, getCost, cost;
165
165
  return _ts_generator(this, function(_state) {
166
166
  switch (_state.label) {
167
167
  case 0:
@@ -179,7 +179,10 @@ var CustomServer = /* @__PURE__ */ function() {
179
179
  }
180
180
  reporter = c.get("reporter");
181
181
  locals = {};
182
- customMiddlewareCtx = createCustomMiddlewaresCtx(c, locals);
182
+ resArgs = {
183
+ headers: new Headers()
184
+ };
185
+ customMiddlewareCtx = createCustomMiddlewaresCtx(c, locals, resArgs);
183
186
  getCost = time();
184
187
  return [
185
188
  4,
@@ -190,6 +193,12 @@ var CustomServer = /* @__PURE__ */ function() {
190
193
  cost = getCost();
191
194
  cost && (reporter === null || reporter === void 0 ? void 0 : reporter.reportTiming(ServerReportTimings.SERVER_MIDDLEWARE, cost));
192
195
  c.set("locals", locals);
196
+ if (isRedirect(resArgs.headers, resArgs.status)) {
197
+ return [
198
+ 2,
199
+ c.redirect(resArgs.headers.get("Location") || "", resArgs.status || 302)
200
+ ];
201
+ }
193
202
  if ((_c_env = c.env) === null || _c_env === void 0 ? void 0 : _c_env.node.res.headersSent) {
194
203
  return [
195
204
  2,
@@ -215,6 +224,14 @@ var CustomServer = /* @__PURE__ */ function() {
215
224
  };
216
225
  return CustomServer2;
217
226
  }();
227
+ function isRedirect(headers, code) {
228
+ return [
229
+ 301,
230
+ 302,
231
+ 307,
232
+ 308
233
+ ].includes(code || 0) || headers.get("Location");
234
+ }
218
235
  export {
219
236
  CustomServer
220
237
  };
@@ -8,7 +8,7 @@ import { createRender } from "./render";
8
8
  function createRenderHandler(render) {
9
9
  return function() {
10
10
  var _ref = _async_to_generator(function(c, _) {
11
- var _c_env_node, logger, reporter, templates, serverManifest, locals, metrics, request, nodeReq, res;
11
+ var _c_env_node, logger, reporter, templates, serverManifest, locals, metrics, request, nodeReq, res, body, status, headers, headersData;
12
12
  return _ts_generator(this, function(_state) {
13
13
  switch (_state.label) {
14
14
  case 0:
@@ -34,9 +34,14 @@ function createRenderHandler(render) {
34
34
  ];
35
35
  case 1:
36
36
  res = _state.sent();
37
+ body = res.body, status = res.status, headers = res.headers;
38
+ headersData = {};
39
+ headers.forEach(function(v, k) {
40
+ headersData[k] = v;
41
+ });
37
42
  return [
38
43
  2,
39
- res
44
+ c.body(body, status, headersData)
40
45
  ];
41
46
  }
42
47
  });
@@ -1,28 +1,64 @@
1
1
  import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
2
+ import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
2
3
  import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
3
4
  import { cutNameByHyphen } from "@modern-js/utils/universal";
5
+ import { TrieRouter } from "hono/router/trie-router";
4
6
  import { REPLACE_REG } from "../../../base/constants";
5
7
  import { createErrorHtml, sortRoutes, parseQuery, transformResponse, getPathname, onError as onErrorFn, ErrorDigest } from "../../utils";
6
8
  import { dataHandler } from "./dataHandler";
7
9
  import { ssrRender } from "./ssrRender";
10
+ function getRouter(routes) {
11
+ var sorted = routes.sort(sortRoutes);
12
+ var router = new TrieRouter();
13
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
14
+ try {
15
+ for (var _iterator = sorted[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
16
+ var route = _step.value;
17
+ var originUrlPath = route.urlPath;
18
+ var urlPath = originUrlPath.endsWith("/") ? "".concat(originUrlPath, "*") : "".concat(originUrlPath, "/*");
19
+ router.add("*", urlPath, route);
20
+ }
21
+ } catch (err) {
22
+ _didIteratorError = true;
23
+ _iteratorError = err;
24
+ } finally {
25
+ try {
26
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
27
+ _iterator.return();
28
+ }
29
+ } finally {
30
+ if (_didIteratorError) {
31
+ throw _iteratorError;
32
+ }
33
+ }
34
+ }
35
+ return router;
36
+ }
37
+ function matchRoute(router, request) {
38
+ var pathname = getPathname(request);
39
+ var matched = router.match("*", pathname);
40
+ var result = matched[0][0];
41
+ return result || [];
42
+ }
8
43
  function createRender(_) {
9
44
  return _createRender.apply(this, arguments);
10
45
  }
11
46
  function _createRender() {
12
47
  _createRender = _async_to_generator(function(param) {
13
- var routes, pwd, metaName, staticGenerate, forceCSR, nonce, onFallbackFn;
48
+ var routes, pwd, metaName, staticGenerate, forceCSR, nonce, onFallbackFn, router;
14
49
  return _ts_generator(this, function(_state) {
15
50
  routes = param.routes, pwd = param.pwd, metaName = param.metaName, staticGenerate = param.staticGenerate, forceCSR = param.forceCSR, nonce = param.nonce, onFallbackFn = param.onFallback;
51
+ router = getRouter(routes);
16
52
  return [
17
53
  2,
18
54
  function() {
19
55
  var _ref = _async_to_generator(function(req, param2) {
20
- var logger, nodeReq, reporter, templates, serverManifest, locals, metrics, routeInfo, onFallback, html, renderMode, onError, renderOptions, response;
56
+ var logger, nodeReq, reporter, templates, serverManifest, locals, metrics, _matchRoute, routeInfo, params, onFallback, html, renderMode, onError, renderOptions, response;
21
57
  return _ts_generator(this, function(_state2) {
22
58
  switch (_state2.label) {
23
59
  case 0:
24
60
  logger = param2.logger, nodeReq = param2.nodeReq, reporter = param2.reporter, templates = param2.templates, serverManifest = param2.serverManifest, locals = param2.locals, metrics = param2.metrics;
25
- routeInfo = matchRoute(req, routes);
61
+ _matchRoute = _sliced_to_array(matchRoute(router, req), 2), routeInfo = _matchRoute[0], params = _matchRoute[1];
26
62
  onFallback = function() {
27
63
  var _ref2 = _async_to_generator(function(reason, error) {
28
64
  return _ts_generator(this, function(_state3) {
@@ -102,6 +138,7 @@ function _createRender() {
102
138
  nodeReq,
103
139
  reporter,
104
140
  serverRoutes: routes,
141
+ params,
105
142
  locals,
106
143
  serverManifest,
107
144
  metrics
@@ -179,14 +216,20 @@ function renderHandler(request, options, mode, onError) {
179
216
  }
180
217
  function _renderHandler() {
181
218
  _renderHandler = _async_to_generator(function(request, options, mode, onError) {
182
- var serverData, response, e;
219
+ var serverData, response, e, newRes, routeInfo;
220
+ function applyExtendHeaders(r, route) {
221
+ Object.entries(route.responseHeaders || {}).forEach(function(param) {
222
+ var _param = _sliced_to_array(param, 2), k = _param[0], v = _param[1];
223
+ r.headers.set(k, v);
224
+ });
225
+ }
183
226
  return _ts_generator(this, function(_state) {
184
227
  switch (_state.label) {
185
228
  case 0:
186
229
  serverData = {
187
230
  router: {
188
231
  baseUrl: options.routeInfo.urlPath,
189
- params: {}
232
+ params: options.params
190
233
  }
191
234
  };
192
235
  if (!(mode === "ssr"))
@@ -234,42 +277,18 @@ function _renderHandler() {
234
277
  response = csrRender(options.html);
235
278
  _state.label = 7;
236
279
  case 7:
280
+ newRes = transformResponse(response, injectServerData(serverData));
281
+ routeInfo = options.routeInfo;
282
+ applyExtendHeaders(newRes, routeInfo);
237
283
  return [
238
284
  2,
239
- transformResponse(response, injectServerData(serverData))
285
+ newRes
240
286
  ];
241
287
  }
242
288
  });
243
289
  });
244
290
  return _renderHandler.apply(this, arguments);
245
291
  }
246
- function matchRoute(req, routes) {
247
- var sorted = routes.sort(sortRoutes);
248
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
249
- try {
250
- for (var _iterator = sorted[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
251
- var route = _step.value;
252
- var pathname = getPathname(req);
253
- if (pathname.startsWith(route.urlPath)) {
254
- return route;
255
- }
256
- }
257
- } catch (err) {
258
- _didIteratorError = true;
259
- _iteratorError = err;
260
- } finally {
261
- try {
262
- if (!_iteratorNormalCompletion && _iterator.return != null) {
263
- _iterator.return();
264
- }
265
- } finally {
266
- if (_didIteratorError) {
267
- throw _iteratorError;
268
- }
269
- }
270
- }
271
- return void 0;
272
- }
273
292
  function getRenderMode(req, framework, isSSR, forceCSR, nodeReq, onFallback) {
274
293
  return _getRenderMode.apply(this, arguments);
275
294
  }
@@ -24,11 +24,11 @@ function ssrRender(request, _) {
24
24
  }
25
25
  function _ssrRender() {
26
26
  _ssrRender = _async_to_generator(function(request, param) {
27
- var routeInfo, html, staticGenerate, nonce, metaName, reporter, logger, nodeReq, serverManifest, locals, metrics, _serverManifest_renderBundles, entryName, loadableStats, routeManifest, host, isSpider, responseProxy, query, headers, key, ssrContext, renderBundle, runtimeEnv, ssrResult, cacheStatus, render, cacheModuleName, ssrCache, incomingMessage, cacheControl, _ref, data, status, redirection, headers1, Readable, streamModule, createReadableStreamFromReadable, _tmp, data1;
27
+ var routeInfo, html, staticGenerate, nonce, metaName, reporter, logger, nodeReq, serverManifest, locals, params, metrics, _serverManifest_renderBundles, entryName, loadableStats, routeManifest, host, isSpider, responseProxy, query, headers, key, ssrContext, renderBundle, runtimeEnv, ssrResult, cacheStatus, render, cacheModuleName, ssrCache, incomingMessage, cacheControl, _ref, data, status, redirection, headers1, Readable, streamModule, createReadableStreamFromReadable, _tmp, data1;
28
28
  return _ts_generator(this, function(_state) {
29
29
  switch (_state.label) {
30
30
  case 0:
31
- routeInfo = param.routeInfo, html = param.html, staticGenerate = param.staticGenerate, nonce = param.nonce, metaName = param.metaName, reporter = param.reporter, logger = param.logger, nodeReq = param.nodeReq, serverManifest = param.serverManifest, locals = param.locals, metrics = param.metrics;
31
+ routeInfo = param.routeInfo, html = param.html, staticGenerate = param.staticGenerate, nonce = param.nonce, metaName = param.metaName, reporter = param.reporter, logger = param.logger, nodeReq = param.nodeReq, serverManifest = param.serverManifest, locals = param.locals, params = param.params, metrics = param.metrics;
32
32
  entryName = routeInfo.entryName;
33
33
  loadableStats = serverManifest.loadableStats || {};
34
34
  routeManifest = serverManifest.routeManifest || {};
@@ -47,7 +47,7 @@ function _ssrRender() {
47
47
  ssrContext = {
48
48
  request: {
49
49
  baseUrl: routeInfo.urlPath,
50
- params: {},
50
+ params,
51
51
  pathname: nodeReq ? getPathnameFromNodeReq(nodeReq) : getPathname(request),
52
52
  host,
53
53
  query,
@@ -14,6 +14,9 @@ function createPublicMiddleware({ pwd, routes }) {
14
14
  if (mimeType) {
15
15
  c.header("Content-Type", mimeType);
16
16
  }
17
+ Object.entries(route.responseHeaders || {}).forEach(([k, v]) => {
18
+ c.header(k, v);
19
+ });
17
20
  return c.body(data, 200);
18
21
  }
19
22
  }
@@ -22,7 +25,7 @@ function createPublicMiddleware({ pwd, routes }) {
22
25
  }
23
26
  function matchRoute(req, routes) {
24
27
  for (const route of routes.sort(sortRoutes)) {
25
- if (!route.isSSR && !route.isApi && route.entryPath.startsWith("public") && req.path.startsWith(route.urlPath)) {
28
+ if (!route.isSSR && route.entryPath.startsWith("public") && req.path.startsWith(route.urlPath)) {
26
29
  return route;
27
30
  }
28
31
  }
@@ -2,7 +2,6 @@ import path from "path";
2
2
  import { fs } from "@modern-js/utils";
3
3
  import { getMimeType } from "hono/utils/mime";
4
4
  import { fileReader } from "@modern-js/runtime-utils/fileReader";
5
- import { createErrorHtml } from "../../../utils";
6
5
  import { createPublicMiddleware } from "./serverPublic";
7
6
  function createStaticMiddleware(options) {
8
7
  const { pwd, routes } = options;
@@ -36,7 +35,7 @@ function createStaticMiddleware(options) {
36
35
  if (hit) {
37
36
  const filepath = path.join(pwd, pathname.replace(prefix, () => ""));
38
37
  if (!await fs.pathExists(filepath)) {
39
- return c.html(createErrorHtml(404), 404);
38
+ return next();
40
39
  }
41
40
  const mimeType = getMimeType(filepath);
42
41
  if (mimeType) {
@@ -1,4 +1,4 @@
1
- import { createServer, ServerResponse } from "node:http";
1
+ import { ServerResponse } from "node:http";
2
2
  import { createReadableStreamFromReadable, writeReadableStreamToWritable } from "./polyfills/stream";
3
3
  import { installGlobals } from "./polyfills/install";
4
4
  installGlobals();
@@ -87,9 +87,16 @@ const getRequestListener = (handler) => {
87
87
  }
88
88
  };
89
89
  };
90
- const createNodeServer = (requestHandler) => {
90
+ const createNodeServer = async (requestHandler, httpsOptions) => {
91
91
  const requestListener = getRequestListener(requestHandler);
92
- const nodeServer = createServer(requestListener);
92
+ let nodeServer;
93
+ if (httpsOptions) {
94
+ const { createServer } = await import("node:https");
95
+ nodeServer = createServer(httpsOptions, requestListener);
96
+ } else {
97
+ const { createServer } = await import("node:http");
98
+ nodeServer = createServer(requestListener);
99
+ }
93
100
  nodeServer.getRequestListener = () => requestListener;
94
101
  nodeServer.getRequestHandler = () => requestHandler;
95
102
  return nodeServer;
@@ -3,17 +3,24 @@ async function writeReadableStreamToWritable(stream, writable) {
3
3
  const reader = stream.getReader();
4
4
  const flushable = writable;
5
5
  try {
6
- while (true) {
7
- const { done, value } = await reader.read();
8
- if (done) {
9
- writable.end();
10
- break;
11
- }
12
- writable.write(value);
13
- if (typeof flushable.flush === "function") {
14
- flushable.flush();
15
- }
16
- }
6
+ await new Promise((resolve, reject) => {
7
+ writable.on("finish", resolve);
8
+ writable.on("error", reject);
9
+ const writeAndFlush = async () => {
10
+ while (true) {
11
+ const { done, value } = await reader.read();
12
+ if (done) {
13
+ writable.end();
14
+ break;
15
+ }
16
+ writable.write(value);
17
+ if (typeof flushable.flush === "function") {
18
+ flushable.flush();
19
+ }
20
+ }
21
+ };
22
+ writeAndFlush().catch(reject);
23
+ });
17
24
  } catch (error) {
18
25
  writable.destroy(error);
19
26
  throw error;
@@ -3,12 +3,12 @@ import { _ as _class_private_field_init } from "@swc/helpers/_/_class_private_fi
3
3
  import { _ as _class_private_field_set } from "@swc/helpers/_/_class_private_field_set";
4
4
  import { getCookie } from "hono/cookie";
5
5
  import { getHost } from "../../utils";
6
- function createBaseHookContext(c) {
6
+ function createBaseHookContext(c, resParams) {
7
7
  const logger = c.get("logger");
8
8
  const metrics = c.get("metrics");
9
9
  return {
10
10
  request: new BaseHookRequest(c),
11
- response: new BaseHookResponse(c),
11
+ response: new BaseHookResponse(c, resParams),
12
12
  logger,
13
13
  metrics
14
14
  };
@@ -95,7 +95,7 @@ class BaseHookRequest {
95
95
  }));
96
96
  }
97
97
  }
98
- var _c1 = /* @__PURE__ */ new WeakMap();
98
+ var _c1 = /* @__PURE__ */ new WeakMap(), _resArgs = /* @__PURE__ */ new WeakMap();
99
99
  class BaseHookResponse {
100
100
  get(key) {
101
101
  return _class_private_field_get(this, _c1).res.headers.get(key);
@@ -105,15 +105,20 @@ class BaseHookResponse {
105
105
  "set-cookie",
106
106
  "Set-Cookie"
107
107
  ].includes(key)) {
108
+ var _class_private_field_get1;
108
109
  _class_private_field_get(this, _c1).header(key, value.toString(), {
109
110
  append: true
110
111
  });
112
+ (_class_private_field_get1 = _class_private_field_get(this, _resArgs)) === null || _class_private_field_get1 === void 0 ? void 0 : _class_private_field_get1.headers.append(key, value.toString());
111
113
  } else {
114
+ var _class_private_field_get2;
112
115
  _class_private_field_get(this, _c1).header(key, value.toString());
116
+ (_class_private_field_get2 = _class_private_field_get(this, _resArgs)) === null || _class_private_field_get2 === void 0 ? void 0 : _class_private_field_get2.headers.set(key, value.toString());
113
117
  }
114
118
  }
115
119
  status(code) {
116
120
  _class_private_field_get(this, _c1).status(code);
121
+ _class_private_field_get(this, _resArgs) && (_class_private_field_get(this, _resArgs).status = code);
117
122
  }
118
123
  get cookies() {
119
124
  const setCookie = (key, value) => {
@@ -133,13 +138,18 @@ class BaseHookResponse {
133
138
  _class_private_field_get(this, _c1).res = _class_private_field_get(this, _c1).newResponse(body, options);
134
139
  this.private_overrided = true;
135
140
  }
136
- constructor(c) {
141
+ constructor(c, resArgs) {
137
142
  _class_private_field_init(this, _c1, {
138
143
  writable: true,
139
144
  value: void 0
140
145
  });
146
+ _class_private_field_init(this, _resArgs, {
147
+ writable: true,
148
+ value: void 0
149
+ });
141
150
  this.private_overrided = false;
142
151
  _class_private_field_set(this, _c1, c);
152
+ _class_private_field_set(this, _resArgs, resArgs);
143
153
  }
144
154
  }
145
155
  export {
@@ -13,9 +13,9 @@ async function getAfterRenderCtx(c, baseHookCtx, route) {
13
13
  afterRenderCtx.route = route;
14
14
  return afterRenderCtx;
15
15
  }
16
- function createCustomMiddlewaresCtx(c, locals) {
16
+ function createCustomMiddlewaresCtx(c, locals, resArgs) {
17
17
  var _c_env_node, _c_env_node1;
18
- const baseContext = createBaseHookContext(c);
18
+ const baseContext = createBaseHookContext(c, resArgs);
19
19
  const reporter = c.get("reporter");
20
20
  const response = baseContext.response;
21
21
  response.locals = locals;
@@ -79,12 +79,18 @@ class CustomServer {
79
79
  }
80
80
  const reporter = c.get("reporter");
81
81
  const locals = {};
82
- const customMiddlewareCtx = createCustomMiddlewaresCtx(c, locals);
82
+ const resArgs = {
83
+ headers: new Headers()
84
+ };
85
+ const customMiddlewareCtx = createCustomMiddlewaresCtx(c, locals, resArgs);
83
86
  const getCost = time();
84
87
  await serverMiddleware(customMiddlewareCtx);
85
88
  const cost = getCost();
86
89
  cost && (reporter === null || reporter === void 0 ? void 0 : reporter.reportTiming(ServerReportTimings.SERVER_MIDDLEWARE, cost));
87
90
  c.set("locals", locals);
91
+ if (isRedirect(resArgs.headers, resArgs.status)) {
92
+ return c.redirect(resArgs.headers.get("Location") || "", resArgs.status || 302);
93
+ }
88
94
  if ((_c_env = c.env) === null || _c_env === void 0 ? void 0 : _c_env.node.res.headersSent) {
89
95
  return void 0;
90
96
  }
@@ -107,6 +113,14 @@ class CustomServer {
107
113
  });
108
114
  }
109
115
  }
116
+ function isRedirect(headers, code) {
117
+ return [
118
+ 301,
119
+ 302,
120
+ 307,
121
+ 308
122
+ ].includes(code || 0) || headers.get("Location");
123
+ }
110
124
  export {
111
125
  CustomServer
112
126
  };
@@ -22,7 +22,12 @@ function createRenderHandler(render) {
22
22
  serverManifest,
23
23
  locals
24
24
  });
25
- return res;
25
+ const { body, status, headers } = res;
26
+ const headersData = {};
27
+ headers.forEach((v, k) => {
28
+ headersData[k] = v;
29
+ });
30
+ return c.body(body, status, headersData);
26
31
  };
27
32
  }
28
33
  async function getRenderHandler(options, serverBase) {
@@ -1,11 +1,29 @@
1
1
  import { cutNameByHyphen } from "@modern-js/utils/universal";
2
+ import { TrieRouter } from "hono/router/trie-router";
2
3
  import { REPLACE_REG } from "../../../base/constants";
3
4
  import { createErrorHtml, sortRoutes, parseQuery, transformResponse, getPathname, onError as onErrorFn, ErrorDigest } from "../../utils";
4
5
  import { dataHandler } from "./dataHandler";
5
6
  import { ssrRender } from "./ssrRender";
7
+ function getRouter(routes) {
8
+ const sorted = routes.sort(sortRoutes);
9
+ const router = new TrieRouter();
10
+ for (const route of sorted) {
11
+ const { urlPath: originUrlPath } = route;
12
+ const urlPath = originUrlPath.endsWith("/") ? `${originUrlPath}*` : `${originUrlPath}/*`;
13
+ router.add("*", urlPath, route);
14
+ }
15
+ return router;
16
+ }
17
+ function matchRoute(router, request) {
18
+ const pathname = getPathname(request);
19
+ const matched = router.match("*", pathname);
20
+ const result = matched[0][0];
21
+ return result || [];
22
+ }
6
23
  async function createRender({ routes, pwd, metaName, staticGenerate, forceCSR, nonce, onFallback: onFallbackFn }) {
24
+ const router = getRouter(routes);
7
25
  return async (req, { logger, nodeReq, reporter, templates, serverManifest, locals, metrics }) => {
8
- const routeInfo = matchRoute(req, routes);
26
+ const [routeInfo, params] = matchRoute(router, req);
9
27
  const onFallback = async (reason, error) => {
10
28
  return onFallbackFn === null || onFallbackFn === void 0 ? void 0 : onFallbackFn(reason, {
11
29
  logger,
@@ -46,6 +64,7 @@ async function createRender({ routes, pwd, metaName, staticGenerate, forceCSR, n
46
64
  nodeReq,
47
65
  reporter,
48
66
  serverRoutes: routes,
67
+ params,
49
68
  locals,
50
69
  serverManifest,
51
70
  metrics
@@ -69,7 +88,7 @@ async function renderHandler(request, options, mode, onError) {
69
88
  const serverData = {
70
89
  router: {
71
90
  baseUrl: options.routeInfo.urlPath,
72
- params: {}
91
+ params: options.params
73
92
  }
74
93
  };
75
94
  let response;
@@ -83,17 +102,15 @@ async function renderHandler(request, options, mode, onError) {
83
102
  } else {
84
103
  response = csrRender(options.html);
85
104
  }
86
- return transformResponse(response, injectServerData(serverData));
87
- }
88
- function matchRoute(req, routes) {
89
- const sorted = routes.sort(sortRoutes);
90
- for (const route of sorted) {
91
- const pathname = getPathname(req);
92
- if (pathname.startsWith(route.urlPath)) {
93
- return route;
94
- }
105
+ const newRes = transformResponse(response, injectServerData(serverData));
106
+ const { routeInfo } = options;
107
+ applyExtendHeaders(newRes, routeInfo);
108
+ return newRes;
109
+ function applyExtendHeaders(r, route) {
110
+ Object.entries(route.responseHeaders || {}).forEach(([k, v]) => {
111
+ r.headers.set(k, v);
112
+ });
95
113
  }
96
- return void 0;
97
114
  }
98
115
  async function getRenderMode(req, framework, isSSR, forceCSR, nodeReq, onFallback) {
99
116
  const query = parseQuery(req);
@@ -15,7 +15,7 @@ const defaultReporter = {
15
15
  reportWarn() {
16
16
  }
17
17
  };
18
- async function ssrRender(request, { routeInfo, html, staticGenerate, nonce, metaName, reporter, logger, nodeReq, serverManifest, locals, metrics }) {
18
+ async function ssrRender(request, { routeInfo, html, staticGenerate, nonce, metaName, reporter, logger, nodeReq, serverManifest, locals, params, metrics }) {
19
19
  var _serverManifest_renderBundles;
20
20
  const { entryName } = routeInfo;
21
21
  const loadableStats = serverManifest.loadableStats || {};
@@ -35,7 +35,7 @@ async function ssrRender(request, { routeInfo, html, staticGenerate, nonce, meta
35
35
  const ssrContext = {
36
36
  request: {
37
37
  baseUrl: routeInfo.urlPath,
38
- params: {},
38
+ params,
39
39
  pathname: nodeReq ? getPathnameFromNodeReq(nodeReq) : getPathname(request),
40
40
  host,
41
41
  query,
@@ -1,13 +1,15 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import { Server as NodeServer } from 'node:http';
4
+ import type { Server as NodeHttpsServer } from 'node:https';
3
5
  import { NodeRequest, NodeResponse } from '../../../core/plugin';
4
6
  import { RequestHandler } from '../../../core/server';
5
7
  export declare const createWebRequest: (req: NodeRequest, res: NodeResponse) => Request;
6
8
  export declare const sendResponse: (response: Response, res: NodeResponse) => Promise<void>;
7
9
  declare const getRequestListener: (handler: RequestHandler) => (req: NodeRequest, res: NodeResponse) => Promise<void>;
8
- type NodeServerWrapper = NodeServer & {
10
+ type NodeServerWrapper = (NodeServer | NodeHttpsServer) & {
9
11
  getRequestListener: () => ReturnType<typeof getRequestListener>;
10
12
  getRequestHandler: () => RequestHandler;
11
13
  };
12
- export declare const createNodeServer: (requestHandler: RequestHandler) => NodeServerWrapper;
14
+ export declare const createNodeServer: (requestHandler: RequestHandler, httpsOptions?: Record<string, unknown>) => Promise<NodeServerWrapper>;
13
15
  export {};
@@ -1,3 +1,7 @@
1
1
  import { HookContext } from '@modern-js/types';
2
2
  import type { Context, ServerEnv } from '../../../core/server';
3
- export declare function createBaseHookContext(c: Context<ServerEnv>): HookContext;
3
+ export type ResArgs = {
4
+ status?: number;
5
+ headers: Headers;
6
+ };
7
+ export declare function createBaseHookContext(c: Context<ServerEnv>, resParams?: ResArgs): HookContext;
@@ -1,7 +1,8 @@
1
1
  import { AfterMatchContext, AfterRenderContext, MiddlewareContext, AfterStreamingRenderContext, ServerRoute, HookContext } from '@modern-js/types';
2
2
  import { Context, ServerEnv } from '../../../core/server';
3
3
  import type { ServerNodeEnv } from '../../adapters/node/hono';
4
+ import { ResArgs } from './base';
4
5
  export declare function getAfterMatchCtx(entryName: string, baseHookCtx: HookContext): AfterMatchContext;
5
6
  export declare function getAfterRenderCtx(c: Context, baseHookCtx: HookContext, route: Partial<ServerRoute>): Promise<AfterRenderContext>;
6
- export declare function createCustomMiddlewaresCtx(c: Context<ServerNodeEnv & ServerEnv>, locals: Record<string, any>): MiddlewareContext;
7
+ export declare function createCustomMiddlewaresCtx(c: Context<ServerNodeEnv & ServerEnv>, locals: Record<string, any>, resArgs?: ResArgs): MiddlewareContext;
7
8
  export declare function createAfterStreamingRenderContext(baseHookCtx: HookContext, route: Partial<ServerRoute>): (chunk: string) => AfterStreamingRenderContext;
@@ -2,6 +2,7 @@
2
2
  import type { IncomingMessage } from 'http';
3
3
  import type { Logger, Metrics, Reporter, ServerRoute } from '@modern-js/types';
4
4
  import { ServerManifest } from '../../../core/server';
5
+ export type Params = Record<string, any>;
5
6
  export interface SSRRenderOptions {
6
7
  pwd: string;
7
8
  html: string;
@@ -10,6 +11,7 @@ export interface SSRRenderOptions {
10
11
  metaName: string;
11
12
  logger: Logger;
12
13
  serverManifest: ServerManifest;
14
+ params: Params;
13
15
  /** Produce by custom server hook */
14
16
  locals?: Record<string, any>;
15
17
  reporter?: Reporter;
@@ -17,5 +19,5 @@ export interface SSRRenderOptions {
17
19
  nodeReq?: IncomingMessage;
18
20
  nonce?: string;
19
21
  }
20
- export declare function ssrRender(request: Request, { routeInfo, html, staticGenerate, nonce, metaName, reporter, logger, nodeReq, serverManifest, locals, metrics, }: SSRRenderOptions): Promise<Response>;
22
+ export declare function ssrRender(request: Request, { routeInfo, html, staticGenerate, nonce, metaName, reporter, logger, nodeReq, serverManifest, locals, params, metrics, }: SSRRenderOptions): Promise<Response>;
21
23
  export declare function getPathnameFromNodeReq(nodeReq: IncomingMessage): string;
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "2.49.4-alpha.1",
18
+ "version": "2.49.4",
19
19
  "jsnext:source": "./src/index.ts",
20
20
  "types": "./dist/types/index.d.ts",
21
21
  "main": "./dist/cjs/index.js",
@@ -69,9 +69,9 @@
69
69
  "hono": "^3.12.2",
70
70
  "isbot": "3.8.0",
71
71
  "merge-deep": "^3.0.3",
72
- "@modern-js/runtime-utils": "2.49.3",
73
- "@modern-js/utils": "2.49.3",
74
- "@modern-js/plugin": "2.49.3"
72
+ "@modern-js/plugin": "2.49.4",
73
+ "@modern-js/runtime-utils": "2.49.4",
74
+ "@modern-js/utils": "2.49.4"
75
75
  },
76
76
  "devDependencies": {
77
77
  "@types/jest": "^29",
@@ -81,9 +81,9 @@
81
81
  "jest": "^29",
82
82
  "ts-jest": "^29.1.0",
83
83
  "typescript": "^5",
84
- "@scripts/build": "2.49.3",
85
- "@modern-js/types": "2.49.3",
86
- "@scripts/jest-config": "2.49.3"
84
+ "@modern-js/types": "2.49.4",
85
+ "@scripts/jest-config": "2.49.4",
86
+ "@scripts/build": "2.49.4"
87
87
  },
88
88
  "sideEffects": false,
89
89
  "publishConfig": {