@tanstack/router-core 1.142.7 → 1.142.11
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/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +17 -5
- package/dist/cjs/ssr/constants.cjs +2 -0
- package/dist/cjs/ssr/constants.cjs.map +1 -1
- package/dist/cjs/ssr/constants.d.cts +1 -0
- package/dist/cjs/ssr/json.cjs +1 -8
- package/dist/cjs/ssr/json.cjs.map +1 -1
- package/dist/cjs/ssr/json.d.cts +6 -0
- package/dist/cjs/ssr/ssr-server.cjs +85 -39
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.d.cts +3 -1
- package/dist/cjs/ssr/transformStreamWithRouter.cjs +202 -185
- package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
- package/dist/cjs/ssr/transformStreamWithRouter.d.cts +3 -1
- package/dist/esm/router.d.ts +17 -5
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/ssr/constants.d.ts +1 -0
- package/dist/esm/ssr/constants.js +3 -1
- package/dist/esm/ssr/constants.js.map +1 -1
- package/dist/esm/ssr/json.d.ts +6 -0
- package/dist/esm/ssr/json.js +1 -8
- package/dist/esm/ssr/json.js.map +1 -1
- package/dist/esm/ssr/ssr-server.d.ts +3 -1
- package/dist/esm/ssr/ssr-server.js +85 -39
- package/dist/esm/ssr/ssr-server.js.map +1 -1
- package/dist/esm/ssr/transformStreamWithRouter.d.ts +3 -1
- package/dist/esm/ssr/transformStreamWithRouter.js +202 -185
- package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
- package/package.json +1 -1
- package/src/router.ts +17 -6
- package/src/ssr/constants.ts +1 -0
- package/src/ssr/json.ts +7 -9
- package/src/ssr/ssr-server.ts +107 -46
- package/src/ssr/transformStreamWithRouter.ts +331 -253
package/dist/cjs/router.d.cts
CHANGED
|
@@ -485,15 +485,27 @@ export type ClearCacheFn<TRouter extends AnyRouter> = (opts?: {
|
|
|
485
485
|
filter?: (d: MakeRouteMatchUnion<TRouter>) => boolean;
|
|
486
486
|
}) => void;
|
|
487
487
|
export interface ServerSsr {
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
488
|
+
/**
|
|
489
|
+
* Injects HTML synchronously into the stream.
|
|
490
|
+
* Emits an onInjectedHtml event that listeners can handle.
|
|
491
|
+
* If no subscriber is listening, the HTML is buffered and can be retrieved via takeBufferedHtml().
|
|
492
|
+
*/
|
|
493
|
+
injectHtml: (html: string) => void;
|
|
494
|
+
/**
|
|
495
|
+
* Injects a script tag synchronously into the stream.
|
|
496
|
+
*/
|
|
497
|
+
injectScript: (script: string) => void;
|
|
493
498
|
isDehydrated: () => boolean;
|
|
499
|
+
isSerializationFinished: () => boolean;
|
|
494
500
|
onRenderFinished: (listener: () => void) => void;
|
|
501
|
+
onSerializationFinished: (listener: () => void) => void;
|
|
495
502
|
dehydrate: () => Promise<void>;
|
|
496
503
|
takeBufferedScripts: () => RouterManagedTag | undefined;
|
|
504
|
+
/**
|
|
505
|
+
* Takes any buffered HTML that was injected.
|
|
506
|
+
* Returns the buffered HTML string (which may include multiple script tags) or undefined if empty.
|
|
507
|
+
*/
|
|
508
|
+
takeBufferedHtml: () => string | undefined;
|
|
497
509
|
liftScriptBarrier: () => void;
|
|
498
510
|
}
|
|
499
511
|
export type AnyRouterWithContext<TContext> = RouterCore<AnyRouteWithContext<TContext>, any, any, any, any>;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const GLOBAL_TSR = "$_TSR";
|
|
4
|
+
const TSR_SCRIPT_BARRIER_ID = "$tsr-stream-barrier";
|
|
4
5
|
exports.GLOBAL_TSR = GLOBAL_TSR;
|
|
6
|
+
exports.TSR_SCRIPT_BARRIER_ID = TSR_SCRIPT_BARRIER_ID;
|
|
5
7
|
//# sourceMappingURL=constants.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.cjs","sources":["../../../src/ssr/constants.ts"],"sourcesContent":["export const GLOBAL_TSR = '$_TSR'\nexport declare const GLOBAL_SEROVAL: '$R'\n"],"names":[],"mappings":";;AAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"constants.cjs","sources":["../../../src/ssr/constants.ts"],"sourcesContent":["export const GLOBAL_TSR = '$_TSR'\nexport declare const GLOBAL_SEROVAL: '$R'\nexport const TSR_SCRIPT_BARRIER_ID = '$tsr-stream-barrier'\n"],"names":[],"mappings":";;AAAO,MAAM,aAAa;AAEnB,MAAM,wBAAwB;;;"}
|
package/dist/cjs/ssr/json.cjs
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const headers = require("./headers.cjs");
|
|
4
3
|
function json(payload, init) {
|
|
5
|
-
return
|
|
6
|
-
...init,
|
|
7
|
-
headers: headers.mergeHeaders(
|
|
8
|
-
{ "content-type": "application/json" },
|
|
9
|
-
init?.headers
|
|
10
|
-
)
|
|
11
|
-
});
|
|
4
|
+
return Response.json(payload, init);
|
|
12
5
|
}
|
|
13
6
|
exports.json = json;
|
|
14
7
|
//# sourceMappingURL=json.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json.cjs","sources":["../../../src/ssr/json.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"json.cjs","sources":["../../../src/ssr/json.ts"],"sourcesContent":["/**\n * @deprecated Use [`Response.json`](https://developer.mozilla.org/en-US/docs/Web/API/Response/json_static) from the standard Web API directly.\n */\nexport interface JsonResponse<TData> extends Response {\n json: () => Promise<TData>\n}\n\n/**\n * @deprecated Use [`Response.json`](https://developer.mozilla.org/en-US/docs/Web/API/Response/json_static) from the standard Web API directly.\n */\nexport function json<TData>(\n payload: TData,\n init?: ResponseInit,\n): JsonResponse<TData> {\n return Response.json(payload, init)\n}\n"],"names":[],"mappings":";;AAUO,SAAS,KACd,SACA,MACqB;AACrB,SAAO,SAAS,KAAK,SAAS,IAAI;AACpC;;"}
|
package/dist/cjs/ssr/json.d.cts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated Use [`Response.json`](https://developer.mozilla.org/en-US/docs/Web/API/Response/json_static) from the standard Web API directly.
|
|
3
|
+
*/
|
|
1
4
|
export interface JsonResponse<TData> extends Response {
|
|
2
5
|
json: () => Promise<TData>;
|
|
3
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated Use [`Response.json`](https://developer.mozilla.org/en-US/docs/Web/API/Response/json_static) from the standard Web API directly.
|
|
9
|
+
*/
|
|
4
10
|
export declare function json<TData>(payload: TData, init?: ResponseInit): JsonResponse<TData>;
|
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const seroval = require("seroval");
|
|
4
4
|
const invariant = require("tiny-invariant");
|
|
5
|
-
const utils = require("../utils.cjs");
|
|
6
5
|
const tsrScript = require("./tsrScript.cjs");
|
|
7
6
|
const constants = require("./constants.cjs");
|
|
8
7
|
const serovalPlugins = require("./serializer/seroval-plugins.cjs");
|
|
9
8
|
const transformer = require("./serializer/transformer.cjs");
|
|
10
|
-
const transformStreamWithRouter = require("./transformStreamWithRouter.cjs");
|
|
11
9
|
const SCOPE_ID = "tsr";
|
|
12
10
|
function dehydrateMatch(match) {
|
|
13
11
|
const dehydratedMatch = {
|
|
@@ -34,44 +32,64 @@ const INITIAL_SCRIPTS = [
|
|
|
34
32
|
];
|
|
35
33
|
class ScriptBuffer {
|
|
36
34
|
constructor(router) {
|
|
37
|
-
this._queue = [...INITIAL_SCRIPTS];
|
|
38
35
|
this._scriptBarrierLifted = false;
|
|
39
36
|
this._cleanedUp = false;
|
|
37
|
+
this._pendingMicrotask = false;
|
|
40
38
|
this.router = router;
|
|
39
|
+
this._queue = INITIAL_SCRIPTS.slice();
|
|
41
40
|
}
|
|
42
41
|
enqueue(script) {
|
|
43
42
|
if (this._cleanedUp) return;
|
|
44
|
-
|
|
43
|
+
this._queue.push(script);
|
|
44
|
+
if (this._scriptBarrierLifted && !this._pendingMicrotask) {
|
|
45
|
+
this._pendingMicrotask = true;
|
|
45
46
|
queueMicrotask(() => {
|
|
47
|
+
this._pendingMicrotask = false;
|
|
46
48
|
this.injectBufferedScripts();
|
|
47
49
|
});
|
|
48
50
|
}
|
|
49
|
-
this._queue.push(script);
|
|
50
51
|
}
|
|
51
52
|
liftBarrier() {
|
|
52
53
|
if (this._scriptBarrierLifted || this._cleanedUp) return;
|
|
53
54
|
this._scriptBarrierLifted = true;
|
|
54
|
-
if (this._queue.length > 0) {
|
|
55
|
+
if (this._queue.length > 0 && !this._pendingMicrotask) {
|
|
56
|
+
this._pendingMicrotask = true;
|
|
55
57
|
queueMicrotask(() => {
|
|
58
|
+
this._pendingMicrotask = false;
|
|
56
59
|
this.injectBufferedScripts();
|
|
57
60
|
});
|
|
58
61
|
}
|
|
59
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) {
|
|
76
|
+
this.router.serverSsr.injectScript(scriptsToInject);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
60
79
|
takeAll() {
|
|
61
80
|
const bufferedScripts = this._queue;
|
|
62
81
|
this._queue = [];
|
|
63
82
|
if (bufferedScripts.length === 0) {
|
|
64
83
|
return void 0;
|
|
65
84
|
}
|
|
66
|
-
bufferedScripts.
|
|
67
|
-
const joinedScripts = bufferedScripts.join(";");
|
|
68
|
-
return joinedScripts;
|
|
85
|
+
return bufferedScripts.join(";") + ";document.currentScript.remove()";
|
|
69
86
|
}
|
|
70
87
|
injectBufferedScripts() {
|
|
71
88
|
if (this._cleanedUp) return;
|
|
89
|
+
if (this._queue.length === 0) return;
|
|
72
90
|
const scriptsToInject = this.takeAll();
|
|
73
91
|
if (scriptsToInject && this.router?.serverSsr) {
|
|
74
|
-
this.router.serverSsr.injectScript(
|
|
92
|
+
this.router.serverSsr.injectScript(scriptsToInject);
|
|
75
93
|
}
|
|
76
94
|
}
|
|
77
95
|
cleanup() {
|
|
@@ -88,28 +106,23 @@ function attachRouterServerSsrUtils({
|
|
|
88
106
|
manifest
|
|
89
107
|
};
|
|
90
108
|
let _dehydrated = false;
|
|
91
|
-
|
|
109
|
+
let _serializationFinished = false;
|
|
110
|
+
const renderFinishedListeners = [];
|
|
111
|
+
const serializationFinishedListeners = [];
|
|
92
112
|
const scriptBuffer = new ScriptBuffer(router);
|
|
113
|
+
let injectedHtmlBuffer = [];
|
|
93
114
|
router.serverSsr = {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
router.serverSsr.injectedHtml.push(promise);
|
|
115
|
+
injectHtml: (html) => {
|
|
116
|
+
if (!html) return;
|
|
117
|
+
injectedHtmlBuffer.push(html);
|
|
98
118
|
router.emit({
|
|
99
|
-
type: "onInjectedHtml"
|
|
100
|
-
promise
|
|
101
|
-
});
|
|
102
|
-
return promise.then(() => {
|
|
119
|
+
type: "onInjectedHtml"
|
|
103
120
|
});
|
|
104
121
|
},
|
|
105
|
-
injectScript: (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return "";
|
|
110
|
-
}
|
|
111
|
-
return `<script${router.options.ssr?.nonce ? ` nonce='${router.options.ssr.nonce}'` : ""}>${script}<\/script>`;
|
|
112
|
-
});
|
|
122
|
+
injectScript: (script) => {
|
|
123
|
+
if (!script) return;
|
|
124
|
+
const html = `<script${router.options.ssr?.nonce ? ` nonce='${router.options.ssr.nonce}'` : ""}>${script}<\/script>`;
|
|
125
|
+
router.serverSsr.injectHtml(html);
|
|
113
126
|
},
|
|
114
127
|
dehydrate: async () => {
|
|
115
128
|
invariant(!_dehydrated, "router is already dehydrated!");
|
|
@@ -159,12 +172,24 @@ function attachRouterServerSsrUtils({
|
|
|
159
172
|
dehydratedRouter.dehydratedData = dehydratedData;
|
|
160
173
|
}
|
|
161
174
|
_dehydrated = true;
|
|
162
|
-
const p = utils.createControlledPromise();
|
|
163
175
|
const trackPlugins = { didRun: false };
|
|
164
|
-
const
|
|
176
|
+
const serializationAdapters = router.options.serializationAdapters;
|
|
177
|
+
const plugins = serializationAdapters ? serializationAdapters.map((t) => transformer.makeSsrSerovalPlugin(t, trackPlugins)).concat(serovalPlugins.defaultSerovalPlugins) : serovalPlugins.defaultSerovalPlugins;
|
|
178
|
+
const signalSerializationComplete = () => {
|
|
179
|
+
_serializationFinished = true;
|
|
180
|
+
try {
|
|
181
|
+
serializationFinishedListeners.forEach((l) => l());
|
|
182
|
+
router.emit({ type: "onSerializationFinished" });
|
|
183
|
+
} catch (err) {
|
|
184
|
+
console.error("Serialization listener error:", err);
|
|
185
|
+
} finally {
|
|
186
|
+
serializationFinishedListeners.length = 0;
|
|
187
|
+
renderFinishedListeners.length = 0;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
165
190
|
seroval.crossSerializeStream(dehydratedRouter, {
|
|
166
191
|
refs: /* @__PURE__ */ new Map(),
|
|
167
|
-
plugins
|
|
192
|
+
plugins,
|
|
168
193
|
onSerialize: (data, initial) => {
|
|
169
194
|
let serialized = initial ? constants.GLOBAL_TSR + ".router=" + data : data;
|
|
170
195
|
if (trackPlugins.didRun) {
|
|
@@ -175,19 +200,31 @@ function attachRouterServerSsrUtils({
|
|
|
175
200
|
scopeId: SCOPE_ID,
|
|
176
201
|
onDone: () => {
|
|
177
202
|
scriptBuffer.enqueue(constants.GLOBAL_TSR + ".e()");
|
|
178
|
-
|
|
203
|
+
scriptBuffer.flush();
|
|
204
|
+
signalSerializationComplete();
|
|
179
205
|
},
|
|
180
|
-
onError: (err) =>
|
|
206
|
+
onError: (err) => {
|
|
207
|
+
console.error("Serialization error:", err);
|
|
208
|
+
signalSerializationComplete();
|
|
209
|
+
}
|
|
181
210
|
});
|
|
182
|
-
router.serverSsr.injectHtml(() => p);
|
|
183
211
|
},
|
|
184
212
|
isDehydrated() {
|
|
185
213
|
return _dehydrated;
|
|
186
214
|
},
|
|
187
|
-
|
|
215
|
+
isSerializationFinished() {
|
|
216
|
+
return _serializationFinished;
|
|
217
|
+
},
|
|
218
|
+
onRenderFinished: (listener) => renderFinishedListeners.push(listener),
|
|
219
|
+
onSerializationFinished: (listener) => serializationFinishedListeners.push(listener),
|
|
188
220
|
setRenderFinished: () => {
|
|
189
|
-
|
|
190
|
-
|
|
221
|
+
try {
|
|
222
|
+
renderFinishedListeners.forEach((l) => l());
|
|
223
|
+
} catch (err) {
|
|
224
|
+
console.error("Error in render finished listener:", err);
|
|
225
|
+
} finally {
|
|
226
|
+
renderFinishedListeners.length = 0;
|
|
227
|
+
}
|
|
191
228
|
scriptBuffer.liftBarrier();
|
|
192
229
|
},
|
|
193
230
|
takeBufferedScripts() {
|
|
@@ -197,7 +234,7 @@ function attachRouterServerSsrUtils({
|
|
|
197
234
|
attrs: {
|
|
198
235
|
nonce: router.options.ssr?.nonce,
|
|
199
236
|
className: "$tsr",
|
|
200
|
-
id:
|
|
237
|
+
id: constants.TSR_SCRIPT_BARRIER_ID
|
|
201
238
|
},
|
|
202
239
|
children: scripts
|
|
203
240
|
};
|
|
@@ -206,11 +243,20 @@ function attachRouterServerSsrUtils({
|
|
|
206
243
|
liftScriptBarrier() {
|
|
207
244
|
scriptBuffer.liftBarrier();
|
|
208
245
|
},
|
|
246
|
+
takeBufferedHtml() {
|
|
247
|
+
if (injectedHtmlBuffer.length === 0) {
|
|
248
|
+
return void 0;
|
|
249
|
+
}
|
|
250
|
+
const buffered = injectedHtmlBuffer.join("");
|
|
251
|
+
injectedHtmlBuffer = [];
|
|
252
|
+
return buffered;
|
|
253
|
+
},
|
|
209
254
|
cleanup() {
|
|
210
255
|
if (!router.serverSsr) return;
|
|
211
|
-
|
|
256
|
+
renderFinishedListeners.length = 0;
|
|
257
|
+
serializationFinishedListeners.length = 0;
|
|
258
|
+
injectedHtmlBuffer = [];
|
|
212
259
|
scriptBuffer.cleanup();
|
|
213
|
-
router.serverSsr.injectedHtml = [];
|
|
214
260
|
router.serverSsr = void 0;
|
|
215
261
|
}
|
|
216
262
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-server.cjs","sources":["../../../src/ssr/ssr-server.ts"],"sourcesContent":["import { crossSerializeStream, getCrossReferenceHeader } from 'seroval'\nimport invariant from 'tiny-invariant'\nimport { createControlledPromise } from '../utils'\nimport minifiedTsrBootStrapScript from './tsrScript?script-string'\nimport { GLOBAL_TSR } from './constants'\nimport { defaultSerovalPlugins } from './serializer/seroval-plugins'\nimport { makeSsrSerovalPlugin } from './serializer/transformer'\nimport { TSR_SCRIPT_BARRIER_ID } from './transformStreamWithRouter'\nimport type { DehydratedMatch, DehydratedRouter } from './types'\nimport type { AnySerializationAdapter } from './serializer/transformer'\nimport type { AnyRouter } from '../router'\nimport type { AnyRouteMatch } from '../Matches'\nimport type { Manifest, RouterManagedTag } from '../manifest'\n\ndeclare module '../router' {\n interface ServerSsr {\n setRenderFinished: () => void\n cleanup: () => void\n }\n interface RouterEvents {\n onInjectedHtml: {\n type: 'onInjectedHtml'\n promise: Promise<string>\n }\n }\n}\n\nconst SCOPE_ID = 'tsr'\n\nexport function dehydrateMatch(match: AnyRouteMatch): DehydratedMatch {\n const dehydratedMatch: DehydratedMatch = {\n i: 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 return dehydratedMatch\n}\n\nconst INITIAL_SCRIPTS = [\n getCrossReferenceHeader(SCOPE_ID),\n minifiedTsrBootStrapScript,\n]\n\nclass ScriptBuffer {\n private router: AnyRouter | undefined\n private _queue: Array<string> = [...INITIAL_SCRIPTS]\n private _scriptBarrierLifted = false\n private _cleanedUp = false\n\n constructor(router: AnyRouter) {\n this.router = router\n }\n\n enqueue(script: string) {\n if (this._cleanedUp) return\n if (this._scriptBarrierLifted && this._queue.length === 0) {\n queueMicrotask(() => {\n this.injectBufferedScripts()\n })\n }\n this._queue.push(script)\n }\n\n liftBarrier() {\n if (this._scriptBarrierLifted || this._cleanedUp) return\n this._scriptBarrierLifted = true\n if (this._queue.length > 0) {\n queueMicrotask(() => {\n this.injectBufferedScripts()\n })\n }\n }\n\n takeAll() {\n const bufferedScripts = this._queue\n this._queue = []\n if (bufferedScripts.length === 0) {\n return undefined\n }\n bufferedScripts.push(`document.currentScript.remove()`)\n const joinedScripts = bufferedScripts.join(';')\n return joinedScripts\n }\n\n injectBufferedScripts() {\n if (this._cleanedUp) return\n const scriptsToInject = this.takeAll()\n if (scriptsToInject && this.router?.serverSsr) {\n this.router.serverSsr.injectScript(() => scriptsToInject)\n }\n }\n\n cleanup() {\n this._cleanedUp = true\n this._queue = []\n this.router = undefined\n }\n}\n\nexport function attachRouterServerSsrUtils({\n router,\n manifest,\n}: {\n router: AnyRouter\n manifest: Manifest | undefined\n}) {\n router.ssr = {\n manifest,\n }\n let _dehydrated = false\n const listeners: Array<() => void> = []\n const scriptBuffer = new ScriptBuffer(router)\n\n router.serverSsr = {\n injectedHtml: [],\n injectHtml: (getHtml) => {\n const promise = Promise.resolve().then(getHtml)\n router.serverSsr!.injectedHtml.push(promise)\n router.emit({\n type: 'onInjectedHtml',\n promise,\n })\n\n return promise.then(() => {})\n },\n injectScript: (getScript) => {\n return router.serverSsr!.injectHtml(async () => {\n const script = await getScript()\n if (!script) {\n return ''\n }\n return `<script${router.options.ssr?.nonce ? ` nonce='${router.options.ssr.nonce}'` : ''}>${script}</script>`\n })\n },\n dehydrate: async () => {\n invariant(!_dehydrated, 'router is already dehydrated!')\n let matchesToDehydrate = router.state.matches\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 // For currently matched routes, send full manifest (preloads + assets)\n // For all other routes, only send assets (no preloads as they are handled via dynamic imports)\n if (manifest) {\n const currentRouteIds = new Set(\n router.state.matches.map((k) => k.routeId),\n )\n const filteredRoutes = Object.fromEntries(\n Object.entries(manifest.routes).flatMap(\n ([routeId, routeManifest]) => {\n if (currentRouteIds.has(routeId)) {\n return [[routeId, routeManifest]]\n } else if (\n routeManifest.assets &&\n routeManifest.assets.length > 0\n ) {\n return [\n [\n routeId,\n {\n assets: routeManifest.assets,\n },\n ],\n ]\n }\n return []\n },\n ),\n )\n manifestToDehydrate = {\n routes: filteredRoutes,\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 = lastMatchId\n }\n const dehydratedData = await router.options.dehydrate?.()\n if (dehydratedData) {\n dehydratedRouter.dehydratedData = dehydratedData\n }\n _dehydrated = true\n\n const p = createControlledPromise<string>()\n const trackPlugins = { didRun: false }\n const plugins =\n (\n router.options.serializationAdapters as\n | Array<AnySerializationAdapter>\n | undefined\n )?.map((t) => makeSsrSerovalPlugin(t, trackPlugins)) ?? []\n\n crossSerializeStream(dehydratedRouter, {\n refs: new Map(),\n plugins: [...plugins, ...defaultSerovalPlugins],\n onSerialize: (data, initial) => {\n let serialized = initial ? GLOBAL_TSR + '.router=' + data : data\n if (trackPlugins.didRun) {\n serialized = GLOBAL_TSR + '.p(()=>' + serialized + ')'\n }\n scriptBuffer.enqueue(serialized)\n },\n scopeId: SCOPE_ID,\n onDone: () => {\n scriptBuffer.enqueue(GLOBAL_TSR + '.e()')\n p.resolve('')\n },\n onError: (err) => p.reject(err),\n })\n // make sure the stream is kept open until the promise is resolved\n router.serverSsr!.injectHtml(() => p)\n },\n isDehydrated() {\n return _dehydrated\n },\n onRenderFinished: (listener) => listeners.push(listener),\n setRenderFinished: () => {\n listeners.forEach((l) => l())\n // Clear listeners after calling them to prevent memory leaks\n listeners.length = 0\n scriptBuffer.liftBarrier()\n },\n takeBufferedScripts() {\n const scripts = scriptBuffer.takeAll()\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 cleanup() {\n // Guard against multiple cleanup calls\n if (!router.serverSsr) return\n listeners.length = 0\n scriptBuffer.cleanup()\n router.serverSsr.injectedHtml = []\n router.serverSsr = undefined\n },\n }\n}\n\nexport function getOrigin(request: Request) {\n const originHeader = request.headers.get('Origin')\n if (originHeader) {\n try {\n new URL(originHeader)\n return originHeader\n } catch {}\n }\n try {\n return new URL(request.url).origin\n } catch {}\n return 'http://localhost'\n}\n"],"names":["getCrossReferenceHeader","minifiedTsrBootStrapScript","createControlledPromise","makeSsrSerovalPlugin","crossSerializeStream","defaultSerovalPlugins","GLOBAL_TSR","TSR_SCRIPT_BARRIER_ID"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ssr-server.cjs","sources":["../../../src/ssr/ssr-server.ts"],"sourcesContent":["import { crossSerializeStream, getCrossReferenceHeader } from 'seroval'\nimport invariant from 'tiny-invariant'\nimport minifiedTsrBootStrapScript from './tsrScript?script-string'\nimport { GLOBAL_TSR, TSR_SCRIPT_BARRIER_ID } from './constants'\nimport { defaultSerovalPlugins } from './serializer/seroval-plugins'\nimport { makeSsrSerovalPlugin } from './serializer/transformer'\nimport type { DehydratedMatch, DehydratedRouter } from './types'\nimport type { AnySerializationAdapter } from './serializer/transformer'\nimport type { AnyRouter } from '../router'\nimport type { AnyRouteMatch } from '../Matches'\nimport type { Manifest, RouterManagedTag } from '../manifest'\n\ndeclare module '../router' {\n interface ServerSsr {\n setRenderFinished: () => void\n cleanup: () => void\n }\n interface RouterEvents {\n onInjectedHtml: {\n type: 'onInjectedHtml'\n }\n onSerializationFinished: {\n type: 'onSerializationFinished'\n }\n }\n}\n\nconst SCOPE_ID = 'tsr'\n\nexport function dehydrateMatch(match: AnyRouteMatch): DehydratedMatch {\n const dehydratedMatch: DehydratedMatch = {\n i: 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 return dehydratedMatch\n}\n\nconst INITIAL_SCRIPTS = [\n getCrossReferenceHeader(SCOPE_ID),\n minifiedTsrBootStrapScript,\n]\n\nclass ScriptBuffer {\n private router: AnyRouter | undefined\n private _queue: Array<string>\n private _scriptBarrierLifted = false\n private _cleanedUp = false\n private _pendingMicrotask = false\n\n constructor(router: AnyRouter) {\n this.router = router\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 barrier is lifted, schedule injection (if not already scheduled)\n if (this._scriptBarrierLifted && !this._pendingMicrotask) {\n this._pendingMicrotask = true\n queueMicrotask(() => {\n this._pendingMicrotask = false\n this.injectBufferedScripts()\n })\n }\n }\n\n liftBarrier() {\n if (this._scriptBarrierLifted || this._cleanedUp) return\n this._scriptBarrierLifted = true\n if (this._queue.length > 0 && !this._pendingMicrotask) {\n this._pendingMicrotask = true\n queueMicrotask(() => {\n this._pendingMicrotask = false\n this.injectBufferedScripts()\n })\n }\n }\n\n /**\n * Flushes any pending scripts synchronously.\n * Call this before emitting onSerializationFinished 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._pendingMicrotask = false\n const scriptsToInject = this.takeAll()\n if (scriptsToInject && this.router?.serverSsr) {\n this.router.serverSsr.injectScript(scriptsToInject)\n }\n }\n\n takeAll() {\n const bufferedScripts = this._queue\n this._queue = []\n if (bufferedScripts.length === 0) {\n return undefined\n }\n // Append cleanup script and join - avoid push() to not mutate then iterate\n return bufferedScripts.join(';') + ';document.currentScript.remove()'\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 && this.router?.serverSsr) {\n this.router.serverSsr.injectScript(scriptsToInject)\n }\n }\n\n cleanup() {\n this._cleanedUp = true\n this._queue = []\n this.router = undefined\n }\n}\n\nexport function attachRouterServerSsrUtils({\n router,\n manifest,\n}: {\n router: AnyRouter\n manifest: Manifest | undefined\n}) {\n router.ssr = {\n manifest,\n }\n let _dehydrated = false\n let _serializationFinished = false\n const renderFinishedListeners: Array<() => void> = []\n const serializationFinishedListeners: Array<() => void> = []\n const scriptBuffer = new ScriptBuffer(router)\n let injectedHtmlBuffer: Array<string> = []\n\n router.serverSsr = {\n injectHtml: (html: string) => {\n if (!html) return\n // Buffer the HTML so it can be retrieved via takeBufferedHtml()\n injectedHtmlBuffer.push(html)\n // Emit event to notify subscribers that new HTML is available\n router.emit({\n type: 'onInjectedHtml',\n })\n },\n injectScript: (script: string) => {\n if (!script) return\n const html = `<script${router.options.ssr?.nonce ? ` nonce='${router.options.ssr.nonce}'` : ''}>${script}</script>`\n router.serverSsr!.injectHtml(html)\n },\n dehydrate: async () => {\n invariant(!_dehydrated, 'router is already dehydrated!')\n let matchesToDehydrate = router.state.matches\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 // For currently matched routes, send full manifest (preloads + assets)\n // For all other routes, only send assets (no preloads as they are handled via dynamic imports)\n if (manifest) {\n const currentRouteIds = new Set(\n router.state.matches.map((k) => k.routeId),\n )\n const filteredRoutes = Object.fromEntries(\n Object.entries(manifest.routes).flatMap(\n ([routeId, routeManifest]) => {\n if (currentRouteIds.has(routeId)) {\n return [[routeId, routeManifest]]\n } else if (\n routeManifest.assets &&\n routeManifest.assets.length > 0\n ) {\n return [\n [\n routeId,\n {\n assets: routeManifest.assets,\n },\n ],\n ]\n }\n return []\n },\n ),\n )\n manifestToDehydrate = {\n routes: filteredRoutes,\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 = 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 const signalSerializationComplete = () => {\n _serializationFinished = true\n try {\n serializationFinishedListeners.forEach((l) => l())\n router.emit({ type: 'onSerializationFinished' })\n } catch (err) {\n console.error('Serialization listener error:', err)\n } finally {\n serializationFinishedListeners.length = 0\n renderFinishedListeners.length = 0\n }\n }\n\n crossSerializeStream(dehydratedRouter, {\n refs: new Map(),\n plugins,\n onSerialize: (data, initial) => {\n let serialized = initial ? GLOBAL_TSR + '.router=' + data : data\n if (trackPlugins.didRun) {\n serialized = GLOBAL_TSR + '.p(()=>' + serialized + ')'\n }\n scriptBuffer.enqueue(serialized)\n },\n scopeId: SCOPE_ID,\n onDone: () => {\n scriptBuffer.enqueue(GLOBAL_TSR + '.e()')\n // Flush all pending scripts synchronously before signaling completion\n // This ensures all scripts are injected before onSerializationFinished is emitted\n scriptBuffer.flush()\n signalSerializationComplete()\n },\n onError: (err) => {\n console.error('Serialization error:', err)\n signalSerializationComplete()\n },\n })\n },\n isDehydrated() {\n return _dehydrated\n },\n isSerializationFinished() {\n return _serializationFinished\n },\n onRenderFinished: (listener) => renderFinishedListeners.push(listener),\n onSerializationFinished: (listener) =>\n serializationFinishedListeners.push(listener),\n setRenderFinished: () => {\n // Wrap in try-catch to ensure scriptBuffer.liftBarrier() is always called\n try {\n renderFinishedListeners.forEach((l) => l())\n } catch (err) {\n console.error('Error in render finished listener:', err)\n } finally {\n // Clear listeners after calling them to prevent memory leaks\n renderFinishedListeners.length = 0\n }\n scriptBuffer.liftBarrier()\n },\n takeBufferedScripts() {\n const scripts = scriptBuffer.takeAll()\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.length === 0) {\n return undefined\n }\n const buffered = injectedHtmlBuffer.join('')\n injectedHtmlBuffer = []\n return buffered\n },\n cleanup() {\n // Guard against multiple cleanup calls\n if (!router.serverSsr) return\n renderFinishedListeners.length = 0\n serializationFinishedListeners.length = 0\n injectedHtmlBuffer = []\n scriptBuffer.cleanup()\n router.serverSsr = undefined\n },\n }\n}\n\nexport function getOrigin(request: Request) {\n const originHeader = request.headers.get('Origin')\n if (originHeader) {\n try {\n new URL(originHeader)\n return originHeader\n } catch {}\n }\n try {\n return new URL(request.url).origin\n } catch {}\n return 'http://localhost'\n}\n"],"names":["getCrossReferenceHeader","minifiedTsrBootStrapScript","makeSsrSerovalPlugin","defaultSerovalPlugins","crossSerializeStream","GLOBAL_TSR","TSR_SCRIPT_BARRIER_ID"],"mappings":"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"}
|