@bleedingdev/modern-js-plugin-tanstack 3.2.0-ultramodern.12 → 3.2.0-ultramodern.121

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 (136) hide show
  1. package/dist/cjs/cli/index.js +89 -31
  2. package/dist/cjs/cli/routeSplitting.js +55 -0
  3. package/dist/cjs/cli/tanstackTypes.js +172 -170
  4. package/dist/cjs/cli.js +12 -8
  5. package/dist/cjs/runtime/basepathRewrite.js +12 -8
  6. package/dist/cjs/runtime/dataMutation.js +9 -5
  7. package/dist/cjs/runtime/hooks.js +20 -19
  8. package/dist/cjs/runtime/hydrationBoundary.js +48 -0
  9. package/dist/cjs/runtime/index.js +79 -35
  10. package/dist/cjs/runtime/lifecycle.js +21 -91
  11. package/dist/cjs/runtime/loaderBridge.js +173 -0
  12. package/dist/cjs/runtime/outlet.js +58 -0
  13. package/dist/cjs/runtime/plugin.js +195 -114
  14. package/dist/cjs/runtime/plugin.node.js +45 -45
  15. package/dist/cjs/runtime/plugin.worker.js +53 -0
  16. package/dist/cjs/runtime/pluginCore.js +55 -0
  17. package/dist/cjs/runtime/prefetchLink.js +10 -6
  18. package/dist/cjs/runtime/register.js +56 -0
  19. package/dist/cjs/runtime/routeTree.js +74 -207
  20. package/dist/cjs/runtime/router.js +41 -0
  21. package/dist/cjs/runtime/rsc/ClientSlot.js +9 -5
  22. package/dist/cjs/runtime/rsc/CompositeComponent.js +9 -5
  23. package/dist/cjs/runtime/rsc/ReplayableStream.js +14 -9
  24. package/dist/cjs/runtime/rsc/RscNodeRenderer.js +9 -5
  25. package/dist/cjs/runtime/rsc/SlotContext.js +9 -5
  26. package/dist/cjs/runtime/rsc/client.js +9 -5
  27. package/dist/cjs/runtime/rsc/createRscProxy.js +9 -5
  28. package/dist/cjs/runtime/rsc/index.js +9 -5
  29. package/dist/cjs/runtime/rsc/payloadRouter.js +44 -6
  30. package/dist/cjs/runtime/rsc/server.js +9 -5
  31. package/dist/cjs/runtime/rsc/slotUsageSanitizer.js +9 -5
  32. package/dist/cjs/runtime/rsc/symbols.js +20 -15
  33. package/dist/cjs/runtime/state.js +45 -0
  34. package/dist/cjs/runtime/types.js +31 -1
  35. package/dist/cjs/runtime/utils.js +9 -10
  36. package/dist/cjs/runtime.js +9 -5
  37. package/dist/esm/cli/index.mjs +75 -27
  38. package/dist/esm/cli/routeSplitting.mjs +14 -0
  39. package/dist/esm/cli/tanstackTypes.mjs +158 -160
  40. package/dist/esm/runtime/hooks.mjs +1 -8
  41. package/dist/esm/runtime/hydrationBoundary.mjs +10 -0
  42. package/dist/esm/runtime/index.mjs +5 -2
  43. package/dist/esm/runtime/lifecycle.mjs +1 -82
  44. package/dist/esm/runtime/loaderBridge.mjs +114 -0
  45. package/dist/esm/runtime/outlet.mjs +17 -0
  46. package/dist/esm/runtime/plugin.mjs +191 -114
  47. package/dist/esm/runtime/plugin.node.mjs +40 -44
  48. package/dist/esm/runtime/plugin.worker.mjs +1 -0
  49. package/dist/esm/runtime/pluginCore.mjs +14 -0
  50. package/dist/esm/runtime/prefetchLink.mjs +1 -1
  51. package/dist/esm/runtime/register.mjs +18 -0
  52. package/dist/esm/runtime/routeTree.mjs +59 -193
  53. package/dist/esm/runtime/router.mjs +2 -0
  54. package/dist/esm/runtime/rsc/payloadRouter.mjs +35 -1
  55. package/dist/esm/runtime/state.mjs +7 -0
  56. package/dist/esm/runtime/types.mjs +7 -0
  57. package/dist/esm/runtime/utils.mjs +0 -5
  58. package/dist/esm-node/cli/index.mjs +75 -27
  59. package/dist/esm-node/cli/routeSplitting.mjs +15 -0
  60. package/dist/esm-node/cli/tanstackTypes.mjs +158 -160
  61. package/dist/esm-node/runtime/hooks.mjs +1 -8
  62. package/dist/esm-node/runtime/hydrationBoundary.mjs +11 -0
  63. package/dist/esm-node/runtime/index.mjs +5 -2
  64. package/dist/esm-node/runtime/lifecycle.mjs +1 -82
  65. package/dist/esm-node/runtime/loaderBridge.mjs +115 -0
  66. package/dist/esm-node/runtime/outlet.mjs +18 -0
  67. package/dist/esm-node/runtime/plugin.mjs +191 -114
  68. package/dist/esm-node/runtime/plugin.node.mjs +40 -44
  69. package/dist/esm-node/runtime/plugin.worker.mjs +2 -0
  70. package/dist/esm-node/runtime/pluginCore.mjs +15 -0
  71. package/dist/esm-node/runtime/prefetchLink.mjs +1 -1
  72. package/dist/esm-node/runtime/register.mjs +19 -0
  73. package/dist/esm-node/runtime/routeTree.mjs +59 -193
  74. package/dist/esm-node/runtime/router.mjs +3 -0
  75. package/dist/esm-node/runtime/rsc/payloadRouter.mjs +35 -1
  76. package/dist/esm-node/runtime/state.mjs +8 -0
  77. package/dist/esm-node/runtime/types.mjs +7 -0
  78. package/dist/esm-node/runtime/utils.mjs +0 -5
  79. package/dist/types/cli/index.d.ts +14 -1
  80. package/dist/types/cli/routeSplitting.d.ts +20 -0
  81. package/dist/types/cli/tanstackTypes.d.ts +21 -1
  82. package/dist/types/runtime/hooks.d.ts +8 -33
  83. package/dist/types/runtime/hydrationBoundary.d.ts +2 -0
  84. package/dist/types/runtime/index.d.ts +8 -3
  85. package/dist/types/runtime/lifecycle.d.ts +7 -22
  86. package/dist/types/runtime/loaderBridge.d.ts +48 -0
  87. package/dist/types/runtime/outlet.d.ts +2 -0
  88. package/dist/types/runtime/plugin.d.ts +2 -15
  89. package/dist/types/runtime/plugin.node.d.ts +2 -15
  90. package/dist/types/runtime/plugin.worker.d.ts +1 -0
  91. package/dist/types/runtime/pluginCore.d.ts +21 -0
  92. package/dist/types/runtime/register.d.ts +9 -0
  93. package/dist/types/runtime/routeTree.d.ts +0 -2
  94. package/dist/types/runtime/router.d.ts +14 -0
  95. package/dist/types/runtime/state.d.ts +16 -0
  96. package/dist/types/runtime/types.d.ts +14 -53
  97. package/package.json +42 -40
  98. package/rstest.config.mts +6 -0
  99. package/src/cli/index.ts +162 -23
  100. package/src/cli/routeSplitting.ts +43 -0
  101. package/src/cli/tanstackTypes.ts +331 -187
  102. package/src/runtime/hooks.ts +10 -27
  103. package/src/runtime/hydrationBoundary.tsx +12 -0
  104. package/src/runtime/index.tsx +17 -7
  105. package/src/runtime/lifecycle.ts +16 -151
  106. package/src/runtime/loaderBridge.ts +257 -0
  107. package/src/runtime/outlet.tsx +48 -0
  108. package/src/runtime/plugin.node.tsx +72 -85
  109. package/src/runtime/plugin.tsx +361 -206
  110. package/src/runtime/plugin.worker.tsx +4 -0
  111. package/src/runtime/pluginCore.ts +48 -0
  112. package/src/runtime/prefetchLink.tsx +1 -1
  113. package/src/runtime/register.ts +58 -0
  114. package/src/runtime/routeTree.ts +163 -354
  115. package/src/runtime/router.ts +15 -0
  116. package/src/runtime/rsc/payloadRouter.ts +45 -2
  117. package/src/runtime/ssr-shim.d.ts +1 -3
  118. package/src/runtime/state.ts +29 -0
  119. package/src/runtime/types.ts +32 -66
  120. package/src/runtime/utils.tsx +3 -6
  121. package/tests/router/cli.test.ts +586 -5
  122. package/tests/router/fastDefaults.test.ts +25 -0
  123. package/tests/router/hooks.test.ts +26 -0
  124. package/tests/router/hydrationBoundary.test.tsx +23 -0
  125. package/tests/router/loaderBridge.test.ts +211 -0
  126. package/tests/router/packageSurface.test.ts +24 -0
  127. package/tests/router/prefetchLink.test.tsx +43 -7
  128. package/tests/router/register.test.ts +46 -0
  129. package/tests/router/routeTree.test.ts +381 -81
  130. package/tests/router/rsc.test.tsx +70 -0
  131. package/tests/router/tanstackTypes.test.ts +573 -1
  132. package/dist/cjs/runtime/DefaultNotFound.js +0 -47
  133. package/dist/esm/runtime/DefaultNotFound.mjs +0 -13
  134. package/dist/esm-node/runtime/DefaultNotFound.mjs +0 -14
  135. package/dist/types/runtime/DefaultNotFound.d.ts +0 -2
  136. package/src/runtime/DefaultNotFound.tsx +0 -15
@@ -1,7 +1,10 @@
1
1
  import "node:module";
2
+ import "./register.mjs";
2
3
  export * from "@tanstack/react-router";
3
- export { useMatch } from "@tanstack/react-router";
4
4
  export { Form, RouteActionResponseError, useFetcher } from "./dataMutation.mjs";
5
+ export { createRouteStaticData, isAbsoluteUrl, modernLoaderToTanstack, throwTanstackRedirect } from "./loaderBridge.mjs";
6
+ export { Outlet } from "./outlet.mjs";
5
7
  export { tanstackRouterPlugin as default, tanstackRouterPlugin } from "./plugin.mjs";
6
8
  export { Link, NavLink } from "./prefetchLink.mjs";
7
- export { CompositeComponent } from "./rsc/client.mjs";
9
+ export { getTanstackRouterState } from "./state.mjs";
10
+ export { getModernTanstackRouterFastDefaults, modernTanstackRouterFastDefaults } from "./types.mjs";
@@ -1,83 +1,2 @@
1
1
  import "node:module";
2
- function toHydrationScripts(state) {
3
- if (state.hydrationScripts?.length) return state.hydrationScripts;
4
- return state.hydrationScript ? [
5
- state.hydrationScript
6
- ] : void 0;
7
- }
8
- function getMatchedRouteIdsFromMatches(matches) {
9
- const routeIds = matches?.map((match)=>match.assetRouteId ?? match.routeId).filter((routeId)=>'string' == typeof routeId);
10
- return routeIds?.length ? routeIds : void 0;
11
- }
12
- function createRouterServerSnapshot(state) {
13
- const hydrationScripts = toHydrationScripts(state);
14
- const matchedRouteIds = state.matchedRouteIds ?? getMatchedRouteIdsFromMatches(state.matches);
15
- return {
16
- ...state,
17
- ...hydrationScripts?.length ? {
18
- hydrationScript: state.hydrationScript ?? hydrationScripts[0],
19
- hydrationScripts
20
- } : {},
21
- ...matchedRouteIds ? {
22
- matchedRouteIds
23
- } : {}
24
- };
25
- }
26
- function createRouterRuntimeState(state) {
27
- const hasSnapshotState = Boolean(state.serverSnapshot) || Boolean(state.hydrationScript) || Boolean(state.hydrationScripts?.length) || Boolean(state.matchedRouteIds?.length) || Boolean(state.matches?.length);
28
- const serverSnapshot = state.serverSnapshot ? createRouterServerSnapshot({
29
- ...state.serverSnapshot,
30
- framework: state.serverSnapshot.framework ?? state.framework,
31
- basename: state.serverSnapshot.basename ?? state.basename,
32
- hydrationScript: state.serverSnapshot.hydrationScript ?? state.hydrationScript,
33
- hydrationScripts: state.serverSnapshot.hydrationScripts ?? state.hydrationScripts,
34
- matchedRouteIds: state.serverSnapshot.matchedRouteIds ?? state.matchedRouteIds,
35
- matches: state.serverSnapshot.matches ?? state.matches
36
- }) : hasSnapshotState ? createRouterServerSnapshot({
37
- framework: state.framework,
38
- basename: state.basename,
39
- hydrationScript: state.hydrationScript,
40
- hydrationScripts: state.hydrationScripts,
41
- matchedRouteIds: state.matchedRouteIds,
42
- matches: state.matches
43
- }) : void 0;
44
- const hydrationScripts = toHydrationScripts({
45
- hydrationScript: state.hydrationScript ?? serverSnapshot?.hydrationScript,
46
- hydrationScripts: state.hydrationScripts ?? serverSnapshot?.hydrationScripts
47
- });
48
- const matchedRouteIds = state.matchedRouteIds ?? serverSnapshot?.matchedRouteIds ?? getMatchedRouteIdsFromMatches(state.matches);
49
- return {
50
- ...state,
51
- ...hydrationScripts?.length ? {
52
- hydrationScript: state.hydrationScript ?? hydrationScripts[0],
53
- hydrationScripts
54
- } : {},
55
- ...matchedRouteIds ? {
56
- matchedRouteIds
57
- } : {},
58
- ...serverSnapshot ? {
59
- serverSnapshot
60
- } : {}
61
- };
62
- }
63
- function applyRouterRuntimeState(runtimeContext, state) {
64
- const normalized = createRouterRuntimeState(state);
65
- const mutableRuntimeContext = runtimeContext;
66
- mutableRuntimeContext.routerFramework = normalized.framework;
67
- mutableRuntimeContext.routerInstance = normalized.instance;
68
- mutableRuntimeContext.routerHydrationScript = normalized.hydrationScript;
69
- mutableRuntimeContext.routerMatchedRouteIds = normalized.matchedRouteIds;
70
- mutableRuntimeContext.routerRuntime = normalized;
71
- if (normalized.serverSnapshot) mutableRuntimeContext.routerServerSnapshot = normalized.serverSnapshot;
72
- return runtimeContext;
73
- }
74
- function applyRouterServerPrepareResult(runtimeContext, result) {
75
- const state = createRouterRuntimeState({
76
- ...result.state,
77
- cleanup: result.cleanup ?? result.state.cleanup,
78
- serverSnapshot: result.snapshot ?? result.state.serverSnapshot
79
- });
80
- applyRouterRuntimeState(runtimeContext, state);
81
- return runtimeContext;
82
- }
83
- export { applyRouterRuntimeState, applyRouterServerPrepareResult, createRouterRuntimeState, createRouterServerSnapshot };
2
+ export { applyRouterRuntimeState, applyRouterServerPrepareResult, createRouterRuntimeState, createRouterServerSnapshot, getRouterRuntimeState, getRouterServerSnapshot } from "@modern-js/runtime/context";
@@ -0,0 +1,115 @@
1
+ import "node:module";
2
+ import { notFound, redirect } from "@tanstack/react-router";
3
+ function isResponse(value) {
4
+ const record = value;
5
+ return null != record && 'object' == typeof record && 'number' == typeof record.status && 'object' == typeof record.headers;
6
+ }
7
+ const redirectStatusCodes = new Set([
8
+ 301,
9
+ 302,
10
+ 303,
11
+ 307,
12
+ 308
13
+ ]);
14
+ function isRedirectResponse(res) {
15
+ return redirectStatusCodes.has(res.status);
16
+ }
17
+ function isTanstackRedirect(value) {
18
+ return isResponse(value) && 'object' == typeof value.options;
19
+ }
20
+ function isAbsoluteUrl(value) {
21
+ try {
22
+ new URL(value);
23
+ return true;
24
+ } catch {
25
+ return false;
26
+ }
27
+ }
28
+ function throwTanstackRedirect(location) {
29
+ const target = location || '/';
30
+ if (isAbsoluteUrl(target)) throw redirect({
31
+ href: target
32
+ });
33
+ throw redirect({
34
+ to: target
35
+ });
36
+ }
37
+ function mapSplatParamsForModernLoader(params, hasSplat) {
38
+ if (!hasSplat) return params;
39
+ const { _splat, ...rest } = params;
40
+ if (void 0 !== _splat) return {
41
+ ...rest,
42
+ '*': _splat
43
+ };
44
+ return rest;
45
+ }
46
+ function createRouteStaticData(opts) {
47
+ const staticData = {};
48
+ if ('string' == typeof opts.modernRouteId && opts.modernRouteId.length > 0) staticData.modernRouteId = opts.modernRouteId;
49
+ if (void 0 !== opts.modernRouteLoader) staticData.modernRouteLoader = opts.modernRouteLoader;
50
+ if (void 0 !== opts.modernRouteAction) staticData.modernRouteAction = opts.modernRouteAction;
51
+ return staticData;
52
+ }
53
+ function getLoaderSignal(ctx) {
54
+ const abortSignal = ctx?.abortController?.signal;
55
+ if (abortSignal instanceof AbortSignal) return abortSignal;
56
+ if (ctx?.signal instanceof AbortSignal) return ctx.signal;
57
+ return new AbortController().signal;
58
+ }
59
+ function getLoaderHref(ctx) {
60
+ if ('string' == typeof ctx?.location) return ctx.location;
61
+ const publicHref = ctx?.location?.publicHref;
62
+ if ('string' == typeof publicHref) return publicHref;
63
+ const href = ctx?.location?.href;
64
+ if ('string' == typeof href) return href;
65
+ const urlHref = ctx?.location?.url?.href;
66
+ return 'string' == typeof urlHref ? urlHref : '';
67
+ }
68
+ function getLoaderParams(ctx) {
69
+ return 'object' == typeof ctx?.params && null !== ctx.params ? ctx.params : {};
70
+ }
71
+ function handleModernLoaderResult(result) {
72
+ if (isResponse(result)) {
73
+ if (isRedirectResponse(result)) {
74
+ const location = result.headers.get('Location') ?? '/';
75
+ throwTanstackRedirect(location);
76
+ }
77
+ if (404 === result.status) throw notFound();
78
+ }
79
+ return result;
80
+ }
81
+ function handleModernLoaderError(err) {
82
+ if (isResponse(err)) {
83
+ if (isTanstackRedirect(err)) throw err;
84
+ if (isRedirectResponse(err)) {
85
+ const location = err.headers.get('Location') ?? '/';
86
+ throwTanstackRedirect(location);
87
+ }
88
+ if (404 === err.status) throw notFound();
89
+ }
90
+ throw err;
91
+ }
92
+ function modernLoaderToTanstack(opts, modernLoader) {
93
+ return (rawCtx)=>{
94
+ const ctx = rawCtx;
95
+ try {
96
+ const signal = getLoaderSignal(ctx);
97
+ const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
98
+ const href = getLoaderHref(ctx);
99
+ const request = void 0 !== baseRequest ? new Request(baseRequest, {
100
+ signal
101
+ }) : new Request(href, {
102
+ signal
103
+ });
104
+ const params = mapSplatParamsForModernLoader(getLoaderParams(ctx), opts.hasSplat);
105
+ return Promise.resolve(modernLoader({
106
+ request,
107
+ params,
108
+ context: ctx?.context?.requestContext
109
+ })).then((result)=>handleModernLoaderResult(result)).catch(handleModernLoaderError);
110
+ } catch (err) {
111
+ handleModernLoaderError(err);
112
+ }
113
+ };
114
+ }
115
+ export { createRouteStaticData, isAbsoluteUrl, isRedirectResponse, isResponse, isTanstackRedirect, mapSplatParamsForModernLoader, modernLoaderToTanstack, throwTanstackRedirect };
@@ -0,0 +1,18 @@
1
+ import "node:module";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Outlet } from "@tanstack/react-router";
4
+ import { createElement, memo } from "react";
5
+ const outlet_Outlet = /*#__PURE__*/ memo(function() {
6
+ return /*#__PURE__*/ jsx(Outlet, {});
7
+ });
8
+ function withModernRouteMatchContext(component, _routeId) {
9
+ if (null == component) return component;
10
+ const Component = component;
11
+ const WrappedRouteComponent = (props)=>/*#__PURE__*/ createElement(Component, props);
12
+ const preloadable = component;
13
+ if ('function' == typeof preloadable.load) WrappedRouteComponent.load = preloadable.load.bind(preloadable);
14
+ if ('function' == typeof preloadable.preload) WrappedRouteComponent.preload = preloadable.preload.bind(preloadable);
15
+ else if ('function' == typeof preloadable.load) WrappedRouteComponent.preload = WrappedRouteComponent.load;
16
+ return WrappedRouteComponent;
17
+ }
18
+ export { outlet_Outlet as Outlet, withModernRouteMatchContext };
@@ -1,17 +1,21 @@
1
1
  import "node:module";
2
2
  import { jsx } from "react/jsx-runtime";
3
- import { InternalRuntimeContext, getGlobalEnableRsc, getGlobalLayoutApp, getGlobalRoutes } from "@modern-js/runtime/context";
4
- import { merge } from "@modern-js/runtime-utils/merge";
3
+ import { InternalRuntimeContext, getGlobalEnableRsc } from "@modern-js/runtime/context";
5
4
  import { normalizePathname } from "@modern-js/runtime-utils/url";
6
5
  import { RouterProvider, createBrowserHistory, createHashHistory, createRouter, useLocation, useMatches, useNavigate, useRouter } from "@tanstack/react-router";
7
- import { RouterClient } from "@tanstack/react-router/ssr/client";
6
+ import { hydrate } from "@tanstack/react-router/ssr/client";
7
+ import { useContext, useMemo } from "react";
8
8
  import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
9
- import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
9
+ import { routerProviderRegistryHooks } from "./hooks.mjs";
10
+ import { wrapTanstackSsrHydrationBoundary } from "./hydrationBoundary.mjs";
10
11
  import { applyRouterRuntimeState } from "./lifecycle.mjs";
12
+ import { withModernRouteMatchContext } from "./outlet.mjs";
13
+ import { getFinalRouteConfig, getMergedRouterConfig } from "./pluginCore.mjs";
14
+ import { Link } from "./prefetchLink.mjs";
11
15
  import { createRouteTreeFromRouteObjects } from "./routeTree.mjs";
12
16
  import { getTanstackRscSerializationAdapters } from "./rsc/client.mjs";
17
+ import { getModernTanstackRouterFastDefaults } from "./types.mjs";
13
18
  import { createRouteObjectsFromConfig, urlJoin } from "./utils.mjs";
14
- import * as __rspack_external_react from "react";
15
19
  const BLOCKING_SUBSCRIBE_SYMBOL = Symbol.for('@modern-js/plugin-tanstack:blocking-subscribe');
16
20
  const BLOCKING_STATE_SYMBOL = Symbol.for('@modern-js/plugin-tanstack:blocking-state');
17
21
  function normalizeBase(b) {
@@ -39,133 +43,207 @@ function wrapRouterSubscribeWithBlockState(router, getBlockNavState) {
39
43
  };
40
44
  target[BLOCKING_SUBSCRIBE_SYMBOL] = true;
41
45
  }
42
- function stripSyntheticNotFoundRoute(routes) {
43
- return routes.filter((route)=>!('*' === route.path && !route.id && !route.loader)).map((route)=>{
44
- if (!route.children?.length) return route;
45
- return {
46
- ...route,
47
- children: stripSyntheticNotFoundRoute(route.children)
48
- };
46
+ const routerHydrationRecords = new WeakMap();
47
+ const routeModulesKey = '_routeModules';
48
+ function pickRouteModuleComponent(routeModule, seen = new Set()) {
49
+ if ('function' == typeof routeModule || routeModule && 'object' == typeof routeModule && '$$typeof' in routeModule) return routeModule;
50
+ if (!routeModule || 'object' != typeof routeModule) return;
51
+ if (seen.has(routeModule)) return;
52
+ seen.add(routeModule);
53
+ const module = routeModule;
54
+ for (const candidate of [
55
+ module.default,
56
+ module.Component
57
+ ]){
58
+ const component = pickRouteModuleComponent(candidate, seen);
59
+ if (component) return component;
60
+ }
61
+ }
62
+ function getCachedRouteModule(routeId) {
63
+ if ("u" < typeof window) return;
64
+ return window[routeModulesKey]?.[routeId];
65
+ }
66
+ function preloadHydratedRouteComponents(router) {
67
+ const preloadableRouter = router;
68
+ const routesById = preloadableRouter.routesById || {};
69
+ const matches = preloadableRouter.stores.matches.get();
70
+ return Promise.all(matches.map((match)=>{
71
+ if (void 0 === match.routeId || '' === match.routeId) return;
72
+ const route = routesById[match.routeId];
73
+ const component = route?.options?.component;
74
+ const preload = component?.load || component?.preload;
75
+ if ('function' != typeof preload) return;
76
+ return Promise.resolve(preload.call(component)).then((routeModule)=>{
77
+ const modernRouteId = route?.options?.staticData?.modernRouteId;
78
+ const cachedRouteModule = 'string' == typeof modernRouteId && '' !== modernRouteId ? getCachedRouteModule(modernRouteId) : void 0;
79
+ const resolvedComponent = pickRouteModuleComponent(cachedRouteModule ?? routeModule);
80
+ if (void 0 !== resolvedComponent && 'string' == typeof modernRouteId && '' !== modernRouteId) route.options.component = withModernRouteMatchContext(resolvedComponent, modernRouteId);
81
+ });
82
+ })).then(()=>void 0);
83
+ }
84
+ function getTanstackSsrHydrationRecord(router) {
85
+ const existingHydrationRecord = routerHydrationRecords.get(router);
86
+ if (void 0 !== existingHydrationRecord) return existingHydrationRecord;
87
+ const hydrationRecord = {
88
+ promise: Promise.resolve(),
89
+ status: 'pending'
90
+ };
91
+ routerHydrationRecords.set(router, hydrationRecord);
92
+ try {
93
+ hydrationRecord.promise = hydrate(router).then((value)=>preloadHydratedRouteComponents(router).then(()=>value)).then((value)=>{
94
+ hydrationRecord.status = 'fulfilled';
95
+ return value;
96
+ }, (error)=>{
97
+ hydrationRecord.status = 'rejected';
98
+ hydrationRecord.error = error;
99
+ throw error;
100
+ });
101
+ } catch (error) {
102
+ hydrationRecord.status = 'rejected';
103
+ hydrationRecord.error = error;
104
+ hydrationRecord.promise = Promise.reject(error);
105
+ hydrationRecord.promise.catch(()=>{});
106
+ }
107
+ return hydrationRecord;
108
+ }
109
+ function getTanstackSsrHydrationPromise(router) {
110
+ return getTanstackSsrHydrationRecord(router).promise;
111
+ }
112
+ function hasTanstackSsrHydrationRecord(router) {
113
+ return routerHydrationRecords.has(router);
114
+ }
115
+ function ModernRouterClient({ router }) {
116
+ const hydrationRecord = getTanstackSsrHydrationRecord(router);
117
+ if ('rejected' === hydrationRecord.status) throw hydrationRecord.error;
118
+ return /*#__PURE__*/ jsx(RouterProvider, {
119
+ router: router
49
120
  });
50
121
  }
51
122
  const tanstackRouterPlugin = (userConfig = {})=>{
52
123
  const plugin = {
53
124
  name: '@modern-js/plugin-router-tanstack',
54
- registryHooks: {
55
- modifyRoutes: modifyRoutes,
56
- onAfterCreateRouter: onAfterCreateRouter,
57
- onAfterHydrateRouter: onAfterHydrateRouter,
58
- onBeforeCreateRouter: onBeforeCreateRouter,
59
- onBeforeCreateRoutes: onBeforeCreateRoutes,
60
- onBeforeHydrateRouter: onBeforeHydrateRouter
61
- },
125
+ registryHooks: routerProviderRegistryHooks,
62
126
  setup: (api)=>{
127
+ const hooks = api.getHooks();
128
+ let cachedRouteObjects;
129
+ let cachedRouteTree = null;
130
+ let cachedRouter = null;
131
+ let cachedRouterBasepath = null;
132
+ const getMergedConfig = ()=>getMergedRouterConfig(api, userConfig);
133
+ const getRouteObjects = ()=>{
134
+ if (void 0 !== cachedRouteObjects) return cachedRouteObjects;
135
+ const mergedConfig = getMergedConfig();
136
+ const { createRoutes } = mergedConfig;
137
+ const finalRouteConfig = getFinalRouteConfig(mergedConfig);
138
+ const routeObjects = createRoutes ? createRoutes() : createRouteObjectsFromConfig({
139
+ routesConfig: finalRouteConfig
140
+ }) || [];
141
+ cachedRouteObjects = hooks.modifyRoutes.call(routeObjects);
142
+ return cachedRouteObjects;
143
+ };
144
+ const getRouteTree = ()=>{
145
+ if (cachedRouteTree) return cachedRouteTree;
146
+ const routeObjects = getRouteObjects();
147
+ if (!routeObjects.length) return null;
148
+ cachedRouteTree = createRouteTreeFromRouteObjects(routeObjects, {
149
+ rscPayloadRouter: getGlobalEnableRsc()
150
+ });
151
+ return cachedRouteTree;
152
+ };
153
+ const selectBasePath = (pathname)=>{
154
+ const { serverBase = [] } = getMergedConfig();
155
+ const match = serverBase.find((baseUrl)=>isSegmentPrefix(pathname, baseUrl));
156
+ return match || '/';
157
+ };
158
+ const getClientBasename = (runtimeContext)=>{
159
+ const { basename = '' } = getMergedConfig();
160
+ const baseUrl = selectBasePath(location.pathname).replace(/^\/*/, '/');
161
+ return '/' === baseUrl ? urlJoin(baseUrl, runtimeContext._internalRouterBaseName || basename || '') : baseUrl;
162
+ };
163
+ const getRouter = (runtimeContext, _basename)=>{
164
+ const routeTree = getRouteTree();
165
+ if (!routeTree) return null;
166
+ const lifecycleContext = {
167
+ framework: 'tanstack',
168
+ phase: 'client-create',
169
+ routes: getRouteObjects(),
170
+ runtimeContext,
171
+ basename: _basename
172
+ };
173
+ hooks.onBeforeCreateRouter.call(lifecycleContext);
174
+ if (cachedRouter && cachedRouterBasepath === _basename) {
175
+ wrapRouterSubscribeWithBlockState(cachedRouter, runtimeContext.unstable_getBlockNavState);
176
+ hooks.onAfterCreateRouter.call({
177
+ ...lifecycleContext,
178
+ router: cachedRouter,
179
+ runtimeContext
180
+ });
181
+ return cachedRouter;
182
+ }
183
+ const mergedConfig = getMergedConfig();
184
+ const { supportHtml5History = true } = mergedConfig;
185
+ const history = supportHtml5History ? createBrowserHistory() : createHashHistory();
186
+ const rewrite = createModernBasepathRewrite(_basename);
187
+ const serializationAdapters = getGlobalEnableRsc() ? getTanstackRscSerializationAdapters() : void 0;
188
+ cachedRouter = createRouter({
189
+ ...getModernTanstackRouterFastDefaults(mergedConfig),
190
+ routeTree,
191
+ basepath: '/',
192
+ rewrite,
193
+ history,
194
+ context: {},
195
+ ...serializationAdapters ? {
196
+ serializationAdapters
197
+ } : {}
198
+ });
199
+ cachedRouterBasepath = _basename;
200
+ wrapRouterSubscribeWithBlockState(cachedRouter, runtimeContext.unstable_getBlockNavState);
201
+ hooks.onAfterCreateRouter.call({
202
+ ...lifecycleContext,
203
+ router: cachedRouter,
204
+ runtimeContext
205
+ });
206
+ return cachedRouter;
207
+ };
63
208
  api.onBeforeRender((context)=>{
64
- const pluginConfig = api.getRuntimeConfig();
65
- const mergedConfig = merge(pluginConfig.router || {}, userConfig);
66
- if ("u" > typeof window && window._SSR_DATA && mergedConfig.unstable_reloadOnURLMismatch) {
209
+ const mergedConfig = getMergedConfig();
210
+ if ("u" > typeof window && void 0 !== window._SSR_DATA && mergedConfig.unstable_reloadOnURLMismatch) {
67
211
  const { ssrContext } = context;
68
212
  const currentPathname = normalizePathname(window.location.pathname);
69
- const initialPathname = ssrContext?.request?.pathname && normalizePathname(ssrContext.request.pathname);
70
- if (initialPathname && initialPathname !== currentPathname) {
213
+ const initialPathname = 'string' == typeof ssrContext?.request?.pathname ? normalizePathname(ssrContext.request.pathname) : void 0;
214
+ if (void 0 !== initialPathname && '' !== initialPathname && initialPathname !== currentPathname) {
71
215
  const errorMsg = `The initial URL ${initialPathname} and the URL ${currentPathname} to be hydrated do not match, reload.`;
72
216
  console.error(errorMsg);
73
217
  window.location.reload();
74
218
  }
75
219
  }
76
220
  context.router = {
221
+ Link: Link,
77
222
  useMatches: useMatches,
78
223
  useLocation: useLocation,
79
224
  useNavigate: useNavigate,
80
225
  useRouter: useRouter
81
226
  };
227
+ const hasSSRBootstrap = "u" > typeof window && Boolean(window.$_TSR);
228
+ if (hasSSRBootstrap && getRouteObjects().length > 0) {
229
+ const runtimeContext = context;
230
+ const router = getRouter(runtimeContext, getClientBasename(runtimeContext));
231
+ if (null != router) return getTanstackSsrHydrationPromise(router).then(()=>void 0);
232
+ }
82
233
  });
83
234
  api.wrapRoot((App)=>{
84
- const mergedConfig = merge(api.getRuntimeConfig().router || {}, userConfig);
85
- const { serverBase = [], supportHtml5History = true, basename = '', routesConfig, createRoutes } = mergedConfig;
86
- const finalRouteConfig = {
87
- routes: getGlobalRoutes(),
88
- globalApp: getGlobalLayoutApp(),
89
- ...routesConfig
90
- };
91
- if (!finalRouteConfig.routes && !createRoutes) return App;
92
- const hooks = api.getHooks();
93
- let cachedRouteObjects;
94
- const getRouteObjects = ()=>{
95
- if (void 0 !== cachedRouteObjects) return cachedRouteObjects;
96
- const routeObjects = createRoutes ? createRoutes() : createRouteObjectsFromConfig({
97
- routesConfig: finalRouteConfig
98
- }) || [];
99
- const normalizedRouteObjects = createRoutes ? routeObjects : stripSyntheticNotFoundRoute(routeObjects);
100
- cachedRouteObjects = hooks.modifyRoutes.call(normalizedRouteObjects);
101
- return cachedRouteObjects;
102
- };
103
- const selectBasePath = (pathname)=>{
104
- const match = serverBase.find((baseUrl)=>isSegmentPrefix(pathname, baseUrl));
105
- return match || '/';
106
- };
107
- let cachedRouteTree = null;
108
- let cachedRouter = null;
109
- let cachedRouterBasepath = null;
235
+ if (0 === getRouteObjects().length) return App;
110
236
  const RouterWrapper = ()=>{
111
- const runtimeContext = (0, __rspack_external_react.useContext)(InternalRuntimeContext);
112
- const baseUrl = selectBasePath(location.pathname).replace(/^\/*/, '/');
113
- const _basename = '/' === baseUrl ? urlJoin(baseUrl, runtimeContext._internalRouterBaseName || basename || '') : baseUrl;
114
- const routeTree = (0, __rspack_external_react.useMemo)(()=>{
115
- if (cachedRouteTree) return cachedRouteTree;
116
- const routeObjects = getRouteObjects();
117
- if (!routeObjects.length) return null;
118
- cachedRouteTree = createRouteTreeFromRouteObjects(routeObjects, {
119
- rscPayloadRouter: getGlobalEnableRsc()
120
- });
121
- return cachedRouteTree;
122
- }, []);
237
+ const runtimeContext = useContext(InternalRuntimeContext);
238
+ const _basename = getClientBasename(runtimeContext);
239
+ const routeTree = useMemo(()=>getRouteTree(), []);
123
240
  if (!routeTree) return App ? /*#__PURE__*/ jsx(App, {}) : null;
124
- const router = (0, __rspack_external_react.useMemo)(()=>{
125
- const lifecycleContext = {
126
- framework: 'tanstack',
127
- phase: 'client-create',
128
- routes: getRouteObjects(),
129
- runtimeContext,
130
- basename: _basename
131
- };
132
- hooks.onBeforeCreateRouter.call(lifecycleContext);
133
- if (cachedRouter && cachedRouterBasepath === _basename) {
134
- wrapRouterSubscribeWithBlockState(cachedRouter, runtimeContext.unstable_getBlockNavState);
135
- hooks.onAfterCreateRouter.call({
136
- ...lifecycleContext,
137
- router: cachedRouter,
138
- runtimeContext
139
- });
140
- return cachedRouter;
141
- }
142
- const history = supportHtml5History ? createBrowserHistory() : createHashHistory();
143
- const rewrite = createModernBasepathRewrite(_basename);
144
- const serializationAdapters = getGlobalEnableRsc() ? getTanstackRscSerializationAdapters() : void 0;
145
- cachedRouter = createRouter({
146
- routeTree,
147
- basepath: '/',
148
- rewrite,
149
- history,
150
- context: {},
151
- ...serializationAdapters ? {
152
- serializationAdapters
153
- } : {}
154
- });
155
- cachedRouterBasepath = _basename;
156
- wrapRouterSubscribeWithBlockState(cachedRouter, runtimeContext.unstable_getBlockNavState);
157
- hooks.onAfterCreateRouter.call({
158
- ...lifecycleContext,
159
- router: cachedRouter,
160
- runtimeContext
161
- });
162
- return cachedRouter;
163
- }, [
241
+ const router = useMemo(()=>getRouter(runtimeContext, _basename), [
164
242
  _basename,
165
243
  routeTree,
166
- supportHtml5History,
167
244
  runtimeContext
168
245
  ]);
246
+ if (!router) return App ? /*#__PURE__*/ jsx(App, {}) : null;
169
247
  const runtimeState = applyRouterRuntimeState(runtimeContext, {
170
248
  framework: 'tanstack',
171
249
  basename: _basename,
@@ -179,30 +257,29 @@ const tanstackRouterPlugin = (userConfig = {})=>{
179
257
  basename: _basename,
180
258
  router
181
259
  };
182
- const hasSSRBootstrap = "u" > typeof window && Boolean(window.$_TSR);
183
- if (hasSSRBootstrap) hooks.onBeforeHydrateRouter.call({
260
+ const hasSSRBootstrap = "u" > typeof window && (Boolean(window.$_TSR) || hasTanstackSsrHydrationRecord(router));
261
+ const needsRouterClient = hasSSRBootstrap;
262
+ if (needsRouterClient) hooks.onBeforeHydrateRouter.call({
184
263
  ...lifecycleContext,
185
264
  phase: 'hydrate',
186
265
  router,
187
266
  runtimeContext: runtimeState
188
267
  });
189
- const RouterContent = hasSSRBootstrap ? /*#__PURE__*/ jsx(__rspack_external_react.Suspense, {
190
- fallback: null,
191
- children: /*#__PURE__*/ jsx(RouterClient, {
192
- router: router
193
- })
268
+ const RouterContent = needsRouterClient ? /*#__PURE__*/ jsx(ModernRouterClient, {
269
+ router: router
194
270
  }) : /*#__PURE__*/ jsx(RouterProvider, {
195
271
  router: router
196
272
  });
197
- if (hasSSRBootstrap) hooks.onAfterHydrateRouter.call({
273
+ const HydratableRouterContent = wrapTanstackSsrHydrationBoundary(RouterContent, hasSSRBootstrap);
274
+ if (needsRouterClient) hooks.onAfterHydrateRouter.call({
198
275
  ...lifecycleContext,
199
276
  phase: 'hydrate',
200
277
  router,
201
278
  runtimeContext: runtimeState
202
279
  });
203
280
  return App ? /*#__PURE__*/ jsx(App, {
204
- children: RouterContent
205
- }) : RouterContent;
281
+ children: HydratableRouterContent
282
+ }) : HydratableRouterContent;
206
283
  };
207
284
  return RouterWrapper;
208
285
  });