@tanstack/router-core 1.125.4 → 1.127.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 (77) hide show
  1. package/dist/cjs/Matches.cjs.map +1 -1
  2. package/dist/cjs/Matches.d.cts +1 -1
  3. package/dist/cjs/RouterProvider.d.cts +1 -0
  4. package/dist/cjs/index.d.cts +1 -2
  5. package/dist/cjs/router.cjs +26 -33
  6. package/dist/cjs/router.cjs.map +1 -1
  7. package/dist/cjs/router.d.cts +10 -57
  8. package/dist/cjs/ssr/client.cjs +0 -2
  9. package/dist/cjs/ssr/client.cjs.map +1 -1
  10. package/dist/cjs/ssr/client.d.cts +1 -2
  11. package/dist/cjs/ssr/createRequestHandler.cjs +2 -1
  12. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
  13. package/dist/cjs/ssr/seroval-plugins.cjs +34 -0
  14. package/dist/cjs/ssr/seroval-plugins.cjs.map +1 -0
  15. package/dist/cjs/ssr/seroval-plugins.d.cts +10 -0
  16. package/dist/cjs/ssr/server.cjs +0 -4
  17. package/dist/cjs/ssr/server.cjs.map +1 -1
  18. package/dist/cjs/ssr/server.d.cts +1 -3
  19. package/dist/cjs/ssr/ssr-client.cjs +18 -56
  20. package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
  21. package/dist/cjs/ssr/ssr-client.d.cts +17 -57
  22. package/dist/cjs/ssr/ssr-server.cjs +75 -220
  23. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  24. package/dist/cjs/ssr/ssr-server.d.cts +14 -28
  25. package/dist/cjs/ssr/transformStreamWithRouter.cjs +1 -0
  26. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
  27. package/dist/cjs/ssr/tsrScript.cjs +1 -1
  28. package/dist/cjs/ssr/tsrScript.cjs.map +1 -1
  29. package/dist/cjs/ssr/tsrScript.d.cts +0 -1
  30. package/dist/esm/Matches.d.ts +1 -1
  31. package/dist/esm/Matches.js.map +1 -1
  32. package/dist/esm/RouterProvider.d.ts +1 -0
  33. package/dist/esm/index.d.ts +1 -2
  34. package/dist/esm/router.d.ts +10 -57
  35. package/dist/esm/router.js +26 -33
  36. package/dist/esm/router.js.map +1 -1
  37. package/dist/esm/ssr/client.d.ts +1 -2
  38. package/dist/esm/ssr/client.js +1 -3
  39. package/dist/esm/ssr/client.js.map +1 -1
  40. package/dist/esm/ssr/createRequestHandler.js +3 -2
  41. package/dist/esm/ssr/createRequestHandler.js.map +1 -1
  42. package/dist/esm/ssr/seroval-plugins.d.ts +10 -0
  43. package/dist/esm/ssr/seroval-plugins.js +34 -0
  44. package/dist/esm/ssr/seroval-plugins.js.map +1 -0
  45. package/dist/esm/ssr/server.d.ts +1 -3
  46. package/dist/esm/ssr/server.js +1 -5
  47. package/dist/esm/ssr/ssr-client.d.ts +17 -57
  48. package/dist/esm/ssr/ssr-client.js +18 -56
  49. package/dist/esm/ssr/ssr-client.js.map +1 -1
  50. package/dist/esm/ssr/ssr-server.d.ts +14 -28
  51. package/dist/esm/ssr/ssr-server.js +76 -221
  52. package/dist/esm/ssr/ssr-server.js.map +1 -1
  53. package/dist/esm/ssr/transformStreamWithRouter.js +1 -0
  54. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
  55. package/dist/esm/ssr/tsrScript.d.ts +0 -1
  56. package/dist/esm/ssr/tsrScript.js +1 -1
  57. package/dist/esm/ssr/tsrScript.js.map +1 -1
  58. package/package.json +3 -1
  59. package/src/Matches.ts +1 -1
  60. package/src/RouterProvider.ts +1 -0
  61. package/src/index.ts +0 -18
  62. package/src/router.ts +41 -89
  63. package/src/ssr/client.ts +1 -11
  64. package/src/ssr/createRequestHandler.ts +2 -2
  65. package/src/ssr/seroval-plugins.ts +43 -0
  66. package/src/ssr/server.ts +1 -14
  67. package/src/ssr/ssr-client.ts +35 -128
  68. package/src/ssr/ssr-server.ts +89 -307
  69. package/src/ssr/transformStreamWithRouter.ts +1 -0
  70. package/src/ssr/tsrScript.ts +4 -88
  71. package/dist/cjs/serializer.cjs +0 -146
  72. package/dist/cjs/serializer.cjs.map +0 -1
  73. package/dist/cjs/serializer.d.cts +0 -28
  74. package/dist/esm/serializer.d.ts +0 -28
  75. package/dist/esm/serializer.js +0 -146
  76. package/dist/esm/serializer.js.map +0 -1
  77. package/src/serializer.ts +0 -205
@@ -2,5 +2,4 @@ export { mergeHeaders, headersInitToObject } from './headers.js';
2
2
  export { json } from './json.js';
3
3
  export type { JsonResponse } from './json.js';
4
4
  export { hydrate } from './ssr-client.js';
5
- export type { DehydratedRouter, ClientExtractedBaseEntry, TsrSsrGlobal, ClientExtractedEntry, SsrMatch, ClientExtractedPromise, ClientExtractedStream, ResolvePromiseState, } from './ssr-client.js';
6
- export { tsrSerializer } from '../serializer.js';
5
+ export * from './ssr-client.js';
@@ -1,12 +1,10 @@
1
1
  import { headersInitToObject, mergeHeaders } from "./headers.js";
2
2
  import { json } from "./json.js";
3
3
  import { hydrate } from "./ssr-client.js";
4
- import { tsrSerializer } from "../serializer.js";
5
4
  export {
6
5
  headersInitToObject,
7
6
  hydrate,
8
7
  json,
9
- mergeHeaders,
10
- tsrSerializer
8
+ mergeHeaders
11
9
  };
12
10
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
1
+ {"version":3,"file":"client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
@@ -1,12 +1,13 @@
1
1
  import { createMemoryHistory } from "@tanstack/history";
2
2
  import { mergeHeaders } from "./headers.js";
3
- import { attachRouterServerSsrUtils, dehydrateRouter } from "./ssr-server.js";
3
+ import { attachRouterServerSsrUtils } from "./ssr-server.js";
4
4
  function createRequestHandler({
5
5
  createRouter,
6
6
  request,
7
7
  getRouterManifest
8
8
  }) {
9
9
  return async (cb) => {
10
+ var _a;
10
11
  const router = createRouter();
11
12
  attachRouterServerSsrUtils(router, await (getRouterManifest == null ? void 0 : getRouterManifest()));
12
13
  const url = new URL(request.url, "http://localhost");
@@ -18,7 +19,7 @@ function createRequestHandler({
18
19
  history
19
20
  });
20
21
  await router.load();
21
- dehydrateRouter(router);
22
+ await ((_a = router.serverSsr) == null ? void 0 : _a.dehydrate());
22
23
  const responseHeaders = getRequestHeaders({
23
24
  router
24
25
  });
@@ -1 +1 @@
1
- {"version":3,"file":"createRequestHandler.js","sources":["../../../src/ssr/createRequestHandler.ts"],"sourcesContent":["import { createMemoryHistory } from '@tanstack/history'\nimport { mergeHeaders } from './headers'\nimport { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server'\nimport type { HandlerCallback } from './handlerCallback'\nimport type { AnyRouter } from '../router'\nimport type { Manifest } from '../manifest'\n\nexport type RequestHandler<TRouter extends AnyRouter> = (\n cb: HandlerCallback<TRouter>,\n) => Promise<Response>\n\nexport function createRequestHandler<TRouter extends AnyRouter>({\n createRouter,\n request,\n getRouterManifest,\n}: {\n createRouter: () => TRouter\n request: Request\n getRouterManifest?: () => Manifest | Promise<Manifest>\n}): RequestHandler<TRouter> {\n return async (cb) => {\n const router = createRouter()\n\n attachRouterServerSsrUtils(router, await getRouterManifest?.())\n\n const url = new URL(request.url, 'http://localhost')\n\n const href = url.href.replace(url.origin, '')\n\n // Create a history for the router\n const history = createMemoryHistory({\n initialEntries: [href],\n })\n\n // Update the router with the history and context\n router.update({\n history,\n })\n\n await router.load()\n\n dehydrateRouter(router)\n\n const responseHeaders = getRequestHeaders({\n router,\n })\n\n return cb({\n request,\n router,\n responseHeaders,\n } as any)\n }\n}\n\nfunction getRequestHeaders(opts: { router: AnyRouter }): Headers {\n let headers = mergeHeaders(\n {\n 'Content-Type': 'text/html; charset=UTF-8',\n },\n ...opts.router.state.matches.map((match) => {\n return match.headers\n }),\n )\n\n // Handle Redirects\n const { redirect } = opts.router.state\n\n if (redirect) {\n headers = mergeHeaders(headers, redirect.headers)\n }\n\n return headers\n}\n"],"names":[],"mappings":";;;AAWO,SAAS,qBAAgD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AACF,GAI4B;AAC1B,SAAO,OAAO,OAAO;AACnB,UAAM,SAAS,aAAa;AAED,+BAAA,QAAQ,OAAM,yDAAqB;AAE9D,UAAM,MAAM,IAAI,IAAI,QAAQ,KAAK,kBAAkB;AAEnD,UAAM,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,EAAE;AAG5C,UAAM,UAAU,oBAAoB;AAAA,MAClC,gBAAgB,CAAC,IAAI;AAAA,IAAA,CACtB;AAGD,WAAO,OAAO;AAAA,MACZ;AAAA,IAAA,CACD;AAED,UAAM,OAAO,KAAK;AAElB,oBAAgB,MAAM;AAEtB,UAAM,kBAAkB,kBAAkB;AAAA,MACxC;AAAA,IAAA,CACD;AAED,WAAO,GAAG;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACM;AAAA,EACV;AACF;AAEA,SAAS,kBAAkB,MAAsC;AAC/D,MAAI,UAAU;AAAA,IACZ;AAAA,MACE,gBAAgB;AAAA,IAClB;AAAA,IACA,GAAG,KAAK,OAAO,MAAM,QAAQ,IAAI,CAAC,UAAU;AAC1C,aAAO,MAAM;AAAA,IACd,CAAA;AAAA,EACH;AAGA,QAAM,EAAE,SAAA,IAAa,KAAK,OAAO;AAEjC,MAAI,UAAU;AACF,cAAA,aAAa,SAAS,SAAS,OAAO;AAAA,EAAA;AAG3C,SAAA;AACT;"}
1
+ {"version":3,"file":"createRequestHandler.js","sources":["../../../src/ssr/createRequestHandler.ts"],"sourcesContent":["import { createMemoryHistory } from '@tanstack/history'\nimport { mergeHeaders } from './headers'\nimport { attachRouterServerSsrUtils } from './ssr-server'\nimport type { HandlerCallback } from './handlerCallback'\nimport type { AnyRouter } from '../router'\nimport type { Manifest } from '../manifest'\n\nexport type RequestHandler<TRouter extends AnyRouter> = (\n cb: HandlerCallback<TRouter>,\n) => Promise<Response>\n\nexport function createRequestHandler<TRouter extends AnyRouter>({\n createRouter,\n request,\n getRouterManifest,\n}: {\n createRouter: () => TRouter\n request: Request\n getRouterManifest?: () => Manifest | Promise<Manifest>\n}): RequestHandler<TRouter> {\n return async (cb) => {\n const router = createRouter()\n\n attachRouterServerSsrUtils(router, await getRouterManifest?.())\n\n const url = new URL(request.url, 'http://localhost')\n\n const href = url.href.replace(url.origin, '')\n\n // Create a history for the router\n const history = createMemoryHistory({\n initialEntries: [href],\n })\n\n // Update the router with the history and context\n router.update({\n history,\n })\n\n await router.load()\n\n await router.serverSsr?.dehydrate()\n\n const responseHeaders = getRequestHeaders({\n router,\n })\n\n return cb({\n request,\n router,\n responseHeaders,\n } as any)\n }\n}\n\nfunction getRequestHeaders(opts: { router: AnyRouter }): Headers {\n let headers = mergeHeaders(\n {\n 'Content-Type': 'text/html; charset=UTF-8',\n },\n ...opts.router.state.matches.map((match) => {\n return match.headers\n }),\n )\n\n // Handle Redirects\n const { redirect } = opts.router.state\n\n if (redirect) {\n headers = mergeHeaders(headers, redirect.headers)\n }\n\n return headers\n}\n"],"names":[],"mappings":";;;AAWO,SAAS,qBAAgD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AACF,GAI4B;AAC1B,SAAO,OAAO,OAAO;;AACnB,UAAM,SAAS,aAAa;AAED,+BAAA,QAAQ,OAAM,yDAAqB;AAE9D,UAAM,MAAM,IAAI,IAAI,QAAQ,KAAK,kBAAkB;AAEnD,UAAM,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,EAAE;AAG5C,UAAM,UAAU,oBAAoB;AAAA,MAClC,gBAAgB,CAAC,IAAI;AAAA,IAAA,CACtB;AAGD,WAAO,OAAO;AAAA,MACZ;AAAA,IAAA,CACD;AAED,UAAM,OAAO,KAAK;AAEZ,YAAA,YAAO,cAAP,mBAAkB;AAExB,UAAM,kBAAkB,kBAAkB;AAAA,MACxC;AAAA,IAAA,CACD;AAED,WAAO,GAAG;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACM;AAAA,EACV;AACF;AAEA,SAAS,kBAAkB,MAAsC;AAC/D,MAAI,UAAU;AAAA,IACZ;AAAA,MACE,gBAAgB;AAAA,IAClB;AAAA,IACA,GAAG,KAAK,OAAO,MAAM,QAAQ,IAAI,CAAC,UAAU;AAC1C,aAAO,MAAM;AAAA,IACd,CAAA;AAAA,EACH;AAGA,QAAM,EAAE,SAAA,IAAa,KAAK,OAAO;AAEjC,MAAI,UAAU;AACF,cAAA,aAAa,SAAS,SAAS,OAAO;AAAA,EAAA;AAG3C,SAAA;AACT;"}
@@ -0,0 +1,10 @@
1
+ import { SerovalNode } from 'seroval';
2
+ interface ErrorNode {
3
+ message: SerovalNode;
4
+ }
5
+ /**
6
+ * this plugin serializes only the `message` part of an Error
7
+ * this helps with serializing e.g. a ZodError which has functions attached that cannot be serialized
8
+ */
9
+ export declare const ShallowErrorPlugin: import('seroval').Plugin<Error, ErrorNode>;
10
+ export {};
@@ -0,0 +1,34 @@
1
+ import { createPlugin } from "seroval";
2
+ const ShallowErrorPlugin = /* @__PURE__ */ createPlugin({
3
+ tag: "tanstack-start:seroval-plugins/Error",
4
+ test(value) {
5
+ return value instanceof Error;
6
+ },
7
+ parse: {
8
+ sync(value, ctx) {
9
+ return {
10
+ message: ctx.parse(value.message)
11
+ };
12
+ },
13
+ async async(value, ctx) {
14
+ return {
15
+ message: await ctx.parse(value.message)
16
+ };
17
+ },
18
+ stream(value, ctx) {
19
+ return {
20
+ message: ctx.parse(value.message)
21
+ };
22
+ }
23
+ },
24
+ serialize(node, ctx) {
25
+ return "new Error(" + ctx.serialize(node.message) + ")";
26
+ },
27
+ deserialize(node, ctx) {
28
+ return new Error(ctx.deserialize(node.message));
29
+ }
30
+ });
31
+ export {
32
+ ShallowErrorPlugin
33
+ };
34
+ //# sourceMappingURL=seroval-plugins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seroval-plugins.js","sources":["../../../src/ssr/seroval-plugins.ts"],"sourcesContent":["import { createPlugin } from 'seroval'\nimport type { SerovalNode } from 'seroval'\n\ninterface ErrorNode {\n message: SerovalNode\n}\n\n/**\n * this plugin serializes only the `message` part of an Error\n * this helps with serializing e.g. a ZodError which has functions attached that cannot be serialized\n */\nexport const ShallowErrorPlugin = /* @__PURE__ */ createPlugin<\n Error,\n ErrorNode\n>({\n tag: 'tanstack-start:seroval-plugins/Error',\n test(value) {\n return value instanceof Error\n },\n parse: {\n sync(value, ctx) {\n return {\n message: ctx.parse(value.message),\n }\n },\n async async(value, ctx) {\n return {\n message: await ctx.parse(value.message),\n }\n },\n stream(value, ctx) {\n return {\n message: ctx.parse(value.message),\n }\n },\n },\n serialize(node, ctx) {\n return 'new Error(' + ctx.serialize(node.message) + ')'\n },\n deserialize(node, ctx) {\n return new Error(ctx.deserialize(node.message) as string)\n },\n})\n"],"names":[],"mappings":";AAWO,MAAM,qBAGX,6BAAA;AAAA,EACA,KAAK;AAAA,EACL,KAAK,OAAO;AACV,WAAO,iBAAiB;AAAA,EAC1B;AAAA,EACA,OAAO;AAAA,IACL,KAAK,OAAO,KAAK;AACR,aAAA;AAAA,QACL,SAAS,IAAI,MAAM,MAAM,OAAO;AAAA,MAClC;AAAA,IACF;AAAA,IACA,MAAM,MAAM,OAAO,KAAK;AACf,aAAA;AAAA,QACL,SAAS,MAAM,IAAI,MAAM,MAAM,OAAO;AAAA,MACxC;AAAA,IACF;AAAA,IACA,OAAO,OAAO,KAAK;AACV,aAAA;AAAA,QACL,SAAS,IAAI,MAAM,MAAM,OAAO;AAAA,MAClC;AAAA,IAAA;AAAA,EAEJ;AAAA,EACA,UAAU,MAAM,KAAK;AACnB,WAAO,eAAe,IAAI,UAAU,KAAK,OAAO,IAAI;AAAA,EACtD;AAAA,EACA,YAAY,MAAM,KAAK;AACrB,WAAO,IAAI,MAAM,IAAI,YAAY,KAAK,OAAO,CAAW;AAAA,EAAA;AAE5D,CAAC;"}
@@ -3,6 +3,4 @@ export type { RequestHandler } from './createRequestHandler.js';
3
3
  export { defineHandlerCallback } from './handlerCallback.js';
4
4
  export type { HandlerCallback } from './handlerCallback.js';
5
5
  export { transformPipeableStreamWithRouter, transformStreamWithRouter, transformReadableStreamWithRouter, } from './transformStreamWithRouter.js';
6
- export { attachRouterServerSsrUtils, dehydrateRouter, extractAsyncLoaderData, onMatchSettled, replaceBy, } from './ssr-server.js';
7
- export type { ServerExtractedBaseEntry, ServerExtractedEntry, ServerExtractedPromise, ServerExtractedStream, } from './ssr-server.js';
8
- export * from './tsrScript.js';
6
+ export { attachRouterServerSsrUtils } from './ssr-server.js';
@@ -1,15 +1,11 @@
1
1
  import { createRequestHandler } from "./createRequestHandler.js";
2
2
  import { defineHandlerCallback } from "./handlerCallback.js";
3
3
  import { transformPipeableStreamWithRouter, transformReadableStreamWithRouter, transformStreamWithRouter } from "./transformStreamWithRouter.js";
4
- import { attachRouterServerSsrUtils, dehydrateRouter, extractAsyncLoaderData, onMatchSettled, replaceBy } from "./ssr-server.js";
4
+ import { attachRouterServerSsrUtils } from "./ssr-server.js";
5
5
  export {
6
6
  attachRouterServerSsrUtils,
7
7
  createRequestHandler,
8
8
  defineHandlerCallback,
9
- dehydrateRouter,
10
- extractAsyncLoaderData,
11
- onMatchSettled,
12
- replaceBy,
13
9
  transformPipeableStreamWithRouter,
14
10
  transformReadableStreamWithRouter,
15
11
  transformStreamWithRouter
@@ -1,69 +1,29 @@
1
- import { DeferredPromiseState } from '../defer.js';
2
1
  import { MakeRouteMatch } from '../Matches.js';
3
- import { AnyRouter, ControllablePromise } from '../router.js';
2
+ import { AnyRouter } from '../router.js';
4
3
  import { Manifest } from '../manifest.js';
4
+ import { GLOBAL_TSR } from './ssr-server.js';
5
5
  declare global {
6
6
  interface Window {
7
- __TSR_SSR__?: TsrSsrGlobal;
7
+ [GLOBAL_TSR]?: TsrSsrGlobal;
8
8
  }
9
9
  }
10
10
  export interface TsrSsrGlobal {
11
- matches: Array<SsrMatch>;
12
- streamedValues: Record<string, {
13
- value: any;
14
- parsed: any;
15
- }>;
16
- cleanScripts: () => void;
17
- dehydrated?: any;
18
- initMatch: (match: SsrMatch) => void;
19
- resolvePromise: (opts: {
20
- matchId: string;
21
- id: number;
22
- promiseState: DeferredPromiseState<any>;
23
- }) => void;
24
- injectChunk: (opts: {
25
- matchId: string;
26
- id: number;
27
- chunk: string;
28
- }) => void;
29
- closeStream: (opts: {
30
- matchId: string;
31
- id: number;
32
- }) => void;
33
- }
34
- export interface SsrMatch {
35
- id: string;
36
- __beforeLoadContext: string;
37
- loaderData?: string;
38
- error?: string;
39
- extracted?: Array<ClientExtractedEntry>;
40
- updatedAt: MakeRouteMatch['updatedAt'];
41
- status: MakeRouteMatch['status'];
42
- ssr?: boolean | 'data-only';
43
- }
44
- export type ClientExtractedEntry = ClientExtractedStream | ClientExtractedPromise;
45
- export interface ClientExtractedPromise extends ClientExtractedBaseEntry {
46
- type: 'promise';
47
- value?: ControllablePromise<any>;
48
- }
49
- export interface ClientExtractedStream extends ClientExtractedBaseEntry {
50
- type: 'stream';
51
- value?: ReadableStream & {
52
- controller?: ReadableStreamDefaultController;
53
- };
54
- }
55
- export interface ClientExtractedBaseEntry {
56
- type: string;
57
- path: Array<string>;
58
- }
59
- export interface ResolvePromiseState {
60
- matchId: string;
61
- id: number;
62
- promiseState: DeferredPromiseState<any>;
11
+ router?: DehydratedRouter;
12
+ c: () => void;
13
+ }
14
+ export interface DehydratedMatch {
15
+ i: MakeRouteMatch['id'];
16
+ b?: MakeRouteMatch['__beforeLoadContext'];
17
+ l?: MakeRouteMatch['loaderData'];
18
+ e?: MakeRouteMatch['error'];
19
+ u: MakeRouteMatch['updatedAt'];
20
+ s: MakeRouteMatch['status'];
21
+ ssr?: MakeRouteMatch['ssr'];
63
22
  }
64
23
  export interface DehydratedRouter {
65
24
  manifest: Manifest | undefined;
66
- dehydratedData: any;
67
- lastMatchId: string;
25
+ dehydratedData?: any;
26
+ lastMatchId?: string;
27
+ matches: Array<DehydratedMatch>;
68
28
  }
69
29
  export declare function hydrate(router: AnyRouter): Promise<any>;
@@ -1,34 +1,24 @@
1
1
  import invariant from "tiny-invariant";
2
- import { isPlainObject } from "../utils.js";
3
- import { tsrSerializer } from "../serializer.js";
2
+ function hydrateMatch(deyhydratedMatch) {
3
+ return {
4
+ id: deyhydratedMatch.i,
5
+ __beforeLoadContext: deyhydratedMatch.b,
6
+ loaderData: deyhydratedMatch.l,
7
+ status: deyhydratedMatch.s,
8
+ ssr: deyhydratedMatch.ssr,
9
+ updatedAt: deyhydratedMatch.u,
10
+ error: deyhydratedMatch.e
11
+ };
12
+ }
4
13
  async function hydrate(router) {
5
14
  var _a, _b, _c;
6
15
  invariant(
7
- (_a = window.__TSR_SSR__) == null ? void 0 : _a.dehydrated,
8
- "Expected to find a dehydrated data on window.__TSR_SSR__.dehydrated... but we did not. Please file an issue!"
9
- );
10
- const { manifest, dehydratedData, lastMatchId } = tsrSerializer.parse(
11
- window.__TSR_SSR__.dehydrated
16
+ (_a = window.$_TSR) == null ? void 0 : _a.router,
17
+ "Expected to find a dehydrated data on window.$_TSR.router, but we did not. Please file an issue!"
12
18
  );
19
+ const { manifest, dehydratedData, lastMatchId } = window.$_TSR.router;
13
20
  router.ssr = {
14
- manifest,
15
- serializer: tsrSerializer
16
- };
17
- router.clientSsr = {
18
- getStreamedValue: (key) => {
19
- var _a2;
20
- if (router.isServer) {
21
- return void 0;
22
- }
23
- const streamedValue = (_a2 = window.__TSR_SSR__) == null ? void 0 : _a2.streamedValues[key];
24
- if (!streamedValue) {
25
- return;
26
- }
27
- if (!streamedValue.parsed) {
28
- streamedValue.parsed = router.ssr.serializer.parse(streamedValue.value);
29
- }
30
- return streamedValue.parsed;
31
- }
21
+ manifest
32
22
  };
33
23
  const matches = router.matchRoutes(router.state.location);
34
24
  const routeChunkPromise = Promise.all(
@@ -39,15 +29,14 @@ async function hydrate(router) {
39
29
  );
40
30
  let firstNonSsrMatchIndex = void 0;
41
31
  matches.forEach((match) => {
42
- var _a2;
43
- const dehydratedMatch = window.__TSR_SSR__.matches.find(
44
- (d) => d.id === match.id
32
+ const dehydratedMatch = window.$_TSR.router.matches.find(
33
+ (d) => d.i === match.id
45
34
  );
46
35
  if (!dehydratedMatch) {
47
36
  Object.assign(match, { dehydrated: false, ssr: false });
48
37
  return;
49
38
  }
50
- Object.assign(match, dehydratedMatch);
39
+ Object.assign(match, hydrateMatch(dehydratedMatch));
51
40
  if (match.ssr === false) {
52
41
  match._dehydrated = false;
53
42
  } else {
@@ -62,22 +51,6 @@ async function hydrate(router) {
62
51
  if (match.ssr === false) {
63
52
  return;
64
53
  }
65
- if (dehydratedMatch.__beforeLoadContext) {
66
- match.__beforeLoadContext = router.ssr.serializer.parse(
67
- dehydratedMatch.__beforeLoadContext
68
- );
69
- }
70
- if (dehydratedMatch.loaderData) {
71
- match.loaderData = router.ssr.serializer.parse(
72
- dehydratedMatch.loaderData
73
- );
74
- }
75
- if (dehydratedMatch.error) {
76
- match.error = router.ssr.serializer.parse(dehydratedMatch.error);
77
- }
78
- (_a2 = match.extracted) == null ? void 0 : _a2.forEach((ex) => {
79
- deepMutableSetByPath(match, ["loaderData", ...ex.path], ex.value);
80
- });
81
54
  });
82
55
  router.__store.setState((s) => {
83
56
  return {
@@ -151,17 +124,6 @@ async function hydrate(router) {
151
124
  }
152
125
  return routeChunkPromise;
153
126
  }
154
- function deepMutableSetByPath(obj, path, value) {
155
- if (path.length === 1) {
156
- obj[path[0]] = value;
157
- }
158
- const [key, ...rest] = path;
159
- if (Array.isArray(obj)) {
160
- deepMutableSetByPath(obj[Number(key)], rest, value);
161
- } else if (isPlainObject(obj)) {
162
- deepMutableSetByPath(obj[key], rest, value);
163
- }
164
- }
165
127
  export {
166
128
  hydrate
167
129
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-client.js","sources":["../../../src/ssr/ssr-client.ts"],"sourcesContent":["import invariant from 'tiny-invariant'\nimport { isPlainObject } from '../utils'\nimport { tsrSerializer } from '../serializer'\nimport type { DeferredPromiseState } from '../defer'\nimport type { MakeRouteMatch } from '../Matches'\nimport type { AnyRouter, ControllablePromise } from '../router'\nimport type { Manifest } from '../manifest'\nimport type { RouteContextOptions } from '../route'\n\ndeclare global {\n interface Window {\n __TSR_SSR__?: TsrSsrGlobal\n }\n}\n\nexport interface TsrSsrGlobal {\n matches: Array<SsrMatch>\n streamedValues: Record<\n string,\n {\n value: any\n parsed: any\n }\n >\n cleanScripts: () => void\n dehydrated?: any\n initMatch: (match: SsrMatch) => void\n resolvePromise: (opts: {\n matchId: string\n id: number\n promiseState: DeferredPromiseState<any>\n }) => void\n injectChunk: (opts: { matchId: string; id: number; chunk: string }) => void\n closeStream: (opts: { matchId: string; id: number }) => void\n}\n\nexport interface SsrMatch {\n id: string\n __beforeLoadContext: string\n loaderData?: string\n error?: string\n extracted?: Array<ClientExtractedEntry>\n updatedAt: MakeRouteMatch['updatedAt']\n status: MakeRouteMatch['status']\n ssr?: boolean | 'data-only'\n}\n\nexport type ClientExtractedEntry =\n | ClientExtractedStream\n | ClientExtractedPromise\n\nexport interface ClientExtractedPromise extends ClientExtractedBaseEntry {\n type: 'promise'\n value?: ControllablePromise<any>\n}\n\nexport interface ClientExtractedStream extends ClientExtractedBaseEntry {\n type: 'stream'\n value?: ReadableStream & { controller?: ReadableStreamDefaultController }\n}\n\nexport interface ClientExtractedBaseEntry {\n type: string\n path: Array<string>\n}\n\nexport interface ResolvePromiseState {\n matchId: string\n id: number\n promiseState: DeferredPromiseState<any>\n}\n\nexport interface DehydratedRouter {\n manifest: Manifest | undefined\n dehydratedData: any\n lastMatchId: string\n}\n\nexport async function hydrate(router: AnyRouter): Promise<any> {\n invariant(\n window.__TSR_SSR__?.dehydrated,\n 'Expected to find a dehydrated data on window.__TSR_SSR__.dehydrated... but we did not. Please file an issue!',\n )\n\n const { manifest, dehydratedData, lastMatchId } = tsrSerializer.parse(\n window.__TSR_SSR__.dehydrated,\n ) as DehydratedRouter\n\n router.ssr = {\n manifest,\n serializer: tsrSerializer,\n }\n\n router.clientSsr = {\n getStreamedValue: <T>(key: string): T | undefined => {\n if (router.isServer) {\n return undefined\n }\n\n const streamedValue = window.__TSR_SSR__?.streamedValues[key]\n\n if (!streamedValue) {\n return\n }\n\n if (!streamedValue.parsed) {\n streamedValue.parsed = router.ssr!.serializer.parse(streamedValue.value)\n }\n\n return streamedValue.parsed\n },\n }\n\n // Hydrate the router state\n const matches = router.matchRoutes(router.state.location)\n\n // kick off loading the route chunks\n const routeChunkPromise = Promise.all(\n matches.map((match) => {\n const route = router.looseRoutesById[match.routeId]!\n return router.loadRouteChunk(route)\n }),\n )\n\n // Right after hydration and before the first render, we need to rehydrate each match\n // First step is to reyhdrate loaderData and __beforeLoadContext\n let firstNonSsrMatchIndex: number | undefined = undefined\n matches.forEach((match) => {\n const dehydratedMatch = window.__TSR_SSR__!.matches.find(\n (d) => d.id === match.id,\n )\n\n if (!dehydratedMatch) {\n Object.assign(match, { dehydrated: false, ssr: false })\n return\n }\n\n Object.assign(match, dehydratedMatch)\n\n if (match.ssr === false) {\n match._dehydrated = false\n } else {\n match._dehydrated = true\n }\n\n if (match.ssr === 'data-only' || match.ssr === false) {\n if (firstNonSsrMatchIndex === undefined) {\n firstNonSsrMatchIndex = match.index\n match._forcePending = true\n }\n }\n\n if (match.ssr === false) {\n return\n }\n\n // Handle beforeLoadContext\n if (dehydratedMatch.__beforeLoadContext) {\n match.__beforeLoadContext = router.ssr!.serializer.parse(\n dehydratedMatch.__beforeLoadContext,\n ) as any\n }\n\n // Handle loaderData\n if (dehydratedMatch.loaderData) {\n match.loaderData = router.ssr!.serializer.parse(\n dehydratedMatch.loaderData,\n )\n }\n\n // Handle error\n if (dehydratedMatch.error) {\n match.error = router.ssr!.serializer.parse(dehydratedMatch.error)\n }\n\n // Handle extracted\n ;(match as unknown as SsrMatch).extracted?.forEach((ex) => {\n deepMutableSetByPath(match, ['loaderData', ...ex.path], ex.value)\n })\n })\n\n router.__store.setState((s) => {\n return {\n ...s,\n matches,\n }\n })\n\n // Allow the user to handle custom hydration data\n await router.options.hydrate?.(dehydratedData)\n\n // now that all necessary data is hydrated:\n // 1) fully reconstruct the route context\n // 2) execute `head()` and `scripts()` for each match\n await Promise.all(\n router.state.matches.map(async (match) => {\n const route = router.looseRoutesById[match.routeId]!\n\n const parentMatch = router.state.matches[match.index - 1]\n const parentContext = parentMatch?.context ?? router.options.context ?? {}\n\n // `context()` was already executed by `matchRoutes`, however route context was not yet fully reconstructed\n // so run it again and merge route context\n const contextFnContext: RouteContextOptions<any, any, any, any> = {\n deps: match.loaderDeps,\n params: match.params,\n context: parentContext,\n location: router.state.location,\n navigate: (opts: any) =>\n router.navigate({ ...opts, _fromLocation: router.state.location }),\n buildLocation: router.buildLocation,\n cause: match.cause,\n abortController: match.abortController,\n preload: false,\n matches,\n }\n match.__routeContext = route.options.context?.(contextFnContext) ?? {}\n\n match.context = {\n ...parentContext,\n ...match.__routeContext,\n ...match.__beforeLoadContext,\n }\n\n const assetContext = {\n matches: router.state.matches,\n match,\n params: match.params,\n loaderData: match.loaderData,\n }\n const headFnContent = await route.options.head?.(assetContext)\n\n const scripts = await route.options.scripts?.(assetContext)\n\n match.meta = headFnContent?.meta\n match.links = headFnContent?.links\n match.headScripts = headFnContent?.scripts\n match.styles = headFnContent?.styles\n match.scripts = scripts\n }),\n )\n\n // schedule router.load() to run after the next tick so we can store the promise in the match before loading starts\n const loadPromise = Promise.resolve()\n .then(() => router.load())\n .catch((err) => {\n console.error('Error during router hydration:', err)\n })\n\n // in SPA mode we need to keep the outermost match pending until router.load() is finished\n // this will prevent that other pending components are rendered but hydration is not blocked\n if (matches[matches.length - 1]!.id !== lastMatchId) {\n const matchId = matches[0]!.id\n router.updateMatch(matchId, (prev) => {\n return {\n ...prev,\n _displayPending: true,\n displayPendingPromise: loadPromise,\n // make sure that the pending component is displayed for at least pendingMinMs\n _forcePending: true,\n }\n })\n // hide the pending component once the load is finished\n loadPromise.then(() => {\n router.updateMatch(matchId, (prev) => {\n return {\n ...prev,\n _displayPending: undefined,\n displayPendingPromise: undefined,\n }\n })\n })\n }\n\n return routeChunkPromise\n}\n\nfunction deepMutableSetByPath<T>(obj: T, path: Array<string>, value: any) {\n // mutable set by path retaining array and object references\n if (path.length === 1) {\n ;(obj as any)[path[0]!] = value\n }\n\n const [key, ...rest] = path\n\n if (Array.isArray(obj)) {\n deepMutableSetByPath(obj[Number(key)], rest, value)\n } else if (isPlainObject(obj)) {\n deepMutableSetByPath((obj as any)[key!], rest, value)\n }\n}\n"],"names":["_a","_b","_c"],"mappings":"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"}
1
+ {"version":3,"file":"ssr-client.js","sources":["../../../src/ssr/ssr-client.ts"],"sourcesContent":["import invariant from 'tiny-invariant'\nimport type { MakeRouteMatch } from '../Matches'\nimport type { AnyRouter } from '../router'\nimport type { Manifest } from '../manifest'\nimport type { RouteContextOptions } from '../route'\nimport type { GLOBAL_TSR } from './ssr-server'\n\ndeclare global {\n interface Window {\n [GLOBAL_TSR]?: TsrSsrGlobal\n }\n}\n\nexport interface TsrSsrGlobal {\n router?: DehydratedRouter\n // clean scripts, shortened since this is sent for each streamed script\n c: () => void\n}\n\nfunction hydrateMatch(\n deyhydratedMatch: DehydratedMatch,\n): Partial<MakeRouteMatch> {\n return {\n id: deyhydratedMatch.i,\n __beforeLoadContext: deyhydratedMatch.b,\n loaderData: deyhydratedMatch.l,\n status: deyhydratedMatch.s,\n ssr: deyhydratedMatch.ssr,\n updatedAt: deyhydratedMatch.u,\n error: deyhydratedMatch.e,\n }\n}\nexport interface DehydratedMatch {\n i: MakeRouteMatch['id']\n b?: MakeRouteMatch['__beforeLoadContext']\n l?: MakeRouteMatch['loaderData']\n e?: MakeRouteMatch['error']\n u: MakeRouteMatch['updatedAt']\n s: MakeRouteMatch['status']\n ssr?: MakeRouteMatch['ssr']\n}\n\nexport interface DehydratedRouter {\n manifest: Manifest | undefined\n dehydratedData?: any\n lastMatchId?: string\n matches: Array<DehydratedMatch>\n}\n\nexport async function hydrate(router: AnyRouter): Promise<any> {\n invariant(\n window.$_TSR?.router,\n 'Expected to find a dehydrated data on window.$_TSR.router, but we did not. Please file an issue!',\n )\n\n const { manifest, dehydratedData, lastMatchId } = window.$_TSR.router\n\n router.ssr = {\n manifest,\n }\n\n // Hydrate the router state\n const matches = router.matchRoutes(router.state.location)\n\n // kick off loading the route chunks\n const routeChunkPromise = Promise.all(\n matches.map((match) => {\n const route = router.looseRoutesById[match.routeId]!\n return router.loadRouteChunk(route)\n }),\n )\n\n // Right after hydration and before the first render, we need to rehydrate each match\n // First step is to reyhdrate loaderData and __beforeLoadContext\n let firstNonSsrMatchIndex: number | undefined = undefined\n matches.forEach((match) => {\n const dehydratedMatch = window.$_TSR!.router!.matches.find(\n (d) => d.i === match.id,\n )\n if (!dehydratedMatch) {\n Object.assign(match, { dehydrated: false, ssr: false })\n return\n }\n\n Object.assign(match, hydrateMatch(dehydratedMatch))\n\n if (match.ssr === false) {\n match._dehydrated = false\n } else {\n match._dehydrated = true\n }\n\n if (match.ssr === 'data-only' || match.ssr === false) {\n if (firstNonSsrMatchIndex === undefined) {\n firstNonSsrMatchIndex = match.index\n match._forcePending = true\n }\n }\n\n if (match.ssr === false) {\n return\n }\n })\n\n router.__store.setState((s) => {\n return {\n ...s,\n matches,\n }\n })\n\n // Allow the user to handle custom hydration data\n await router.options.hydrate?.(dehydratedData)\n\n // now that all necessary data is hydrated:\n // 1) fully reconstruct the route context\n // 2) execute `head()` and `scripts()` for each match\n await Promise.all(\n router.state.matches.map(async (match) => {\n const route = router.looseRoutesById[match.routeId]!\n\n const parentMatch = router.state.matches[match.index - 1]\n const parentContext = parentMatch?.context ?? router.options.context ?? {}\n\n // `context()` was already executed by `matchRoutes`, however route context was not yet fully reconstructed\n // so run it again and merge route context\n const contextFnContext: RouteContextOptions<any, any, any, any> = {\n deps: match.loaderDeps,\n params: match.params,\n context: parentContext,\n location: router.state.location,\n navigate: (opts: any) =>\n router.navigate({ ...opts, _fromLocation: router.state.location }),\n buildLocation: router.buildLocation,\n cause: match.cause,\n abortController: match.abortController,\n preload: false,\n matches,\n }\n match.__routeContext = route.options.context?.(contextFnContext) ?? {}\n\n match.context = {\n ...parentContext,\n ...match.__routeContext,\n ...match.__beforeLoadContext,\n }\n\n const assetContext = {\n matches: router.state.matches,\n match,\n params: match.params,\n loaderData: match.loaderData,\n }\n const headFnContent = await route.options.head?.(assetContext)\n\n const scripts = await route.options.scripts?.(assetContext)\n\n match.meta = headFnContent?.meta\n match.links = headFnContent?.links\n match.headScripts = headFnContent?.scripts\n match.styles = headFnContent?.styles\n match.scripts = scripts\n }),\n )\n\n // schedule router.load() to run after the next tick so we can store the promise in the match before loading starts\n const loadPromise = Promise.resolve()\n .then(() => router.load())\n .catch((err) => {\n console.error('Error during router hydration:', err)\n })\n\n // in SPA mode we need to keep the outermost match pending until router.load() is finished\n // this will prevent that other pending components are rendered but hydration is not blocked\n if (matches[matches.length - 1]!.id !== lastMatchId) {\n const matchId = matches[0]!.id\n router.updateMatch(matchId, (prev) => {\n return {\n ...prev,\n _displayPending: true,\n displayPendingPromise: loadPromise,\n // make sure that the pending component is displayed for at least pendingMinMs\n _forcePending: true,\n }\n })\n // hide the pending component once the load is finished\n loadPromise.then(() => {\n router.updateMatch(matchId, (prev) => {\n return {\n ...prev,\n _displayPending: undefined,\n displayPendingPromise: undefined,\n }\n })\n })\n }\n return routeChunkPromise\n}\n"],"names":["_b","_a","_c"],"mappings":"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"}
@@ -1,32 +1,18 @@
1
- import { DeferredPromise } from '../defer.js';
2
- import { ClientExtractedBaseEntry } from './ssr-client.js';
3
1
  import { AnyRouter } from '../router.js';
4
- import { Manifest } from '../manifest.js';
2
+ import { DehydratedMatch } from './ssr-client.js';
5
3
  import { AnyRouteMatch } from '../Matches.js';
6
- export type ServerExtractedEntry = ServerExtractedStream | ServerExtractedPromise;
7
- export interface ServerExtractedBaseEntry extends ClientExtractedBaseEntry {
8
- id: number;
9
- matchIndex: number;
10
- }
11
- export interface ServerExtractedStream extends ServerExtractedBaseEntry {
12
- type: 'stream';
13
- stream: ReadableStream;
14
- }
15
- export interface ServerExtractedPromise extends ServerExtractedBaseEntry {
16
- type: 'promise';
17
- promise: DeferredPromise<any>;
4
+ import { Manifest } from '../manifest.js';
5
+ declare module '../router' {
6
+ interface ServerSsr {
7
+ setRenderFinished: () => void;
8
+ }
9
+ interface RouterEvents {
10
+ onInjectedHtml: {
11
+ type: 'onInjectedHtml';
12
+ promise: Promise<string>;
13
+ };
14
+ }
18
15
  }
16
+ export declare const GLOBAL_TSR = "$_TSR";
17
+ export declare function dehydrateMatch(match: AnyRouteMatch): DehydratedMatch;
19
18
  export declare function attachRouterServerSsrUtils(router: AnyRouter, manifest: Manifest | undefined): void;
20
- export declare function dehydrateRouter(router: AnyRouter): void;
21
- export declare function extractAsyncLoaderData(loaderData: any, ctx: {
22
- match: AnyRouteMatch;
23
- router: AnyRouter;
24
- }): {
25
- replaced: any;
26
- extracted: ServerExtractedEntry[];
27
- };
28
- export declare function onMatchSettled(opts: {
29
- router: AnyRouter;
30
- match: AnyRouteMatch;
31
- }): void;
32
- export declare function replaceBy<T>(obj: T, cb: (value: any, path: Array<string>) => any, path?: Array<string>): T;