@tanstack/router-core 1.167.1 → 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.
- package/dist/cjs/Matches.cjs +15 -12
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/cjs/config.cjs +9 -8
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/defer.cjs +37 -21
- package/dist/cjs/defer.cjs.map +1 -1
- package/dist/cjs/index.cjs +87 -89
- package/dist/cjs/isServer/client.cjs +5 -3
- package/dist/cjs/isServer/client.cjs.map +1 -1
- package/dist/cjs/isServer/development.cjs +5 -3
- package/dist/cjs/isServer/development.cjs.map +1 -1
- package/dist/cjs/isServer/server.cjs +5 -3
- package/dist/cjs/isServer/server.cjs.map +1 -1
- package/dist/cjs/link.cjs +5 -4
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/load-matches.cjs +619 -766
- package/dist/cjs/load-matches.cjs.map +1 -1
- package/dist/cjs/lru-cache.cjs +67 -64
- package/dist/cjs/lru-cache.cjs.map +1 -1
- package/dist/cjs/new-process-route-tree.cjs +707 -792
- package/dist/cjs/new-process-route-tree.cjs.map +1 -1
- package/dist/cjs/not-found.cjs +20 -7
- package/dist/cjs/not-found.cjs.map +1 -1
- package/dist/cjs/path.cjs +221 -232
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/qss.cjs +62 -28
- package/dist/cjs/qss.cjs.map +1 -1
- package/dist/cjs/redirect.cjs +44 -30
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/rewrite.cjs +56 -56
- package/dist/cjs/rewrite.cjs.map +1 -1
- package/dist/cjs/root.cjs +6 -4
- package/dist/cjs/root.cjs.map +1 -1
- package/dist/cjs/route.cjs +96 -105
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/router.cjs +1153 -1524
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/scroll-restoration.cjs +189 -207
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/searchMiddleware.cjs +48 -37
- package/dist/cjs/searchMiddleware.cjs.map +1 -1
- package/dist/cjs/searchParams.cjs +57 -45
- package/dist/cjs/searchParams.cjs.map +1 -1
- package/dist/cjs/ssr/client.cjs +6 -8
- package/dist/cjs/ssr/constants.cjs +6 -5
- package/dist/cjs/ssr/constants.cjs.map +1 -1
- package/dist/cjs/ssr/createRequestHandler.cjs +41 -59
- package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
- package/dist/cjs/ssr/handlerCallback.cjs +5 -4
- package/dist/cjs/ssr/handlerCallback.cjs.map +1 -1
- package/dist/cjs/ssr/headers.cjs +17 -26
- package/dist/cjs/ssr/headers.cjs.map +1 -1
- package/dist/cjs/ssr/json.cjs +8 -4
- package/dist/cjs/ssr/json.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/RawStream.cjs +268 -268
- package/dist/cjs/ssr/serializer/RawStream.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs +31 -32
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/seroval-plugins.cjs +12 -12
- package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/transformer.cjs +45 -41
- package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -1
- package/dist/cjs/ssr/server.cjs +12 -14
- package/dist/cjs/ssr/ssr-client.cjs +173 -211
- package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-match-id.cjs +6 -5
- package/dist/cjs/ssr/ssr-match-id.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.cjs +266 -300
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
- package/dist/cjs/ssr/transformStreamWithRouter.cjs +317 -337
- package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
- package/dist/cjs/ssr/tsrScript.cjs +6 -4
- package/dist/cjs/ssr/tsrScript.cjs.map +1 -1
- package/dist/cjs/utils/batch.cjs +13 -13
- package/dist/cjs/utils/batch.cjs.map +1 -1
- package/dist/cjs/utils.cjs +274 -208
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/esm/Matches.js +16 -13
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/config.js +10 -9
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/defer.js +37 -22
- package/dist/esm/defer.js.map +1 -1
- package/dist/esm/index.js +12 -82
- package/dist/esm/isServer/client.js +6 -5
- package/dist/esm/isServer/client.js.map +1 -1
- package/dist/esm/isServer/development.js +6 -5
- package/dist/esm/isServer/development.js.map +1 -1
- package/dist/esm/isServer/server.js +6 -5
- package/dist/esm/isServer/server.js.map +1 -1
- package/dist/esm/link.js +6 -5
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/load-matches.js +614 -765
- package/dist/esm/load-matches.js.map +1 -1
- package/dist/esm/lru-cache.js +68 -65
- package/dist/esm/lru-cache.js.map +1 -1
- package/dist/esm/new-process-route-tree.js +705 -797
- package/dist/esm/new-process-route-tree.js.map +1 -1
- package/dist/esm/not-found.js +21 -9
- package/dist/esm/not-found.js.map +1 -1
- package/dist/esm/path.js +220 -241
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/qss.js +63 -30
- package/dist/esm/qss.js.map +1 -1
- package/dist/esm/redirect.js +45 -34
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/rewrite.js +57 -60
- package/dist/esm/rewrite.js.map +1 -1
- package/dist/esm/root.js +7 -5
- package/dist/esm/root.js.map +1 -1
- package/dist/esm/route.js +92 -105
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.js +1147 -1527
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.js +188 -213
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/searchMiddleware.js +48 -38
- package/dist/esm/searchMiddleware.js.map +1 -1
- package/dist/esm/searchParams.js +57 -48
- package/dist/esm/searchParams.js.map +1 -1
- package/dist/esm/ssr/client.js +1 -6
- package/dist/esm/ssr/constants.js +7 -7
- package/dist/esm/ssr/constants.js.map +1 -1
- package/dist/esm/ssr/createRequestHandler.js +39 -58
- package/dist/esm/ssr/createRequestHandler.js.map +1 -1
- package/dist/esm/ssr/handlerCallback.js +6 -5
- package/dist/esm/ssr/handlerCallback.js.map +1 -1
- package/dist/esm/ssr/headers.js +16 -26
- package/dist/esm/ssr/headers.js.map +1 -1
- package/dist/esm/ssr/json.js +9 -5
- package/dist/esm/ssr/json.js.map +1 -1
- package/dist/esm/ssr/serializer/RawStream.js +267 -273
- package/dist/esm/ssr/serializer/RawStream.js.map +1 -1
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.js +31 -32
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -1
- package/dist/esm/ssr/serializer/seroval-plugins.js +10 -11
- package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -1
- package/dist/esm/ssr/serializer/transformer.js +44 -43
- package/dist/esm/ssr/serializer/transformer.js.map +1 -1
- package/dist/esm/ssr/server.js +2 -12
- package/dist/esm/ssr/ssr-client.js +169 -209
- package/dist/esm/ssr/ssr-client.js.map +1 -1
- package/dist/esm/ssr/ssr-match-id.js +7 -7
- package/dist/esm/ssr/ssr-match-id.js.map +1 -1
- package/dist/esm/ssr/ssr-server.js +262 -300
- package/dist/esm/ssr/ssr-server.js.map +1 -1
- package/dist/esm/ssr/transformStreamWithRouter.js +315 -338
- package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
- package/dist/esm/ssr/tsrScript.js +6 -5
- package/dist/esm/ssr/tsrScript.js.map +1 -1
- package/dist/esm/utils/batch.js +13 -14
- package/dist/esm/utils/batch.js.map +1 -1
- package/dist/esm/utils.js +273 -224
- package/dist/esm/utils.js.map +1 -1
- package/package.json +2 -2
- package/dist/cjs/index.cjs.map +0 -1
- package/dist/cjs/ssr/client.cjs.map +0 -1
- package/dist/cjs/ssr/server.cjs.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/ssr/client.js.map +0 -1
- package/dist/esm/ssr/server.js.map +0 -1
|
@@ -1,348 +1,325 @@
|
|
|
1
|
+
import "./constants.js";
|
|
1
2
|
import { ReadableStream } from "node:stream/web";
|
|
2
3
|
import { Readable } from "node:stream";
|
|
3
|
-
|
|
4
|
+
//#region src/ssr/transformStreamWithRouter.ts
|
|
4
5
|
function transformReadableStreamWithRouter(router, routerStream) {
|
|
5
|
-
|
|
6
|
+
return transformStreamWithRouter(router, routerStream);
|
|
6
7
|
}
|
|
7
8
|
function transformPipeableStreamWithRouter(router, routerStream) {
|
|
8
|
-
|
|
9
|
-
transformStreamWithRouter(router, Readable.toWeb(routerStream))
|
|
10
|
-
);
|
|
9
|
+
return Readable.fromWeb(transformStreamWithRouter(router, Readable.toWeb(routerStream)));
|
|
11
10
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
var BODY_END_TAG = "</body>";
|
|
12
|
+
var HTML_END_TAG = "</html>";
|
|
13
|
+
var MIN_CLOSING_TAG_LENGTH = 4;
|
|
14
|
+
var DEFAULT_SERIALIZATION_TIMEOUT_MS = 6e4;
|
|
15
|
+
var DEFAULT_LIFETIME_TIMEOUT_MS = 6e4;
|
|
16
|
+
var textEncoder = new TextEncoder();
|
|
17
|
+
/**
|
|
18
|
+
* Finds the position just after the last valid HTML closing tag in the string.
|
|
19
|
+
*
|
|
20
|
+
* Valid closing tags match the pattern: </[a-zA-Z][\w:.-]*>
|
|
21
|
+
* Examples: </div>, </my-component>, </slot:name.nested>
|
|
22
|
+
*
|
|
23
|
+
* @returns Position after the last closing tag, or -1 if none found
|
|
24
|
+
*/
|
|
18
25
|
function findLastClosingTagEnd(str) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const startCode = str.charCodeAt(tagNameStart);
|
|
42
|
-
if (startCode >= 97 && startCode <= 122 || startCode >= 65 && startCode <= 90) {
|
|
43
|
-
if (j >= 1 && str.charCodeAt(j) === 47 && str.charCodeAt(j - 1) === 60) {
|
|
44
|
-
return i + 1;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
i--;
|
|
50
|
-
}
|
|
51
|
-
return -1;
|
|
26
|
+
const len = str.length;
|
|
27
|
+
if (len < MIN_CLOSING_TAG_LENGTH) return -1;
|
|
28
|
+
let i = len - 1;
|
|
29
|
+
while (i >= MIN_CLOSING_TAG_LENGTH - 1) {
|
|
30
|
+
if (str.charCodeAt(i) === 62) {
|
|
31
|
+
let j = i - 1;
|
|
32
|
+
while (j >= 1) {
|
|
33
|
+
const code = str.charCodeAt(j);
|
|
34
|
+
if (code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57 || code === 95 || code === 58 || code === 46 || code === 45) j--;
|
|
35
|
+
else break;
|
|
36
|
+
}
|
|
37
|
+
const tagNameStart = j + 1;
|
|
38
|
+
if (tagNameStart < i) {
|
|
39
|
+
const startCode = str.charCodeAt(tagNameStart);
|
|
40
|
+
if (startCode >= 97 && startCode <= 122 || startCode >= 65 && startCode <= 90) {
|
|
41
|
+
if (j >= 1 && str.charCodeAt(j) === 47 && str.charCodeAt(j - 1) === 60) return i + 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
i--;
|
|
46
|
+
}
|
|
47
|
+
return -1;
|
|
52
48
|
}
|
|
53
49
|
function transformStreamWithRouter(router, appStream, opts) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
} catch (error) {
|
|
326
|
-
if (cleanedUp) return;
|
|
327
|
-
console.error("Error reading appStream:", error);
|
|
328
|
-
isAppRendering = false;
|
|
329
|
-
router.serverSsr?.setRenderFinished();
|
|
330
|
-
safeError(error);
|
|
331
|
-
cleanup();
|
|
332
|
-
} finally {
|
|
333
|
-
reader.releaseLock();
|
|
334
|
-
}
|
|
335
|
-
})().catch((error) => {
|
|
336
|
-
if (cleanedUp) return;
|
|
337
|
-
console.error("Error in stream transform:", error);
|
|
338
|
-
safeError(error);
|
|
339
|
-
cleanup();
|
|
340
|
-
});
|
|
341
|
-
return stream;
|
|
50
|
+
const serializationAlreadyFinished = router.serverSsr?.isSerializationFinished() ?? false;
|
|
51
|
+
const initialBufferedHtml = router.serverSsr?.takeBufferedHtml();
|
|
52
|
+
if (serializationAlreadyFinished && !initialBufferedHtml) {
|
|
53
|
+
let cleanedUp = false;
|
|
54
|
+
let controller;
|
|
55
|
+
let isStreamClosed = false;
|
|
56
|
+
let lifetimeTimeoutHandle;
|
|
57
|
+
const cleanup = () => {
|
|
58
|
+
if (cleanedUp) return;
|
|
59
|
+
cleanedUp = true;
|
|
60
|
+
if (lifetimeTimeoutHandle !== void 0) {
|
|
61
|
+
clearTimeout(lifetimeTimeoutHandle);
|
|
62
|
+
lifetimeTimeoutHandle = void 0;
|
|
63
|
+
}
|
|
64
|
+
router.serverSsr?.cleanup();
|
|
65
|
+
};
|
|
66
|
+
const safeClose = () => {
|
|
67
|
+
if (isStreamClosed) return;
|
|
68
|
+
isStreamClosed = true;
|
|
69
|
+
try {
|
|
70
|
+
controller?.close();
|
|
71
|
+
} catch {}
|
|
72
|
+
};
|
|
73
|
+
const safeError = (error) => {
|
|
74
|
+
if (isStreamClosed) return;
|
|
75
|
+
isStreamClosed = true;
|
|
76
|
+
try {
|
|
77
|
+
controller?.error(error);
|
|
78
|
+
} catch {}
|
|
79
|
+
};
|
|
80
|
+
const lifetimeMs = opts?.lifetimeMs ?? DEFAULT_LIFETIME_TIMEOUT_MS;
|
|
81
|
+
lifetimeTimeoutHandle = setTimeout(() => {
|
|
82
|
+
if (!cleanedUp && !isStreamClosed) {
|
|
83
|
+
console.warn(`SSR stream transform exceeded maximum lifetime (${lifetimeMs}ms), forcing cleanup`);
|
|
84
|
+
safeError(/* @__PURE__ */ new Error("Stream lifetime exceeded"));
|
|
85
|
+
cleanup();
|
|
86
|
+
}
|
|
87
|
+
}, lifetimeMs);
|
|
88
|
+
const stream = new ReadableStream({
|
|
89
|
+
start(c) {
|
|
90
|
+
controller = c;
|
|
91
|
+
},
|
|
92
|
+
cancel() {
|
|
93
|
+
isStreamClosed = true;
|
|
94
|
+
cleanup();
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
(async () => {
|
|
98
|
+
const reader = appStream.getReader();
|
|
99
|
+
try {
|
|
100
|
+
while (true) {
|
|
101
|
+
const { done, value } = await reader.read();
|
|
102
|
+
if (done) break;
|
|
103
|
+
if (cleanedUp || isStreamClosed) return;
|
|
104
|
+
controller?.enqueue(value);
|
|
105
|
+
}
|
|
106
|
+
if (cleanedUp || isStreamClosed) return;
|
|
107
|
+
router.serverSsr?.setRenderFinished();
|
|
108
|
+
safeClose();
|
|
109
|
+
cleanup();
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if (cleanedUp) return;
|
|
112
|
+
console.error("Error reading appStream:", error);
|
|
113
|
+
router.serverSsr?.setRenderFinished();
|
|
114
|
+
safeError(error);
|
|
115
|
+
cleanup();
|
|
116
|
+
} finally {
|
|
117
|
+
reader.releaseLock();
|
|
118
|
+
}
|
|
119
|
+
})().catch((error) => {
|
|
120
|
+
if (cleanedUp) return;
|
|
121
|
+
console.error("Error in stream transform:", error);
|
|
122
|
+
safeError(error);
|
|
123
|
+
cleanup();
|
|
124
|
+
});
|
|
125
|
+
return stream;
|
|
126
|
+
}
|
|
127
|
+
let stopListeningToInjectedHtml;
|
|
128
|
+
let stopListeningToSerializationFinished;
|
|
129
|
+
let serializationTimeoutHandle;
|
|
130
|
+
let lifetimeTimeoutHandle;
|
|
131
|
+
let cleanedUp = false;
|
|
132
|
+
let controller;
|
|
133
|
+
let isStreamClosed = false;
|
|
134
|
+
const textDecoder = new TextDecoder();
|
|
135
|
+
let pendingRouterHtml = initialBufferedHtml ?? "";
|
|
136
|
+
let leftover = "";
|
|
137
|
+
let pendingClosingTags = "";
|
|
138
|
+
const MAX_LEFTOVER_CHARS = 2048;
|
|
139
|
+
let isAppRendering = true;
|
|
140
|
+
let streamBarrierLifted = false;
|
|
141
|
+
let serializationFinished = serializationAlreadyFinished;
|
|
142
|
+
function safeEnqueue(chunk) {
|
|
143
|
+
if (isStreamClosed) return;
|
|
144
|
+
if (typeof chunk === "string") controller.enqueue(textEncoder.encode(chunk));
|
|
145
|
+
else controller.enqueue(chunk);
|
|
146
|
+
}
|
|
147
|
+
function safeClose() {
|
|
148
|
+
if (isStreamClosed) return;
|
|
149
|
+
isStreamClosed = true;
|
|
150
|
+
try {
|
|
151
|
+
controller.close();
|
|
152
|
+
} catch {}
|
|
153
|
+
}
|
|
154
|
+
function safeError(error) {
|
|
155
|
+
if (isStreamClosed) return;
|
|
156
|
+
isStreamClosed = true;
|
|
157
|
+
try {
|
|
158
|
+
controller.error(error);
|
|
159
|
+
} catch {}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Cleanup with guards; must be idempotent.
|
|
163
|
+
*/
|
|
164
|
+
function cleanup() {
|
|
165
|
+
if (cleanedUp) return;
|
|
166
|
+
cleanedUp = true;
|
|
167
|
+
try {
|
|
168
|
+
stopListeningToInjectedHtml?.();
|
|
169
|
+
stopListeningToSerializationFinished?.();
|
|
170
|
+
} catch {}
|
|
171
|
+
stopListeningToInjectedHtml = void 0;
|
|
172
|
+
stopListeningToSerializationFinished = void 0;
|
|
173
|
+
if (serializationTimeoutHandle !== void 0) {
|
|
174
|
+
clearTimeout(serializationTimeoutHandle);
|
|
175
|
+
serializationTimeoutHandle = void 0;
|
|
176
|
+
}
|
|
177
|
+
if (lifetimeTimeoutHandle !== void 0) {
|
|
178
|
+
clearTimeout(lifetimeTimeoutHandle);
|
|
179
|
+
lifetimeTimeoutHandle = void 0;
|
|
180
|
+
}
|
|
181
|
+
pendingRouterHtml = "";
|
|
182
|
+
leftover = "";
|
|
183
|
+
pendingClosingTags = "";
|
|
184
|
+
router.serverSsr?.cleanup();
|
|
185
|
+
}
|
|
186
|
+
const stream = new ReadableStream({
|
|
187
|
+
start(c) {
|
|
188
|
+
controller = c;
|
|
189
|
+
},
|
|
190
|
+
cancel() {
|
|
191
|
+
isStreamClosed = true;
|
|
192
|
+
cleanup();
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
function flushPendingRouterHtml() {
|
|
196
|
+
if (!pendingRouterHtml) return;
|
|
197
|
+
safeEnqueue(pendingRouterHtml);
|
|
198
|
+
pendingRouterHtml = "";
|
|
199
|
+
}
|
|
200
|
+
function appendRouterHtml(html) {
|
|
201
|
+
if (!html) return;
|
|
202
|
+
pendingRouterHtml += html;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Finish only when app done and serialization complete.
|
|
206
|
+
*/
|
|
207
|
+
function tryFinish() {
|
|
208
|
+
if (isAppRendering || !serializationFinished) return;
|
|
209
|
+
if (cleanedUp || isStreamClosed) return;
|
|
210
|
+
if (serializationTimeoutHandle !== void 0) {
|
|
211
|
+
clearTimeout(serializationTimeoutHandle);
|
|
212
|
+
serializationTimeoutHandle = void 0;
|
|
213
|
+
}
|
|
214
|
+
const decoderRemainder = textDecoder.decode();
|
|
215
|
+
if (leftover) safeEnqueue(leftover);
|
|
216
|
+
if (decoderRemainder) safeEnqueue(decoderRemainder);
|
|
217
|
+
flushPendingRouterHtml();
|
|
218
|
+
if (pendingClosingTags) safeEnqueue(pendingClosingTags);
|
|
219
|
+
safeClose();
|
|
220
|
+
cleanup();
|
|
221
|
+
}
|
|
222
|
+
const lifetimeMs = opts?.lifetimeMs ?? DEFAULT_LIFETIME_TIMEOUT_MS;
|
|
223
|
+
lifetimeTimeoutHandle = setTimeout(() => {
|
|
224
|
+
if (!cleanedUp && !isStreamClosed) {
|
|
225
|
+
console.warn(`SSR stream transform exceeded maximum lifetime (${lifetimeMs}ms), forcing cleanup`);
|
|
226
|
+
safeError(/* @__PURE__ */ new Error("Stream lifetime exceeded"));
|
|
227
|
+
cleanup();
|
|
228
|
+
}
|
|
229
|
+
}, lifetimeMs);
|
|
230
|
+
if (!serializationAlreadyFinished) {
|
|
231
|
+
stopListeningToInjectedHtml = router.subscribe("onInjectedHtml", () => {
|
|
232
|
+
if (cleanedUp || isStreamClosed) return;
|
|
233
|
+
const html = router.serverSsr?.takeBufferedHtml();
|
|
234
|
+
if (!html) return;
|
|
235
|
+
if (isAppRendering || leftover || pendingClosingTags) appendRouterHtml(html);
|
|
236
|
+
else safeEnqueue(html);
|
|
237
|
+
});
|
|
238
|
+
stopListeningToSerializationFinished = router.subscribe("onSerializationFinished", () => {
|
|
239
|
+
serializationFinished = true;
|
|
240
|
+
tryFinish();
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
(async () => {
|
|
244
|
+
const reader = appStream.getReader();
|
|
245
|
+
try {
|
|
246
|
+
while (true) {
|
|
247
|
+
const { done, value } = await reader.read();
|
|
248
|
+
if (done) break;
|
|
249
|
+
if (cleanedUp || isStreamClosed) return;
|
|
250
|
+
const text = value instanceof Uint8Array ? textDecoder.decode(value, { stream: true }) : String(value);
|
|
251
|
+
const chunkString = leftover ? leftover + text : text;
|
|
252
|
+
if (!streamBarrierLifted) {
|
|
253
|
+
if (chunkString.includes("$tsr-stream-barrier")) {
|
|
254
|
+
streamBarrierLifted = true;
|
|
255
|
+
router.serverSsr?.liftScriptBarrier();
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (pendingClosingTags) {
|
|
259
|
+
pendingClosingTags += chunkString;
|
|
260
|
+
leftover = "";
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
const bodyEndIndex = chunkString.indexOf(BODY_END_TAG);
|
|
264
|
+
const htmlEndIndex = chunkString.indexOf(HTML_END_TAG);
|
|
265
|
+
if (bodyEndIndex !== -1 && htmlEndIndex !== -1 && bodyEndIndex < htmlEndIndex) {
|
|
266
|
+
pendingClosingTags = chunkString.slice(bodyEndIndex);
|
|
267
|
+
safeEnqueue(chunkString.slice(0, bodyEndIndex));
|
|
268
|
+
flushPendingRouterHtml();
|
|
269
|
+
leftover = "";
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
const lastClosingTagEnd = findLastClosingTagEnd(chunkString);
|
|
273
|
+
if (lastClosingTagEnd > 0) {
|
|
274
|
+
safeEnqueue(chunkString.slice(0, lastClosingTagEnd));
|
|
275
|
+
flushPendingRouterHtml();
|
|
276
|
+
leftover = chunkString.slice(lastClosingTagEnd);
|
|
277
|
+
if (leftover.length > MAX_LEFTOVER_CHARS) {
|
|
278
|
+
safeEnqueue(leftover.slice(0, leftover.length - MAX_LEFTOVER_CHARS));
|
|
279
|
+
leftover = leftover.slice(-MAX_LEFTOVER_CHARS);
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
const combined = chunkString;
|
|
283
|
+
if (combined.length > MAX_LEFTOVER_CHARS) {
|
|
284
|
+
const flushUpto = combined.length - MAX_LEFTOVER_CHARS;
|
|
285
|
+
safeEnqueue(combined.slice(0, flushUpto));
|
|
286
|
+
leftover = combined.slice(flushUpto);
|
|
287
|
+
} else leftover = combined;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (cleanedUp || isStreamClosed) return;
|
|
291
|
+
isAppRendering = false;
|
|
292
|
+
router.serverSsr?.setRenderFinished();
|
|
293
|
+
if (serializationFinished) tryFinish();
|
|
294
|
+
else {
|
|
295
|
+
const timeoutMs = opts?.timeoutMs ?? DEFAULT_SERIALIZATION_TIMEOUT_MS;
|
|
296
|
+
serializationTimeoutHandle = setTimeout(() => {
|
|
297
|
+
if (!cleanedUp && !isStreamClosed) {
|
|
298
|
+
console.error("Serialization timeout after app render finished");
|
|
299
|
+
safeError(/* @__PURE__ */ new Error("Serialization timeout after app render finished"));
|
|
300
|
+
cleanup();
|
|
301
|
+
}
|
|
302
|
+
}, timeoutMs);
|
|
303
|
+
}
|
|
304
|
+
} catch (error) {
|
|
305
|
+
if (cleanedUp) return;
|
|
306
|
+
console.error("Error reading appStream:", error);
|
|
307
|
+
isAppRendering = false;
|
|
308
|
+
router.serverSsr?.setRenderFinished();
|
|
309
|
+
safeError(error);
|
|
310
|
+
cleanup();
|
|
311
|
+
} finally {
|
|
312
|
+
reader.releaseLock();
|
|
313
|
+
}
|
|
314
|
+
})().catch((error) => {
|
|
315
|
+
if (cleanedUp) return;
|
|
316
|
+
console.error("Error in stream transform:", error);
|
|
317
|
+
safeError(error);
|
|
318
|
+
cleanup();
|
|
319
|
+
});
|
|
320
|
+
return stream;
|
|
342
321
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
};
|
|
348
|
-
//# sourceMappingURL=transformStreamWithRouter.js.map
|
|
322
|
+
//#endregion
|
|
323
|
+
export { transformPipeableStreamWithRouter, transformReadableStreamWithRouter, transformStreamWithRouter };
|
|
324
|
+
|
|
325
|
+
//# sourceMappingURL=transformStreamWithRouter.js.map
|