@bleedingdev/modern-js-plugin-tanstack 3.2.0-ultramodern.120 → 3.2.0-ultramodern.122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/cli/index.js +47 -27
- package/dist/cjs/cli/routeSplitting.js +0 -32
- package/dist/cjs/cli/tanstackTypes.js +34 -199
- package/dist/cjs/runtime/hooks.js +11 -14
- package/dist/cjs/runtime/index.js +107 -319
- package/dist/cjs/runtime/lifecycle.js +12 -86
- package/dist/cjs/runtime/loaderBridge.js +173 -0
- package/dist/cjs/runtime/plugin.js +6 -30
- package/dist/cjs/runtime/plugin.node.js +7 -29
- package/dist/cjs/runtime/pluginCore.js +55 -0
- package/dist/cjs/runtime/register.js +56 -0
- package/dist/cjs/runtime/routeTree.js +10 -207
- package/dist/cjs/runtime/{DefaultNotFound.js → router.js} +5 -15
- package/dist/cjs/runtime/rsc/payloadRouter.js +35 -1
- package/dist/cjs/runtime/state.js +45 -0
- package/dist/cjs/runtime/utils.js +0 -5
- package/dist/esm/cli/index.mjs +52 -26
- package/dist/esm/cli/routeSplitting.mjs +1 -30
- package/dist/esm/cli/tanstackTypes.mjs +32 -194
- package/dist/esm/runtime/hooks.mjs +1 -8
- package/dist/esm/runtime/index.mjs +4 -2
- package/dist/esm/runtime/lifecycle.mjs +1 -82
- package/dist/esm/runtime/loaderBridge.mjs +114 -0
- package/dist/esm/runtime/plugin.mjs +8 -32
- package/dist/esm/runtime/plugin.node.mjs +10 -32
- package/dist/esm/runtime/pluginCore.mjs +14 -0
- package/dist/esm/runtime/register.mjs +18 -0
- package/dist/esm/runtime/routeTree.mjs +4 -198
- package/dist/esm/runtime/router.mjs +2 -0
- package/dist/esm/runtime/rsc/payloadRouter.mjs +35 -1
- package/dist/esm/runtime/state.mjs +7 -0
- package/dist/esm/runtime/utils.mjs +0 -5
- package/dist/esm-node/cli/index.mjs +52 -26
- package/dist/esm-node/cli/routeSplitting.mjs +1 -30
- package/dist/esm-node/cli/tanstackTypes.mjs +32 -194
- package/dist/esm-node/runtime/hooks.mjs +1 -8
- package/dist/esm-node/runtime/index.mjs +4 -2
- package/dist/esm-node/runtime/lifecycle.mjs +1 -82
- package/dist/esm-node/runtime/loaderBridge.mjs +115 -0
- package/dist/esm-node/runtime/plugin.mjs +8 -32
- package/dist/esm-node/runtime/plugin.node.mjs +10 -32
- package/dist/esm-node/runtime/pluginCore.mjs +15 -0
- package/dist/esm-node/runtime/register.mjs +19 -0
- package/dist/esm-node/runtime/routeTree.mjs +4 -198
- package/dist/esm-node/runtime/router.mjs +3 -0
- package/dist/esm-node/runtime/rsc/payloadRouter.mjs +35 -1
- package/dist/esm-node/runtime/state.mjs +8 -0
- package/dist/esm-node/runtime/utils.mjs +0 -5
- package/dist/types/cli/index.d.ts +9 -2
- package/dist/types/cli/routeSplitting.d.ts +6 -15
- package/dist/types/cli/tanstackTypes.d.ts +13 -2
- package/dist/types/runtime/hooks.d.ts +8 -18
- package/dist/types/runtime/index.d.ts +6 -4
- package/dist/types/runtime/lifecycle.d.ts +7 -22
- package/dist/types/runtime/loaderBridge.d.ts +48 -0
- package/dist/types/runtime/plugin.d.ts +1 -14
- package/dist/types/runtime/plugin.node.d.ts +1 -14
- package/dist/types/runtime/pluginCore.d.ts +21 -0
- package/dist/types/runtime/register.d.ts +9 -0
- package/dist/types/runtime/routeTree.d.ts +0 -2
- package/dist/types/runtime/router.d.ts +14 -0
- package/dist/types/runtime/state.d.ts +16 -0
- package/dist/types/runtime/types.d.ts +7 -53
- package/package.json +31 -29
- package/rstest.config.mts +6 -0
- package/src/cli/index.ts +111 -29
- package/src/cli/routeSplitting.ts +6 -44
- package/src/cli/tanstackTypes.ts +78 -214
- package/src/runtime/hooks.ts +10 -27
- package/src/runtime/index.tsx +12 -107
- package/src/runtime/lifecycle.ts +16 -151
- package/src/runtime/loaderBridge.ts +257 -0
- package/src/runtime/plugin.node.tsx +14 -77
- package/src/runtime/plugin.tsx +12 -72
- package/src/runtime/pluginCore.ts +48 -0
- package/src/runtime/register.ts +58 -0
- package/src/runtime/routeTree.ts +8 -370
- package/src/runtime/router.ts +15 -0
- package/src/runtime/rsc/payloadRouter.ts +45 -2
- package/src/runtime/state.ts +29 -0
- package/src/runtime/types.ts +20 -67
- package/src/runtime/utils.tsx +3 -6
- package/tests/router/cli.test.ts +297 -31
- package/tests/router/hooks.test.ts +26 -0
- package/tests/router/loaderBridge.test.ts +211 -0
- package/tests/router/packageSurface.test.ts +24 -0
- package/tests/router/register.test.ts +46 -0
- package/tests/router/routeTree.test.ts +65 -180
- package/tests/router/rsc.test.tsx +70 -0
- package/tests/router/tanstackTypes.test.ts +164 -6
- package/dist/esm/runtime/DefaultNotFound.mjs +0 -13
- package/dist/esm-node/runtime/DefaultNotFound.mjs +0 -14
- package/dist/types/runtime/DefaultNotFound.d.ts +0 -2
- package/src/runtime/DefaultNotFound.tsx +0 -15
|
@@ -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>>>;
|
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { RuntimePluginAPI } from '@modern-js/plugin/runtime';
|
|
3
|
-
import { type TInternalRuntimeContext } from '@modern-js/runtime/context';
|
|
4
|
-
import { type RouterExtendsHooks } from './hooks';
|
|
1
|
+
import { type TanstackRouterRuntimePlugin } from './pluginCore';
|
|
5
2
|
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>;
|
|
16
3
|
export declare const tanstackRouterPlugin: (userConfig?: Partial<RouterConfig>) => TanstackRouterRuntimePlugin;
|
|
17
4
|
export default tanstackRouterPlugin;
|
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { RuntimePluginAPI } from '@modern-js/plugin/runtime';
|
|
3
|
-
import { type TInternalRuntimeContext } from '@modern-js/runtime/context';
|
|
4
|
-
import { type RouterExtendsHooks } from './hooks';
|
|
1
|
+
import { type TanstackRouterRuntimePlugin } from './pluginCore';
|
|
5
2
|
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>;
|
|
16
3
|
export declare const tanstackRouterPlugin: (userConfig?: Partial<RouterConfig>) => TanstackRouterRuntimePlugin;
|
|
17
4
|
export default tanstackRouterPlugin;
|
|
@@ -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,23 +1,23 @@
|
|
|
1
|
-
import type {
|
|
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
|
|
6
|
-
|
|
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
21
|
defaultStructuralSharing?: boolean;
|
|
22
22
|
unstable_reloadOnURLMismatch?: boolean;
|
|
23
23
|
};
|
|
@@ -27,49 +27,3 @@ export declare const modernTanstackRouterFastDefaults: {
|
|
|
27
27
|
export declare const getModernTanstackRouterFastDefaults: (config?: Partial<Pick<RouterConfig, 'defaultStructuralSharing'>>) => {
|
|
28
28
|
defaultStructuralSharing: boolean;
|
|
29
29
|
};
|
|
30
|
-
export interface RouterRouteMatchSnapshot {
|
|
31
|
-
routeId: string;
|
|
32
|
-
assetRouteId?: string;
|
|
33
|
-
pathname?: string;
|
|
34
|
-
params?: Record<string, string>;
|
|
35
|
-
}
|
|
36
|
-
export interface InternalRouterServerSnapshot {
|
|
37
|
-
framework?: RouterFramework;
|
|
38
|
-
basename?: string;
|
|
39
|
-
statusCode?: number;
|
|
40
|
-
errors?: Record<string, unknown>;
|
|
41
|
-
routerData?: {
|
|
42
|
-
loaderData?: Record<string, unknown>;
|
|
43
|
-
errors?: Record<string, unknown>;
|
|
44
|
-
};
|
|
45
|
-
hydrationScript?: string;
|
|
46
|
-
hydrationScripts?: string[];
|
|
47
|
-
matchedRouteIds?: string[];
|
|
48
|
-
matches?: RouterRouteMatchSnapshot[];
|
|
49
|
-
}
|
|
50
|
-
export interface InternalRouterRuntimeState {
|
|
51
|
-
framework: RouterFramework;
|
|
52
|
-
basename?: string;
|
|
53
|
-
instance?: unknown;
|
|
54
|
-
hydrationScript?: string;
|
|
55
|
-
hydrationScripts?: string[];
|
|
56
|
-
matchedRouteIds?: string[];
|
|
57
|
-
matches?: RouterRouteMatchSnapshot[];
|
|
58
|
-
serverSnapshot?: InternalRouterServerSnapshot;
|
|
59
|
-
cleanup?: () => void | Promise<void>;
|
|
60
|
-
}
|
|
61
|
-
export interface RouterServerPrepareResult {
|
|
62
|
-
state: InternalRouterRuntimeState;
|
|
63
|
-
snapshot?: InternalRouterServerSnapshot;
|
|
64
|
-
redirect?: Response;
|
|
65
|
-
cleanup?: () => void | Promise<void>;
|
|
66
|
-
}
|
|
67
|
-
interface DataFunctionArgs<D = any> {
|
|
68
|
-
request: Request;
|
|
69
|
-
params: Record<string, string>;
|
|
70
|
-
context?: D;
|
|
71
|
-
}
|
|
72
|
-
export type LoaderFunctionArgs<P extends Record<string, unknown> = Record<string, unknown>> = DataFunctionArgs<RequestContext<P>>;
|
|
73
|
-
type DataFunctionValue = Response | NonNullable<unknown> | null;
|
|
74
|
-
export type LoaderFunction = <P extends Record<string, unknown> = Record<string, unknown>>(args: LoaderFunctionArgs<P>) => Promise<DataFunctionValue> | DataFunctionValue;
|
|
75
|
-
export {};
|
package/package.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"modern.js",
|
|
19
19
|
"tanstack-router"
|
|
20
20
|
],
|
|
21
|
-
"version": "3.2.0-ultramodern.
|
|
21
|
+
"version": "3.2.0-ultramodern.122",
|
|
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/
|
|
53
|
-
"types": "./dist/types/runtime/
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
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,14 +68,8 @@
|
|
|
73
68
|
"runtime": [
|
|
74
69
|
"./dist/types/runtime/index.d.ts"
|
|
75
70
|
],
|
|
76
|
-
"runtime/
|
|
77
|
-
"./dist/types/runtime/
|
|
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
|
},
|
|
@@ -88,13 +77,13 @@
|
|
|
88
77
|
"@swc/helpers": "^0.5.23",
|
|
89
78
|
"@tanstack/react-router": "1.170.15",
|
|
90
79
|
"@tanstack/router-core": "1.171.13",
|
|
91
|
-
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.2.0-ultramodern.
|
|
92
|
-
"@modern-js/
|
|
93
|
-
"@modern-js/
|
|
94
|
-
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.2.0-ultramodern.
|
|
80
|
+
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.2.0-ultramodern.122",
|
|
81
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.2.0-ultramodern.122",
|
|
82
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.2.0-ultramodern.122",
|
|
83
|
+
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.2.0-ultramodern.122"
|
|
95
84
|
},
|
|
96
85
|
"peerDependencies": {
|
|
97
|
-
"@modern-js/runtime": "3.2.0-ultramodern.
|
|
86
|
+
"@modern-js/runtime": "3.2.0-ultramodern.122",
|
|
98
87
|
"react": "^19.2.7",
|
|
99
88
|
"react-dom": "^19.2.7"
|
|
100
89
|
},
|
|
@@ -109,11 +98,24 @@
|
|
|
109
98
|
"@typescript/native-preview": "7.0.0-dev.20260610.1",
|
|
110
99
|
"react": "^19.2.7",
|
|
111
100
|
"react-dom": "^19.2.7",
|
|
112
|
-
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.2.0-ultramodern.
|
|
113
|
-
"@
|
|
114
|
-
"@
|
|
101
|
+
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.2.0-ultramodern.122",
|
|
102
|
+
"@scripts/rstest-config": "2.66.0",
|
|
103
|
+
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.2.0-ultramodern.122"
|
|
115
104
|
},
|
|
116
|
-
"sideEffects":
|
|
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,
|
package/src/cli/index.ts
CHANGED
|
@@ -25,7 +25,6 @@ import {
|
|
|
25
25
|
import {
|
|
26
26
|
collectCanonicalRoutesForEntry,
|
|
27
27
|
generateTanstackRouterTypesSourceForEntry,
|
|
28
|
-
isTanstackRouterFrameworkEnabled,
|
|
29
28
|
} from './tanstackTypes';
|
|
30
29
|
|
|
31
30
|
export type {
|
|
@@ -34,13 +33,12 @@ export type {
|
|
|
34
33
|
} from './routeSplitting';
|
|
35
34
|
export {
|
|
36
35
|
createTanstackRsbuildRouteSplittingProfile,
|
|
37
|
-
isTanstackStartRouteModuleSource,
|
|
38
36
|
resolveTanstackRouteCodeSplittingEnabled,
|
|
39
37
|
} from './routeSplitting';
|
|
40
38
|
export {
|
|
39
|
+
type CollectCanonicalRoutesOptions,
|
|
41
40
|
collectCanonicalRoutesForEntry,
|
|
42
41
|
generateTanstackRouterTypesSourceForEntry,
|
|
43
|
-
isTanstackRouterFrameworkEnabled,
|
|
44
42
|
} from './tanstackTypes';
|
|
45
43
|
|
|
46
44
|
const DEFAULT_ROUTES_DIR = 'routes';
|
|
@@ -55,6 +53,7 @@ export type TanstackRouterPluginOptions = {
|
|
|
55
53
|
|
|
56
54
|
type RuntimeRouterCliHelpers = {
|
|
57
55
|
getEntrypointRoutesDir: (entrypoint: Entrypoint) => string | null;
|
|
56
|
+
getEntrypointRoutesOwner: (entrypoint: Entrypoint) => string | null;
|
|
58
57
|
handleFileChange: (
|
|
59
58
|
api: CLIPluginAPI<AppTools>,
|
|
60
59
|
event: unknown,
|
|
@@ -74,9 +73,6 @@ type RuntimeRouterCliHelpers = {
|
|
|
74
73
|
entrypoints: Entrypoint[],
|
|
75
74
|
options?: {
|
|
76
75
|
entrypointsKey?: string;
|
|
77
|
-
generateCodeOptions?: {
|
|
78
|
-
enableTanstackTypes?: boolean;
|
|
79
|
-
};
|
|
80
76
|
},
|
|
81
77
|
) => Promise<Record<string, (NestedRouteForCli | PageRoute)[]>>;
|
|
82
78
|
handleModifyEntrypoints: (
|
|
@@ -98,7 +94,11 @@ function getRuntimeRouterCli(): RuntimeRouterCliHelpers {
|
|
|
98
94
|
|
|
99
95
|
const cli =
|
|
100
96
|
require('@modern-js/runtime/cli') as Partial<RuntimeRouterCliHelpers>;
|
|
101
|
-
if (
|
|
97
|
+
if (
|
|
98
|
+
cli.handleGeneratorEntryCode &&
|
|
99
|
+
cli.getEntrypointRoutesDir &&
|
|
100
|
+
cli.getEntrypointRoutesOwner
|
|
101
|
+
) {
|
|
102
102
|
runtimeRouterCli = cli as RuntimeRouterCliHelpers;
|
|
103
103
|
return runtimeRouterCli;
|
|
104
104
|
}
|
|
@@ -207,11 +207,19 @@ export async function writeTanstackRouterTypesForEntries(opts: {
|
|
|
207
207
|
appContext: AppToolsContext;
|
|
208
208
|
generatedDirName?: string;
|
|
209
209
|
routesByEntry: Record<string, (NestedRouteForCli | PageRoute)[]>;
|
|
210
|
+
/**
|
|
211
|
+
* Whether `@modern-js/plugin-i18n` is actually installed in the app. The
|
|
212
|
+
* `register.gen.d.ts` augmentation of '@modern-js/plugin-i18n/runtime' is
|
|
213
|
+
* only emitted when this is true — otherwise apps with a hand-rolled
|
|
214
|
+
* `/:lang/` param would fail typechecking on an unresolvable module.
|
|
215
|
+
*/
|
|
216
|
+
i18nPluginInstalled?: boolean;
|
|
210
217
|
}) {
|
|
211
218
|
const {
|
|
212
219
|
appContext,
|
|
213
220
|
generatedDirName = DEFAULT_GENERATED_DIR_NAME,
|
|
214
221
|
routesByEntry,
|
|
222
|
+
i18nPluginInstalled = false,
|
|
215
223
|
} = opts;
|
|
216
224
|
|
|
217
225
|
const entryNames = Object.keys(routesByEntry);
|
|
@@ -253,14 +261,22 @@ export async function writeTanstackRouterTypesForEntries(opts: {
|
|
|
253
261
|
});
|
|
254
262
|
|
|
255
263
|
// Merge the canonical (language-agnostic) route maps of every entry so the
|
|
256
|
-
// typed i18n Link covers all routes the app can navigate to.
|
|
264
|
+
// typed i18n Link covers all routes the app can navigate to. Only relevant
|
|
265
|
+
// when plugin-i18n is actually installed — without it the emitted module
|
|
266
|
+
// augmentation would reference an unresolvable module.
|
|
257
267
|
let canonicalRoutes: Record<string, string> | null = null;
|
|
258
|
-
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
268
|
+
if (i18nPluginInstalled) {
|
|
269
|
+
for (const entryName of registerEntries) {
|
|
270
|
+
const entryCanonicalRoutes = collectCanonicalRoutesForEntry(
|
|
271
|
+
routesByEntry[entryName],
|
|
272
|
+
{ localeParamHeuristic: true },
|
|
273
|
+
);
|
|
274
|
+
if (entryCanonicalRoutes) {
|
|
275
|
+
canonicalRoutes = {
|
|
276
|
+
...entryCanonicalRoutes,
|
|
277
|
+
...(canonicalRoutes ?? {}),
|
|
278
|
+
};
|
|
279
|
+
}
|
|
264
280
|
}
|
|
265
281
|
}
|
|
266
282
|
|
|
@@ -292,11 +308,38 @@ export function tanstackRouterPlugin(
|
|
|
292
308
|
return getEntrypointRoutesDir(entrypoint) === routesDir;
|
|
293
309
|
};
|
|
294
310
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
311
|
+
// Entrypoints claimed by another file-route convention — the built-in
|
|
312
|
+
// pages/ or routes/ entries of @modern-js/runtime's router plugin, or
|
|
313
|
+
// an entry tagged by a different routes-owner plugin. Their router
|
|
314
|
+
// runtime plugin must be left untouched: redirecting it through our
|
|
315
|
+
// wrapper would value-import the TanStack runtime into bundles that
|
|
316
|
+
// never use it, and pushing a second `router` plugin can install two
|
|
317
|
+
// routers for one entry.
|
|
318
|
+
const isForeignRouteEntrypoint = (entrypoint: Entrypoint) => {
|
|
319
|
+
const { getEntrypointRoutesDir, getEntrypointRoutesOwner } =
|
|
320
|
+
getRuntimeRouterCli();
|
|
321
|
+
if (getEntrypointRoutesOwner(entrypoint)) {
|
|
322
|
+
// Owned by some routes-owner plugin. TanStack-owned entries were
|
|
323
|
+
// already claimed by the isTanstackEntrypoint branch, so any owner
|
|
324
|
+
// seen here is foreign.
|
|
325
|
+
return true;
|
|
326
|
+
}
|
|
327
|
+
if (entrypoint.pageRoutesEntry) {
|
|
328
|
+
return true;
|
|
298
329
|
}
|
|
330
|
+
return getEntrypointRoutesDir(entrypoint) !== null;
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
const isI18nPluginInstalled = () => {
|
|
334
|
+
const { plugins } = api.getAppContext() as {
|
|
335
|
+
plugins?: Array<{ name?: string }>;
|
|
336
|
+
};
|
|
337
|
+
return Boolean(
|
|
338
|
+
plugins?.some(plugin => plugin?.name === '@modern-js/plugin-i18n'),
|
|
339
|
+
);
|
|
340
|
+
};
|
|
299
341
|
|
|
342
|
+
api._internalRuntimePlugins(({ entrypoint, plugins }) => {
|
|
300
343
|
const { metaName, serverRoutes } = api.getAppContext();
|
|
301
344
|
const serverBase = serverRoutes
|
|
302
345
|
.filter(
|
|
@@ -305,11 +348,44 @@ export function tanstackRouterPlugin(
|
|
|
305
348
|
.map(route => route.urlPath)
|
|
306
349
|
.sort((a, b) => (a.length - b.length > 0 ? -1 : 1));
|
|
307
350
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
351
|
+
if (isTanstackEntrypoint(entrypoint as Entrypoint)) {
|
|
352
|
+
plugins.push({
|
|
353
|
+
name: 'tanstackRouter',
|
|
354
|
+
path: `@${metaName}/plugin-tanstack/runtime`,
|
|
355
|
+
config: { serverBase },
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
return { entrypoint, plugins };
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Entries owned by the built-in router (classic routes/ or pages/
|
|
362
|
+
// conventions) or by another routes-owner plugin keep their own
|
|
363
|
+
// router runtime plugin untouched.
|
|
364
|
+
if (isForeignRouteEntrypoint(entrypoint as Entrypoint)) {
|
|
365
|
+
return { entrypoint, plugins };
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// True custom entry without any file-route convention (`createRoutes`
|
|
369
|
+
// apps, hand-rolled App entries, ...): having this plugin installed
|
|
370
|
+
// is the explicit signal that the app routes through the
|
|
371
|
+
// router-provider registry — no source sniffing of modern.runtime.ts.
|
|
372
|
+
// Inject the framework-resolving router plugin of @modern-js/runtime
|
|
373
|
+
// through our own runtime/router module, so the TanStack provider
|
|
374
|
+
// registration is value-imported together with it and can never be
|
|
375
|
+
// tree-shaken away from the entry.
|
|
376
|
+
const routerWrapperPath = `@${metaName}/plugin-tanstack/runtime/router`;
|
|
377
|
+
const existingRouterPlugin = plugins.find(
|
|
378
|
+
plugin => plugin.name === 'router',
|
|
379
|
+
);
|
|
380
|
+
if (existingRouterPlugin) {
|
|
381
|
+
existingRouterPlugin.path = routerWrapperPath;
|
|
382
|
+
} else {
|
|
383
|
+
plugins.push({
|
|
384
|
+
name: 'router',
|
|
385
|
+
path: routerWrapperPath,
|
|
386
|
+
config: { serverBase },
|
|
387
|
+
});
|
|
388
|
+
}
|
|
313
389
|
|
|
314
390
|
return { entrypoint, plugins };
|
|
315
391
|
});
|
|
@@ -324,8 +400,18 @@ export function tanstackRouterPlugin(
|
|
|
324
400
|
...routeSplittingProfile.defaultConfig,
|
|
325
401
|
source: {
|
|
326
402
|
include: [
|
|
403
|
+
// TanStack Router and its runtime deps ship modern syntax and
|
|
404
|
+
// must be down-leveled for the app's browser targets.
|
|
327
405
|
/[\\/]node_modules[\\/]@tanstack[\\/]react-router[\\/]/,
|
|
328
|
-
|
|
406
|
+
/[\\/]node_modules[\\/]@tanstack[\\/]router-core[\\/]/,
|
|
407
|
+
/[\\/]node_modules[\\/]@tanstack[\\/]react-store[\\/]/,
|
|
408
|
+
// This package's own dist runtime, too. `__dirname` is
|
|
409
|
+
// dist/{cjs,esm-node}/cli (or src/cli in tests), so the package
|
|
410
|
+
// dist root is two levels up. Resolution-based — no string
|
|
411
|
+
// surgery: the old `.replace('cjs', 'esm')` corrupted workspace
|
|
412
|
+
// paths containing 'cjs' and, under the ESM CLI condition, never
|
|
413
|
+
// matched the dist/esm runtime that browsers actually bundle.
|
|
414
|
+
path.resolve(__dirname, '..', '..'),
|
|
329
415
|
],
|
|
330
416
|
},
|
|
331
417
|
}));
|
|
@@ -352,9 +438,6 @@ export function tanstackRouterPlugin(
|
|
|
352
438
|
tanstackEntrypoints,
|
|
353
439
|
{
|
|
354
440
|
entrypointsKey: ENTRYPOINTS_KEY,
|
|
355
|
-
generateCodeOptions: {
|
|
356
|
-
enableTanstackTypes: false,
|
|
357
|
-
},
|
|
358
441
|
},
|
|
359
442
|
);
|
|
360
443
|
|
|
@@ -362,6 +445,7 @@ export function tanstackRouterPlugin(
|
|
|
362
445
|
appContext: api.getAppContext(),
|
|
363
446
|
generatedDirName,
|
|
364
447
|
routesByEntry,
|
|
448
|
+
i18nPluginInstalled: isI18nPluginInstalled(),
|
|
365
449
|
});
|
|
366
450
|
});
|
|
367
451
|
|
|
@@ -380,9 +464,6 @@ export function tanstackRouterPlugin(
|
|
|
380
464
|
entrypoints,
|
|
381
465
|
{
|
|
382
466
|
entrypointsKey: ENTRYPOINTS_KEY,
|
|
383
|
-
generateCodeOptions: {
|
|
384
|
-
enableTanstackTypes: false,
|
|
385
|
-
},
|
|
386
467
|
},
|
|
387
468
|
);
|
|
388
469
|
|
|
@@ -390,6 +471,7 @@ export function tanstackRouterPlugin(
|
|
|
390
471
|
appContext: api.getAppContext(),
|
|
391
472
|
generatedDirName,
|
|
392
473
|
routesByEntry,
|
|
474
|
+
i18nPluginInstalled: isI18nPluginInstalled(),
|
|
393
475
|
});
|
|
394
476
|
},
|
|
395
477
|
});
|