@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,20 +1,33 @@
1
1
  import type { AppTools, AppToolsContext, CliPlugin } from '@modern-js/app-tools';
2
2
  import type { NestedRouteForCli, PageRoute } from '@modern-js/types';
3
- export { generateTanstackRouterTypesSourceForEntry, isTanstackRouterFrameworkEnabled, } from './tanstackTypes';
3
+ import { type TanstackRouteCodeSplittingOption } from './routeSplitting';
4
+ export type { TanstackRouteCodeSplittingOption, TanstackRsbuildRouteSplittingProfile, } from './routeSplitting';
5
+ export { createTanstackRsbuildRouteSplittingProfile, resolveTanstackRouteCodeSplittingEnabled, } from './routeSplitting';
6
+ export { type CollectCanonicalRoutesOptions, collectCanonicalRoutesForEntry, generateTanstackRouterTypesSourceForEntry, } from './tanstackTypes';
4
7
  export type TanstackRouterPluginOptions = {
5
8
  routesDir?: string;
6
9
  generatedDirName?: string;
10
+ routeCodeSplitting?: TanstackRouteCodeSplittingOption;
7
11
  };
8
12
  export declare function writeTanstackRegisterFile(opts: {
9
13
  entries: string[];
10
14
  generatedDirName?: string;
11
15
  runtimeModule?: string;
12
16
  srcDirectory: string;
17
+ canonicalRoutes?: Record<string, string> | null;
18
+ i18nRuntimeModule?: string;
13
19
  }): Promise<void>;
14
20
  export declare function writeTanstackRouterTypesForEntries(opts: {
15
21
  appContext: AppToolsContext;
16
22
  generatedDirName?: string;
17
23
  routesByEntry: Record<string, (NestedRouteForCli | PageRoute)[]>;
24
+ /**
25
+ * Whether `@modern-js/plugin-i18n` is actually installed in the app. The
26
+ * `register.gen.d.ts` augmentation of '@modern-js/plugin-i18n/runtime' is
27
+ * only emitted when this is true — otherwise apps with a hand-rolled
28
+ * `/:lang/` param would fail typechecking on an unresolvable module.
29
+ */
30
+ i18nPluginInstalled?: boolean;
18
31
  }): Promise<void>;
19
32
  export declare function tanstackRouterPlugin(options?: TanstackRouterPluginOptions): CliPlugin<AppTools>;
20
33
  export default tanstackRouterPlugin;
@@ -0,0 +1,20 @@
1
+ export type TanstackRouteCodeSplittingOption = boolean | {
2
+ enabled?: boolean;
3
+ };
4
+ export type TanstackRsbuildRouteSplittingProfile = {
5
+ defaultConfig: {
6
+ output: {
7
+ splitRouteChunks: boolean;
8
+ };
9
+ };
10
+ };
11
+ export declare function resolveTanstackRouteCodeSplittingEnabled(option?: TanstackRouteCodeSplittingOption): boolean;
12
+ /**
13
+ * Route chunking for TanStack entries is owned by Modern's
14
+ * `output.splitRouteChunks`; the TanStack Start Rspack splitter does not
15
+ * apply because Modern generates TanStack route trees from Modern route
16
+ * metadata rather than TanStack file-route factory modules.
17
+ */
18
+ export declare function createTanstackRsbuildRouteSplittingProfile(opts: {
19
+ routeCodeSplitting?: TanstackRouteCodeSplittingOption;
20
+ }): TanstackRsbuildRouteSplittingProfile;
@@ -1,6 +1,26 @@
1
1
  import type { AppToolsContext } from '@modern-js/app-tools';
2
2
  import type { NestedRouteForCli, PageRoute } from '@modern-js/types';
3
- export declare function isTanstackRouterFrameworkEnabled(appContext: AppToolsContext): Promise<boolean>;
3
+ export type CollectCanonicalRoutesOptions = {
4
+ /**
5
+ * Whether a leading `:lang`/`:locale`/`:language` route param may be
6
+ * treated as an i18n locale prefix. This MUST only be enabled when
7
+ * `@modern-js/plugin-i18n` is actually installed: the emitted
8
+ * `declare module '@modern-js/plugin-i18n/runtime'` augmentation breaks
9
+ * typechecking (TS2664) for apps that hand-roll a `/:lang/` param without
10
+ * the plugin. Routes carrying `modernCanonicalPath` metadata are always
11
+ * honored — only plugin-i18n produces them.
12
+ */
13
+ localeParamHeuristic?: boolean;
14
+ };
15
+ /**
16
+ * Derive the canonical (language-agnostic) route map for an entry: the
17
+ * leading locale param is stripped and localized physical variants (routes
18
+ * carrying `modernCanonicalPath` metadata from `@modern-js/plugin-i18n`)
19
+ * collapse to their canonical pattern. Returns `null` when the entry has no
20
+ * i18n routing surface (no locale param and no localized variants), so plain
21
+ * TanStack apps never get a `@modern-js/plugin-i18n` module augmentation.
22
+ */
23
+ export declare function collectCanonicalRoutesForEntry(routes: (NestedRouteForCli | PageRoute)[], options?: CollectCanonicalRoutesOptions): Record<string, string> | null;
4
24
  export declare function generateTanstackRouterTypesSourceForEntry(opts: {
5
25
  appContext: AppToolsContext;
6
26
  entryName: string;
@@ -1,33 +1,8 @@
1
- declare const modifyRoutes: {
2
- tap: (cb: any) => void;
3
- call: (...params: any[]) => any;
4
- };
5
- declare const onBeforeCreateRoutes: {
6
- tap: (cb: any) => void;
7
- call: (...params: any[]) => any;
8
- };
9
- declare const onBeforeCreateRouter: {
10
- tap: (cb: any) => void;
11
- call: (...params: any[]) => any;
12
- };
13
- declare const onAfterCreateRouter: {
14
- tap: (cb: any) => void;
15
- call: (...params: any[]) => any;
16
- };
17
- declare const onBeforeHydrateRouter: {
18
- tap: (cb: any) => void;
19
- call: (...params: any[]) => any;
20
- };
21
- declare const onAfterHydrateRouter: {
22
- tap: (cb: any) => void;
23
- call: (...params: any[]) => any;
24
- };
25
- export { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter, };
26
- export type RouterExtendsHooks = {
27
- modifyRoutes: typeof modifyRoutes;
28
- onBeforeCreateRoutes: typeof onBeforeCreateRoutes;
29
- onBeforeCreateRouter: typeof onBeforeCreateRouter;
30
- onAfterCreateRouter: typeof onAfterCreateRouter;
31
- onBeforeHydrateRouter: typeof onBeforeHydrateRouter;
32
- onAfterHydrateRouter: typeof onAfterHydrateRouter;
33
- };
1
+ /**
2
+ * The router hooks are owned by @modern-js/runtime — this module re-exports
3
+ * the canonical instances through the `/context` seam, so the TanStack
4
+ * provider taps and calls the exact same hooks the built-in router wrapper
5
+ * registers. Creating separate hook instances here would silently split the
6
+ * hook registry between the wrapper and this provider.
7
+ */
8
+ export { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter, type RouterExtendsHooks, routerProviderRegistryHooks, } from '@modern-js/runtime/context';
@@ -0,0 +1,2 @@
1
+ import { type ReactElement } from 'react';
2
+ export declare function wrapTanstackSsrHydrationBoundary(routerContent: ReactElement, shouldWrap: boolean): import("react").JSX.Element;
@@ -1,9 +1,14 @@
1
+ import './register';
1
2
  export * from '@tanstack/react-router';
2
- export { useMatch } from '@tanstack/react-router';
3
3
  export type { Fetcher, FetcherState, FetcherSubmitOptions, FormProps, SubmitOptions, } from './dataMutation';
4
4
  export { Form, RouteActionResponseError, useFetcher, } from './dataMutation';
5
+ export type { ModernRouterContext } from './loaderBridge';
6
+ export { createRouteStaticData, isAbsoluteUrl, modernLoaderToTanstack, throwTanstackRedirect, } from './loaderBridge';
7
+ export { Outlet } from './outlet';
5
8
  export { tanstackRouterPlugin, tanstackRouterPlugin as default, } from './plugin';
6
9
  export type { LinkProps, NavLinkProps, PrefetchBehavior, } from './prefetchLink';
7
10
  export { Link, NavLink } from './prefetchLink';
8
- export type { AnyCompositeComponent, AnyRenderableServerComponent, CompositeComponentProps, } from './rsc/client';
9
- export { CompositeComponent } from './rsc/client';
11
+ export type { TanstackRouterState } from './state';
12
+ export { getTanstackRouterState } from './state';
13
+ export type { RouterConfig } from './types';
14
+ export { getModernTanstackRouterFastDefaults, modernTanstackRouterFastDefaults, } from './types';
@@ -1,22 +1,7 @@
1
- import type { TInternalRuntimeContext } from '@modern-js/runtime/context';
2
- import type { RouteObject } from '@modern-js/runtime-utils/router';
3
- import type { InternalRouterRuntimeState, InternalRouterServerSnapshot, RouterFramework, RouterRouteMatchSnapshot, RouterServerPrepareResult } from './types';
4
- export type RouterLifecyclePhase = 'ssr-prepare' | 'client-create' | 'hydrate';
5
- export type RouterLifecycleContext = {
6
- framework: RouterFramework;
7
- phase: RouterLifecyclePhase;
8
- routes: RouteObject[];
9
- runtimeContext: TInternalRuntimeContext;
10
- basename?: string;
11
- hydrationData?: unknown;
12
- router?: unknown;
13
- matches?: RouterRouteMatchSnapshot[];
14
- cleanup?: () => void | Promise<void>;
15
- serverSnapshot?: InternalRouterServerSnapshot;
16
- };
17
- type RouterSnapshotLike = Partial<InternalRouterServerSnapshot>;
18
- export declare function createRouterServerSnapshot(state: RouterSnapshotLike): InternalRouterServerSnapshot;
19
- export declare function createRouterRuntimeState(state: InternalRouterRuntimeState): InternalRouterRuntimeState;
20
- export declare function applyRouterRuntimeState(runtimeContext: TInternalRuntimeContext, state: InternalRouterRuntimeState): TInternalRuntimeContext;
21
- export declare function applyRouterServerPrepareResult(runtimeContext: TInternalRuntimeContext, result: RouterServerPrepareResult): TInternalRuntimeContext;
22
- export {};
1
+ /**
2
+ * The router runtime state helpers are owned by @modern-js/runtime (the same
3
+ * implementation backs the built-in react-router provider and the SSR
4
+ * pipeline). This module only re-exports them so every router provider
5
+ * writes to the exact same runtime-context extension slot.
6
+ */
7
+ export { applyRouterRuntimeState, applyRouterServerPrepareResult, createRouterRuntimeState, createRouterServerSnapshot, getRouterRuntimeState, getRouterServerSnapshot, type RouterLifecycleContext, type RouterLifecyclePhase, } from '@modern-js/runtime/context';
@@ -0,0 +1,48 @@
1
+ /** Router context shape used by the generated TanStack router types. */
2
+ export type ModernRouterContext = {
3
+ request?: Request;
4
+ requestContext?: unknown;
5
+ };
6
+ export declare function isResponse(value: unknown): value is Response;
7
+ export declare function isRedirectResponse(res: Response): boolean;
8
+ /**
9
+ * TanStack redirects are Response objects carrying the original redirect
10
+ * `options`. They must be re-thrown untouched — re-translating them through
11
+ * the Modern Response handling would lose `to`-based (internal) targets.
12
+ */
13
+ export declare function isTanstackRedirect(value: unknown): boolean;
14
+ export declare function isAbsoluteUrl(value: string): boolean;
15
+ /**
16
+ * Re-throw a Modern.js `Location` redirect as a TanStack redirect.
17
+ *
18
+ * Prefers `to` for internal/relative redirects so the basepath rewrite can be
19
+ * applied; absolute (external) URLs go through `href` untouched.
20
+ */
21
+ export declare function throwTanstackRedirect(location: string): never;
22
+ /**
23
+ * React Router uses `*` for splat params, TanStack Router uses `_splat`.
24
+ * Modern loaders expect the React Router spelling.
25
+ */
26
+ export declare function mapSplatParamsForModernLoader(params: Record<string, string>, hasSplat: boolean): Record<string, string>;
27
+ /**
28
+ * Static-data factory used by the generated router files: drops empty fields
29
+ * so route static data stays minimal.
30
+ */
31
+ export declare function createRouteStaticData(opts: {
32
+ modernRouteId?: string;
33
+ modernRouteAction?: unknown;
34
+ modernRouteLoader?: unknown;
35
+ }): {
36
+ modernRouteId?: string;
37
+ modernRouteAction?: unknown;
38
+ modernRouteLoader?: unknown;
39
+ };
40
+ /**
41
+ * Wrap a Modern.js data loader (`page.data.ts` loader/action style) into a
42
+ * TanStack Router loader: builds a `Request` from the loader context, maps
43
+ * splat params, and translates Response redirects/404s into TanStack
44
+ * `redirect()`/`notFound()`.
45
+ */
46
+ export declare function modernLoaderToTanstack<TLoader extends (args: any) => any>(opts: {
47
+ hasSplat: boolean;
48
+ }, modernLoader: TLoader): (ctx: unknown) => Promise<Awaited<ReturnType<TLoader>>>;
@@ -0,0 +1,2 @@
1
+ export declare const Outlet: import("react").MemoExoticComponent<() => import("react").JSX.Element>;
2
+ export declare function withModernRouteMatchContext(component: unknown, _routeId: string): unknown;
@@ -1,17 +1,4 @@
1
- import type { Plugin, RuntimePluginExtends } from '@modern-js/plugin';
2
- import type { RuntimePluginAPI } from '@modern-js/plugin/runtime';
3
- import { type TInternalRuntimeContext } from '@modern-js/runtime/context';
4
- import { type RouterExtendsHooks } from './hooks';
5
- import type { RouterConfig } from './types';
6
- type TanstackRouterRuntimeConfig = {
7
- plugins?: TanstackRouterRuntimePlugin[];
8
- router?: Partial<RouterConfig>;
9
- [key: string]: unknown;
10
- };
11
- type TanstackRouterRuntimeExtends = Required<RuntimePluginExtends<TanstackRouterRuntimeConfig, TInternalRuntimeContext>> & {
12
- extendHooks: RouterExtendsHooks;
13
- };
14
- type TanstackRouterPluginAPI = RuntimePluginAPI<TanstackRouterRuntimeExtends>;
15
- type TanstackRouterRuntimePlugin = Plugin<TanstackRouterPluginAPI, TInternalRuntimeContext>;
1
+ import { type TanstackRouterRuntimePlugin } from './pluginCore';
2
+ import { type RouterConfig } from './types';
16
3
  export declare const tanstackRouterPlugin: (userConfig?: Partial<RouterConfig>) => TanstackRouterRuntimePlugin;
17
4
  export default tanstackRouterPlugin;
@@ -1,17 +1,4 @@
1
- import type { Plugin, RuntimePluginExtends } from '@modern-js/plugin';
2
- import type { RuntimePluginAPI } from '@modern-js/plugin/runtime';
3
- import { type TInternalRuntimeContext } from '@modern-js/runtime/context';
4
- import { type RouterExtendsHooks } from './hooks';
5
- import type { RouterConfig } from './types';
6
- type TanstackRouterRuntimeConfig = {
7
- plugins?: TanstackRouterRuntimePlugin[];
8
- router?: Partial<RouterConfig>;
9
- [key: string]: unknown;
10
- };
11
- type TanstackRouterRuntimeExtends = Required<RuntimePluginExtends<TanstackRouterRuntimeConfig, TInternalRuntimeContext>> & {
12
- extendHooks: RouterExtendsHooks;
13
- };
14
- type TanstackRouterPluginAPI = RuntimePluginAPI<TanstackRouterRuntimeExtends>;
15
- type TanstackRouterRuntimePlugin = Plugin<TanstackRouterPluginAPI, TInternalRuntimeContext>;
1
+ import { type TanstackRouterRuntimePlugin } from './pluginCore';
2
+ import { type RouterConfig } from './types';
16
3
  export declare const tanstackRouterPlugin: (userConfig?: Partial<RouterConfig>) => TanstackRouterRuntimePlugin;
17
4
  export default tanstackRouterPlugin;
@@ -0,0 +1 @@
1
+ export { default, tanstackRouterPlugin, } from './plugin.node';
@@ -0,0 +1,21 @@
1
+ import type { Plugin, RuntimePluginExtends } from '@modern-js/plugin';
2
+ import type { RuntimePluginAPI } from '@modern-js/plugin/runtime';
3
+ import { type TInternalRuntimeContext } from '@modern-js/runtime/context';
4
+ import type { RouterExtendsHooks } from './hooks';
5
+ import type { RouterConfig } from './types';
6
+ export type TanstackRouterRuntimeConfig = {
7
+ plugins?: TanstackRouterRuntimePlugin[];
8
+ router?: Partial<RouterConfig>;
9
+ [key: string]: unknown;
10
+ };
11
+ type TanstackRouterRuntimeExtends = Required<RuntimePluginExtends<TanstackRouterRuntimeConfig, TInternalRuntimeContext>> & {
12
+ extendHooks: RouterExtendsHooks;
13
+ };
14
+ export type TanstackRouterPluginAPI = RuntimePluginAPI<TanstackRouterRuntimeExtends>;
15
+ export type TanstackRouterRuntimePlugin = Plugin<TanstackRouterPluginAPI, TInternalRuntimeContext>;
16
+ export declare function getMergedRouterConfig(api: TanstackRouterPluginAPI, userConfig: Partial<RouterConfig>): RouterConfig;
17
+ export declare function getFinalRouteConfig(mergedConfig: RouterConfig): {
18
+ routes: (import("@modern-js/types").NestedRoute<string | (() => JSX.Element)> | import("@modern-js/types").PageRoute)[] | undefined;
19
+ globalApp: import("react").ComponentClass<{}, any> | import("react").FunctionComponent<{}> | undefined;
20
+ };
21
+ export {};
@@ -0,0 +1,9 @@
1
+ import { Form, RouteActionResponseError, useFetcher } from './dataMutation';
2
+ export declare const tanstackRouterCompatBindings: {
3
+ Form: typeof Form;
4
+ Link: <TRouter extends import("@tanstack/router-core").AnyRouter = import("@tanstack/router-core").AnyRouter, const TFrom extends string = string, const TTo extends string | undefined = undefined, const TMaskFrom extends string = TFrom, const TMaskTo extends string = "">(props: import("./prefetchLink").LinkProps<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>) => import("react").ReactElement;
5
+ NavLink: <TRouter extends import("@tanstack/router-core").AnyRouter = import("@tanstack/router-core").AnyRouter, const TFrom extends string = string, const TTo extends string | undefined = undefined, const TMaskFrom extends string = TFrom, const TMaskTo extends string = "">(props: import("./prefetchLink").LinkProps<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>) => import("react").ReactElement;
6
+ Outlet: import("react").MemoExoticComponent<() => import("react").JSX.Element>;
7
+ RouteActionResponseError: typeof RouteActionResponseError;
8
+ useFetcher: typeof useFetcher;
9
+ };
@@ -1,11 +1,9 @@
1
1
  import type { RouteObject } from '@modern-js/runtime-utils/router';
2
- import type { NestedRoute, PageRoute } from '@modern-js/types';
3
2
  import type { AnyRouter, RootRoute as TanstackRootRoute } from '@tanstack/react-router';
4
3
  type ModernTanstackRootRoute = TanstackRootRoute;
5
4
  type RouteTreeOptions = {
6
5
  rscPayloadRouter?: boolean;
7
6
  };
8
- export declare function createRouteTreeFromModernRoutes(routes: Array<NestedRoute | PageRoute>, options?: RouteTreeOptions): ModernTanstackRootRoute;
9
7
  export declare function createRouteTreeFromRouteObjects(routes: RouteObject[], options?: RouteTreeOptions): ModernTanstackRootRoute;
10
8
  export declare function getModernRouteIdsFromMatches(router: AnyRouter): string[];
11
9
  export {};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Entry-injected router module for entrypoints that are NOT TanStack
3
+ * file-route entrypoints (e.g. apps configuring
4
+ * `router: { framework: 'tanstack', createRoutes }` in modern.runtime.ts).
5
+ *
6
+ * The CLI plugin injects `{ name: 'router', path: '<pkg>/runtime/router' }`
7
+ * for those entries, so the generated entry code value-imports `routerPlugin`
8
+ * from here. That single import both installs the framework-resolving router
9
+ * plugin of @modern-js/runtime AND registers the TanStack router provider
10
+ * (the './register' side effect) — the registration can therefore never be
11
+ * tree-shaken away from the entry that needs it.
12
+ */
13
+ import './register';
14
+ export { routerPlugin } from '@modern-js/runtime/router/internal';
@@ -0,0 +1,16 @@
1
+ import type { AnyRouter } from '@tanstack/react-router';
2
+ import type { InternalRouterRuntimeState } from './types';
3
+ /**
4
+ * Router runtime state as published by the TanStack router provider into the
5
+ * runtime-context extension slot.
6
+ */
7
+ export interface TanstackRouterState extends Omit<InternalRouterRuntimeState, 'framework' | 'instance'> {
8
+ framework: 'tanstack';
9
+ instance?: AnyRouter;
10
+ }
11
+ /**
12
+ * Typed accessor for the TanStack router state stored on a Modern.js runtime
13
+ * context. Returns `undefined` when the active router provider is not
14
+ * TanStack (e.g. react-router) or no router has been created yet.
15
+ */
16
+ export declare function getTanstackRouterState(context: object): TanstackRouterState | undefined;
@@ -1,68 +1,29 @@
1
- import type { RequestContext } from '@modern-js/runtime-utils/node';
1
+ import type { RouterFramework } from '@modern-js/runtime/context';
2
2
  import type { RouteObject } from '@modern-js/runtime-utils/router';
3
3
  import type { NestedRoute, PageRoute } from '@modern-js/types';
4
4
  import type React from 'react';
5
- export type BuiltInRouterFramework = 'react-router' | 'tanstack';
6
- export type RouterFramework = BuiltInRouterFramework | (string & {});
5
+ export type { BuiltInRouterFramework, InternalRouterRuntimeState, InternalRouterServerSnapshot, RouterFramework, RouterRouteMatchSnapshot, RouterServerPrepareResult, } from '@modern-js/runtime/context';
6
+ /**
7
+ * TanStack-specific router config. Unlike the react-router provider config,
8
+ * this intentionally has no `oldVersion`/`future` fields — those are
9
+ * react-router-only knobs with no meaning here.
10
+ */
7
11
  export type RouterConfig = {
8
12
  framework?: RouterFramework;
9
13
  routesConfig: {
10
14
  globalApp?: React.ComponentType<any>;
11
15
  routes?: (NestedRoute | PageRoute)[];
12
16
  };
13
- oldVersion?: boolean;
14
17
  serverBase?: string[];
15
18
  supportHtml5History?: boolean;
16
19
  basename?: string;
17
20
  createRoutes?: () => RouteObject[];
18
- future?: Partial<{
19
- v7_startTransition: boolean;
20
- }>;
21
+ defaultStructuralSharing?: boolean;
21
22
  unstable_reloadOnURLMismatch?: boolean;
22
23
  };
23
- export interface RouterRouteMatchSnapshot {
24
- routeId: string;
25
- assetRouteId?: string;
26
- pathname?: string;
27
- params?: Record<string, string>;
28
- }
29
- export interface InternalRouterServerSnapshot {
30
- framework?: RouterFramework;
31
- basename?: string;
32
- statusCode?: number;
33
- errors?: Record<string, unknown>;
34
- routerData?: {
35
- loaderData?: Record<string, unknown>;
36
- errors?: Record<string, unknown>;
37
- };
38
- hydrationScript?: string;
39
- hydrationScripts?: string[];
40
- matchedRouteIds?: string[];
41
- matches?: RouterRouteMatchSnapshot[];
42
- }
43
- export interface InternalRouterRuntimeState {
44
- framework: RouterFramework;
45
- basename?: string;
46
- instance?: unknown;
47
- hydrationScript?: string;
48
- hydrationScripts?: string[];
49
- matchedRouteIds?: string[];
50
- matches?: RouterRouteMatchSnapshot[];
51
- serverSnapshot?: InternalRouterServerSnapshot;
52
- cleanup?: () => void | Promise<void>;
53
- }
54
- export interface RouterServerPrepareResult {
55
- state: InternalRouterRuntimeState;
56
- snapshot?: InternalRouterServerSnapshot;
57
- redirect?: Response;
58
- cleanup?: () => void | Promise<void>;
59
- }
60
- interface DataFunctionArgs<D = any> {
61
- request: Request;
62
- params: Record<string, string>;
63
- context?: D;
64
- }
65
- export type LoaderFunctionArgs<P extends Record<string, unknown> = Record<string, unknown>> = DataFunctionArgs<RequestContext<P>>;
66
- type DataFunctionValue = Response | NonNullable<unknown> | null;
67
- export type LoaderFunction = <P extends Record<string, unknown> = Record<string, unknown>>(args: LoaderFunctionArgs<P>) => Promise<DataFunctionValue> | DataFunctionValue;
68
- export {};
24
+ export declare const modernTanstackRouterFastDefaults: {
25
+ readonly defaultStructuralSharing: true;
26
+ };
27
+ export declare const getModernTanstackRouterFastDefaults: (config?: Partial<Pick<RouterConfig, 'defaultStructuralSharing'>>) => {
28
+ defaultStructuralSharing: boolean;
29
+ };
package/package.json CHANGED
@@ -18,7 +18,7 @@
18
18
  "modern.js",
19
19
  "tanstack-router"
20
20
  ],
21
- "version": "3.2.0-ultramodern.12",
21
+ "version": "3.2.0-ultramodern.121",
22
22
  "engines": {
23
23
  "node": ">=20"
24
24
  },
@@ -49,17 +49,12 @@
49
49
  },
50
50
  "default": "./dist/esm/runtime/index.mjs"
51
51
  },
52
- "./runtime/rsc": {
53
- "types": "./dist/types/runtime/rsc/index.d.ts",
54
- "default": "./dist/esm/runtime/rsc/index.mjs"
55
- },
56
- "./runtime/rsc/client": {
57
- "types": "./dist/types/runtime/rsc/client.d.ts",
58
- "default": "./dist/esm/runtime/rsc/client.mjs"
59
- },
60
- "./runtime/rsc/server": {
61
- "types": "./dist/types/runtime/rsc/server.d.ts",
62
- "default": "./dist/esm/runtime/rsc/server.mjs"
52
+ "./runtime/router": {
53
+ "types": "./dist/types/runtime/router.d.ts",
54
+ "node": {
55
+ "module": "./dist/esm/runtime/router.mjs"
56
+ },
57
+ "default": "./dist/esm/runtime/router.mjs"
63
58
  }
64
59
  },
65
60
  "typesVersions": {
@@ -73,47 +68,54 @@
73
68
  "runtime": [
74
69
  "./dist/types/runtime/index.d.ts"
75
70
  ],
76
- "runtime/rsc": [
77
- "./dist/types/runtime/rsc/index.d.ts"
78
- ],
79
- "runtime/rsc/client": [
80
- "./dist/types/runtime/rsc/client.d.ts"
81
- ],
82
- "runtime/rsc/server": [
83
- "./dist/types/runtime/rsc/server.d.ts"
71
+ "runtime/router": [
72
+ "./dist/types/runtime/router.d.ts"
84
73
  ]
85
74
  }
86
75
  },
87
76
  "dependencies": {
88
- "@swc/helpers": "^0.5.21",
89
- "@tanstack/react-router": "1.170.1",
90
- "@tanstack/router-core": "1.170.1",
91
- "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.2.0-ultramodern.12",
92
- "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.2.0-ultramodern.12",
93
- "@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.2.0-ultramodern.12",
94
- "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.2.0-ultramodern.12"
77
+ "@swc/helpers": "^0.5.23",
78
+ "@tanstack/react-router": "1.170.15",
79
+ "@tanstack/router-core": "1.171.13",
80
+ "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.2.0-ultramodern.121",
81
+ "@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.2.0-ultramodern.121",
82
+ "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.2.0-ultramodern.121",
83
+ "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.2.0-ultramodern.121"
95
84
  },
96
85
  "peerDependencies": {
97
- "@modern-js/runtime": "3.2.0-ultramodern.12",
98
- "react": "^19.2.6",
99
- "react-dom": "^19.2.6"
86
+ "@modern-js/runtime": "3.2.0-ultramodern.121",
87
+ "react": "^19.2.7",
88
+ "react-dom": "^19.2.7"
100
89
  },
101
90
  "devDependencies": {
102
- "@rslib/core": "0.21.5",
91
+ "@rslib/core": "0.22.0",
103
92
  "@tanstack/history": "1.162.0",
104
93
  "@testing-library/dom": "^10.4.1",
105
94
  "@testing-library/react": "^16.3.2",
106
- "@types/node": "^25.8.0",
107
- "@types/react": "^19.2.14",
95
+ "@types/node": "^25.9.3",
96
+ "@types/react": "^19.2.17",
108
97
  "@types/react-dom": "^19.2.3",
109
- "@typescript/native-preview": "7.0.0-dev.20260516.1",
110
- "react": "^19.2.6",
111
- "react-dom": "^19.2.6",
112
- "@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.2.0-ultramodern.12",
113
- "@scripts/rstest-config": "2.66.0",
114
- "@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.2.0-ultramodern.12"
98
+ "@typescript/native-preview": "7.0.0-dev.20260610.1",
99
+ "react": "^19.2.7",
100
+ "react-dom": "^19.2.7",
101
+ "@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.2.0-ultramodern.121",
102
+ "@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.2.0-ultramodern.121",
103
+ "@scripts/rstest-config": "2.66.0"
115
104
  },
116
- "sideEffects": false,
105
+ "sideEffects": [
106
+ "./src/runtime/register.ts",
107
+ "./src/runtime/index.tsx",
108
+ "./src/runtime/router.ts",
109
+ "./dist/esm/runtime/register.mjs",
110
+ "./dist/esm/runtime/index.mjs",
111
+ "./dist/esm/runtime/router.mjs",
112
+ "./dist/esm-node/runtime/register.mjs",
113
+ "./dist/esm-node/runtime/index.mjs",
114
+ "./dist/esm-node/runtime/router.mjs",
115
+ "./dist/cjs/runtime/register.js",
116
+ "./dist/cjs/runtime/index.js",
117
+ "./dist/cjs/runtime/router.js"
118
+ ],
117
119
  "publishConfig": {
118
120
  "registry": "https://registry.npmjs.org/",
119
121
  "access": "public"
package/rstest.config.mts CHANGED
@@ -24,6 +24,11 @@ export default {
24
24
  testEnvironment: 'node',
25
25
  include: [
26
26
  'tests/router/cli.test.ts',
27
+ 'tests/router/fastDefaults.test.ts',
28
+ 'tests/router/hooks.test.ts',
29
+ 'tests/router/loaderBridge.test.ts',
30
+ 'tests/router/packageSurface.test.ts',
31
+ 'tests/router/register.test.ts',
27
32
  'tests/router/rsc.test.tsx',
28
33
  'tests/router/tanstackTypes.test.ts',
29
34
  'tests/router/routeTree.test.ts',
@@ -35,6 +40,7 @@ export default {
35
40
  testEnvironment: 'happy-dom',
36
41
  include: [
37
42
  'tests/router/dataMutation.test.tsx',
43
+ 'tests/router/hydrationBoundary.test.tsx',
38
44
  'tests/router/prefetchLink.test.tsx',
39
45
  ],
40
46
  extends: commonConfig,