@tanstack/router-core 1.171.14 → 1.171.16-pre.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 (139) hide show
  1. package/dist/cjs/Matches.cjs.map +1 -1
  2. package/dist/cjs/Matches.d.cts +3 -12
  3. package/dist/cjs/await-signal.cjs +21 -0
  4. package/dist/cjs/await-signal.cjs.map +1 -0
  5. package/dist/cjs/await-signal.d.cts +1 -0
  6. package/dist/cjs/index.cjs +3 -1
  7. package/dist/cjs/index.d.cts +3 -2
  8. package/dist/cjs/isServer/client.cjs +2 -0
  9. package/dist/cjs/isServer/client.cjs.map +1 -1
  10. package/dist/cjs/isServer/client.d.cts +1 -0
  11. package/dist/cjs/isServer/development.cjs +2 -0
  12. package/dist/cjs/isServer/development.cjs.map +1 -1
  13. package/dist/cjs/isServer/development.d.cts +1 -0
  14. package/dist/cjs/isServer/server.cjs +2 -0
  15. package/dist/cjs/isServer/server.cjs.map +1 -1
  16. package/dist/cjs/isServer/server.d.cts +1 -0
  17. package/dist/cjs/load-client.cjs +1470 -0
  18. package/dist/cjs/load-client.cjs.map +1 -0
  19. package/dist/cjs/load-client.d.cts +147 -0
  20. package/dist/cjs/load-server.cjs +565 -0
  21. package/dist/cjs/load-server.cjs.map +1 -0
  22. package/dist/cjs/load-server.d.cts +16 -0
  23. package/dist/cjs/redirect.cjs.map +1 -1
  24. package/dist/cjs/redirect.d.cts +0 -1
  25. package/dist/cjs/route.cjs.map +1 -1
  26. package/dist/cjs/router.cjs +187 -445
  27. package/dist/cjs/router.cjs.map +1 -1
  28. package/dist/cjs/router.d.cts +62 -52
  29. package/dist/cjs/scroll-restoration.cjs +27 -34
  30. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  31. package/dist/cjs/ssr/client.cjs +2 -2
  32. package/dist/cjs/ssr/createRequestHandler.cjs +60 -9
  33. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
  34. package/dist/cjs/ssr/createRequestHandler.d.cts +1 -0
  35. package/dist/cjs/ssr/handlerCallback.cjs +49 -4
  36. package/dist/cjs/ssr/handlerCallback.cjs.map +1 -1
  37. package/dist/cjs/ssr/handlerCallback.d.cts +3 -0
  38. package/dist/cjs/ssr/server.cjs +4 -0
  39. package/dist/cjs/ssr/server.d.cts +2 -2
  40. package/dist/cjs/ssr/ssr-client.d.cts +1 -10
  41. package/dist/cjs/ssr/ssr-match-id.cjs +2 -2
  42. package/dist/cjs/ssr/ssr-match-id.cjs.map +1 -1
  43. package/dist/cjs/ssr/ssr-server.cjs +6 -6
  44. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  45. package/dist/cjs/ssr/transformStreamWithRouter.cjs +27 -1
  46. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
  47. package/dist/cjs/ssr/transformStreamWithRouter.d.cts +2 -0
  48. package/dist/cjs/ssr/types.d.cts +0 -1
  49. package/dist/cjs/stores.cjs +30 -104
  50. package/dist/cjs/stores.cjs.map +1 -1
  51. package/dist/cjs/stores.d.cts +7 -32
  52. package/dist/cjs/utils.cjs +0 -4
  53. package/dist/cjs/utils.cjs.map +1 -1
  54. package/dist/esm/Matches.d.ts +3 -12
  55. package/dist/esm/Matches.js.map +1 -1
  56. package/dist/esm/await-signal.d.ts +1 -0
  57. package/dist/esm/await-signal.js +21 -0
  58. package/dist/esm/await-signal.js.map +1 -0
  59. package/dist/esm/index.d.ts +3 -2
  60. package/dist/esm/index.js +3 -2
  61. package/dist/esm/isServer/client.d.ts +1 -0
  62. package/dist/esm/isServer/client.js +2 -1
  63. package/dist/esm/isServer/client.js.map +1 -1
  64. package/dist/esm/isServer/development.d.ts +1 -0
  65. package/dist/esm/isServer/development.js +2 -1
  66. package/dist/esm/isServer/development.js.map +1 -1
  67. package/dist/esm/isServer/server.d.ts +1 -0
  68. package/dist/esm/isServer/server.js +2 -1
  69. package/dist/esm/isServer/server.js.map +1 -1
  70. package/dist/esm/load-client.d.ts +147 -0
  71. package/dist/esm/load-client.js +1462 -0
  72. package/dist/esm/load-client.js.map +1 -0
  73. package/dist/esm/load-server.d.ts +16 -0
  74. package/dist/esm/load-server.js +565 -0
  75. package/dist/esm/load-server.js.map +1 -0
  76. package/dist/esm/redirect.d.ts +0 -1
  77. package/dist/esm/redirect.js.map +1 -1
  78. package/dist/esm/route.js.map +1 -1
  79. package/dist/esm/router.d.ts +62 -52
  80. package/dist/esm/router.js +188 -446
  81. package/dist/esm/router.js.map +1 -1
  82. package/dist/esm/scroll-restoration.js +27 -34
  83. package/dist/esm/scroll-restoration.js.map +1 -1
  84. package/dist/esm/ssr/client.js +1 -1
  85. package/dist/esm/ssr/createRequestHandler.d.ts +1 -0
  86. package/dist/esm/ssr/createRequestHandler.js +61 -11
  87. package/dist/esm/ssr/createRequestHandler.js.map +1 -1
  88. package/dist/esm/ssr/handlerCallback.d.ts +3 -0
  89. package/dist/esm/ssr/handlerCallback.js +47 -5
  90. package/dist/esm/ssr/handlerCallback.js.map +1 -1
  91. package/dist/esm/ssr/server.d.ts +2 -2
  92. package/dist/esm/ssr/server.js +3 -3
  93. package/dist/esm/ssr/ssr-client.d.ts +1 -10
  94. package/dist/esm/ssr/ssr-match-id.js +2 -2
  95. package/dist/esm/ssr/ssr-match-id.js.map +1 -1
  96. package/dist/esm/ssr/ssr-server.js +6 -6
  97. package/dist/esm/ssr/ssr-server.js.map +1 -1
  98. package/dist/esm/ssr/transformStreamWithRouter.d.ts +2 -0
  99. package/dist/esm/ssr/transformStreamWithRouter.js +27 -1
  100. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
  101. package/dist/esm/ssr/types.d.ts +0 -1
  102. package/dist/esm/stores.d.ts +7 -32
  103. package/dist/esm/stores.js +30 -104
  104. package/dist/esm/stores.js.map +1 -1
  105. package/dist/esm/utils.js +1 -4
  106. package/dist/esm/utils.js.map +1 -1
  107. package/package.json +3 -3
  108. package/src/Matches.ts +6 -21
  109. package/src/await-signal.ts +27 -0
  110. package/src/index.ts +1 -3
  111. package/src/isServer/client.ts +1 -0
  112. package/src/isServer/development.ts +1 -0
  113. package/src/isServer/server.ts +1 -0
  114. package/src/load-client.ts +2701 -0
  115. package/src/load-server.ts +849 -0
  116. package/src/redirect.ts +0 -1
  117. package/src/route.ts +2 -11
  118. package/src/router.ts +380 -774
  119. package/src/scroll-restoration.ts +40 -56
  120. package/src/ssr/createRequestHandler.ts +109 -16
  121. package/src/ssr/handlerCallback.ts +76 -10
  122. package/src/ssr/server.ts +4 -1
  123. package/src/ssr/ssr-client.ts +1 -310
  124. package/src/ssr/ssr-match-id.ts +11 -2
  125. package/src/ssr/ssr-server.ts +9 -8
  126. package/src/ssr/transformStreamWithRouter.ts +37 -1
  127. package/src/ssr/types.ts +0 -1
  128. package/src/stores.ts +46 -208
  129. package/dist/cjs/load-matches.cjs +0 -658
  130. package/dist/cjs/load-matches.cjs.map +0 -1
  131. package/dist/cjs/load-matches.d.cts +0 -18
  132. package/dist/cjs/ssr/ssr-client.cjs +0 -183
  133. package/dist/cjs/ssr/ssr-client.cjs.map +0 -1
  134. package/dist/esm/load-matches.d.ts +0 -18
  135. package/dist/esm/load-matches.js +0 -656
  136. package/dist/esm/load-matches.js.map +0 -1
  137. package/dist/esm/ssr/ssr-client.js +0 -183
  138. package/dist/esm/ssr/ssr-client.js.map +0 -1
  139. package/src/load-matches.ts +0 -1278
@@ -8,6 +8,26 @@ function normalizeSsrResponse(result) {
8
8
  serverSsrCleanup: "none"
9
9
  };
10
10
  }
11
+ function disposeSsrResponse(response, reason) {
12
+ if (response.serverSsrCleanup !== "stream") return Promise.resolve();
13
+ try {
14
+ return Promise.resolve(response.dispose(reason));
15
+ } catch (error) {
16
+ return Promise.reject(error);
17
+ }
18
+ }
19
+ function disposeSsrResponseDetached(result, reason, onError = console.error) {
20
+ const ssrResponse = normalizeSsrResponse(result);
21
+ if (ssrResponse.serverSsrCleanup === "stream") {
22
+ disposeSsrResponse(ssrResponse, reason).catch(onError);
23
+ return;
24
+ }
25
+ if (ssrResponse.response.body) try {
26
+ ssrResponse.response.body.cancel(reason).catch(onError);
27
+ } catch (error) {
28
+ onError(error);
29
+ }
30
+ }
11
31
  function createSsrStreamResponse(router, response) {
12
32
  if (!response.body) throw new Error("Invariant failed: SSR stream response requires a body");
13
33
  let disposed = false;
@@ -17,16 +37,38 @@ function createSsrStreamResponse(router, response) {
17
37
  async dispose(reason) {
18
38
  if (disposed) return;
19
39
  disposed = true;
40
+ router.serverSsr?.cleanup();
20
41
  try {
21
42
  await response.body.cancel(reason);
22
43
  } catch {}
23
- router.serverSsr?.cleanup();
24
44
  }
25
45
  };
26
46
  }
27
- async function replaceSsrResponse(result, response, reason) {
47
+ function bindSsrResponseToRequest(router, result, signal) {
28
48
  const ssrResponse = normalizeSsrResponse(result);
29
- if (ssrResponse.serverSsrCleanup === "stream") await ssrResponse.dispose(reason);
49
+ if (ssrResponse.serverSsrCleanup !== "stream") {
50
+ if (signal.aborted) disposeSsrResponseDetached(result, signal.reason);
51
+ return ssrResponse;
52
+ }
53
+ const failed = (error) => {
54
+ router?.serverSsr?.cleanup();
55
+ console.error(error);
56
+ };
57
+ const abort = () => {
58
+ disposeSsrResponseDetached(ssrResponse, signal.reason, failed);
59
+ };
60
+ if (signal.aborted) {
61
+ abort();
62
+ return ssrResponse;
63
+ }
64
+ signal.addEventListener("abort", abort, { once: true });
65
+ router?.serverSsr?.onCleanup(() => {
66
+ signal.removeEventListener("abort", abort);
67
+ });
68
+ return ssrResponse;
69
+ }
70
+ async function replaceSsrResponse(result, response, reason) {
71
+ await disposeSsrResponse(normalizeSsrResponse(result), reason);
30
72
  return {
31
73
  response,
32
74
  serverSsrCleanup: "none"
@@ -34,7 +76,7 @@ async function replaceSsrResponse(result, response, reason) {
34
76
  }
35
77
  async function stripSsrResponseBody(result, reason) {
36
78
  const ssrResponse = normalizeSsrResponse(result);
37
- if (ssrResponse.serverSsrCleanup === "stream") await ssrResponse.dispose(reason);
79
+ await disposeSsrResponse(ssrResponse, reason);
38
80
  return {
39
81
  response: new Response(null, ssrResponse.response),
40
82
  serverSsrCleanup: "none"
@@ -44,8 +86,11 @@ function defineHandlerCallback(handler) {
44
86
  return handler;
45
87
  }
46
88
  //#endregion
89
+ exports.bindSsrResponseToRequest = bindSsrResponseToRequest;
47
90
  exports.createSsrStreamResponse = createSsrStreamResponse;
48
91
  exports.defineHandlerCallback = defineHandlerCallback;
92
+ exports.disposeSsrResponse = disposeSsrResponse;
93
+ exports.disposeSsrResponseDetached = disposeSsrResponseDetached;
49
94
  exports.isSsrResponse = isSsrResponse;
50
95
  exports.normalizeSsrResponse = normalizeSsrResponse;
51
96
  exports.replaceSsrResponse = replaceSsrResponse;
@@ -1 +1 @@
1
- {"version":3,"file":"handlerCallback.cjs","names":[],"sources":["../../../src/ssr/handlerCallback.ts"],"sourcesContent":["import type { AnyRouter } from '../router'\n\nexport type SsrResponse =\n | {\n response: Response\n serverSsrCleanup: 'none'\n }\n | {\n response: Response\n serverSsrCleanup: 'stream'\n dispose: (reason?: unknown) => Promise<void>\n }\n\nexport type HandlerCallbackResult = Response | SsrResponse\n\nexport function isSsrResponse(value: unknown): value is SsrResponse {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'response' in value &&\n 'serverSsrCleanup' in value\n )\n}\n\nexport function normalizeSsrResponse(\n result: HandlerCallbackResult,\n): SsrResponse {\n return isSsrResponse(result)\n ? result\n : { response: result, serverSsrCleanup: 'none' }\n}\n\nexport function createSsrStreamResponse<TRouter extends AnyRouter>(\n router: TRouter,\n response: Response,\n): SsrResponse {\n if (!response.body) {\n throw new Error('Invariant failed: SSR stream response requires a body')\n }\n\n let disposed = false\n return {\n response,\n serverSsrCleanup: 'stream',\n async dispose(reason?: unknown) {\n if (disposed) return\n disposed = true\n\n try {\n await response.body!.cancel(reason)\n } catch {\n // ignore; fallback cleanup below still releases router SSR state\n }\n\n router.serverSsr?.cleanup()\n },\n }\n}\n\nexport async function replaceSsrResponse(\n result: HandlerCallbackResult,\n response: Response,\n reason?: unknown,\n): Promise<SsrResponse> {\n const ssrResponse = normalizeSsrResponse(result)\n if (ssrResponse.serverSsrCleanup === 'stream') {\n await ssrResponse.dispose(reason)\n }\n return { response, serverSsrCleanup: 'none' }\n}\n\nexport async function stripSsrResponseBody(\n result: HandlerCallbackResult,\n reason?: unknown,\n): Promise<SsrResponse> {\n const ssrResponse = normalizeSsrResponse(result)\n if (ssrResponse.serverSsrCleanup === 'stream') {\n await ssrResponse.dispose(reason)\n }\n return {\n response: new Response(null, ssrResponse.response),\n serverSsrCleanup: 'none',\n }\n}\n\nexport interface HandlerCallback<TRouter extends AnyRouter> {\n (ctx: {\n request: Request\n router: TRouter\n responseHeaders: Headers\n }): HandlerCallbackResult | Promise<HandlerCallbackResult>\n}\n\nexport function defineHandlerCallback<TRouter extends AnyRouter>(\n handler: HandlerCallback<TRouter>,\n): HandlerCallback<TRouter> {\n return handler\n}\n"],"mappings":";AAeA,SAAgB,cAAc,OAAsC;CAClE,OACE,OAAO,UAAU,YACjB,UAAU,QACV,cAAc,SACd,sBAAsB;AAE1B;AAEA,SAAgB,qBACd,QACa;CACb,OAAO,cAAc,MAAM,IACvB,SACA;EAAE,UAAU;EAAQ,kBAAkB;CAAO;AACnD;AAEA,SAAgB,wBACd,QACA,UACa;CACb,IAAI,CAAC,SAAS,MACZ,MAAM,IAAI,MAAM,uDAAuD;CAGzE,IAAI,WAAW;CACf,OAAO;EACL;EACA,kBAAkB;EAClB,MAAM,QAAQ,QAAkB;GAC9B,IAAI,UAAU;GACd,WAAW;GAEX,IAAI;IACF,MAAM,SAAS,KAAM,OAAO,MAAM;GACpC,QAAQ,CAER;GAEA,OAAO,WAAW,QAAQ;EAC5B;CACF;AACF;AAEA,eAAsB,mBACpB,QACA,UACA,QACsB;CACtB,MAAM,cAAc,qBAAqB,MAAM;CAC/C,IAAI,YAAY,qBAAqB,UACnC,MAAM,YAAY,QAAQ,MAAM;CAElC,OAAO;EAAE;EAAU,kBAAkB;CAAO;AAC9C;AAEA,eAAsB,qBACpB,QACA,QACsB;CACtB,MAAM,cAAc,qBAAqB,MAAM;CAC/C,IAAI,YAAY,qBAAqB,UACnC,MAAM,YAAY,QAAQ,MAAM;CAElC,OAAO;EACL,UAAU,IAAI,SAAS,MAAM,YAAY,QAAQ;EACjD,kBAAkB;CACpB;AACF;AAUA,SAAgB,sBACd,SAC0B;CAC1B,OAAO;AACT"}
1
+ {"version":3,"file":"handlerCallback.cjs","names":[],"sources":["../../../src/ssr/handlerCallback.ts"],"sourcesContent":["import type { AnyRouter } from '../router'\n\nexport type SsrResponse =\n | {\n response: Response\n serverSsrCleanup: 'none'\n }\n | {\n response: Response\n serverSsrCleanup: 'stream'\n dispose: (reason?: unknown) => Promise<void>\n }\n\nexport type HandlerCallbackResult = Response | SsrResponse\n\nexport function isSsrResponse(value: unknown): value is SsrResponse {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'response' in value &&\n 'serverSsrCleanup' in value\n )\n}\n\nexport function normalizeSsrResponse(\n result: HandlerCallbackResult,\n): SsrResponse {\n return isSsrResponse(result)\n ? result\n : { response: result, serverSsrCleanup: 'none' }\n}\n\nexport function disposeSsrResponse(\n response: SsrResponse,\n reason?: unknown,\n): Promise<void> {\n if (response.serverSsrCleanup !== 'stream') {\n return Promise.resolve()\n }\n try {\n return Promise.resolve(response.dispose(reason))\n } catch (error) {\n return Promise.reject(error)\n }\n}\n\nexport function disposeSsrResponseDetached(\n result: HandlerCallbackResult,\n reason?: unknown,\n onError: (error: unknown) => void = console.error,\n): void {\n const ssrResponse = normalizeSsrResponse(result)\n if (ssrResponse.serverSsrCleanup === 'stream') {\n void disposeSsrResponse(ssrResponse, reason).catch(onError)\n return\n }\n\n if (ssrResponse.response.body) {\n try {\n void ssrResponse.response.body.cancel(reason).catch(onError)\n } catch (error) {\n onError(error)\n }\n }\n}\n\nexport function createSsrStreamResponse<TRouter extends AnyRouter>(\n router: TRouter,\n response: Response,\n): SsrResponse {\n if (!response.body) {\n throw new Error('Invariant failed: SSR stream response requires a body')\n }\n\n let disposed = false\n return {\n response,\n serverSsrCleanup: 'stream',\n async dispose(reason?: unknown) {\n if (disposed) {\n return\n }\n disposed = true\n\n // Sever router ownership before asking user/renderer stream machinery to\n // cancel. A custom stream is allowed to ignore cancellation forever.\n router.serverSsr?.cleanup()\n\n try {\n await response.body!.cancel(reason)\n } catch {\n // Cleanup above already released router SSR state.\n }\n },\n }\n}\n\nexport function bindSsrResponseToRequest(\n router: AnyRouter | undefined,\n result: HandlerCallbackResult,\n signal: AbortSignal,\n): SsrResponse {\n const ssrResponse = normalizeSsrResponse(result)\n if (ssrResponse.serverSsrCleanup !== 'stream') {\n if (signal.aborted) {\n disposeSsrResponseDetached(result, signal.reason)\n }\n return ssrResponse\n }\n\n const failed = (error: unknown) => {\n router?.serverSsr?.cleanup()\n console.error(error)\n }\n const abort = () => {\n disposeSsrResponseDetached(ssrResponse, signal.reason, failed)\n }\n if (signal.aborted) {\n abort()\n return ssrResponse\n }\n\n signal.addEventListener('abort', abort, { once: true })\n router?.serverSsr?.onCleanup(() => {\n signal.removeEventListener('abort', abort)\n })\n return ssrResponse\n}\n\nexport async function replaceSsrResponse(\n result: HandlerCallbackResult,\n response: Response,\n reason?: unknown,\n): Promise<SsrResponse> {\n const ssrResponse = normalizeSsrResponse(result)\n await disposeSsrResponse(ssrResponse, reason)\n return { response, serverSsrCleanup: 'none' }\n}\n\nexport async function stripSsrResponseBody(\n result: HandlerCallbackResult,\n reason?: unknown,\n): Promise<SsrResponse> {\n const ssrResponse = normalizeSsrResponse(result)\n await disposeSsrResponse(ssrResponse, reason)\n return {\n response: new Response(null, ssrResponse.response),\n serverSsrCleanup: 'none',\n }\n}\n\nexport interface HandlerCallback<TRouter extends AnyRouter> {\n (ctx: {\n request: Request\n router: TRouter\n responseHeaders: Headers\n }): HandlerCallbackResult | Promise<HandlerCallbackResult>\n}\n\nexport function defineHandlerCallback<TRouter extends AnyRouter>(\n handler: HandlerCallback<TRouter>,\n): HandlerCallback<TRouter> {\n return handler\n}\n"],"mappings":";AAeA,SAAgB,cAAc,OAAsC;CAClE,OACE,OAAO,UAAU,YACjB,UAAU,QACV,cAAc,SACd,sBAAsB;AAE1B;AAEA,SAAgB,qBACd,QACa;CACb,OAAO,cAAc,MAAM,IACvB,SACA;EAAE,UAAU;EAAQ,kBAAkB;CAAO;AACnD;AAEA,SAAgB,mBACd,UACA,QACe;CACf,IAAI,SAAS,qBAAqB,UAChC,OAAO,QAAQ,QAAQ;CAEzB,IAAI;EACF,OAAO,QAAQ,QAAQ,SAAS,QAAQ,MAAM,CAAC;CACjD,SAAS,OAAO;EACd,OAAO,QAAQ,OAAO,KAAK;CAC7B;AACF;AAEA,SAAgB,2BACd,QACA,QACA,UAAoC,QAAQ,OACtC;CACN,MAAM,cAAc,qBAAqB,MAAM;CAC/C,IAAI,YAAY,qBAAqB,UAAU;EAC7C,mBAAwB,aAAa,MAAM,EAAE,MAAM,OAAO;EAC1D;CACF;CAEA,IAAI,YAAY,SAAS,MACvB,IAAI;EACF,YAAiB,SAAS,KAAK,OAAO,MAAM,EAAE,MAAM,OAAO;CAC7D,SAAS,OAAO;EACd,QAAQ,KAAK;CACf;AAEJ;AAEA,SAAgB,wBACd,QACA,UACa;CACb,IAAI,CAAC,SAAS,MACZ,MAAM,IAAI,MAAM,uDAAuD;CAGzE,IAAI,WAAW;CACf,OAAO;EACL;EACA,kBAAkB;EAClB,MAAM,QAAQ,QAAkB;GAC9B,IAAI,UACF;GAEF,WAAW;GAIX,OAAO,WAAW,QAAQ;GAE1B,IAAI;IACF,MAAM,SAAS,KAAM,OAAO,MAAM;GACpC,QAAQ,CAER;EACF;CACF;AACF;AAEA,SAAgB,yBACd,QACA,QACA,QACa;CACb,MAAM,cAAc,qBAAqB,MAAM;CAC/C,IAAI,YAAY,qBAAqB,UAAU;EAC7C,IAAI,OAAO,SACT,2BAA2B,QAAQ,OAAO,MAAM;EAElD,OAAO;CACT;CAEA,MAAM,UAAU,UAAmB;EACjC,QAAQ,WAAW,QAAQ;EAC3B,QAAQ,MAAM,KAAK;CACrB;CACA,MAAM,cAAc;EAClB,2BAA2B,aAAa,OAAO,QAAQ,MAAM;CAC/D;CACA,IAAI,OAAO,SAAS;EAClB,MAAM;EACN,OAAO;CACT;CAEA,OAAO,iBAAiB,SAAS,OAAO,EAAE,MAAM,KAAK,CAAC;CACtD,QAAQ,WAAW,gBAAgB;EACjC,OAAO,oBAAoB,SAAS,KAAK;CAC3C,CAAC;CACD,OAAO;AACT;AAEA,eAAsB,mBACpB,QACA,UACA,QACsB;CAEtB,MAAM,mBADc,qBAAqB,MAChB,GAAa,MAAM;CAC5C,OAAO;EAAE;EAAU,kBAAkB;CAAO;AAC9C;AAEA,eAAsB,qBACpB,QACA,QACsB;CACtB,MAAM,cAAc,qBAAqB,MAAM;CAC/C,MAAM,mBAAmB,aAAa,MAAM;CAC5C,OAAO;EACL,UAAU,IAAI,SAAS,MAAM,YAAY,QAAQ;EACjD,kBAAkB;CACpB;AACF;AAUA,SAAgB,sBACd,SAC0B;CAC1B,OAAO;AACT"}
@@ -10,7 +10,10 @@ export type SsrResponse = {
10
10
  export type HandlerCallbackResult = Response | SsrResponse;
11
11
  export declare function isSsrResponse(value: unknown): value is SsrResponse;
12
12
  export declare function normalizeSsrResponse(result: HandlerCallbackResult): SsrResponse;
13
+ export declare function disposeSsrResponse(response: SsrResponse, reason?: unknown): Promise<void>;
14
+ export declare function disposeSsrResponseDetached(result: HandlerCallbackResult, reason?: unknown, onError?: (error: unknown) => void): void;
13
15
  export declare function createSsrStreamResponse<TRouter extends AnyRouter>(router: TRouter, response: Response): SsrResponse;
16
+ export declare function bindSsrResponseToRequest(router: AnyRouter | undefined, result: HandlerCallbackResult, signal: AbortSignal): SsrResponse;
14
17
  export declare function replaceSsrResponse(result: HandlerCallbackResult, response: Response, reason?: unknown): Promise<SsrResponse>;
15
18
  export declare function stripSsrResponseBody(result: HandlerCallbackResult, reason?: unknown): Promise<SsrResponse>;
16
19
  export interface HandlerCallback<TRouter extends AnyRouter> {
@@ -4,9 +4,12 @@ const require_handlerCallback = require("./handlerCallback.cjs");
4
4
  const require_createRequestHandler = require("./createRequestHandler.cjs");
5
5
  const require_transformStreamWithRouter = require("./transformStreamWithRouter.cjs");
6
6
  exports.attachRouterServerSsrUtils = require_ssr_server.attachRouterServerSsrUtils;
7
+ exports.bindSsrResponseToRequest = require_handlerCallback.bindSsrResponseToRequest;
7
8
  exports.createRequestHandler = require_createRequestHandler.createRequestHandler;
8
9
  exports.createSsrStreamResponse = require_handlerCallback.createSsrStreamResponse;
9
10
  exports.defineHandlerCallback = require_handlerCallback.defineHandlerCallback;
11
+ exports.disposeSsrResponse = require_handlerCallback.disposeSsrResponse;
12
+ exports.disposeSsrResponseDetached = require_handlerCallback.disposeSsrResponseDetached;
10
13
  exports.getNormalizedURL = require_ssr_server.getNormalizedURL;
11
14
  exports.getOrigin = require_ssr_server.getOrigin;
12
15
  exports.isSsrResponse = require_handlerCallback.isSsrResponse;
@@ -16,3 +19,4 @@ exports.stripSsrResponseBody = require_handlerCallback.stripSsrResponseBody;
16
19
  exports.transformPipeableStreamWithRouter = require_transformStreamWithRouter.transformPipeableStreamWithRouter;
17
20
  exports.transformReadableStreamWithRouter = require_transformStreamWithRouter.transformReadableStreamWithRouter;
18
21
  exports.transformStreamWithRouter = require_transformStreamWithRouter.transformStreamWithRouter;
22
+ exports.waitForRequest = require_createRequestHandler.waitForRequest;
@@ -1,6 +1,6 @@
1
- export { createRequestHandler } from './createRequestHandler.cjs';
1
+ export { createRequestHandler, waitForRequest } from './createRequestHandler.cjs';
2
2
  export type { RequestHandler } from './createRequestHandler.cjs';
3
- export { createSsrStreamResponse, defineHandlerCallback, isSsrResponse, normalizeSsrResponse, replaceSsrResponse, stripSsrResponseBody, } from './handlerCallback.cjs';
3
+ export { bindSsrResponseToRequest, createSsrStreamResponse, defineHandlerCallback, disposeSsrResponse, disposeSsrResponseDetached, isSsrResponse, normalizeSsrResponse, replaceSsrResponse, stripSsrResponseBody, } from './handlerCallback.cjs';
4
4
  export type { HandlerCallback, HandlerCallbackResult, SsrResponse, } from './handlerCallback.cjs';
5
5
  export { transformPipeableStreamWithRouter, transformStreamWithRouter, transformReadableStreamWithRouter, } from './transformStreamWithRouter.cjs';
6
6
  export type { TransformStreamWithRouterOptions } from './transformStreamWithRouter.cjs';
@@ -1,10 +1 @@
1
- import { GLOBAL_SEROVAL, GLOBAL_TSR } from './constants.cjs';
2
- import { TsrSsrGlobal } from './types.cjs';
3
- import { AnyRouter } from '../router.cjs';
4
- declare global {
5
- interface Window {
6
- [GLOBAL_TSR]?: TsrSsrGlobal;
7
- [GLOBAL_SEROVAL]?: any;
8
- }
9
- }
10
- export declare function hydrate(router: AnyRouter): Promise<any>;
1
+ export { hydrate } from '../load-client.cjs';
@@ -1,9 +1,9 @@
1
1
  //#region src/ssr/ssr-match-id.ts
2
2
  function dehydrateSsrMatchId(id) {
3
- return id.replaceAll("/", "\0");
3
+ return id.replaceAll("~", "~~").replaceAll("\0", "~0").replaceAll("�", "~r").replaceAll("/", "\0");
4
4
  }
5
5
  function hydrateSsrMatchId(id) {
6
- return id.replaceAll("\0", "/").replaceAll("�", "/");
6
+ return id.replaceAll("\0", "/").replaceAll("�", "/").replace(/~([~0r])/g, (_, code) => code === "0" ? "\0" : code === "r" ? "�" : code);
7
7
  }
8
8
  //#endregion
9
9
  exports.dehydrateSsrMatchId = dehydrateSsrMatchId;
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-match-id.cjs","names":[],"sources":["../../../src/ssr/ssr-match-id.ts"],"sourcesContent":["export function dehydrateSsrMatchId(id: string): string {\n return id.replaceAll('/', '\\0')\n}\n\nexport function hydrateSsrMatchId(id: string): string {\n return id.replaceAll('\\0', '/').replaceAll('\\uFFFD', '/')\n}\n"],"mappings":";AAAA,SAAgB,oBAAoB,IAAoB;CACtD,OAAO,GAAG,WAAW,KAAK,IAAI;AAChC;AAEA,SAAgB,kBAAkB,IAAoB;CACpD,OAAO,GAAG,WAAW,MAAM,GAAG,EAAE,WAAW,KAAU,GAAG;AAC1D"}
1
+ {"version":3,"file":"ssr-match-id.cjs","names":[],"sources":["../../../src/ssr/ssr-match-id.ts"],"sourcesContent":["export function dehydrateSsrMatchId(id: string): string {\n return id\n .replaceAll('~', '~~')\n .replaceAll('\\0', '~0')\n .replaceAll('\\uFFFD', '~r')\n .replaceAll('/', '\\0')\n}\n\nexport function hydrateSsrMatchId(id: string): string {\n return id\n .replaceAll('\\0', '/')\n .replaceAll('\\uFFFD', '/')\n .replace(/~([~0r])/g, (_, code) =>\n code === '0' ? '\\0' : code === 'r' ? '\\uFFFD' : code,\n )\n}\n"],"mappings":";AAAA,SAAgB,oBAAoB,IAAoB;CACtD,OAAO,GACJ,WAAW,KAAK,IAAI,EACpB,WAAW,MAAM,IAAI,EACrB,WAAW,KAAU,IAAI,EACzB,WAAW,KAAK,IAAI;AACzB;AAEA,SAAgB,kBAAkB,IAAoB;CACpD,OAAO,GACJ,WAAW,MAAM,GAAG,EACpB,WAAW,KAAU,GAAG,EACxB,QAAQ,cAAc,GAAG,SACxB,SAAS,MAAM,OAAO,SAAS,MAAM,MAAW,IAClD;AACJ"}
@@ -2,11 +2,12 @@ const require_utils = require("../utils.cjs");
2
2
  const require_invariant = require("../invariant.cjs");
3
3
  const require_lru_cache = require("../lru-cache.cjs");
4
4
  const require_root = require("../root.cjs");
5
+ const require_ssr_match_id = require("./ssr-match-id.cjs");
6
+ const require_load_client = require("../load-client.cjs");
5
7
  const require_manifest = require("../manifest.cjs");
6
8
  const require_constants = require("./constants.cjs");
7
9
  const require_transformer = require("./serializer/transformer.cjs");
8
10
  const require_seroval_plugins = require("./serializer/seroval-plugins.cjs");
9
- const require_ssr_match_id = require("./ssr-match-id.cjs");
10
11
  const require_tsrScript = require("./tsrScript.cjs");
11
12
  let seroval = require("seroval");
12
13
  //#region src/ssr/ssr-server.ts
@@ -26,7 +27,7 @@ function dehydrateMatch(match) {
26
27
  ["error", "e"],
27
28
  ["ssr", "ssr"]
28
29
  ]) if (match[key] !== void 0) dehydratedMatch[shorthand] = match[key];
29
- if (match.globalNotFound) dehydratedMatch.g = true;
30
+ if (match._notFound) dehydratedMatch.g = true;
30
31
  return dehydratedMatch;
31
32
  }
32
33
  const INITIAL_SCRIPTS = [(0, seroval.getCrossReferenceHeader)(SCOPE_ID), require_tsrScript.default];
@@ -223,7 +224,7 @@ function attachRouterServerSsrUtils({ router, manifest, getRequestAssets }) {
223
224
  router.ssr = { get manifest() {
224
225
  if (!manifest) return manifest;
225
226
  const requestAssets = getRequestAssets?.();
226
- const matches = router.stores.matches.get();
227
+ const matches = require_load_client._getRenderedMatches(router.stores.matches.get());
227
228
  const hasAssets = hasRequestAssets(requestAssets);
228
229
  if (!hasAssets && !manifest.inlineCss) return manifest;
229
230
  let inlineCssAsset;
@@ -291,7 +292,7 @@ function attachRouterServerSsrUtils({ router, manifest, getRequestAssets }) {
291
292
  if (process.env.NODE_ENV !== "production") throw new Error("Invariant failed: router is already dehydrated!");
292
293
  require_invariant.invariant();
293
294
  }
294
- let matchesToDehydrate = router.stores.matches.get();
295
+ let matchesToDehydrate = require_load_client._getRenderedMatches(router.stores.matches.get());
295
296
  if (router.isShell()) matchesToDehydrate = matchesToDehydrate.slice(0, 1);
296
297
  const matches = matchesToDehydrate.map(dehydrateMatch);
297
298
  let manifestToDehydrate = void 0;
@@ -316,9 +317,8 @@ function attachRouterServerSsrUtils({ router, manifest, getRequestAssets }) {
316
317
  manifest: manifestToDehydrate,
317
318
  matches
318
319
  };
319
- const lastMatchId = matchesToDehydrate[matchesToDehydrate.length - 1]?.id;
320
- if (lastMatchId) dehydratedRouter.lastMatchId = require_ssr_match_id.dehydrateSsrMatchId(lastMatchId);
321
320
  const dehydratedData = await router.options.dehydrate?.();
321
+ if (cleanupStarted) return;
322
322
  if (dehydratedData) dehydratedRouter.dehydratedData = dehydratedData;
323
323
  _dehydrated = true;
324
324
  const trackPlugins = { didRun: false };
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-server.cjs","names":[],"sources":["../../../src/ssr/ssr-server.ts"],"sourcesContent":["import { crossSerializeStream, getCrossReferenceHeader } from 'seroval'\nimport { invariant } from '../invariant'\nimport {\n createInlineCssPlaceholderAsset,\n createInlineCssStyleAsset,\n getStylesheetHref,\n} from '../manifest'\nimport { decodePath } from '../utils'\nimport { createLRUCache } from '../lru-cache'\nimport { rootRouteId } from '../root'\nimport minifiedTsrBootStrapScript from './tsrScript?script-string'\nimport { GLOBAL_TSR, TSR_SCRIPT_BARRIER_ID } from './constants'\nimport { dehydrateSsrMatchId } from './ssr-match-id'\nimport { defaultSerovalPlugins } from './serializer/seroval-plugins'\nimport { makeSsrSerovalPlugin } from './serializer/transformer'\nimport type { LRUCache } from '../lru-cache'\nimport type { DehydratedMatch, DehydratedRouter } from './types'\nimport type { AnySerializationAdapter } from './serializer/transformer'\nimport type { AnyRouter, ServerSsr } from '../router'\nimport type { AnyRouteMatch } from '../Matches'\nimport type {\n Manifest,\n ManifestRoute,\n ManifestRouteAssets,\n RouterManagedTag,\n ServerManifest,\n} from '../manifest'\n\nconst SCOPE_ID = 'tsr'\n\nconst TSR_PREFIX = GLOBAL_TSR + '.router='\nconst P_PREFIX = GLOBAL_TSR + '.p(()=>'\nconst P_SUFFIX = ')'\n\nexport function dehydrateMatch(match: AnyRouteMatch): DehydratedMatch {\n const dehydratedMatch: DehydratedMatch = {\n i: dehydrateSsrMatchId(match.id),\n u: match.updatedAt,\n s: match.status,\n }\n\n const properties = [\n ['__beforeLoadContext', 'b'],\n ['loaderData', 'l'],\n ['error', 'e'],\n ['ssr', 'ssr'],\n ] as const\n\n for (const [key, shorthand] of properties) {\n if (match[key] !== undefined) {\n dehydratedMatch[shorthand] = match[key]\n }\n }\n if (match.globalNotFound) {\n dehydratedMatch.g = true\n }\n return dehydratedMatch\n}\n\nconst INITIAL_SCRIPTS = [\n getCrossReferenceHeader(SCOPE_ID),\n minifiedTsrBootStrapScript,\n]\n\nclass ScriptBuffer {\n private injectScript: ((script: string) => void) | undefined\n private _queue: Array<string>\n private _scriptBarrierLifted = false\n private _cleanedUp = false\n private _microtaskVersion = 0\n private _pendingMicrotaskVersion = 0\n\n constructor(injectScript: (script: string) => void) {\n this.injectScript = injectScript\n // Copy INITIAL_SCRIPTS to avoid mutating the shared array\n this._queue = INITIAL_SCRIPTS.slice()\n }\n\n enqueue(script: string) {\n if (this._cleanedUp) return\n this._queue.push(script)\n if (this._scriptBarrierLifted) {\n this.scheduleInjectBufferedScripts()\n }\n }\n\n liftBarrier() {\n if (this._scriptBarrierLifted || this._cleanedUp) return\n this._scriptBarrierLifted = true\n if (this._queue.length > 0) {\n this.scheduleInjectBufferedScripts()\n }\n }\n\n scheduleInjectBufferedScripts() {\n if (this._pendingMicrotaskVersion !== 0) return\n const pendingVersion = ++this._microtaskVersion\n this._pendingMicrotaskVersion = pendingVersion\n queueMicrotask(() => {\n if (this._pendingMicrotaskVersion !== pendingVersion) return\n this._pendingMicrotaskVersion = 0\n this.injectBufferedScripts()\n })\n }\n\n clearPendingMicrotask() {\n if (this._pendingMicrotaskVersion === 0) return\n this._pendingMicrotaskVersion = 0\n this._microtaskVersion++\n }\n\n /**\n * Flushes any pending scripts synchronously.\n * Call this before signaling serialization finished to ensure all scripts are injected.\n *\n * IMPORTANT: Only injects if the barrier has been lifted. Before the barrier is lifted,\n * scripts should remain in the queue so takeBufferedScripts() can retrieve them\n */\n flush() {\n if (!this._scriptBarrierLifted) return\n if (this._cleanedUp) return\n this.clearPendingMicrotask()\n this.injectBufferedScripts()\n }\n\n takeAll() {\n return this.takeScripts(this._queue.length)\n }\n\n takeScripts(count: number) {\n if (count <= 0) return undefined\n const bufferedScripts = this._queue.splice(0, count)\n if (bufferedScripts.length === 0) {\n return undefined\n }\n // Optimization: if only one script, avoid join\n if (bufferedScripts.length === 1) {\n return bufferedScripts[0] + ';document.currentScript.remove()'\n }\n // Append cleanup script and join - avoid push() to not mutate then iterate\n return bufferedScripts.join(';') + ';document.currentScript.remove()'\n }\n\n hasPending() {\n return this._queue.length > 0\n }\n\n injectBufferedScripts() {\n if (this._cleanedUp) return\n // Early return if queue is empty (avoids unnecessary takeAll() call)\n if (this._queue.length === 0) return\n const scriptsToInject = this.takeAll()\n if (scriptsToInject) {\n this.injectScript?.(scriptsToInject)\n }\n }\n\n cleanup() {\n this._cleanedUp = true\n this.clearPendingMicrotask()\n this._queue = []\n this.injectScript = undefined\n }\n}\n\nconst isProd = process.env.NODE_ENV === 'production'\n\ntype FilteredRoutes = Manifest['routes']\n\ntype PreparedMatchedManifestRoutes = {\n routes: FilteredRoutes\n hasStrippedRoutes: boolean\n inlineCssHrefs?: Array<string>\n inlineCss?: string\n}\n\ntype ManifestLRU = LRUCache<string, PreparedMatchedManifestRoutes>\n\nconst MANIFEST_CACHE_SIZE = 100\nconst manifestCaches = new WeakMap<ServerManifest, ManifestLRU>()\n\nfunction getManifestCache(manifest: ServerManifest): ManifestLRU {\n const cache = manifestCaches.get(manifest)\n if (cache) return cache\n const newCache = createLRUCache<string, PreparedMatchedManifestRoutes>(\n MANIFEST_CACHE_SIZE,\n )\n manifestCaches.set(manifest, newCache)\n return newCache\n}\n\nfunction getInlineCssForPreparedRoutes(\n manifest: ServerManifest,\n preparedRoutes: PreparedMatchedManifestRoutes,\n) {\n if (preparedRoutes.inlineCss !== undefined) return preparedRoutes.inlineCss\n\n const styles = manifest.inlineCss?.styles\n const hrefs = preparedRoutes.inlineCssHrefs\n if (!styles || !hrefs?.length) return undefined\n\n let css = ''\n for (const href of hrefs) {\n css += styles[href]!\n }\n\n preparedRoutes.inlineCss = css\n return css\n}\n\nfunction getInlineCssAssetForPreparedRoutes(\n manifest: ServerManifest,\n preparedRoutes: PreparedMatchedManifestRoutes,\n) {\n const css = getInlineCssForPreparedRoutes(manifest, preparedRoutes)\n\n return css === undefined ? undefined : createInlineCssStyleAsset(css)\n}\n\nfunction getMatchedRoutesCacheKey(matches: Array<AnyRouteMatch>) {\n let cacheKey = ''\n for (let i = 0; i < matches.length; i++) {\n cacheKey += (i === 0 ? '' : '\\0') + matches[i]!.routeId\n }\n return cacheKey\n}\n\nfunction getPreparedMatchedManifestRoutes(\n manifest: ServerManifest,\n matches: Array<AnyRouteMatch>,\n cacheKey: string,\n) {\n if (isProd) {\n const cached = getManifestCache(manifest).get(cacheKey)\n if (cached) {\n return cached\n }\n }\n\n const preparedRoutes = prepareMatchedManifestRoutes(manifest, matches)\n\n if (isProd) {\n getManifestCache(manifest).set(cacheKey, preparedRoutes)\n }\n\n return preparedRoutes\n}\n\nfunction prepareMatchedManifestRoutes(\n manifest: ServerManifest,\n matches: Array<AnyRouteMatch>,\n): PreparedMatchedManifestRoutes {\n const inlineStyles = manifest.inlineCss?.styles\n const routes: FilteredRoutes = {}\n\n if (!inlineStyles) {\n for (const match of matches) {\n const route = manifest.routes[match.routeId]\n if (route) {\n routes[match.routeId] = route\n }\n }\n return { routes, hasStrippedRoutes: false }\n }\n\n const inlineCssHrefs: Array<string> = []\n const seenInlineCssHrefs = new Set<string>()\n let hasStrippedRoutes = false\n\n for (const match of matches) {\n const routeId = match.routeId\n const route = manifest.routes[routeId]\n if (!route) {\n continue\n }\n\n const nextRoute = stripInlinedStylesheetAssetsFromRoute(\n inlineStyles,\n route,\n inlineCssHrefs,\n seenInlineCssHrefs,\n )\n\n if (nextRoute !== route) {\n hasStrippedRoutes = true\n }\n routes[routeId] = nextRoute\n }\n\n return {\n routes,\n hasStrippedRoutes,\n ...(inlineCssHrefs.length ? { inlineCssHrefs } : {}),\n }\n}\n\nfunction stripInlinedStylesheetAssetsFromRoute(\n inlineStyles: Record<string, string>,\n route: ManifestRoute,\n inlineCssHrefs: Array<string>,\n seenInlineCssHrefs: Set<string>,\n): ManifestRoute {\n const css = route.css\n if (!css) {\n return route\n }\n\n if (css.length === 0) {\n const nextRoute = { ...route }\n delete nextRoute.css\n return nextRoute\n }\n\n let cssLinks: typeof css | undefined\n for (let i = 0; i < css.length; i++) {\n const link = css[i]!\n const href = getStylesheetHref(link)\n if (inlineStyles[href] === undefined) {\n if (cssLinks) {\n cssLinks.push(link)\n }\n continue\n }\n\n if (!seenInlineCssHrefs.has(href)) {\n seenInlineCssHrefs.add(href)\n inlineCssHrefs.push(href)\n }\n\n if (!cssLinks) {\n cssLinks = css.slice(0, i)\n }\n }\n\n if (!cssLinks) {\n return route\n }\n\n if (cssLinks.length > 0) {\n return { ...route, css: cssLinks }\n }\n\n const nextRoute = { ...route }\n delete nextRoute.css\n return nextRoute\n}\n\nfunction hasRouteAssets(route: ManifestRoute) {\n return !!route.scripts?.length || !!route.css?.length\n}\n\nfunction hasRequestAssets(assets: ManifestRouteAssets | undefined) {\n return !!assets && (!!assets.preloads?.length || hasRouteAssets(assets))\n}\n\nfunction mergeRequestAssetsIntoRootRoute(\n rootRoute: ManifestRoute | undefined,\n requestAssets: ManifestRouteAssets | undefined,\n): ManifestRoute {\n const preloads = requestAssets?.preloads?.length\n ? [...requestAssets.preloads, ...(rootRoute?.preloads ?? [])]\n : rootRoute?.preloads\n const scripts = requestAssets?.scripts?.length\n ? [...requestAssets.scripts, ...(rootRoute?.scripts ?? [])]\n : rootRoute?.scripts\n const cssLinks = requestAssets?.css?.length\n ? [...requestAssets.css, ...(rootRoute?.css ?? [])]\n : rootRoute?.css\n\n return {\n ...(rootRoute ?? {}),\n ...(preloads?.length ? { preloads } : {}),\n ...(scripts?.length ? { scripts } : {}),\n ...(cssLinks?.length ? { css: cssLinks } : {}),\n }\n}\n\nexport function attachRouterServerSsrUtils({\n router,\n manifest,\n getRequestAssets,\n}: {\n router: AnyRouter\n manifest: ServerManifest | undefined\n getRequestAssets?: () => ManifestRouteAssets | undefined\n}) {\n router.ssr = {\n get manifest() {\n if (!manifest) return manifest\n\n const requestAssets = getRequestAssets?.()\n const matches = router.stores.matches.get()\n const hasAssets = hasRequestAssets(requestAssets)\n\n if (!hasAssets && !manifest.inlineCss) {\n return manifest\n }\n\n let inlineCssAsset: Manifest['inlineStyle'] | undefined\n let routes = manifest.routes\n if (manifest.inlineCss) {\n const cacheKey = getMatchedRoutesCacheKey(matches)\n const preparedManifest = getPreparedMatchedManifestRoutes(\n manifest,\n matches,\n cacheKey,\n )\n inlineCssAsset = getInlineCssAssetForPreparedRoutes(\n manifest,\n preparedManifest,\n )\n if (preparedManifest.hasStrippedRoutes) {\n routes = { ...manifest.routes, ...preparedManifest.routes }\n }\n }\n\n if (!hasAssets) {\n return {\n ...(manifest.scriptFormat\n ? { scriptFormat: manifest.scriptFormat }\n : {}),\n ...(inlineCssAsset ? { inlineStyle: inlineCssAsset } : {}),\n routes,\n }\n }\n\n const rootRoute = routes[rootRouteId]\n\n // Merge request-scoped assets into root route without mutating cached manifest\n return {\n ...(manifest.scriptFormat\n ? { scriptFormat: manifest.scriptFormat }\n : {}),\n ...(inlineCssAsset ? { inlineStyle: inlineCssAsset } : {}),\n routes: {\n ...routes,\n [rootRouteId]: mergeRequestAssetsIntoRootRoute(\n rootRoute,\n requestAssets,\n ),\n },\n }\n },\n }\n let _dehydrated = false\n let _serializationFinished = false\n let streamFastPathReserved = false\n const renderFinishedListeners: Array<() => void> = []\n const injectedHtmlListeners: Array<() => void> = []\n const serializationFinishedListeners: Array<() => void> = []\n const cleanupListeners: Array<() => void> = []\n let cleanupStarted = false\n let injectedHtmlBuffer = ''\n\n const callListeners = (listeners: Array<() => void>, errorPrefix: string) => {\n const snapshot = listeners.slice()\n for (const l of snapshot) {\n try {\n l()\n } catch (err) {\n console.error(`${errorPrefix}:`, err)\n }\n }\n }\n\n const removeListener = (\n listeners: Array<() => void>,\n listener: () => void,\n ) => {\n const index = listeners.indexOf(listener)\n if (index >= 0) listeners.splice(index, 1)\n }\n\n const scriptBuffer = new ScriptBuffer((script) => {\n serverSsr.injectScript(script)\n })\n\n const serverSsr: ServerSsr = {\n injectHtml: (html: string) => {\n if (!html || cleanupStarted) return\n // Buffer the HTML so it can be retrieved via takeBufferedHtml()\n injectedHtmlBuffer += html\n callListeners(injectedHtmlListeners, 'SSR injected HTML listener error')\n },\n injectScript: (script: string) => {\n if (!script || cleanupStarted) return\n const html = `<script${router.options.ssr?.nonce ? ` nonce='${router.options.ssr.nonce}'` : ''}>${script}</script>`\n serverSsr.injectHtml(html)\n },\n dehydrate: async (opts?: { requestAssets?: ManifestRouteAssets }) => {\n if (_dehydrated) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error('Invariant failed: router is already dehydrated!')\n }\n\n invariant()\n }\n let matchesToDehydrate = router.stores.matches.get()\n if (router.isShell()) {\n // In SPA mode we only want to dehydrate the root match\n matchesToDehydrate = matchesToDehydrate.slice(0, 1)\n }\n const matches = matchesToDehydrate.map(dehydrateMatch)\n\n let manifestToDehydrate: Manifest | undefined = undefined\n // Only currently matched routes are dehydrated. Other route assets are\n // loaded through dynamic imports when those routes become active.\n if (manifest) {\n const cacheKey = getMatchedRoutesCacheKey(matchesToDehydrate)\n const preparedManifest = getPreparedMatchedManifestRoutes(\n manifest,\n matchesToDehydrate,\n cacheKey,\n )\n\n manifestToDehydrate = {\n ...(manifest.scriptFormat\n ? { scriptFormat: manifest.scriptFormat }\n : {}),\n ...(preparedManifest.inlineCssHrefs\n ? { inlineStyle: createInlineCssPlaceholderAsset() }\n : {}),\n routes: preparedManifest.routes,\n }\n\n // Merge request-scoped assets into root route (without mutating cached manifest)\n const requestAssets = opts?.requestAssets\n if (hasRequestAssets(requestAssets)) {\n const existingRoot = manifestToDehydrate.routes[rootRouteId]\n manifestToDehydrate.routes = {\n ...manifestToDehydrate.routes,\n [rootRouteId]: mergeRequestAssetsIntoRootRoute(\n existingRoot,\n requestAssets,\n ),\n }\n }\n }\n const dehydratedRouter: DehydratedRouter = {\n manifest: manifestToDehydrate,\n matches,\n }\n const lastMatchId = matchesToDehydrate[matchesToDehydrate.length - 1]?.id\n if (lastMatchId) {\n dehydratedRouter.lastMatchId = dehydrateSsrMatchId(lastMatchId)\n }\n const dehydratedData = await router.options.dehydrate?.()\n if (dehydratedData) {\n dehydratedRouter.dehydratedData = dehydratedData\n }\n _dehydrated = true\n\n const trackPlugins = { didRun: false }\n const serializationAdapters = router.options.serializationAdapters as\n | Array<AnySerializationAdapter>\n | undefined\n const plugins = serializationAdapters\n ? serializationAdapters\n .map((t) => makeSsrSerovalPlugin(t, trackPlugins))\n .concat(defaultSerovalPlugins)\n : defaultSerovalPlugins\n\n let serializationCompleteSignaled = false\n const signalSerializationComplete = () => {\n if (serializationCompleteSignaled || cleanupStarted) return\n serializationCompleteSignaled = true\n _serializationFinished = true\n\n const listeners = serializationFinishedListeners.slice()\n serializationFinishedListeners.length = 0\n\n for (const l of listeners) {\n try {\n l()\n } catch (err) {\n console.error('Serialization listener error:', err)\n }\n }\n }\n\n const finishScriptSerialization = () => {\n if (serializationCompleteSignaled || cleanupStarted) return\n scriptBuffer.enqueue(GLOBAL_TSR + '.e()')\n // Must synchronously notify injected HTML listeners before signaling\n // completion; otherwise the held </body> tail could flush ahead of the\n // end script.\n scriptBuffer.flush()\n signalSerializationComplete()\n }\n\n crossSerializeStream(dehydratedRouter, {\n refs: new Map(),\n plugins,\n onSerialize: (data, initial) => {\n let serialized = initial ? TSR_PREFIX + data : data\n if (trackPlugins.didRun) {\n serialized = P_PREFIX + serialized + P_SUFFIX\n }\n scriptBuffer.enqueue(serialized)\n },\n onError: (err: unknown) => {\n console.error('Serialization error:', err)\n if (err && (err as any).stack) {\n console.error((err as any).stack)\n }\n finishScriptSerialization()\n },\n scopeId: SCOPE_ID,\n onDone: () => {\n finishScriptSerialization()\n },\n })\n },\n isDehydrated() {\n return _dehydrated\n },\n isSerializationFinished() {\n return _serializationFinished\n },\n reserveStreamFastPath() {\n if (\n !cleanupStarted &&\n _serializationFinished &&\n !streamFastPathReserved &&\n renderFinishedListeners.length === 0 &&\n !injectedHtmlBuffer &&\n !scriptBuffer.hasPending()\n ) {\n streamFastPathReserved = true\n return true\n }\n return false\n },\n onInjectedHtml: (listener) => {\n if (cleanupStarted) return () => {}\n injectedHtmlListeners.push(listener)\n return () => removeListener(injectedHtmlListeners, listener)\n },\n onRenderFinished: (listener) => {\n if (cleanupStarted || streamFastPathReserved) return\n renderFinishedListeners.push(listener)\n },\n onSerializationFinished: (listener) => {\n if (cleanupStarted) return () => {}\n if (_serializationFinished && !cleanupStarted) {\n try {\n listener()\n } catch (err) {\n console.error('Serialization listener error:', err)\n }\n return () => {}\n }\n serializationFinishedListeners.push(listener)\n return () => removeListener(serializationFinishedListeners, listener)\n },\n onCleanup: (listener) => {\n if (cleanupStarted) return\n cleanupListeners.push(listener)\n },\n setRenderFinished: () => {\n if (cleanupStarted) return\n scriptBuffer.liftBarrier()\n const listeners = renderFinishedListeners.slice()\n renderFinishedListeners.length = 0\n for (const l of listeners) {\n try {\n l()\n } catch (err) {\n console.error('Error in render finished listener:', err)\n }\n }\n if (_serializationFinished) {\n scriptBuffer.flush()\n }\n },\n takeBufferedScripts() {\n const scripts = scriptBuffer.takeAll()\n if (!scripts) return undefined\n const serverBufferedScript: RouterManagedTag = {\n tag: 'script',\n attrs: {\n nonce: router.options.ssr?.nonce,\n className: '$tsr',\n id: TSR_SCRIPT_BARRIER_ID,\n },\n children: scripts,\n }\n return serverBufferedScript\n },\n liftScriptBarrier() {\n scriptBuffer.liftBarrier()\n },\n takeBufferedHtml() {\n if (!injectedHtmlBuffer) {\n return undefined\n }\n const buffered = injectedHtmlBuffer\n injectedHtmlBuffer = ''\n return buffered\n },\n cleanup() {\n // Guard against multiple/reentrant cleanup calls. A listener could call\n // cleanup() again indirectly; snapshot + clear before invoking so each\n // listener runs exactly once and reentry is a no-op.\n if (cleanupStarted) return\n cleanupStarted = true\n const listeners = cleanupListeners.slice()\n cleanupListeners.length = 0\n for (const l of listeners) {\n try {\n l()\n } catch (err) {\n console.error('Error in SSR cleanup listener:', err)\n }\n }\n renderFinishedListeners.length = 0\n injectedHtmlListeners.length = 0\n serializationFinishedListeners.length = 0\n injectedHtmlBuffer = ''\n scriptBuffer.cleanup()\n router.serverSsr = undefined\n },\n }\n\n router.serverSsr = serverSsr\n for (const listener of router.serverSsrLifecycle?.onServerSsrAttach ?? []) {\n try {\n listener(serverSsr)\n } catch (err) {\n console.error('SSR attach listener error:', err)\n }\n }\n}\n\n/**\n * Get the origin for the request.\n *\n * SECURITY: We intentionally do NOT trust the Origin header for determining\n * the router's origin. The Origin header can be spoofed by attackers, which\n * could lead to SSRF-like vulnerabilities where redirects are constructed\n * using a malicious origin (CVE-2024-34351).\n *\n * Instead, we derive the origin from request.url, which is typically set by\n * the server infrastructure (not client-controlled headers).\n *\n * For applications behind proxies that need to trust forwarded headers,\n * use the router's `origin` option to explicitly configure a trusted origin.\n */\nexport function getOrigin(request: Request) {\n try {\n return new URL(request.url).origin\n } catch {}\n return 'http://localhost'\n}\n\n// server and browser can decode/encode characters differently in paths and search params.\n// Server generally strictly follows the WHATWG URL Standard, while browsers may differ for legacy reasons.\n// for example, in paths \"|\" is not encoded on the server but is encoded on chromium (and not on firefox) while \"대\" is encoded on both sides.\n// Another anomaly is that in Node new URLSearchParams and new URL also decode/encode characters differently.\n// new URLSearchParams() encodes \"|\" while new URL() does not, and in this instance\n// chromium treats search params differently than paths, i.e. \"|\" is not encoded in search params.\nexport function getNormalizedURL(url: string | URL, base?: string | URL) {\n // ensure backslashes are encoded correctly in the URL\n if (typeof url === 'string') url = url.replace('\\\\', '%5C')\n\n const rawUrl = new URL(url, base)\n const { path: decodedPathname, handledProtocolRelativeURL } = decodePath(\n rawUrl.pathname,\n )\n const searchParams = new URLSearchParams(rawUrl.search)\n const normalizedHref =\n decodedPathname +\n (searchParams.size > 0 ? '?' : '') +\n searchParams.toString() +\n rawUrl.hash\n\n return {\n url: new URL(normalizedHref, rawUrl.origin),\n handledProtocolRelativeURL,\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ssr-server.cjs","names":[],"sources":["../../../src/ssr/ssr-server.ts"],"sourcesContent":["import { crossSerializeStream, getCrossReferenceHeader } from 'seroval'\nimport { invariant } from '../invariant'\nimport {\n createInlineCssPlaceholderAsset,\n createInlineCssStyleAsset,\n getStylesheetHref,\n} from '../manifest'\nimport { decodePath } from '../utils'\nimport { createLRUCache } from '../lru-cache'\nimport { rootRouteId } from '../root'\nimport { _getRenderedMatches } from '../load-client'\nimport minifiedTsrBootStrapScript from './tsrScript?script-string'\nimport { GLOBAL_TSR, TSR_SCRIPT_BARRIER_ID } from './constants'\nimport { dehydrateSsrMatchId } from './ssr-match-id'\nimport { defaultSerovalPlugins } from './serializer/seroval-plugins'\nimport { makeSsrSerovalPlugin } from './serializer/transformer'\nimport type { LRUCache } from '../lru-cache'\nimport type { DehydratedMatch, DehydratedRouter } from './types'\nimport type { AnySerializationAdapter } from './serializer/transformer'\nimport type { AnyRouter, ServerSsr } from '../router'\nimport type { AnyRouteMatch } from '../Matches'\nimport type {\n Manifest,\n ManifestRoute,\n ManifestRouteAssets,\n RouterManagedTag,\n ServerManifest,\n} from '../manifest'\n\nconst SCOPE_ID = 'tsr'\n\nconst TSR_PREFIX = GLOBAL_TSR + '.router='\nconst P_PREFIX = GLOBAL_TSR + '.p(()=>'\nconst P_SUFFIX = ')'\n\nexport function dehydrateMatch(match: AnyRouteMatch): DehydratedMatch {\n const dehydratedMatch: DehydratedMatch = {\n i: dehydrateSsrMatchId(match.id),\n u: match.updatedAt,\n s: match.status,\n }\n\n const properties = [\n ['__beforeLoadContext', 'b'],\n ['loaderData', 'l'],\n ['error', 'e'],\n ['ssr', 'ssr'],\n ] as const\n\n for (const [key, shorthand] of properties) {\n if (match[key] !== undefined) {\n dehydratedMatch[shorthand] = match[key]\n }\n }\n if (match._notFound) {\n dehydratedMatch.g = true\n }\n return dehydratedMatch\n}\n\nconst INITIAL_SCRIPTS = [\n getCrossReferenceHeader(SCOPE_ID),\n minifiedTsrBootStrapScript,\n]\n\nclass ScriptBuffer {\n private injectScript: ((script: string) => void) | undefined\n private _queue: Array<string>\n private _scriptBarrierLifted = false\n private _cleanedUp = false\n private _microtaskVersion = 0\n private _pendingMicrotaskVersion = 0\n\n constructor(injectScript: (script: string) => void) {\n this.injectScript = injectScript\n // Copy INITIAL_SCRIPTS to avoid mutating the shared array\n this._queue = INITIAL_SCRIPTS.slice()\n }\n\n enqueue(script: string) {\n if (this._cleanedUp) return\n this._queue.push(script)\n if (this._scriptBarrierLifted) {\n this.scheduleInjectBufferedScripts()\n }\n }\n\n liftBarrier() {\n if (this._scriptBarrierLifted || this._cleanedUp) return\n this._scriptBarrierLifted = true\n if (this._queue.length > 0) {\n this.scheduleInjectBufferedScripts()\n }\n }\n\n scheduleInjectBufferedScripts() {\n if (this._pendingMicrotaskVersion !== 0) return\n const pendingVersion = ++this._microtaskVersion\n this._pendingMicrotaskVersion = pendingVersion\n queueMicrotask(() => {\n if (this._pendingMicrotaskVersion !== pendingVersion) return\n this._pendingMicrotaskVersion = 0\n this.injectBufferedScripts()\n })\n }\n\n clearPendingMicrotask() {\n if (this._pendingMicrotaskVersion === 0) return\n this._pendingMicrotaskVersion = 0\n this._microtaskVersion++\n }\n\n /**\n * Flushes any pending scripts synchronously.\n * Call this before signaling serialization finished to ensure all scripts are injected.\n *\n * IMPORTANT: Only injects if the barrier has been lifted. Before the barrier is lifted,\n * scripts should remain in the queue so takeBufferedScripts() can retrieve them\n */\n flush() {\n if (!this._scriptBarrierLifted) return\n if (this._cleanedUp) return\n this.clearPendingMicrotask()\n this.injectBufferedScripts()\n }\n\n takeAll() {\n return this.takeScripts(this._queue.length)\n }\n\n takeScripts(count: number) {\n if (count <= 0) return undefined\n const bufferedScripts = this._queue.splice(0, count)\n if (bufferedScripts.length === 0) {\n return undefined\n }\n // Optimization: if only one script, avoid join\n if (bufferedScripts.length === 1) {\n return bufferedScripts[0] + ';document.currentScript.remove()'\n }\n // Append cleanup script and join - avoid push() to not mutate then iterate\n return bufferedScripts.join(';') + ';document.currentScript.remove()'\n }\n\n hasPending() {\n return this._queue.length > 0\n }\n\n injectBufferedScripts() {\n if (this._cleanedUp) return\n // Early return if queue is empty (avoids unnecessary takeAll() call)\n if (this._queue.length === 0) return\n const scriptsToInject = this.takeAll()\n if (scriptsToInject) {\n this.injectScript?.(scriptsToInject)\n }\n }\n\n cleanup() {\n this._cleanedUp = true\n this.clearPendingMicrotask()\n this._queue = []\n this.injectScript = undefined\n }\n}\n\nconst isProd = process.env.NODE_ENV === 'production'\n\ntype FilteredRoutes = Manifest['routes']\n\ntype PreparedMatchedManifestRoutes = {\n routes: FilteredRoutes\n hasStrippedRoutes: boolean\n inlineCssHrefs?: Array<string>\n inlineCss?: string\n}\n\ntype ManifestLRU = LRUCache<string, PreparedMatchedManifestRoutes>\n\nconst MANIFEST_CACHE_SIZE = 100\nconst manifestCaches = new WeakMap<ServerManifest, ManifestLRU>()\n\nfunction getManifestCache(manifest: ServerManifest): ManifestLRU {\n const cache = manifestCaches.get(manifest)\n if (cache) return cache\n const newCache = createLRUCache<string, PreparedMatchedManifestRoutes>(\n MANIFEST_CACHE_SIZE,\n )\n manifestCaches.set(manifest, newCache)\n return newCache\n}\n\nfunction getInlineCssForPreparedRoutes(\n manifest: ServerManifest,\n preparedRoutes: PreparedMatchedManifestRoutes,\n) {\n if (preparedRoutes.inlineCss !== undefined) return preparedRoutes.inlineCss\n\n const styles = manifest.inlineCss?.styles\n const hrefs = preparedRoutes.inlineCssHrefs\n if (!styles || !hrefs?.length) return undefined\n\n let css = ''\n for (const href of hrefs) {\n css += styles[href]!\n }\n\n preparedRoutes.inlineCss = css\n return css\n}\n\nfunction getInlineCssAssetForPreparedRoutes(\n manifest: ServerManifest,\n preparedRoutes: PreparedMatchedManifestRoutes,\n) {\n const css = getInlineCssForPreparedRoutes(manifest, preparedRoutes)\n\n return css === undefined ? undefined : createInlineCssStyleAsset(css)\n}\n\nfunction getMatchedRoutesCacheKey(matches: Array<AnyRouteMatch>) {\n let cacheKey = ''\n for (let i = 0; i < matches.length; i++) {\n cacheKey += (i === 0 ? '' : '\\0') + matches[i]!.routeId\n }\n return cacheKey\n}\n\nfunction getPreparedMatchedManifestRoutes(\n manifest: ServerManifest,\n matches: Array<AnyRouteMatch>,\n cacheKey: string,\n) {\n if (isProd) {\n const cached = getManifestCache(manifest).get(cacheKey)\n if (cached) {\n return cached\n }\n }\n\n const preparedRoutes = prepareMatchedManifestRoutes(manifest, matches)\n\n if (isProd) {\n getManifestCache(manifest).set(cacheKey, preparedRoutes)\n }\n\n return preparedRoutes\n}\n\nfunction prepareMatchedManifestRoutes(\n manifest: ServerManifest,\n matches: Array<AnyRouteMatch>,\n): PreparedMatchedManifestRoutes {\n const inlineStyles = manifest.inlineCss?.styles\n const routes: FilteredRoutes = {}\n\n if (!inlineStyles) {\n for (const match of matches) {\n const route = manifest.routes[match.routeId]\n if (route) {\n routes[match.routeId] = route\n }\n }\n return { routes, hasStrippedRoutes: false }\n }\n\n const inlineCssHrefs: Array<string> = []\n const seenInlineCssHrefs = new Set<string>()\n let hasStrippedRoutes = false\n\n for (const match of matches) {\n const routeId = match.routeId\n const route = manifest.routes[routeId]\n if (!route) {\n continue\n }\n\n const nextRoute = stripInlinedStylesheetAssetsFromRoute(\n inlineStyles,\n route,\n inlineCssHrefs,\n seenInlineCssHrefs,\n )\n\n if (nextRoute !== route) {\n hasStrippedRoutes = true\n }\n routes[routeId] = nextRoute\n }\n\n return {\n routes,\n hasStrippedRoutes,\n ...(inlineCssHrefs.length ? { inlineCssHrefs } : {}),\n }\n}\n\nfunction stripInlinedStylesheetAssetsFromRoute(\n inlineStyles: Record<string, string>,\n route: ManifestRoute,\n inlineCssHrefs: Array<string>,\n seenInlineCssHrefs: Set<string>,\n): ManifestRoute {\n const css = route.css\n if (!css) {\n return route\n }\n\n if (css.length === 0) {\n const nextRoute = { ...route }\n delete nextRoute.css\n return nextRoute\n }\n\n let cssLinks: typeof css | undefined\n for (let i = 0; i < css.length; i++) {\n const link = css[i]!\n const href = getStylesheetHref(link)\n if (inlineStyles[href] === undefined) {\n if (cssLinks) {\n cssLinks.push(link)\n }\n continue\n }\n\n if (!seenInlineCssHrefs.has(href)) {\n seenInlineCssHrefs.add(href)\n inlineCssHrefs.push(href)\n }\n\n if (!cssLinks) {\n cssLinks = css.slice(0, i)\n }\n }\n\n if (!cssLinks) {\n return route\n }\n\n if (cssLinks.length > 0) {\n return { ...route, css: cssLinks }\n }\n\n const nextRoute = { ...route }\n delete nextRoute.css\n return nextRoute\n}\n\nfunction hasRouteAssets(route: ManifestRoute) {\n return !!route.scripts?.length || !!route.css?.length\n}\n\nfunction hasRequestAssets(assets: ManifestRouteAssets | undefined) {\n return !!assets && (!!assets.preloads?.length || hasRouteAssets(assets))\n}\n\nfunction mergeRequestAssetsIntoRootRoute(\n rootRoute: ManifestRoute | undefined,\n requestAssets: ManifestRouteAssets | undefined,\n): ManifestRoute {\n const preloads = requestAssets?.preloads?.length\n ? [...requestAssets.preloads, ...(rootRoute?.preloads ?? [])]\n : rootRoute?.preloads\n const scripts = requestAssets?.scripts?.length\n ? [...requestAssets.scripts, ...(rootRoute?.scripts ?? [])]\n : rootRoute?.scripts\n const cssLinks = requestAssets?.css?.length\n ? [...requestAssets.css, ...(rootRoute?.css ?? [])]\n : rootRoute?.css\n\n return {\n ...(rootRoute ?? {}),\n ...(preloads?.length ? { preloads } : {}),\n ...(scripts?.length ? { scripts } : {}),\n ...(cssLinks?.length ? { css: cssLinks } : {}),\n }\n}\n\nexport function attachRouterServerSsrUtils({\n router,\n manifest,\n getRequestAssets,\n}: {\n router: AnyRouter\n manifest: ServerManifest | undefined\n getRequestAssets?: () => ManifestRouteAssets | undefined\n}) {\n router.ssr = {\n get manifest() {\n if (!manifest) return manifest\n\n const requestAssets = getRequestAssets?.()\n const matches = _getRenderedMatches(router.stores.matches.get())\n const hasAssets = hasRequestAssets(requestAssets)\n\n if (!hasAssets && !manifest.inlineCss) {\n return manifest\n }\n\n let inlineCssAsset: Manifest['inlineStyle'] | undefined\n let routes = manifest.routes\n if (manifest.inlineCss) {\n const cacheKey = getMatchedRoutesCacheKey(matches)\n const preparedManifest = getPreparedMatchedManifestRoutes(\n manifest,\n matches,\n cacheKey,\n )\n inlineCssAsset = getInlineCssAssetForPreparedRoutes(\n manifest,\n preparedManifest,\n )\n if (preparedManifest.hasStrippedRoutes) {\n routes = { ...manifest.routes, ...preparedManifest.routes }\n }\n }\n\n if (!hasAssets) {\n return {\n ...(manifest.scriptFormat\n ? { scriptFormat: manifest.scriptFormat }\n : {}),\n ...(inlineCssAsset ? { inlineStyle: inlineCssAsset } : {}),\n routes,\n }\n }\n\n const rootRoute = routes[rootRouteId]\n\n // Merge request-scoped assets into root route without mutating cached manifest\n return {\n ...(manifest.scriptFormat\n ? { scriptFormat: manifest.scriptFormat }\n : {}),\n ...(inlineCssAsset ? { inlineStyle: inlineCssAsset } : {}),\n routes: {\n ...routes,\n [rootRouteId]: mergeRequestAssetsIntoRootRoute(\n rootRoute,\n requestAssets,\n ),\n },\n }\n },\n }\n let _dehydrated = false\n let _serializationFinished = false\n let streamFastPathReserved = false\n const renderFinishedListeners: Array<() => void> = []\n const injectedHtmlListeners: Array<() => void> = []\n const serializationFinishedListeners: Array<() => void> = []\n const cleanupListeners: Array<() => void> = []\n let cleanupStarted = false\n let injectedHtmlBuffer = ''\n\n const callListeners = (listeners: Array<() => void>, errorPrefix: string) => {\n const snapshot = listeners.slice()\n for (const l of snapshot) {\n try {\n l()\n } catch (err) {\n console.error(`${errorPrefix}:`, err)\n }\n }\n }\n\n const removeListener = (\n listeners: Array<() => void>,\n listener: () => void,\n ) => {\n const index = listeners.indexOf(listener)\n if (index >= 0) listeners.splice(index, 1)\n }\n\n const scriptBuffer = new ScriptBuffer((script) => {\n serverSsr.injectScript(script)\n })\n\n const serverSsr: ServerSsr = {\n injectHtml: (html: string) => {\n if (!html || cleanupStarted) return\n // Buffer the HTML so it can be retrieved via takeBufferedHtml()\n injectedHtmlBuffer += html\n callListeners(injectedHtmlListeners, 'SSR injected HTML listener error')\n },\n injectScript: (script: string) => {\n if (!script || cleanupStarted) return\n const html = `<script${router.options.ssr?.nonce ? ` nonce='${router.options.ssr.nonce}'` : ''}>${script}</script>`\n serverSsr.injectHtml(html)\n },\n dehydrate: async (opts?: { requestAssets?: ManifestRouteAssets }) => {\n if (_dehydrated) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error('Invariant failed: router is already dehydrated!')\n }\n\n invariant()\n }\n let matchesToDehydrate = _getRenderedMatches(router.stores.matches.get())\n const isShell = router.isShell()\n if (isShell) {\n // In SPA mode we only want to dehydrate the root match\n matchesToDehydrate = matchesToDehydrate.slice(0, 1)\n }\n const matches = matchesToDehydrate.map(dehydrateMatch)\n\n let manifestToDehydrate: Manifest | undefined = undefined\n // Only currently matched routes are dehydrated. Other route assets are\n // loaded through dynamic imports when those routes become active.\n if (manifest) {\n const cacheKey = getMatchedRoutesCacheKey(matchesToDehydrate)\n const preparedManifest = getPreparedMatchedManifestRoutes(\n manifest,\n matchesToDehydrate,\n cacheKey,\n )\n\n manifestToDehydrate = {\n ...(manifest.scriptFormat\n ? { scriptFormat: manifest.scriptFormat }\n : {}),\n ...(preparedManifest.inlineCssHrefs\n ? { inlineStyle: createInlineCssPlaceholderAsset() }\n : {}),\n routes: preparedManifest.routes,\n }\n\n // Merge request-scoped assets into root route (without mutating cached manifest)\n const requestAssets = opts?.requestAssets\n if (hasRequestAssets(requestAssets)) {\n const existingRoot = manifestToDehydrate.routes[rootRouteId]\n manifestToDehydrate.routes = {\n ...manifestToDehydrate.routes,\n [rootRouteId]: mergeRequestAssetsIntoRootRoute(\n existingRoot,\n requestAssets,\n ),\n }\n }\n }\n const dehydratedRouter: DehydratedRouter = {\n manifest: manifestToDehydrate,\n matches,\n }\n const dehydratedData = await router.options.dehydrate?.()\n if (cleanupStarted) {\n return\n }\n if (dehydratedData) {\n dehydratedRouter.dehydratedData = dehydratedData\n }\n _dehydrated = true\n\n const trackPlugins = { didRun: false }\n const serializationAdapters = router.options.serializationAdapters as\n | Array<AnySerializationAdapter>\n | undefined\n const plugins = serializationAdapters\n ? serializationAdapters\n .map((t) => makeSsrSerovalPlugin(t, trackPlugins))\n .concat(defaultSerovalPlugins)\n : defaultSerovalPlugins\n\n let serializationCompleteSignaled = false\n const signalSerializationComplete = () => {\n if (serializationCompleteSignaled || cleanupStarted) return\n serializationCompleteSignaled = true\n _serializationFinished = true\n\n const listeners = serializationFinishedListeners.slice()\n serializationFinishedListeners.length = 0\n\n for (const l of listeners) {\n try {\n l()\n } catch (err) {\n console.error('Serialization listener error:', err)\n }\n }\n }\n\n const finishScriptSerialization = () => {\n if (serializationCompleteSignaled || cleanupStarted) return\n scriptBuffer.enqueue(GLOBAL_TSR + '.e()')\n // Must synchronously notify injected HTML listeners before signaling\n // completion; otherwise the held </body> tail could flush ahead of the\n // end script.\n scriptBuffer.flush()\n signalSerializationComplete()\n }\n\n crossSerializeStream(dehydratedRouter, {\n refs: new Map(),\n plugins,\n onSerialize: (data, initial) => {\n let serialized = initial ? TSR_PREFIX + data : data\n if (trackPlugins.didRun) {\n serialized = P_PREFIX + serialized + P_SUFFIX\n }\n scriptBuffer.enqueue(serialized)\n },\n onError: (err: unknown) => {\n console.error('Serialization error:', err)\n if (err && (err as any).stack) {\n console.error((err as any).stack)\n }\n finishScriptSerialization()\n },\n scopeId: SCOPE_ID,\n onDone: () => {\n finishScriptSerialization()\n },\n })\n },\n isDehydrated() {\n return _dehydrated\n },\n isSerializationFinished() {\n return _serializationFinished\n },\n reserveStreamFastPath() {\n if (\n !cleanupStarted &&\n _serializationFinished &&\n !streamFastPathReserved &&\n renderFinishedListeners.length === 0 &&\n !injectedHtmlBuffer &&\n !scriptBuffer.hasPending()\n ) {\n streamFastPathReserved = true\n return true\n }\n return false\n },\n onInjectedHtml: (listener) => {\n if (cleanupStarted) return () => {}\n injectedHtmlListeners.push(listener)\n return () => removeListener(injectedHtmlListeners, listener)\n },\n onRenderFinished: (listener) => {\n if (cleanupStarted || streamFastPathReserved) return\n renderFinishedListeners.push(listener)\n },\n onSerializationFinished: (listener) => {\n if (cleanupStarted) return () => {}\n if (_serializationFinished && !cleanupStarted) {\n try {\n listener()\n } catch (err) {\n console.error('Serialization listener error:', err)\n }\n return () => {}\n }\n serializationFinishedListeners.push(listener)\n return () => removeListener(serializationFinishedListeners, listener)\n },\n onCleanup: (listener) => {\n if (cleanupStarted) return\n cleanupListeners.push(listener)\n },\n setRenderFinished: () => {\n if (cleanupStarted) return\n scriptBuffer.liftBarrier()\n const listeners = renderFinishedListeners.slice()\n renderFinishedListeners.length = 0\n for (const l of listeners) {\n try {\n l()\n } catch (err) {\n console.error('Error in render finished listener:', err)\n }\n }\n if (_serializationFinished) {\n scriptBuffer.flush()\n }\n },\n takeBufferedScripts() {\n const scripts = scriptBuffer.takeAll()\n if (!scripts) return undefined\n const serverBufferedScript: RouterManagedTag = {\n tag: 'script',\n attrs: {\n nonce: router.options.ssr?.nonce,\n className: '$tsr',\n id: TSR_SCRIPT_BARRIER_ID,\n },\n children: scripts,\n }\n return serverBufferedScript\n },\n liftScriptBarrier() {\n scriptBuffer.liftBarrier()\n },\n takeBufferedHtml() {\n if (!injectedHtmlBuffer) {\n return undefined\n }\n const buffered = injectedHtmlBuffer\n injectedHtmlBuffer = ''\n return buffered\n },\n cleanup() {\n // Guard against multiple/reentrant cleanup calls. A listener could call\n // cleanup() again indirectly; snapshot + clear before invoking so each\n // listener runs exactly once and reentry is a no-op.\n if (cleanupStarted) return\n cleanupStarted = true\n const listeners = cleanupListeners.slice()\n cleanupListeners.length = 0\n for (const l of listeners) {\n try {\n l()\n } catch (err) {\n console.error('Error in SSR cleanup listener:', err)\n }\n }\n renderFinishedListeners.length = 0\n injectedHtmlListeners.length = 0\n serializationFinishedListeners.length = 0\n injectedHtmlBuffer = ''\n scriptBuffer.cleanup()\n router.serverSsr = undefined\n },\n }\n\n router.serverSsr = serverSsr\n for (const listener of router.serverSsrLifecycle?.onServerSsrAttach ?? []) {\n try {\n listener(serverSsr)\n } catch (err) {\n console.error('SSR attach listener error:', err)\n }\n }\n}\n\n/**\n * Get the origin for the request.\n *\n * SECURITY: We intentionally do NOT trust the Origin header for determining\n * the router's origin. The Origin header can be spoofed by attackers, which\n * could lead to SSRF-like vulnerabilities where redirects are constructed\n * using a malicious origin (CVE-2024-34351).\n *\n * Instead, we derive the origin from request.url, which is typically set by\n * the server infrastructure (not client-controlled headers).\n *\n * For applications behind proxies that need to trust forwarded headers,\n * use the router's `origin` option to explicitly configure a trusted origin.\n */\nexport function getOrigin(request: Request) {\n try {\n return new URL(request.url).origin\n } catch {}\n return 'http://localhost'\n}\n\n// server and browser can decode/encode characters differently in paths and search params.\n// Server generally strictly follows the WHATWG URL Standard, while browsers may differ for legacy reasons.\n// for example, in paths \"|\" is not encoded on the server but is encoded on chromium (and not on firefox) while \"대\" is encoded on both sides.\n// Another anomaly is that in Node new URLSearchParams and new URL also decode/encode characters differently.\n// new URLSearchParams() encodes \"|\" while new URL() does not, and in this instance\n// chromium treats search params differently than paths, i.e. \"|\" is not encoded in search params.\nexport function getNormalizedURL(url: string | URL, base?: string | URL) {\n // ensure backslashes are encoded correctly in the URL\n if (typeof url === 'string') url = url.replace('\\\\', '%5C')\n\n const rawUrl = new URL(url, base)\n const { path: decodedPathname, handledProtocolRelativeURL } = decodePath(\n rawUrl.pathname,\n )\n const searchParams = new URLSearchParams(rawUrl.search)\n const normalizedHref =\n decodedPathname +\n (searchParams.size > 0 ? '?' : '') +\n searchParams.toString() +\n rawUrl.hash\n\n return {\n url: new URL(normalizedHref, rawUrl.origin),\n handledProtocolRelativeURL,\n }\n}\n"],"mappings":"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"}
@@ -99,6 +99,16 @@ function createAbortNotifier(opts) {
99
99
  } catch {}
100
100
  };
101
101
  }
102
+ function listenToAbort(signal, onAbort) {
103
+ if (!signal) return;
104
+ if (signal.aborted) {
105
+ onAbort(signal.reason);
106
+ return;
107
+ }
108
+ const listener = () => onAbort(signal.reason);
109
+ signal.addEventListener("abort", listener, { once: true });
110
+ return () => signal.removeEventListener("abort", listener);
111
+ }
102
112
  function transformStreamWithRouter(router, appStream, opts) {
103
113
  const serverSsr = router.serverSsr;
104
114
  if (!serverSsr) throw new Error("Invariant failed: router.serverSsr is required");
@@ -110,6 +120,7 @@ function makeFastPathStream(appStream, opts, serverSsr) {
110
120
  let controller;
111
121
  let state = MergeState.ReadingBody;
112
122
  let lifetimeTimeoutHandle;
123
+ let stopListeningToAbort;
113
124
  let stopListeningToInjectedHtml;
114
125
  const readerState = createReaderState(appStream);
115
126
  const notifyAbort = createAbortNotifier(opts);
@@ -134,6 +145,8 @@ function makeFastPathStream(appStream, opts, serverSsr) {
134
145
  clearTimeout(lifetimeTimeoutHandle);
135
146
  lifetimeTimeoutHandle = void 0;
136
147
  }
148
+ stopListeningToAbort?.();
149
+ stopListeningToAbort = void 0;
137
150
  try {
138
151
  stopListeningToInjectedHtml?.();
139
152
  } catch {}
@@ -175,7 +188,7 @@ function makeFastPathStream(appStream, opts, serverSsr) {
175
188
  cleanup(err);
176
189
  }
177
190
  }, lifetimeMs);
178
- return new node_stream_web.ReadableStream({
191
+ const stream = new node_stream_web.ReadableStream({
179
192
  start(c) {
180
193
  controller = c;
181
194
  },
@@ -208,12 +221,18 @@ function makeFastPathStream(appStream, opts, serverSsr) {
208
221
  return cleanup(reason);
209
222
  }
210
223
  });
224
+ stopListeningToAbort = listenToAbort(opts?.signal, (reason) => {
225
+ safeError(reason);
226
+ cleanup(reason);
227
+ });
228
+ return stream;
211
229
  }
212
230
  function makeMainStream(serverSsr, appStream, opts) {
213
231
  let stopListeningToInjectedHtml;
214
232
  let stopListeningToSerializationFinished;
215
233
  let serializationTimeoutHandle;
216
234
  let lifetimeTimeoutHandle;
235
+ let stopListeningToAbort;
217
236
  let cleanedUp = false;
218
237
  let controller;
219
238
  let closeWhenDrained = false;
@@ -312,6 +331,8 @@ function makeMainStream(serverSsr, appStream, opts) {
312
331
  } catch {}
313
332
  stopListeningToInjectedHtml = void 0;
314
333
  stopListeningToSerializationFinished = void 0;
334
+ stopListeningToAbort?.();
335
+ stopListeningToAbort = void 0;
315
336
  if (serializationTimeoutHandle !== void 0) {
316
337
  clearTimeout(serializationTimeoutHandle);
317
338
  serializationTimeoutHandle = void 0;
@@ -496,6 +517,11 @@ function makeMainStream(serverSsr, appStream, opts) {
496
517
  drainRouterHtml();
497
518
  if (cleanedUp || isDone()) return stream;
498
519
  }
520
+ stopListeningToAbort = listenToAbort(opts?.signal, (reason) => {
521
+ safeError(reason);
522
+ cleanup(reason);
523
+ });
524
+ if (cleanedUp || isDone()) return stream;
499
525
  (async () => {
500
526
  try {
501
527
  while (true) {