@bleedingdev/modern-js-plugin-tanstack 3.9.0-ultramodern.2 → 3.9.0-ultramodern.20

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 (137) hide show
  1. package/dist/cjs/cli/artifacts.js +15 -1
  2. package/dist/cjs/cli/index.js +12 -0
  3. package/dist/cjs/cli/routeMetadata.js +131 -0
  4. package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +7 -7
  5. package/dist/cjs/cli/tanstackTypes/shared.js +0 -14
  6. package/dist/cjs/cli/tanstackTypes/source.js +27 -60
  7. package/dist/cjs/runtime/basepathRewrite.js +13 -6
  8. package/dist/cjs/runtime/lifecycle.js +6 -9
  9. package/dist/cjs/runtime/loaderBridge.js +10 -4
  10. package/dist/cjs/runtime/navigation.js +102 -0
  11. package/dist/cjs/runtime/plugin.js +7 -2
  12. package/dist/cjs/runtime/plugin.node.js +86 -64
  13. package/dist/cjs/runtime/prefetchLink.js +2 -7
  14. package/dist/cjs/runtime/register.js +0 -2
  15. package/dist/cjs/runtime/routeTree/construction.js +19 -59
  16. package/dist/cjs/runtime/routeTree/loaders.js +1 -1
  17. package/dist/cjs/runtime/routeTree/paths.js +0 -6
  18. package/dist/cjs/runtime/router.js +25 -9
  19. package/dist/cjs/runtime/ssrManagedTags.js +2 -12
  20. package/dist/cjs/runtime/state.js +2 -2
  21. package/dist/cjs/runtime/utils.js +3 -0
  22. package/dist/cjs/shared/routeDescriptor.js +60 -0
  23. package/dist/esm/cli/artifacts.mjs +13 -2
  24. package/dist/esm/cli/index.mjs +12 -9
  25. package/dist/esm/cli/routeMetadata.mjs +71 -0
  26. package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
  27. package/dist/esm/cli/tanstackTypes/shared.mjs +1 -9
  28. package/dist/esm/cli/tanstackTypes/source.mjs +28 -61
  29. package/dist/esm/runtime/basepathRewrite.mjs +10 -3
  30. package/dist/esm/runtime/lifecycle.mjs +1 -1
  31. package/dist/esm/runtime/loaderBridge.mjs +8 -5
  32. package/dist/esm/runtime/navigation.mjs +64 -0
  33. package/dist/esm/runtime/plugin.mjs +7 -2
  34. package/dist/esm/runtime/plugin.node.mjs +88 -66
  35. package/dist/esm/runtime/prefetchLink.mjs +1 -6
  36. package/dist/esm/runtime/register.mjs +0 -2
  37. package/dist/esm/runtime/routeTree/construction.mjs +19 -59
  38. package/dist/esm/runtime/routeTree/loaders.mjs +2 -2
  39. package/dist/esm/runtime/routeTree/paths.mjs +1 -4
  40. package/dist/esm/runtime/router.mjs +27 -11
  41. package/dist/esm/runtime/ssrManagedTags.mjs +1 -8
  42. package/dist/esm/runtime/state.mjs +1 -1
  43. package/dist/esm/runtime/utils.mjs +3 -0
  44. package/dist/esm/shared/routeDescriptor.mjs +22 -0
  45. package/dist/esm-node/cli/artifacts.mjs +13 -2
  46. package/dist/esm-node/cli/index.mjs +12 -9
  47. package/dist/esm-node/cli/routeMetadata.mjs +72 -0
  48. package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
  49. package/dist/esm-node/cli/tanstackTypes/shared.mjs +1 -9
  50. package/dist/esm-node/cli/tanstackTypes/source.mjs +28 -61
  51. package/dist/esm-node/runtime/basepathRewrite.mjs +10 -3
  52. package/dist/esm-node/runtime/lifecycle.mjs +1 -1
  53. package/dist/esm-node/runtime/loaderBridge.mjs +8 -5
  54. package/dist/esm-node/runtime/navigation.mjs +65 -0
  55. package/dist/esm-node/runtime/plugin.mjs +7 -2
  56. package/dist/esm-node/runtime/plugin.node.mjs +88 -66
  57. package/dist/esm-node/runtime/prefetchLink.mjs +1 -6
  58. package/dist/esm-node/runtime/register.mjs +0 -2
  59. package/dist/esm-node/runtime/routeTree/construction.mjs +19 -59
  60. package/dist/esm-node/runtime/routeTree/loaders.mjs +2 -2
  61. package/dist/esm-node/runtime/routeTree/paths.mjs +1 -4
  62. package/dist/esm-node/runtime/router.mjs +27 -11
  63. package/dist/esm-node/runtime/ssrManagedTags.mjs +1 -8
  64. package/dist/esm-node/runtime/state.mjs +1 -1
  65. package/dist/esm-node/runtime/utils.mjs +3 -0
  66. package/dist/esm-node/shared/routeDescriptor.mjs +23 -0
  67. package/dist/types/cli/artifacts.d.ts +13 -5
  68. package/dist/types/cli/index.d.ts +1 -1
  69. package/dist/types/cli/routeMetadata.d.ts +18 -0
  70. package/dist/types/cli/tanstackTypes/shared.d.ts +0 -2
  71. package/dist/types/runtime/basepathRewrite.d.ts +2 -1
  72. package/dist/types/runtime/lifecycle.d.ts +9 -2
  73. package/dist/types/runtime/loaderBridge.d.ts +1 -0
  74. package/dist/types/runtime/navigation.d.ts +4 -0
  75. package/dist/types/runtime/register.d.ts +1 -9
  76. package/dist/types/runtime/routeTree/paths.d.ts +0 -2
  77. package/dist/types/runtime/router.d.ts +2 -13
  78. package/dist/types/runtime/ssrManagedTags.d.ts +0 -1
  79. package/dist/types/runtime/ssrTypes.d.ts +0 -7
  80. package/dist/types/runtime/state.d.ts +1 -1
  81. package/dist/types/runtime/types.d.ts +2 -1
  82. package/dist/types/shared/routeDescriptor.d.ts +26 -0
  83. package/package.json +22 -19
  84. package/rstest.config.mts +2 -24
  85. package/src/cli/artifacts.ts +53 -6
  86. package/src/cli/index.ts +11 -2
  87. package/src/cli/routeMetadata.ts +121 -0
  88. package/src/cli/tanstackTypes/canonicalRoutes.ts +17 -12
  89. package/src/cli/tanstackTypes/shared.ts +0 -14
  90. package/src/cli/tanstackTypes/source.ts +42 -116
  91. package/src/runtime/basepathRewrite.ts +11 -2
  92. package/src/runtime/lifecycle.ts +14 -4
  93. package/src/runtime/loaderBridge.ts +9 -9
  94. package/src/runtime/navigation.ts +78 -0
  95. package/src/runtime/plugin.node.tsx +120 -93
  96. package/src/runtime/plugin.tsx +11 -1
  97. package/src/runtime/prefetchLink.tsx +1 -23
  98. package/src/runtime/register.ts +1 -12
  99. package/src/runtime/routeTree/construction.ts +32 -110
  100. package/src/runtime/routeTree/loaders.ts +2 -4
  101. package/src/runtime/routeTree/paths.ts +0 -6
  102. package/src/runtime/router.ts +25 -40
  103. package/src/runtime/ssrManagedTags.ts +0 -17
  104. package/src/runtime/ssrTypes.ts +0 -7
  105. package/src/runtime/state.ts +1 -1
  106. package/src/runtime/types.ts +2 -2
  107. package/src/runtime/utils.tsx +4 -1
  108. package/src/shared/routeDescriptor.ts +46 -0
  109. package/tests/router/cli.test.ts +148 -824
  110. package/tests/router/clientNavigation.ts +13 -0
  111. package/tests/router/dataMutation.test.tsx +17 -85
  112. package/tests/router/flightSerialization.roundtrip.test.tsx +9 -6
  113. package/tests/router/generateRouteArtifacts.test.ts +139 -27
  114. package/tests/router/loaderBridge.test.ts +0 -25
  115. package/tests/router/localisedIdentity.test.tsx +100 -0
  116. package/tests/router/prefetchLink.test.tsx +46 -21
  117. package/tests/router/prefetchLinkPreload.test.tsx +11 -32
  118. package/tests/router/routeHooks.test.ts +42 -105
  119. package/tests/router/routeMetadata.test.ts +171 -0
  120. package/tests/router/routeTree.test.ts +144 -836
  121. package/tests/router/rsc.test.tsx +131 -166
  122. package/tests/router/serverPlugin.test.ts +193 -1
  123. package/tests/router/tanstackTypes.test.ts +218 -963
  124. package/dist/esm/rslib-runtime~1.mjs +0 -18
  125. package/dist/esm-node/rslib-runtime~0.mjs +0 -19
  126. package/tests/realm-isolation.test.ts +0 -114
  127. package/tests/router/fastDefaults.test.ts +0 -32
  128. package/tests/router/fixtures/legacyRuntimeRouter.ts +0 -10
  129. package/tests/router/fixtures/rscDecoderSecurityChild.cjs +0 -162
  130. package/tests/router/hooks.test.ts +0 -40
  131. package/tests/router/hydrationBoundary.test.tsx +0 -23
  132. package/tests/router/packageSurface.test.ts +0 -24
  133. package/tests/router/preloadRedirect.test.ts +0 -64
  134. package/tests/router/register.test.ts +0 -8
  135. package/tests/router/routerCompatibility.test.ts +0 -239
  136. package/tests/router/rscDecoderSecurity.test.ts +0 -113
  137. package/tests/router/rscPayloadRouterMatrix.test.ts +0 -197
@@ -98,15 +98,15 @@ type LoaderLikeContext = {
98
98
  params?: Record<string, string>;
99
99
  };
100
100
 
101
- function getLoaderSignal(ctx: LoaderLikeContext | undefined): AbortSignal {
102
- const abortSignal = ctx?.abortController?.signal;
103
- if (abortSignal instanceof AbortSignal) {
104
- return abortSignal;
105
- }
106
- if (ctx?.signal instanceof AbortSignal) {
107
- return ctx.signal;
108
- }
109
- return new AbortController().signal;
101
+ export function getLoaderSignal(
102
+ ctx: LoaderLikeContext | undefined,
103
+ ): AbortSignal {
104
+ const matchSignal = ctx?.abortController?.signal ?? ctx?.signal;
105
+ const requestSignal = ctx?.context?.request?.signal;
106
+ const signals = [matchSignal, requestSignal].filter(
107
+ (signal): signal is AbortSignal => signal instanceof AbortSignal,
108
+ );
109
+ return AbortSignal.any(signals);
110
110
  }
111
111
 
112
112
  export function getLoaderHref(ctx: LoaderLikeContext | undefined): string {
@@ -0,0 +1,78 @@
1
+ import type {
2
+ RouterNavigationCapability,
3
+ RouterNavigationSnapshot,
4
+ } from '@modern-js/runtime-extensions/router-state';
5
+ import type { AnyRouter } from '@tanstack/react-router';
6
+ import { Link } from './prefetchLink';
7
+
8
+ /** Native TanStack navigation, exposed through the provider contract. */
9
+ export function createTanstackNavigation(
10
+ router: AnyRouter,
11
+ ): RouterNavigationCapability {
12
+ let location: AnyRouter['state']['location'] | undefined;
13
+ let matches: AnyRouter['state']['matches'] | undefined;
14
+ let snapshot: RouterNavigationSnapshot;
15
+ return {
16
+ Link: Link as RouterNavigationCapability['Link'],
17
+ getSnapshot() {
18
+ const state = router.state;
19
+ if (
20
+ location !== state.location ||
21
+ matches === undefined ||
22
+ matches.length !== state.matches.length ||
23
+ matches.some(
24
+ (match, index) => match.params !== state.matches[index]?.params,
25
+ )
26
+ ) {
27
+ location = state.location;
28
+ matches = state.matches;
29
+ snapshot = {
30
+ location: {
31
+ pathname: location.pathname,
32
+ search: location.searchStr,
33
+ hash:
34
+ location.hash !== '' ? `#${location.hash.replace(/^#/, '')}` : '',
35
+ },
36
+ params: Object.assign({}, ...matches.map(match => match.params)),
37
+ };
38
+ }
39
+ return snapshot;
40
+ },
41
+ subscribe(listener) {
42
+ const stops = (
43
+ ['onBeforeNavigate', 'onBeforeLoad', 'onLoad', 'onResolved'] as const
44
+ ).map(event => router.subscribe(event, listener));
45
+ return () => {
46
+ for (const stop of stops) stop();
47
+ };
48
+ },
49
+ navigate(href, options) {
50
+ return router.navigate({
51
+ to: href,
52
+ replace: options?.replace,
53
+ ...(options?.state === undefined
54
+ ? {}
55
+ : { state: options.state as never }),
56
+ });
57
+ },
58
+ createLinkProps(target) {
59
+ const preload =
60
+ target.preload !== undefined
61
+ ? target.preload
62
+ : target.prefetch === 'none'
63
+ ? false
64
+ : target.prefetch;
65
+ return {
66
+ to: target.pathname,
67
+ ...(target.search !== undefined ? { search: target.search } : {}),
68
+ ...(target.hash !== undefined && target.hash !== ''
69
+ ? { hash: target.hash }
70
+ : {}),
71
+ ...(target.hashScrollIntoView === undefined
72
+ ? {}
73
+ : { hashScrollIntoView: target.hashScrollIntoView }),
74
+ ...(preload === undefined ? {} : { preload }),
75
+ };
76
+ },
77
+ };
78
+ }
@@ -1,10 +1,10 @@
1
1
  // @effect-diagnostics asyncFunction:off newPromise:off strictBooleanExpressions:off unnecessaryArrowBlock:off
2
2
  import {
3
3
  getGlobalEnableRsc,
4
- type InternalRouterServerSnapshot,
5
4
  InternalRuntimeContext,
6
5
  type TInternalRuntimeContext,
7
6
  } from '@modern-js/runtime/context';
7
+ import type { InternalRouterServerSnapshot } from '@modern-js/runtime-extensions/router-state';
8
8
  import {
9
9
  createRequestContext,
10
10
  type RequestContext,
@@ -23,11 +23,13 @@ import { createModernBasepathRewrite } from './basepathRewrite';
23
23
  import { routerProviderRegistryHooks } from './hooks';
24
24
  import { wrapTanstackSsrHydrationBoundary } from './hydrationBoundary';
25
25
  import {
26
+ applyRouterRuntimeState,
26
27
  applyRouterServerPrepareResult,
27
- createRouterServerSnapshot,
28
28
  getRouterRuntimeState,
29
+ getRouterServerSnapshot,
29
30
  type RouterLifecycleContext,
30
31
  } from './lifecycle';
32
+ import { createTanstackNavigation } from './navigation';
31
33
  import {
32
34
  createTanstackRouteObjects,
33
35
  getTanstackRouteConfig,
@@ -35,6 +37,7 @@ import {
35
37
  type TanstackRouterPluginAPI,
36
38
  type TanstackRouterRuntimePlugin,
37
39
  } from './pluginShared';
40
+ import { Link } from './prefetchLink';
38
41
  import {
39
42
  createRouteTreeFromRouteObjects,
40
43
  getModernRouteIdsFromMatches,
@@ -53,7 +56,6 @@ import {
53
56
  collectRouterErrors,
54
57
  createGetSsrHref,
55
58
  routerManagedTagsToHtml,
56
- waitForRouterSerialization,
57
59
  } from './ssrManagedTags';
58
60
  import { preloadMatchedRouteComponents } from './ssrPreload';
59
61
  import type {
@@ -98,6 +100,8 @@ export const tanstackRouterPlugin = (
98
100
  return;
99
101
  }
100
102
 
103
+ context.router = { Link };
104
+
101
105
  const {
102
106
  request,
103
107
  nonce,
@@ -134,7 +138,11 @@ export const tanstackRouterPlugin = (
134
138
  initialEntries: [initialHref],
135
139
  });
136
140
 
137
- const rewrite = createModernBasepathRewrite(_basename);
141
+ const rewrite = createModernBasepathRewrite(
142
+ _basename,
143
+ false,
144
+ modifiedRouteObjects,
145
+ );
138
146
  const routerLifecycleContext: RouterLifecycleContext = {
139
147
  framework: 'tanstack',
140
148
  phase: 'ssr-prepare',
@@ -161,116 +169,135 @@ export const tanstackRouterPlugin = (
161
169
  setTanstackRscRouter(serverRouter);
162
170
  }
163
171
 
164
- await attachServerSsrUtils(serverRouter);
165
-
166
- const end = time();
167
-
172
+ let disposed = false;
173
+ let prepared = false;
174
+ const onAbort = () => controller.abort(rawRequest.signal.reason);
175
+ const cleanup = () => {
176
+ if (disposed) return;
177
+ disposed = true;
178
+ rawRequest.signal.removeEventListener('abort', onAbort);
179
+ controller.abort();
180
+ serverRouter.serverSsr?.cleanup();
181
+ };
182
+ // Acquire the disposer before attachment: every subsequent failure,
183
+ // including partial attachment, has an owner. Successful preparation
184
+ // leaves disposal to the response lifetime in the SSR pipeline.
185
+ applyRouterRuntimeState(context, {
186
+ framework: 'tanstack',
187
+ basename: _basename,
188
+ instance: serverRouter,
189
+ cleanup,
190
+ });
191
+ rawRequest.signal.addEventListener('abort', onAbort, { once: true });
168
192
  try {
169
- await tanstackRouter.load({ sync: true });
170
- } finally {
171
- const cost = end();
172
- context.ssrContext?.onTiming?.(LOADER_REPORTER_NAME, cost);
173
- }
193
+ rawRequest.signal.throwIfAborted();
194
+ await attachServerSsrUtils(serverRouter);
195
+ rawRequest.signal.throwIfAborted();
196
+
197
+ const end = time();
174
198
 
175
- const serverLoadResult = serverRouter._serverResult;
176
- if (!serverLoadResult) {
177
199
  try {
178
- serverRouter.serverSsr?.cleanup?.();
179
- } catch {}
180
- throw new Error(
181
- 'TanStack Router completed an SSR load without a server result.',
182
- );
183
- }
200
+ await tanstackRouter.load({ sync: true });
201
+ } finally {
202
+ const cost = end();
203
+ context.ssrContext?.onTiming?.(LOADER_REPORTER_NAME, cost);
204
+ }
184
205
 
185
- if (serverLoadResult.type === 'redirect') {
186
- const { redirect } = serverLoadResult;
206
+ rawRequest.signal.throwIfAborted();
207
+ const serverLoadResult = serverRouter._serverResult;
208
+ if (!serverLoadResult) {
209
+ throw new Error(
210
+ 'TanStack Router completed an SSR load without a server result.',
211
+ );
212
+ }
187
213
 
188
- try {
189
- serverRouter.serverSsr?.cleanup?.();
190
- } catch {}
191
-
192
- return interrupt(
193
- isRSCNavigation
194
- ? handleTanstackRscRedirect(
195
- redirect.headers,
196
- _basename,
197
- redirect.status,
198
- )
199
- : redirect,
200
- );
201
- }
214
+ if (serverLoadResult.type === 'redirect') {
215
+ const { redirect } = serverLoadResult;
216
+
217
+ return interrupt(
218
+ isRSCNavigation
219
+ ? handleTanstackRscRedirect(
220
+ redirect.headers,
221
+ _basename,
222
+ redirect.status,
223
+ )
224
+ : redirect,
225
+ );
226
+ }
227
+
228
+ const routerErrors = collectRouterErrors(tanstackRouter);
229
+ if (routerErrors && loaderFailureMode === 'clientRender') {
230
+ (
231
+ context.ssrContext?.response as
232
+ | { status: (code: number) => void }
233
+ | undefined
234
+ )?.status(200);
235
+ throw Object.values(routerErrors)[0];
236
+ }
237
+
238
+ await preloadMatchedRouteComponents(serverRouter);
202
239
 
203
- const routerErrors = collectRouterErrors(tanstackRouter);
204
- if (routerErrors && loaderFailureMode === 'clientRender') {
205
240
  (
206
241
  context.ssrContext?.response as
207
242
  | { status: (code: number) => void }
208
243
  | undefined
209
- )?.status(200);
210
- try {
211
- serverRouter.serverSsr?.cleanup?.();
212
- } catch {}
213
- throw Object.values(routerErrors)[0];
214
- }
244
+ )?.status(serverLoadResult.status);
215
245
 
216
- await preloadMatchedRouteComponents(serverRouter);
246
+ await serverRouter.serverSsr?.dehydrate();
217
247
 
218
- (
219
- context.ssrContext?.response as
220
- | { status: (code: number) => void }
221
- | undefined
222
- )?.status(serverLoadResult.status);
223
-
224
- await serverRouter.serverSsr?.dehydrate?.();
225
-
226
- if (enableRsc) {
227
- if (isRSCNavigation) {
228
- // RSC navigations consume the server payload directly. Normal HTML SSR
229
- // emits the buffered bootstrap script below and must not wait here
230
- // because Modern's non-streaming hook has not rendered the app yet.
231
- await waitForRouterSerialization(serverRouter);
248
+ if (enableRsc) {
249
+ setTanstackRscServerPayload(
250
+ createTanstackRscServerPayload(serverRouter, {
251
+ omitClientLoaderData: isRSCNavigation,
252
+ }),
253
+ );
232
254
  }
233
255
 
234
- setTanstackRscServerPayload(
235
- createTanstackRscServerPayload(serverRouter, {
236
- omitClientLoaderData: isRSCNavigation,
237
- }),
238
- );
239
- }
240
-
241
- const ssrScriptTags = serverRouter.serverSsr?.takeBufferedScripts?.();
242
- const hydrationScripts = routerManagedTagsToHtml(ssrScriptTags);
243
- const matchedRouteIds = getModernRouteIdsFromMatches(serverRouter);
244
- const routerServerSnapshot: InternalRouterServerSnapshot =
245
- createRouterServerSnapshot({
256
+ const initialScriptTags =
257
+ serverRouter.serverSsr?.takeInitialHydrationScriptTags();
258
+ const hydrationScripts = initialScriptTags
259
+ ? routerManagedTagsToHtml([
260
+ ...initialScriptTags.before,
261
+ initialScriptTags.boundary,
262
+ ])
263
+ : [];
264
+ const matchedRouteIds = getModernRouteIdsFromMatches(serverRouter);
265
+ const routerServerSnapshot: InternalRouterServerSnapshot = {
246
266
  framework: 'tanstack',
247
267
  basename: _basename,
248
268
  statusCode: serverLoadResult.status,
249
269
  errors: routerErrors,
250
270
  matchedRouteIds,
251
271
  hydrationScripts,
252
- });
253
- const runtimeContext = applyRouterServerPrepareResult(
254
- context as TInternalRuntimeContext,
255
- {
256
- snapshot: routerServerSnapshot,
257
- cleanup: () => serverRouter.serverSsr?.cleanup?.(),
258
- state: {
259
- framework: 'tanstack',
260
- basename: _basename,
261
- instance: serverRouter,
262
- hydrationScripts,
263
- matchedRouteIds,
264
- serverSnapshot: routerServerSnapshot,
272
+ };
273
+ const runtimeContext = applyRouterServerPrepareResult(
274
+ context as TInternalRuntimeContext,
275
+ {
276
+ snapshot: routerServerSnapshot,
277
+ cleanup,
278
+ state: {
279
+ framework: 'tanstack',
280
+ basename: _basename,
281
+ instance: serverRouter,
282
+ navigation: createTanstackNavigation(tanstackRouter),
283
+ },
265
284
  },
266
- },
267
- );
268
- hooks.onAfterCreateRouter.call({
269
- ...routerLifecycleContext,
270
- router: serverRouter,
271
- serverSnapshot: routerServerSnapshot,
272
- runtimeContext,
273
- });
285
+ );
286
+ rawRequest.signal.throwIfAborted();
287
+ hooks.onAfterCreateRouter.call({
288
+ ...routerLifecycleContext,
289
+ router: serverRouter,
290
+ serverSnapshot: getRouterServerSnapshot(runtimeContext),
291
+ runtimeContext,
292
+ });
293
+ prepared = true;
294
+ } finally {
295
+ if (!prepared) {
296
+ try {
297
+ cleanup();
298
+ } catch {}
299
+ }
300
+ }
274
301
  });
275
302
 
276
303
  api.wrapRoot(App => {
@@ -32,6 +32,7 @@ import {
32
32
  applyRouterRuntimeState,
33
33
  type RouterLifecycleContext,
34
34
  } from './lifecycle';
35
+ import { createTanstackNavigation } from './navigation';
35
36
  import {
36
37
  createTanstackRouteObjects,
37
38
  getMergedRouterConfig,
@@ -149,7 +150,11 @@ export const tanstackRouterPlugin = (
149
150
  const history = supportHtml5History
150
151
  ? createBrowserHistory()
151
152
  : createHashHistory();
152
- const rewrite = createModernBasepathRewrite(_basename);
153
+ const rewrite = createModernBasepathRewrite(
154
+ _basename,
155
+ false,
156
+ getRouteObjects(),
157
+ );
153
158
  const serializationAdapters = getGlobalEnableRsc()
154
159
  ? getTanstackRscSerializationAdapters()
155
160
  : undefined;
@@ -255,10 +260,15 @@ export const tanstackRouterPlugin = (
255
260
  if (!router) {
256
261
  return App ? <App /> : null;
257
262
  }
263
+ const navigation = useMemo(
264
+ () => createTanstackNavigation(router),
265
+ [router],
266
+ );
258
267
  const runtimeState = applyRouterRuntimeState(runtimeContext, {
259
268
  framework: 'tanstack',
260
269
  basename: _basename,
261
270
  instance: router,
271
+ navigation,
262
272
  });
263
273
  const lifecycleContext: RouterLifecycleContext = {
264
274
  framework: 'tanstack',
@@ -1,3 +1,4 @@
1
+ import { resolvePreloadFromPrefetch } from '@modern-js/runtime-extensions';
1
2
  import {
2
3
  type AnyRouter,
3
4
  type LinkComponentProps,
@@ -8,29 +9,6 @@ import type { AnchorHTMLAttributes, ReactElement, ReactNode, Ref } from 'react';
8
9
 
9
10
  export type PrefetchBehavior = 'intent' | 'render' | 'viewport' | 'none';
10
11
 
11
- function resolvePreloadFromPrefetch(
12
- prefetch: PrefetchBehavior | undefined,
13
- preload: unknown,
14
- ) {
15
- if (typeof preload !== 'undefined') {
16
- return preload;
17
- }
18
-
19
- if (prefetch === 'none') {
20
- return false;
21
- }
22
-
23
- if (
24
- prefetch === 'intent' ||
25
- prefetch === 'render' ||
26
- prefetch === 'viewport'
27
- ) {
28
- return prefetch;
29
- }
30
-
31
- return 'viewport';
32
- }
33
-
34
12
  export type LinkProps<
35
13
  TRouter extends AnyRouter = RegisteredRouter,
36
14
  TFrom extends string = string,
@@ -1,16 +1,7 @@
1
- /**
2
- * Registers TanStack in the @modern-js/runtime compatibility registry.
3
- * Runtime entries bind the exported local factory into their own provider
4
- * realm; registration remains for older runtime wrappers and mixed cohorts.
5
- *
6
- * This module is intentionally side-effectful (see `sideEffects` in
7
- * package.json).
8
- */
9
1
  import {
10
2
  type RouterProviderFactory,
11
3
  type RouterProviderPlugin,
12
- registerRouterProvider,
13
- } from '@modern-js/runtime/context';
4
+ } from '@modern-js/runtime-extensions/router-provider';
14
5
  import { tanstackRouterPlugin } from './plugin';
15
6
 
16
7
  // TanStack runtime plugin types its API against its own hook registry,
@@ -22,5 +13,3 @@ import { tanstackRouterPlugin } from './plugin';
22
13
  export const tanstackRouterProviderFactory: RouterProviderFactory =
23
14
  userConfig =>
24
15
  tanstackRouterPlugin(userConfig) as unknown as RouterProviderPlugin;
25
-
26
- registerRouterProvider('tanstack', tanstackRouterProviderFactory);