@bleedingdev/modern-js-plugin-tanstack 3.2.0-ultramodern.99 → 3.4.0-ultramodern.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/cli/index.js +80 -34
- package/dist/cjs/cli/routeSplitting.js +13 -41
- package/dist/cjs/cli/tanstackTypes.js +114 -200
- package/dist/cjs/cli.js +12 -8
- package/dist/cjs/runtime/basepathRewrite.js +12 -8
- package/dist/cjs/runtime/dataMutation.js +9 -5
- package/dist/cjs/runtime/hooks.js +20 -19
- package/dist/cjs/runtime/hydrationBoundary.js +12 -7
- package/dist/cjs/runtime/index.js +66 -54
- package/dist/cjs/runtime/lifecycle.js +21 -91
- package/dist/cjs/runtime/loaderBridge.js +173 -0
- package/dist/cjs/runtime/outlet.js +58 -0
- package/dist/cjs/runtime/plugin.js +190 -110
- package/dist/cjs/runtime/plugin.node.js +25 -40
- package/dist/cjs/runtime/plugin.worker.js +9 -5
- package/dist/cjs/runtime/pluginCore.js +55 -0
- package/dist/cjs/runtime/prefetchLink.js +10 -6
- package/dist/cjs/runtime/register.js +56 -0
- package/dist/cjs/runtime/routeTree.js +30 -212
- package/dist/cjs/runtime/router.js +41 -0
- package/dist/cjs/runtime/rsc/ClientSlot.js +9 -5
- package/dist/cjs/runtime/rsc/CompositeComponent.js +9 -5
- package/dist/cjs/runtime/rsc/ReplayableStream.js +14 -9
- package/dist/cjs/runtime/rsc/RscNodeRenderer.js +9 -5
- package/dist/cjs/runtime/rsc/SlotContext.js +9 -5
- package/dist/cjs/runtime/rsc/client.js +9 -5
- package/dist/cjs/runtime/rsc/createRscProxy.js +9 -5
- package/dist/cjs/runtime/rsc/index.js +9 -5
- package/dist/cjs/runtime/rsc/payloadRouter.js +44 -6
- package/dist/cjs/runtime/rsc/server.js +9 -5
- package/dist/cjs/runtime/rsc/slotUsageSanitizer.js +9 -5
- package/dist/cjs/runtime/rsc/symbols.js +20 -15
- package/dist/cjs/runtime/state.js +45 -0
- package/dist/cjs/runtime/types.js +13 -9
- package/dist/cjs/runtime/utils.js +9 -11
- package/dist/cjs/runtime.js +9 -5
- package/dist/esm/cli/index.mjs +73 -28
- package/dist/esm/cli/routeSplitting.mjs +1 -30
- package/dist/esm/cli/tanstackTypes.mjs +100 -190
- package/dist/esm/runtime/hooks.mjs +1 -8
- package/dist/esm/runtime/hydrationBoundary.mjs +3 -2
- 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/outlet.mjs +17 -0
- package/dist/esm/runtime/plugin.mjs +183 -107
- package/dist/esm/runtime/plugin.node.mjs +19 -38
- package/dist/esm/runtime/pluginCore.mjs +14 -0
- package/dist/esm/runtime/prefetchLink.mjs +1 -1
- package/dist/esm/runtime/register.mjs +18 -0
- package/dist/esm/runtime/routeTree.mjs +15 -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 -6
- package/dist/esm-node/cli/index.mjs +73 -28
- package/dist/esm-node/cli/routeSplitting.mjs +1 -30
- package/dist/esm-node/cli/tanstackTypes.mjs +100 -190
- package/dist/esm-node/runtime/hooks.mjs +1 -8
- package/dist/esm-node/runtime/hydrationBoundary.mjs +3 -2
- 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/outlet.mjs +18 -0
- package/dist/esm-node/runtime/plugin.mjs +183 -107
- package/dist/esm-node/runtime/plugin.node.mjs +19 -38
- package/dist/esm-node/runtime/pluginCore.mjs +15 -0
- package/dist/esm-node/runtime/prefetchLink.mjs +1 -1
- package/dist/esm-node/runtime/register.mjs +19 -0
- package/dist/esm-node/runtime/routeTree.mjs +15 -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 -6
- package/dist/types/cli/index.d.ts +11 -2
- package/dist/types/cli/routeSplitting.d.ts +6 -15
- package/dist/types/cli/tanstackTypes.d.ts +21 -1
- package/dist/types/runtime/hooks.d.ts +8 -33
- package/dist/types/runtime/index.d.ts +6 -3
- package/dist/types/runtime/lifecycle.d.ts +7 -22
- package/dist/types/runtime/loaderBridge.d.ts +48 -0
- package/dist/types/runtime/outlet.d.ts +2 -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 +40 -38
- package/rstest.config.mts +6 -0
- package/src/cli/index.ts +146 -24
- package/src/cli/routeSplitting.ts +6 -44
- package/src/cli/tanstackTypes.ts +203 -208
- package/src/runtime/hooks.ts +10 -27
- package/src/runtime/hydrationBoundary.tsx +5 -5
- package/src/runtime/index.tsx +12 -14
- package/src/runtime/lifecycle.ts +16 -151
- package/src/runtime/loaderBridge.ts +257 -0
- package/src/runtime/outlet.tsx +48 -0
- package/src/runtime/plugin.node.tsx +28 -83
- package/src/runtime/plugin.tsx +350 -202
- package/src/runtime/pluginCore.ts +48 -0
- package/src/runtime/prefetchLink.tsx +1 -1
- package/src/runtime/register.ts +58 -0
- package/src/runtime/routeTree.ts +41 -365
- package/src/runtime/router.ts +15 -0
- package/src/runtime/rsc/payloadRouter.ts +45 -2
- package/src/runtime/ssr-shim.d.ts +1 -3
- package/src/runtime/state.ts +29 -0
- package/src/runtime/types.ts +20 -67
- package/src/runtime/utils.tsx +3 -7
- package/tests/router/cli.test.ts +373 -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/prefetchLink.test.tsx +43 -7
- package/tests/router/register.test.ts +46 -0
- package/tests/router/routeTree.test.ts +176 -139
- package/tests/router/rsc.test.tsx +70 -0
- package/tests/router/tanstackTypes.test.ts +395 -7
- package/dist/cjs/runtime/DefaultNotFound.js +0 -47
- 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
|
@@ -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.
|
|
21
|
+
"version": "3.4.0-ultramodern.0",
|
|
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,47 +68,54 @@
|
|
|
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
|
},
|
|
87
76
|
"dependencies": {
|
|
88
77
|
"@swc/helpers": "^0.5.23",
|
|
89
|
-
"@tanstack/react-router": "1.170.
|
|
90
|
-
"@tanstack/router-core": "1.171.
|
|
91
|
-
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.
|
|
92
|
-
"@modern-js/
|
|
93
|
-
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.
|
|
94
|
-
"@modern-js/
|
|
78
|
+
"@tanstack/react-router": "1.170.16",
|
|
79
|
+
"@tanstack/router-core": "1.171.13",
|
|
80
|
+
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.4.0-ultramodern.0",
|
|
81
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.4.0-ultramodern.0",
|
|
82
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.4.0-ultramodern.0",
|
|
83
|
+
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.4.0-ultramodern.0"
|
|
95
84
|
},
|
|
96
85
|
"peerDependencies": {
|
|
97
|
-
"@modern-js/runtime": "3.
|
|
98
|
-
"react": "^19.2.
|
|
99
|
-
"react-dom": "^19.2.
|
|
86
|
+
"@modern-js/runtime": "3.4.0-ultramodern.0",
|
|
87
|
+
"react": "^19.2.7",
|
|
88
|
+
"react-dom": "^19.2.7"
|
|
100
89
|
},
|
|
101
90
|
"devDependencies": {
|
|
102
|
-
"@rslib/core": "0.
|
|
91
|
+
"@rslib/core": "0.23.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": "^
|
|
107
|
-
"@types/react": "^19.2.
|
|
95
|
+
"@types/node": "^26.0.0",
|
|
96
|
+
"@types/react": "^19.2.17",
|
|
108
97
|
"@types/react-dom": "^19.2.3",
|
|
109
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
110
|
-
"react": "^19.2.
|
|
111
|
-
"react-dom": "^19.2.
|
|
112
|
-
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.
|
|
98
|
+
"@typescript/native-preview": "7.0.0-dev.20260624.1",
|
|
99
|
+
"react": "^19.2.7",
|
|
100
|
+
"react-dom": "^19.2.7",
|
|
101
|
+
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.4.0-ultramodern.0",
|
|
113
102
|
"@scripts/rstest-config": "2.66.0",
|
|
114
|
-
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.
|
|
103
|
+
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.4.0-ultramodern.0"
|
|
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
|
@@ -23,8 +23,8 @@ import {
|
|
|
23
23
|
type TanstackRouteCodeSplittingOption,
|
|
24
24
|
} from './routeSplitting';
|
|
25
25
|
import {
|
|
26
|
+
collectCanonicalRoutesForEntry,
|
|
26
27
|
generateTanstackRouterTypesSourceForEntry,
|
|
27
|
-
isTanstackRouterFrameworkEnabled,
|
|
28
28
|
} from './tanstackTypes';
|
|
29
29
|
|
|
30
30
|
export type {
|
|
@@ -33,12 +33,12 @@ export type {
|
|
|
33
33
|
} from './routeSplitting';
|
|
34
34
|
export {
|
|
35
35
|
createTanstackRsbuildRouteSplittingProfile,
|
|
36
|
-
isTanstackStartRouteModuleSource,
|
|
37
36
|
resolveTanstackRouteCodeSplittingEnabled,
|
|
38
37
|
} from './routeSplitting';
|
|
39
38
|
export {
|
|
39
|
+
type CollectCanonicalRoutesOptions,
|
|
40
|
+
collectCanonicalRoutesForEntry,
|
|
40
41
|
generateTanstackRouterTypesSourceForEntry,
|
|
41
|
-
isTanstackRouterFrameworkEnabled,
|
|
42
42
|
} from './tanstackTypes';
|
|
43
43
|
|
|
44
44
|
const DEFAULT_ROUTES_DIR = 'routes';
|
|
@@ -53,6 +53,7 @@ export type TanstackRouterPluginOptions = {
|
|
|
53
53
|
|
|
54
54
|
type RuntimeRouterCliHelpers = {
|
|
55
55
|
getEntrypointRoutesDir: (entrypoint: Entrypoint) => string | null;
|
|
56
|
+
getEntrypointRoutesOwner: (entrypoint: Entrypoint) => string | null;
|
|
56
57
|
handleFileChange: (
|
|
57
58
|
api: CLIPluginAPI<AppTools>,
|
|
58
59
|
event: unknown,
|
|
@@ -72,9 +73,6 @@ type RuntimeRouterCliHelpers = {
|
|
|
72
73
|
entrypoints: Entrypoint[],
|
|
73
74
|
options?: {
|
|
74
75
|
entrypointsKey?: string;
|
|
75
|
-
generateCodeOptions?: {
|
|
76
|
-
enableTanstackTypes?: boolean;
|
|
77
|
-
};
|
|
78
76
|
},
|
|
79
77
|
) => Promise<Record<string, (NestedRouteForCli | PageRoute)[]>>;
|
|
80
78
|
handleModifyEntrypoints: (
|
|
@@ -96,7 +94,11 @@ function getRuntimeRouterCli(): RuntimeRouterCliHelpers {
|
|
|
96
94
|
|
|
97
95
|
const cli =
|
|
98
96
|
require('@modern-js/runtime/cli') as Partial<RuntimeRouterCliHelpers>;
|
|
99
|
-
if (
|
|
97
|
+
if (
|
|
98
|
+
cli.handleGeneratorEntryCode &&
|
|
99
|
+
cli.getEntrypointRoutesDir &&
|
|
100
|
+
cli.getEntrypointRoutesOwner
|
|
101
|
+
) {
|
|
100
102
|
runtimeRouterCli = cli as RuntimeRouterCliHelpers;
|
|
101
103
|
return runtimeRouterCli;
|
|
102
104
|
}
|
|
@@ -124,6 +126,8 @@ async function writeFileIfChanged(filePath: string, content: string) {
|
|
|
124
126
|
function createRegisterDtsContent(opts: {
|
|
125
127
|
entries: string[];
|
|
126
128
|
runtimeModule: string;
|
|
129
|
+
canonicalRoutes?: Record<string, string> | null;
|
|
130
|
+
i18nRuntimeModule?: string;
|
|
127
131
|
}) {
|
|
128
132
|
const importStatements = opts.entries
|
|
129
133
|
.map(
|
|
@@ -135,6 +139,20 @@ function createRegisterDtsContent(opts: {
|
|
|
135
139
|
.map((_, index) => `typeof router${index}`)
|
|
136
140
|
.join(' | ');
|
|
137
141
|
|
|
142
|
+
const canonicalEntries = Object.entries(opts.canonicalRoutes ?? {});
|
|
143
|
+
const canonicalRoutesAugmentation =
|
|
144
|
+
canonicalEntries.length > 0
|
|
145
|
+
? `
|
|
146
|
+
declare module '${opts.i18nRuntimeModule || '@modern-js/plugin-i18n/runtime'}' {
|
|
147
|
+
interface UltramodernCanonicalRoutes {
|
|
148
|
+
${canonicalEntries
|
|
149
|
+
.map(([routePath, paramsType]) => ` '${routePath}': ${paramsType};`)
|
|
150
|
+
.join('\n')}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
`
|
|
154
|
+
: '';
|
|
155
|
+
|
|
138
156
|
return `// This file is auto-generated by Modern.js. Do not edit manually.
|
|
139
157
|
|
|
140
158
|
${importStatements}
|
|
@@ -144,7 +162,7 @@ declare module '${opts.runtimeModule}' {
|
|
|
144
162
|
router: ${routerUnionType};
|
|
145
163
|
}
|
|
146
164
|
}
|
|
147
|
-
`;
|
|
165
|
+
${canonicalRoutesAugmentation}`;
|
|
148
166
|
}
|
|
149
167
|
|
|
150
168
|
export async function writeTanstackRegisterFile(opts: {
|
|
@@ -152,12 +170,16 @@ export async function writeTanstackRegisterFile(opts: {
|
|
|
152
170
|
generatedDirName?: string;
|
|
153
171
|
runtimeModule?: string;
|
|
154
172
|
srcDirectory: string;
|
|
173
|
+
canonicalRoutes?: Record<string, string> | null;
|
|
174
|
+
i18nRuntimeModule?: string;
|
|
155
175
|
}) {
|
|
156
176
|
const {
|
|
157
177
|
entries,
|
|
158
178
|
generatedDirName = DEFAULT_GENERATED_DIR_NAME,
|
|
159
179
|
runtimeModule = '@modern-js/plugin-tanstack/runtime',
|
|
160
180
|
srcDirectory,
|
|
181
|
+
canonicalRoutes,
|
|
182
|
+
i18nRuntimeModule,
|
|
161
183
|
} = opts;
|
|
162
184
|
|
|
163
185
|
if (entries.length === 0) {
|
|
@@ -172,7 +194,12 @@ export async function writeTanstackRegisterFile(opts: {
|
|
|
172
194
|
|
|
173
195
|
await writeFileIfChanged(
|
|
174
196
|
registerDtsPath,
|
|
175
|
-
createRegisterDtsContent({
|
|
197
|
+
createRegisterDtsContent({
|
|
198
|
+
entries,
|
|
199
|
+
runtimeModule,
|
|
200
|
+
canonicalRoutes,
|
|
201
|
+
i18nRuntimeModule,
|
|
202
|
+
}),
|
|
176
203
|
);
|
|
177
204
|
}
|
|
178
205
|
|
|
@@ -180,11 +207,19 @@ export async function writeTanstackRouterTypesForEntries(opts: {
|
|
|
180
207
|
appContext: AppToolsContext;
|
|
181
208
|
generatedDirName?: string;
|
|
182
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;
|
|
183
217
|
}) {
|
|
184
218
|
const {
|
|
185
219
|
appContext,
|
|
186
220
|
generatedDirName = DEFAULT_GENERATED_DIR_NAME,
|
|
187
221
|
routesByEntry,
|
|
222
|
+
i18nPluginInstalled = false,
|
|
188
223
|
} = opts;
|
|
189
224
|
|
|
190
225
|
const entryNames = Object.keys(routesByEntry);
|
|
@@ -225,10 +260,31 @@ export async function writeTanstackRouterTypesForEntries(opts: {
|
|
|
225
260
|
return a.localeCompare(b);
|
|
226
261
|
});
|
|
227
262
|
|
|
263
|
+
// Merge the canonical (language-agnostic) route maps of every entry so the
|
|
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.
|
|
267
|
+
let canonicalRoutes: Record<string, string> | null = null;
|
|
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
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
228
283
|
await writeTanstackRegisterFile({
|
|
229
284
|
entries: registerEntries,
|
|
230
285
|
generatedDirName,
|
|
231
286
|
srcDirectory: appContext.srcDirectory,
|
|
287
|
+
canonicalRoutes,
|
|
232
288
|
});
|
|
233
289
|
}
|
|
234
290
|
|
|
@@ -252,11 +308,38 @@ export function tanstackRouterPlugin(
|
|
|
252
308
|
return getEntrypointRoutesDir(entrypoint) === routesDir;
|
|
253
309
|
};
|
|
254
310
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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;
|
|
258
326
|
}
|
|
327
|
+
if (entrypoint.pageRoutesEntry) {
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
return getEntrypointRoutesDir(entrypoint) !== null;
|
|
331
|
+
};
|
|
259
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
|
+
};
|
|
341
|
+
|
|
342
|
+
api._internalRuntimePlugins(({ entrypoint, plugins }) => {
|
|
260
343
|
const { metaName, serverRoutes } = api.getAppContext();
|
|
261
344
|
const serverBase = serverRoutes
|
|
262
345
|
.filter(
|
|
@@ -265,11 +348,44 @@ export function tanstackRouterPlugin(
|
|
|
265
348
|
.map(route => route.urlPath)
|
|
266
349
|
.sort((a, b) => (a.length - b.length > 0 ? -1 : 1));
|
|
267
350
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
+
}
|
|
273
389
|
|
|
274
390
|
return { entrypoint, plugins };
|
|
275
391
|
});
|
|
@@ -284,8 +400,18 @@ export function tanstackRouterPlugin(
|
|
|
284
400
|
...routeSplittingProfile.defaultConfig,
|
|
285
401
|
source: {
|
|
286
402
|
include: [
|
|
403
|
+
// TanStack Router and its runtime deps ship modern syntax and
|
|
404
|
+
// must be down-leveled for the app's browser targets.
|
|
287
405
|
/[\\/]node_modules[\\/]@tanstack[\\/]react-router[\\/]/,
|
|
288
|
-
|
|
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, '..', '..'),
|
|
289
415
|
],
|
|
290
416
|
},
|
|
291
417
|
}));
|
|
@@ -312,9 +438,6 @@ export function tanstackRouterPlugin(
|
|
|
312
438
|
tanstackEntrypoints,
|
|
313
439
|
{
|
|
314
440
|
entrypointsKey: ENTRYPOINTS_KEY,
|
|
315
|
-
generateCodeOptions: {
|
|
316
|
-
enableTanstackTypes: false,
|
|
317
|
-
},
|
|
318
441
|
},
|
|
319
442
|
);
|
|
320
443
|
|
|
@@ -322,6 +445,7 @@ export function tanstackRouterPlugin(
|
|
|
322
445
|
appContext: api.getAppContext(),
|
|
323
446
|
generatedDirName,
|
|
324
447
|
routesByEntry,
|
|
448
|
+
i18nPluginInstalled: isI18nPluginInstalled(),
|
|
325
449
|
});
|
|
326
450
|
});
|
|
327
451
|
|
|
@@ -340,9 +464,6 @@ export function tanstackRouterPlugin(
|
|
|
340
464
|
entrypoints,
|
|
341
465
|
{
|
|
342
466
|
entrypointsKey: ENTRYPOINTS_KEY,
|
|
343
|
-
generateCodeOptions: {
|
|
344
|
-
enableTanstackTypes: false,
|
|
345
|
-
},
|
|
346
467
|
},
|
|
347
468
|
);
|
|
348
469
|
|
|
@@ -350,6 +471,7 @@ export function tanstackRouterPlugin(
|
|
|
350
471
|
appContext: api.getAppContext(),
|
|
351
472
|
generatedDirName,
|
|
352
473
|
routesByEntry,
|
|
474
|
+
i18nPluginInstalled: isI18nPluginInstalled(),
|
|
353
475
|
});
|
|
354
476
|
},
|
|
355
477
|
});
|