@tanstack/router-core 1.167.0 → 1.167.2

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 (166) hide show
  1. package/dist/cjs/Matches.cjs +15 -12
  2. package/dist/cjs/Matches.cjs.map +1 -1
  3. package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
  4. package/dist/cjs/config.cjs +9 -8
  5. package/dist/cjs/config.cjs.map +1 -1
  6. package/dist/cjs/defer.cjs +37 -21
  7. package/dist/cjs/defer.cjs.map +1 -1
  8. package/dist/cjs/index.cjs +87 -89
  9. package/dist/cjs/isServer/client.cjs +5 -3
  10. package/dist/cjs/isServer/client.cjs.map +1 -1
  11. package/dist/cjs/isServer/development.cjs +5 -3
  12. package/dist/cjs/isServer/development.cjs.map +1 -1
  13. package/dist/cjs/isServer/server.cjs +5 -3
  14. package/dist/cjs/isServer/server.cjs.map +1 -1
  15. package/dist/cjs/link.cjs +5 -4
  16. package/dist/cjs/link.cjs.map +1 -1
  17. package/dist/cjs/load-matches.cjs +619 -766
  18. package/dist/cjs/load-matches.cjs.map +1 -1
  19. package/dist/cjs/lru-cache.cjs +67 -64
  20. package/dist/cjs/lru-cache.cjs.map +1 -1
  21. package/dist/cjs/new-process-route-tree.cjs +707 -792
  22. package/dist/cjs/new-process-route-tree.cjs.map +1 -1
  23. package/dist/cjs/not-found.cjs +20 -7
  24. package/dist/cjs/not-found.cjs.map +1 -1
  25. package/dist/cjs/path.cjs +221 -232
  26. package/dist/cjs/path.cjs.map +1 -1
  27. package/dist/cjs/qss.cjs +62 -28
  28. package/dist/cjs/qss.cjs.map +1 -1
  29. package/dist/cjs/redirect.cjs +44 -30
  30. package/dist/cjs/redirect.cjs.map +1 -1
  31. package/dist/cjs/rewrite.cjs +56 -56
  32. package/dist/cjs/rewrite.cjs.map +1 -1
  33. package/dist/cjs/root.cjs +6 -4
  34. package/dist/cjs/root.cjs.map +1 -1
  35. package/dist/cjs/route.cjs +96 -105
  36. package/dist/cjs/route.cjs.map +1 -1
  37. package/dist/cjs/router.cjs +1153 -1524
  38. package/dist/cjs/router.cjs.map +1 -1
  39. package/dist/cjs/router.d.cts +2 -0
  40. package/dist/cjs/scroll-restoration.cjs +189 -207
  41. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  42. package/dist/cjs/searchMiddleware.cjs +48 -37
  43. package/dist/cjs/searchMiddleware.cjs.map +1 -1
  44. package/dist/cjs/searchParams.cjs +57 -45
  45. package/dist/cjs/searchParams.cjs.map +1 -1
  46. package/dist/cjs/ssr/client.cjs +6 -8
  47. package/dist/cjs/ssr/constants.cjs +6 -5
  48. package/dist/cjs/ssr/constants.cjs.map +1 -1
  49. package/dist/cjs/ssr/createRequestHandler.cjs +41 -59
  50. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
  51. package/dist/cjs/ssr/handlerCallback.cjs +5 -4
  52. package/dist/cjs/ssr/handlerCallback.cjs.map +1 -1
  53. package/dist/cjs/ssr/headers.cjs +17 -26
  54. package/dist/cjs/ssr/headers.cjs.map +1 -1
  55. package/dist/cjs/ssr/json.cjs +8 -4
  56. package/dist/cjs/ssr/json.cjs.map +1 -1
  57. package/dist/cjs/ssr/serializer/RawStream.cjs +268 -268
  58. package/dist/cjs/ssr/serializer/RawStream.cjs.map +1 -1
  59. package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs +31 -32
  60. package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -1
  61. package/dist/cjs/ssr/serializer/seroval-plugins.cjs +12 -12
  62. package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -1
  63. package/dist/cjs/ssr/serializer/transformer.cjs +45 -41
  64. package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -1
  65. package/dist/cjs/ssr/server.cjs +12 -14
  66. package/dist/cjs/ssr/ssr-client.cjs +173 -211
  67. package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
  68. package/dist/cjs/ssr/ssr-match-id.cjs +6 -5
  69. package/dist/cjs/ssr/ssr-match-id.cjs.map +1 -1
  70. package/dist/cjs/ssr/ssr-server.cjs +266 -300
  71. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  72. package/dist/cjs/ssr/transformStreamWithRouter.cjs +317 -337
  73. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
  74. package/dist/cjs/ssr/tsrScript.cjs +6 -4
  75. package/dist/cjs/ssr/tsrScript.cjs.map +1 -1
  76. package/dist/cjs/ssr/tsrScript.d.cts +1 -0
  77. package/dist/cjs/utils/batch.cjs +13 -13
  78. package/dist/cjs/utils/batch.cjs.map +1 -1
  79. package/dist/cjs/utils.cjs +274 -208
  80. package/dist/cjs/utils.cjs.map +1 -1
  81. package/dist/esm/Matches.js +16 -13
  82. package/dist/esm/Matches.js.map +1 -1
  83. package/dist/esm/config.js +10 -9
  84. package/dist/esm/config.js.map +1 -1
  85. package/dist/esm/defer.js +37 -22
  86. package/dist/esm/defer.js.map +1 -1
  87. package/dist/esm/index.js +12 -82
  88. package/dist/esm/isServer/client.js +6 -5
  89. package/dist/esm/isServer/client.js.map +1 -1
  90. package/dist/esm/isServer/development.js +6 -5
  91. package/dist/esm/isServer/development.js.map +1 -1
  92. package/dist/esm/isServer/server.js +6 -5
  93. package/dist/esm/isServer/server.js.map +1 -1
  94. package/dist/esm/link.js +6 -5
  95. package/dist/esm/link.js.map +1 -1
  96. package/dist/esm/load-matches.js +614 -765
  97. package/dist/esm/load-matches.js.map +1 -1
  98. package/dist/esm/lru-cache.js +68 -65
  99. package/dist/esm/lru-cache.js.map +1 -1
  100. package/dist/esm/new-process-route-tree.js +705 -797
  101. package/dist/esm/new-process-route-tree.js.map +1 -1
  102. package/dist/esm/not-found.js +21 -9
  103. package/dist/esm/not-found.js.map +1 -1
  104. package/dist/esm/path.js +220 -241
  105. package/dist/esm/path.js.map +1 -1
  106. package/dist/esm/qss.js +63 -30
  107. package/dist/esm/qss.js.map +1 -1
  108. package/dist/esm/redirect.js +45 -34
  109. package/dist/esm/redirect.js.map +1 -1
  110. package/dist/esm/rewrite.js +57 -60
  111. package/dist/esm/rewrite.js.map +1 -1
  112. package/dist/esm/root.js +7 -5
  113. package/dist/esm/root.js.map +1 -1
  114. package/dist/esm/route.js +92 -105
  115. package/dist/esm/route.js.map +1 -1
  116. package/dist/esm/router.d.ts +2 -0
  117. package/dist/esm/router.js +1147 -1527
  118. package/dist/esm/router.js.map +1 -1
  119. package/dist/esm/scroll-restoration.js +188 -213
  120. package/dist/esm/scroll-restoration.js.map +1 -1
  121. package/dist/esm/searchMiddleware.js +48 -38
  122. package/dist/esm/searchMiddleware.js.map +1 -1
  123. package/dist/esm/searchParams.js +57 -48
  124. package/dist/esm/searchParams.js.map +1 -1
  125. package/dist/esm/ssr/client.js +1 -6
  126. package/dist/esm/ssr/constants.js +7 -7
  127. package/dist/esm/ssr/constants.js.map +1 -1
  128. package/dist/esm/ssr/createRequestHandler.js +39 -58
  129. package/dist/esm/ssr/createRequestHandler.js.map +1 -1
  130. package/dist/esm/ssr/handlerCallback.js +6 -5
  131. package/dist/esm/ssr/handlerCallback.js.map +1 -1
  132. package/dist/esm/ssr/headers.js +16 -26
  133. package/dist/esm/ssr/headers.js.map +1 -1
  134. package/dist/esm/ssr/json.js +9 -5
  135. package/dist/esm/ssr/json.js.map +1 -1
  136. package/dist/esm/ssr/serializer/RawStream.js +267 -273
  137. package/dist/esm/ssr/serializer/RawStream.js.map +1 -1
  138. package/dist/esm/ssr/serializer/ShallowErrorPlugin.js +31 -32
  139. package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -1
  140. package/dist/esm/ssr/serializer/seroval-plugins.js +10 -11
  141. package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -1
  142. package/dist/esm/ssr/serializer/transformer.js +44 -43
  143. package/dist/esm/ssr/serializer/transformer.js.map +1 -1
  144. package/dist/esm/ssr/server.js +2 -12
  145. package/dist/esm/ssr/ssr-client.js +169 -209
  146. package/dist/esm/ssr/ssr-client.js.map +1 -1
  147. package/dist/esm/ssr/ssr-match-id.js +7 -7
  148. package/dist/esm/ssr/ssr-match-id.js.map +1 -1
  149. package/dist/esm/ssr/ssr-server.js +262 -300
  150. package/dist/esm/ssr/ssr-server.js.map +1 -1
  151. package/dist/esm/ssr/transformStreamWithRouter.js +315 -338
  152. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
  153. package/dist/esm/ssr/tsrScript.js +6 -5
  154. package/dist/esm/ssr/tsrScript.js.map +1 -1
  155. package/dist/esm/utils/batch.js +13 -14
  156. package/dist/esm/utils/batch.js.map +1 -1
  157. package/dist/esm/utils.js +273 -224
  158. package/dist/esm/utils.js.map +1 -1
  159. package/package.json +2 -2
  160. package/src/router.ts +2 -0
  161. package/dist/cjs/index.cjs.map +0 -1
  162. package/dist/cjs/ssr/client.cjs.map +0 -1
  163. package/dist/cjs/ssr/server.cjs.map +0 -1
  164. package/dist/esm/index.js.map +0 -1
  165. package/dist/esm/ssr/client.js.map +0 -1
  166. package/dist/esm/ssr/server.js.map +0 -1
@@ -1,312 +1,278 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const seroval = require("seroval");
4
- const invariant = require("tiny-invariant");
5
- const utils = require("../utils.cjs");
6
- const lruCache = require("../lru-cache.cjs");
7
- const tsrScript = require("./tsrScript.cjs");
8
- const constants = require("./constants.cjs");
9
- const ssrMatchId = require("./ssr-match-id.cjs");
10
- const serovalPlugins = require("./serializer/seroval-plugins.cjs");
11
- const transformer = require("./serializer/transformer.cjs");
12
- const SCOPE_ID = "tsr";
13
- const TSR_PREFIX = constants.GLOBAL_TSR + ".router=";
14
- const P_PREFIX = constants.GLOBAL_TSR + ".p(()=>";
15
- const P_SUFFIX = ")";
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_utils = require("../utils.cjs");
3
+ const require_lru_cache = require("../lru-cache.cjs");
4
+ const require_constants = require("./constants.cjs");
5
+ const require_transformer = require("./serializer/transformer.cjs");
6
+ const require_seroval_plugins = require("./serializer/seroval-plugins.cjs");
7
+ const require_ssr_match_id = require("./ssr-match-id.cjs");
8
+ const require_tsrScript = require("./tsrScript.cjs");
9
+ let tiny_invariant = require("tiny-invariant");
10
+ tiny_invariant = require_runtime.__toESM(tiny_invariant);
11
+ let seroval = require("seroval");
12
+ //#region src/ssr/ssr-server.ts
13
+ var SCOPE_ID = "tsr";
14
+ var TSR_PREFIX = require_constants.GLOBAL_TSR + ".router=";
15
+ var P_PREFIX = require_constants.GLOBAL_TSR + ".p(()=>";
16
+ var P_SUFFIX = ")";
16
17
  function dehydrateMatch(match) {
17
- const dehydratedMatch = {
18
- i: ssrMatchId.dehydrateSsrMatchId(match.id),
19
- u: match.updatedAt,
20
- s: match.status
21
- };
22
- const properties = [
23
- ["__beforeLoadContext", "b"],
24
- ["loaderData", "l"],
25
- ["error", "e"],
26
- ["ssr", "ssr"]
27
- ];
28
- for (const [key, shorthand] of properties) {
29
- if (match[key] !== void 0) {
30
- dehydratedMatch[shorthand] = match[key];
31
- }
32
- }
33
- if (match.globalNotFound) {
34
- dehydratedMatch.g = true;
35
- }
36
- return dehydratedMatch;
18
+ const dehydratedMatch = {
19
+ i: require_ssr_match_id.dehydrateSsrMatchId(match.id),
20
+ u: match.updatedAt,
21
+ s: match.status
22
+ };
23
+ for (const [key, shorthand] of [
24
+ ["__beforeLoadContext", "b"],
25
+ ["loaderData", "l"],
26
+ ["error", "e"],
27
+ ["ssr", "ssr"]
28
+ ]) if (match[key] !== void 0) dehydratedMatch[shorthand] = match[key];
29
+ if (match.globalNotFound) dehydratedMatch.g = true;
30
+ return dehydratedMatch;
37
31
  }
38
- const INITIAL_SCRIPTS = [
39
- seroval.getCrossReferenceHeader(SCOPE_ID),
40
- tsrScript
41
- ];
42
- class ScriptBuffer {
43
- constructor(router) {
44
- this._scriptBarrierLifted = false;
45
- this._cleanedUp = false;
46
- this._pendingMicrotask = false;
47
- this.router = router;
48
- this._queue = INITIAL_SCRIPTS.slice();
49
- }
50
- enqueue(script) {
51
- if (this._cleanedUp) return;
52
- this._queue.push(script);
53
- if (this._scriptBarrierLifted && !this._pendingMicrotask) {
54
- this._pendingMicrotask = true;
55
- queueMicrotask(() => {
56
- this._pendingMicrotask = false;
57
- this.injectBufferedScripts();
58
- });
59
- }
60
- }
61
- liftBarrier() {
62
- if (this._scriptBarrierLifted || this._cleanedUp) return;
63
- this._scriptBarrierLifted = true;
64
- if (this._queue.length > 0 && !this._pendingMicrotask) {
65
- this._pendingMicrotask = true;
66
- queueMicrotask(() => {
67
- this._pendingMicrotask = false;
68
- this.injectBufferedScripts();
69
- });
70
- }
71
- }
72
- /**
73
- * Flushes any pending scripts synchronously.
74
- * Call this before emitting onSerializationFinished to ensure all scripts are injected.
75
- *
76
- * IMPORTANT: Only injects if the barrier has been lifted. Before the barrier is lifted,
77
- * scripts should remain in the queue so takeBufferedScripts() can retrieve them
78
- */
79
- flush() {
80
- if (!this._scriptBarrierLifted) return;
81
- if (this._cleanedUp) return;
82
- this._pendingMicrotask = false;
83
- const scriptsToInject = this.takeAll();
84
- if (scriptsToInject && this.router?.serverSsr) {
85
- this.router.serverSsr.injectScript(scriptsToInject);
86
- }
87
- }
88
- takeAll() {
89
- const bufferedScripts = this._queue;
90
- this._queue = [];
91
- if (bufferedScripts.length === 0) {
92
- return void 0;
93
- }
94
- if (bufferedScripts.length === 1) {
95
- return bufferedScripts[0] + ";document.currentScript.remove()";
96
- }
97
- return bufferedScripts.join(";") + ";document.currentScript.remove()";
98
- }
99
- injectBufferedScripts() {
100
- if (this._cleanedUp) return;
101
- if (this._queue.length === 0) return;
102
- const scriptsToInject = this.takeAll();
103
- if (scriptsToInject && this.router?.serverSsr) {
104
- this.router.serverSsr.injectScript(scriptsToInject);
105
- }
106
- }
107
- cleanup() {
108
- this._cleanedUp = true;
109
- this._queue = [];
110
- this.router = void 0;
111
- }
112
- }
113
- const isProd = process.env.NODE_ENV === "production";
114
- const MANIFEST_CACHE_SIZE = 100;
115
- const manifestCaches = /* @__PURE__ */ new WeakMap();
32
+ var INITIAL_SCRIPTS = [(0, seroval.getCrossReferenceHeader)(SCOPE_ID), require_tsrScript.default];
33
+ var ScriptBuffer = class {
34
+ constructor(router) {
35
+ this._scriptBarrierLifted = false;
36
+ this._cleanedUp = false;
37
+ this._pendingMicrotask = false;
38
+ this.router = router;
39
+ this._queue = INITIAL_SCRIPTS.slice();
40
+ }
41
+ enqueue(script) {
42
+ if (this._cleanedUp) return;
43
+ this._queue.push(script);
44
+ if (this._scriptBarrierLifted && !this._pendingMicrotask) {
45
+ this._pendingMicrotask = true;
46
+ queueMicrotask(() => {
47
+ this._pendingMicrotask = false;
48
+ this.injectBufferedScripts();
49
+ });
50
+ }
51
+ }
52
+ liftBarrier() {
53
+ if (this._scriptBarrierLifted || this._cleanedUp) return;
54
+ this._scriptBarrierLifted = true;
55
+ if (this._queue.length > 0 && !this._pendingMicrotask) {
56
+ this._pendingMicrotask = true;
57
+ queueMicrotask(() => {
58
+ this._pendingMicrotask = false;
59
+ this.injectBufferedScripts();
60
+ });
61
+ }
62
+ }
63
+ /**
64
+ * Flushes any pending scripts synchronously.
65
+ * Call this before emitting onSerializationFinished to ensure all scripts are injected.
66
+ *
67
+ * IMPORTANT: Only injects if the barrier has been lifted. Before the barrier is lifted,
68
+ * scripts should remain in the queue so takeBufferedScripts() can retrieve them
69
+ */
70
+ flush() {
71
+ if (!this._scriptBarrierLifted) return;
72
+ if (this._cleanedUp) return;
73
+ this._pendingMicrotask = false;
74
+ const scriptsToInject = this.takeAll();
75
+ if (scriptsToInject && this.router?.serverSsr) this.router.serverSsr.injectScript(scriptsToInject);
76
+ }
77
+ takeAll() {
78
+ const bufferedScripts = this._queue;
79
+ this._queue = [];
80
+ if (bufferedScripts.length === 0) return;
81
+ if (bufferedScripts.length === 1) return bufferedScripts[0] + ";document.currentScript.remove()";
82
+ return bufferedScripts.join(";") + ";document.currentScript.remove()";
83
+ }
84
+ injectBufferedScripts() {
85
+ if (this._cleanedUp) return;
86
+ if (this._queue.length === 0) return;
87
+ const scriptsToInject = this.takeAll();
88
+ if (scriptsToInject && this.router?.serverSsr) this.router.serverSsr.injectScript(scriptsToInject);
89
+ }
90
+ cleanup() {
91
+ this._cleanedUp = true;
92
+ this._queue = [];
93
+ this.router = void 0;
94
+ }
95
+ };
96
+ var isProd = process.env.NODE_ENV === "production";
97
+ var MANIFEST_CACHE_SIZE = 100;
98
+ var manifestCaches = /* @__PURE__ */ new WeakMap();
116
99
  function getManifestCache(manifest) {
117
- const cache = manifestCaches.get(manifest);
118
- if (cache) return cache;
119
- const newCache = lruCache.createLRUCache(MANIFEST_CACHE_SIZE);
120
- manifestCaches.set(manifest, newCache);
121
- return newCache;
100
+ const cache = manifestCaches.get(manifest);
101
+ if (cache) return cache;
102
+ const newCache = require_lru_cache.createLRUCache(MANIFEST_CACHE_SIZE);
103
+ manifestCaches.set(manifest, newCache);
104
+ return newCache;
122
105
  }
123
- function attachRouterServerSsrUtils({
124
- router,
125
- manifest
126
- }) {
127
- router.ssr = {
128
- manifest
129
- };
130
- let _dehydrated = false;
131
- let _serializationFinished = false;
132
- const renderFinishedListeners = [];
133
- const serializationFinishedListeners = [];
134
- const scriptBuffer = new ScriptBuffer(router);
135
- let injectedHtmlBuffer = "";
136
- router.serverSsr = {
137
- injectHtml: (html) => {
138
- if (!html) return;
139
- injectedHtmlBuffer += html;
140
- router.emit({
141
- type: "onInjectedHtml"
142
- });
143
- },
144
- injectScript: (script) => {
145
- if (!script) return;
146
- const html = `<script${router.options.ssr?.nonce ? ` nonce='${router.options.ssr.nonce}'` : ""}>${script}<\/script>`;
147
- router.serverSsr.injectHtml(html);
148
- },
149
- dehydrate: async () => {
150
- invariant(!_dehydrated, "router is already dehydrated!");
151
- let matchesToDehydrate = router.state.matches;
152
- if (router.isShell()) {
153
- matchesToDehydrate = matchesToDehydrate.slice(0, 1);
154
- }
155
- const matches = matchesToDehydrate.map(dehydrateMatch);
156
- let manifestToDehydrate = void 0;
157
- if (manifest) {
158
- const currentRouteIdsList = matchesToDehydrate.map((m) => m.routeId);
159
- const manifestCacheKey = currentRouteIdsList.join("\0");
160
- let filteredRoutes;
161
- if (isProd) {
162
- filteredRoutes = getManifestCache(manifest).get(manifestCacheKey);
163
- }
164
- if (!filteredRoutes) {
165
- const currentRouteIds = new Set(currentRouteIdsList);
166
- const nextFilteredRoutes = {};
167
- for (const routeId in manifest.routes) {
168
- const routeManifest = manifest.routes[routeId];
169
- if (currentRouteIds.has(routeId)) {
170
- nextFilteredRoutes[routeId] = routeManifest;
171
- } else if (routeManifest.assets && routeManifest.assets.length > 0) {
172
- nextFilteredRoutes[routeId] = {
173
- assets: routeManifest.assets
174
- };
175
- }
176
- }
177
- if (isProd) {
178
- getManifestCache(manifest).set(manifestCacheKey, nextFilteredRoutes);
179
- }
180
- filteredRoutes = nextFilteredRoutes;
181
- }
182
- manifestToDehydrate = {
183
- routes: filteredRoutes
184
- };
185
- }
186
- const dehydratedRouter = {
187
- manifest: manifestToDehydrate,
188
- matches
189
- };
190
- const lastMatchId = matchesToDehydrate[matchesToDehydrate.length - 1]?.id;
191
- if (lastMatchId) {
192
- dehydratedRouter.lastMatchId = ssrMatchId.dehydrateSsrMatchId(lastMatchId);
193
- }
194
- const dehydratedData = await router.options.dehydrate?.();
195
- if (dehydratedData) {
196
- dehydratedRouter.dehydratedData = dehydratedData;
197
- }
198
- _dehydrated = true;
199
- const trackPlugins = { didRun: false };
200
- const serializationAdapters = router.options.serializationAdapters;
201
- const plugins = serializationAdapters ? serializationAdapters.map((t) => transformer.makeSsrSerovalPlugin(t, trackPlugins)).concat(serovalPlugins.defaultSerovalPlugins) : serovalPlugins.defaultSerovalPlugins;
202
- const signalSerializationComplete = () => {
203
- _serializationFinished = true;
204
- try {
205
- serializationFinishedListeners.forEach((l) => l());
206
- router.emit({ type: "onSerializationFinished" });
207
- } catch (err) {
208
- console.error("Serialization listener error:", err);
209
- } finally {
210
- serializationFinishedListeners.length = 0;
211
- renderFinishedListeners.length = 0;
212
- }
213
- };
214
- seroval.crossSerializeStream(dehydratedRouter, {
215
- refs: /* @__PURE__ */ new Map(),
216
- plugins,
217
- onSerialize: (data, initial) => {
218
- let serialized = initial ? TSR_PREFIX + data : data;
219
- if (trackPlugins.didRun) {
220
- serialized = P_PREFIX + serialized + P_SUFFIX;
221
- }
222
- scriptBuffer.enqueue(serialized);
223
- },
224
- scopeId: SCOPE_ID,
225
- onDone: () => {
226
- scriptBuffer.enqueue(constants.GLOBAL_TSR + ".e()");
227
- scriptBuffer.flush();
228
- signalSerializationComplete();
229
- },
230
- onError: (err) => {
231
- console.error("Serialization error:", err);
232
- signalSerializationComplete();
233
- }
234
- });
235
- },
236
- isDehydrated() {
237
- return _dehydrated;
238
- },
239
- isSerializationFinished() {
240
- return _serializationFinished;
241
- },
242
- onRenderFinished: (listener) => renderFinishedListeners.push(listener),
243
- onSerializationFinished: (listener) => serializationFinishedListeners.push(listener),
244
- setRenderFinished: () => {
245
- try {
246
- renderFinishedListeners.forEach((l) => l());
247
- } catch (err) {
248
- console.error("Error in render finished listener:", err);
249
- } finally {
250
- renderFinishedListeners.length = 0;
251
- }
252
- scriptBuffer.liftBarrier();
253
- },
254
- takeBufferedScripts() {
255
- const scripts = scriptBuffer.takeAll();
256
- const serverBufferedScript = {
257
- tag: "script",
258
- attrs: {
259
- nonce: router.options.ssr?.nonce,
260
- className: "$tsr",
261
- id: constants.TSR_SCRIPT_BARRIER_ID
262
- },
263
- children: scripts
264
- };
265
- return serverBufferedScript;
266
- },
267
- liftScriptBarrier() {
268
- scriptBuffer.liftBarrier();
269
- },
270
- takeBufferedHtml() {
271
- if (!injectedHtmlBuffer) {
272
- return void 0;
273
- }
274
- const buffered = injectedHtmlBuffer;
275
- injectedHtmlBuffer = "";
276
- return buffered;
277
- },
278
- cleanup() {
279
- if (!router.serverSsr) return;
280
- renderFinishedListeners.length = 0;
281
- serializationFinishedListeners.length = 0;
282
- injectedHtmlBuffer = "";
283
- scriptBuffer.cleanup();
284
- router.serverSsr = void 0;
285
- }
286
- };
106
+ function attachRouterServerSsrUtils({ router, manifest }) {
107
+ router.ssr = { manifest };
108
+ let _dehydrated = false;
109
+ let _serializationFinished = false;
110
+ const renderFinishedListeners = [];
111
+ const serializationFinishedListeners = [];
112
+ const scriptBuffer = new ScriptBuffer(router);
113
+ let injectedHtmlBuffer = "";
114
+ router.serverSsr = {
115
+ injectHtml: (html) => {
116
+ if (!html) return;
117
+ injectedHtmlBuffer += html;
118
+ router.emit({ type: "onInjectedHtml" });
119
+ },
120
+ injectScript: (script) => {
121
+ if (!script) return;
122
+ const html = `<script${router.options.ssr?.nonce ? ` nonce='${router.options.ssr.nonce}'` : ""}>${script}<\/script>`;
123
+ router.serverSsr.injectHtml(html);
124
+ },
125
+ dehydrate: async () => {
126
+ (0, tiny_invariant.default)(!_dehydrated, "router is already dehydrated!");
127
+ let matchesToDehydrate = router.state.matches;
128
+ if (router.isShell()) matchesToDehydrate = matchesToDehydrate.slice(0, 1);
129
+ const matches = matchesToDehydrate.map(dehydrateMatch);
130
+ let manifestToDehydrate = void 0;
131
+ if (manifest) {
132
+ const currentRouteIdsList = matchesToDehydrate.map((m) => m.routeId);
133
+ const manifestCacheKey = currentRouteIdsList.join("\0");
134
+ let filteredRoutes;
135
+ if (isProd) filteredRoutes = getManifestCache(manifest).get(manifestCacheKey);
136
+ if (!filteredRoutes) {
137
+ const currentRouteIds = new Set(currentRouteIdsList);
138
+ const nextFilteredRoutes = {};
139
+ for (const routeId in manifest.routes) {
140
+ const routeManifest = manifest.routes[routeId];
141
+ if (currentRouteIds.has(routeId)) nextFilteredRoutes[routeId] = routeManifest;
142
+ else if (routeManifest.assets && routeManifest.assets.length > 0) nextFilteredRoutes[routeId] = { assets: routeManifest.assets };
143
+ }
144
+ if (isProd) getManifestCache(manifest).set(manifestCacheKey, nextFilteredRoutes);
145
+ filteredRoutes = nextFilteredRoutes;
146
+ }
147
+ manifestToDehydrate = { routes: filteredRoutes };
148
+ }
149
+ const dehydratedRouter = {
150
+ manifest: manifestToDehydrate,
151
+ matches
152
+ };
153
+ const lastMatchId = matchesToDehydrate[matchesToDehydrate.length - 1]?.id;
154
+ if (lastMatchId) dehydratedRouter.lastMatchId = require_ssr_match_id.dehydrateSsrMatchId(lastMatchId);
155
+ const dehydratedData = await router.options.dehydrate?.();
156
+ if (dehydratedData) dehydratedRouter.dehydratedData = dehydratedData;
157
+ _dehydrated = true;
158
+ const trackPlugins = { didRun: false };
159
+ const serializationAdapters = router.options.serializationAdapters;
160
+ const plugins = serializationAdapters ? serializationAdapters.map((t) => require_transformer.makeSsrSerovalPlugin(t, trackPlugins)).concat(require_seroval_plugins.defaultSerovalPlugins) : require_seroval_plugins.defaultSerovalPlugins;
161
+ const signalSerializationComplete = () => {
162
+ _serializationFinished = true;
163
+ try {
164
+ serializationFinishedListeners.forEach((l) => l());
165
+ router.emit({ type: "onSerializationFinished" });
166
+ } catch (err) {
167
+ console.error("Serialization listener error:", err);
168
+ } finally {
169
+ serializationFinishedListeners.length = 0;
170
+ renderFinishedListeners.length = 0;
171
+ }
172
+ };
173
+ (0, seroval.crossSerializeStream)(dehydratedRouter, {
174
+ refs: /* @__PURE__ */ new Map(),
175
+ plugins,
176
+ onSerialize: (data, initial) => {
177
+ let serialized = initial ? TSR_PREFIX + data : data;
178
+ if (trackPlugins.didRun) serialized = P_PREFIX + serialized + P_SUFFIX;
179
+ scriptBuffer.enqueue(serialized);
180
+ },
181
+ scopeId: SCOPE_ID,
182
+ onDone: () => {
183
+ scriptBuffer.enqueue(require_constants.GLOBAL_TSR + ".e()");
184
+ scriptBuffer.flush();
185
+ signalSerializationComplete();
186
+ },
187
+ onError: (err) => {
188
+ console.error("Serialization error:", err);
189
+ signalSerializationComplete();
190
+ }
191
+ });
192
+ },
193
+ isDehydrated() {
194
+ return _dehydrated;
195
+ },
196
+ isSerializationFinished() {
197
+ return _serializationFinished;
198
+ },
199
+ onRenderFinished: (listener) => renderFinishedListeners.push(listener),
200
+ onSerializationFinished: (listener) => serializationFinishedListeners.push(listener),
201
+ setRenderFinished: () => {
202
+ try {
203
+ renderFinishedListeners.forEach((l) => l());
204
+ } catch (err) {
205
+ console.error("Error in render finished listener:", err);
206
+ } finally {
207
+ renderFinishedListeners.length = 0;
208
+ }
209
+ scriptBuffer.liftBarrier();
210
+ },
211
+ takeBufferedScripts() {
212
+ const scripts = scriptBuffer.takeAll();
213
+ return {
214
+ tag: "script",
215
+ attrs: {
216
+ nonce: router.options.ssr?.nonce,
217
+ className: "$tsr",
218
+ id: require_constants.TSR_SCRIPT_BARRIER_ID
219
+ },
220
+ children: scripts
221
+ };
222
+ },
223
+ liftScriptBarrier() {
224
+ scriptBuffer.liftBarrier();
225
+ },
226
+ takeBufferedHtml() {
227
+ if (!injectedHtmlBuffer) return;
228
+ const buffered = injectedHtmlBuffer;
229
+ injectedHtmlBuffer = "";
230
+ return buffered;
231
+ },
232
+ cleanup() {
233
+ if (!router.serverSsr) return;
234
+ renderFinishedListeners.length = 0;
235
+ serializationFinishedListeners.length = 0;
236
+ injectedHtmlBuffer = "";
237
+ scriptBuffer.cleanup();
238
+ router.serverSsr = void 0;
239
+ }
240
+ };
287
241
  }
242
+ /**
243
+ * Get the origin for the request.
244
+ *
245
+ * SECURITY: We intentionally do NOT trust the Origin header for determining
246
+ * the router's origin. The Origin header can be spoofed by attackers, which
247
+ * could lead to SSRF-like vulnerabilities where redirects are constructed
248
+ * using a malicious origin (CVE-2024-34351).
249
+ *
250
+ * Instead, we derive the origin from request.url, which is typically set by
251
+ * the server infrastructure (not client-controlled headers).
252
+ *
253
+ * For applications behind proxies that need to trust forwarded headers,
254
+ * use the router's `origin` option to explicitly configure a trusted origin.
255
+ */
288
256
  function getOrigin(request) {
289
- try {
290
- return new URL(request.url).origin;
291
- } catch {
292
- }
293
- return "http://localhost";
257
+ try {
258
+ return new URL(request.url).origin;
259
+ } catch {}
260
+ return "http://localhost";
294
261
  }
295
262
  function getNormalizedURL(url, base) {
296
- if (typeof url === "string") url = url.replace("\\", "%5C");
297
- const rawUrl = new URL(url, base);
298
- const { path: decodedPathname, handledProtocolRelativeURL } = utils.decodePath(
299
- rawUrl.pathname
300
- );
301
- const searchParams = new URLSearchParams(rawUrl.search);
302
- const normalizedHref = decodedPathname + (searchParams.size > 0 ? "?" : "") + searchParams.toString() + rawUrl.hash;
303
- return {
304
- url: new URL(normalizedHref, rawUrl.origin),
305
- handledProtocolRelativeURL
306
- };
263
+ if (typeof url === "string") url = url.replace("\\", "%5C");
264
+ const rawUrl = new URL(url, base);
265
+ const { path: decodedPathname, handledProtocolRelativeURL } = require_utils.decodePath(rawUrl.pathname);
266
+ const searchParams = new URLSearchParams(rawUrl.search);
267
+ const normalizedHref = decodedPathname + (searchParams.size > 0 ? "?" : "") + searchParams.toString() + rawUrl.hash;
268
+ return {
269
+ url: new URL(normalizedHref, rawUrl.origin),
270
+ handledProtocolRelativeURL
271
+ };
307
272
  }
273
+ //#endregion
308
274
  exports.attachRouterServerSsrUtils = attachRouterServerSsrUtils;
309
- exports.dehydrateMatch = dehydrateMatch;
310
275
  exports.getNormalizedURL = getNormalizedURL;
311
276
  exports.getOrigin = getOrigin;
312
- //# sourceMappingURL=ssr-server.cjs.map
277
+
278
+ //# sourceMappingURL=ssr-server.cjs.map