@bleedingdev/modern-js-plugin-tanstack 3.9.0-ultramodern.11 → 3.9.0-ultramodern.13
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/artifacts.js +2 -1
- package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +7 -7
- package/dist/cjs/cli/tanstackTypes/shared.js +0 -14
- package/dist/cjs/cli/tanstackTypes/source.js +28 -63
- package/dist/cjs/runtime/lifecycle.js +0 -3
- package/dist/cjs/runtime/loaderBridge.js +10 -4
- package/dist/cjs/runtime/navigation.js +102 -0
- package/dist/cjs/runtime/plugin.js +6 -1
- package/dist/cjs/runtime/plugin.node.js +81 -63
- package/dist/cjs/runtime/routeTree/construction.js +19 -61
- package/dist/cjs/runtime/routeTree/loaders.js +1 -1
- package/dist/cjs/runtime/routeTree/paths.js +0 -6
- package/dist/cjs/runtime/ssrManagedTags.js +2 -12
- package/dist/cjs/runtime/utils.js +1 -0
- package/dist/cjs/shared/routeDescriptor.js +60 -0
- package/dist/esm/cli/artifacts.mjs +2 -1
- package/dist/esm/cli/index.mjs +1 -7
- package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
- package/dist/esm/cli/tanstackTypes/shared.mjs +1 -9
- package/dist/esm/cli/tanstackTypes/source.mjs +29 -64
- package/dist/esm/runtime/lifecycle.mjs +1 -1
- package/dist/esm/runtime/loaderBridge.mjs +8 -5
- package/dist/esm/runtime/navigation.mjs +64 -0
- package/dist/esm/runtime/plugin.mjs +6 -1
- package/dist/esm/runtime/plugin.node.mjs +83 -65
- package/dist/esm/runtime/routeTree/construction.mjs +19 -61
- package/dist/esm/runtime/routeTree/loaders.mjs +2 -2
- package/dist/esm/runtime/routeTree/paths.mjs +1 -4
- package/dist/esm/runtime/ssrManagedTags.mjs +1 -8
- package/dist/esm/runtime/utils.mjs +1 -0
- package/dist/esm/shared/routeDescriptor.mjs +22 -0
- package/dist/esm-node/cli/artifacts.mjs +2 -1
- package/dist/esm-node/cli/index.mjs +1 -7
- package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
- package/dist/esm-node/cli/tanstackTypes/shared.mjs +1 -9
- package/dist/esm-node/cli/tanstackTypes/source.mjs +29 -64
- package/dist/esm-node/runtime/lifecycle.mjs +1 -1
- package/dist/esm-node/runtime/loaderBridge.mjs +8 -5
- package/dist/esm-node/runtime/navigation.mjs +65 -0
- package/dist/esm-node/runtime/plugin.mjs +6 -1
- package/dist/esm-node/runtime/plugin.node.mjs +83 -65
- package/dist/esm-node/runtime/routeTree/construction.mjs +19 -61
- package/dist/esm-node/runtime/routeTree/loaders.mjs +2 -2
- package/dist/esm-node/runtime/routeTree/paths.mjs +1 -4
- package/dist/esm-node/runtime/ssrManagedTags.mjs +1 -8
- package/dist/esm-node/runtime/utils.mjs +1 -0
- package/dist/esm-node/shared/routeDescriptor.mjs +23 -0
- package/dist/types/cli/tanstackTypes/shared.d.ts +0 -2
- package/dist/types/runtime/lifecycle.d.ts +1 -1
- package/dist/types/runtime/loaderBridge.d.ts +1 -0
- package/dist/types/runtime/navigation.d.ts +4 -0
- package/dist/types/runtime/routeTree/paths.d.ts +0 -2
- package/dist/types/runtime/ssrManagedTags.d.ts +0 -1
- package/dist/types/runtime/ssrTypes.d.ts +0 -7
- package/dist/types/shared/routeDescriptor.d.ts +26 -0
- package/package.json +21 -21
- package/src/cli/artifacts.ts +6 -1
- package/src/cli/tanstackTypes/canonicalRoutes.ts +17 -12
- package/src/cli/tanstackTypes/shared.ts +0 -14
- package/src/cli/tanstackTypes/source.ts +43 -119
- package/src/runtime/lifecycle.ts +0 -1
- package/src/runtime/loaderBridge.ts +9 -9
- package/src/runtime/navigation.ts +78 -0
- package/src/runtime/plugin.node.tsx +111 -91
- package/src/runtime/plugin.tsx +6 -0
- package/src/runtime/routeTree/construction.ts +32 -112
- package/src/runtime/routeTree/loaders.ts +2 -4
- package/src/runtime/routeTree/paths.ts +0 -6
- package/src/runtime/ssrManagedTags.ts +0 -17
- package/src/runtime/ssrTypes.ts +0 -7
- package/src/runtime/utils.tsx +1 -0
- package/src/shared/routeDescriptor.ts +46 -0
- package/tests/router/clientNavigation.ts +13 -0
- package/tests/router/generateRouteArtifacts.test.ts +36 -2
- package/tests/router/localisedIdentity.test.tsx +7 -2
- package/tests/router/prefetchLink.test.tsx +29 -0
- package/tests/router/routeHooks.test.ts +2 -1
- package/tests/router/serverPlugin.test.ts +150 -0
- package/tests/router/tanstackTypes.test.ts +121 -2
- package/dist/esm/rslib-runtime~1.mjs +0 -18
- package/dist/esm-node/rslib-runtime~0.mjs +0 -19
package/package.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"modern.js",
|
|
19
19
|
"tanstack-router"
|
|
20
20
|
],
|
|
21
|
-
"version": "3.9.0-ultramodern.
|
|
21
|
+
"version": "3.9.0-ultramodern.13",
|
|
22
22
|
"engines": {
|
|
23
23
|
"node": ">=20"
|
|
24
24
|
},
|
|
@@ -94,19 +94,19 @@
|
|
|
94
94
|
}
|
|
95
95
|
},
|
|
96
96
|
"dependencies": {
|
|
97
|
-
"@modern-js/i18n-runtime-extensions": "npm:@bleedingdev/modern-js-i18n-runtime-extensions@3.9.0-ultramodern.
|
|
98
|
-
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.
|
|
99
|
-
"@modern-js/runtime-extensions": "npm:@bleedingdev/modern-js-runtime-extensions@3.9.0-ultramodern.
|
|
100
|
-
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.9.0-ultramodern.
|
|
101
|
-
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.0-ultramodern.
|
|
102
|
-
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.0-ultramodern.
|
|
97
|
+
"@modern-js/i18n-runtime-extensions": "npm:@bleedingdev/modern-js-i18n-runtime-extensions@3.9.0-ultramodern.13",
|
|
98
|
+
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.13",
|
|
99
|
+
"@modern-js/runtime-extensions": "npm:@bleedingdev/modern-js-runtime-extensions@3.9.0-ultramodern.13",
|
|
100
|
+
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.9.0-ultramodern.13",
|
|
101
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.0-ultramodern.13",
|
|
102
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.0-ultramodern.13",
|
|
103
103
|
"@swc/helpers": "^0.5.23",
|
|
104
|
-
"@tanstack/react-router": "1.170.
|
|
105
|
-
"@tanstack/router-core": "1.171.
|
|
104
|
+
"@tanstack/react-router": "1.170.39",
|
|
105
|
+
"@tanstack/router-core": "1.171.32"
|
|
106
106
|
},
|
|
107
107
|
"peerDependencies": {
|
|
108
|
-
"@modern-js/app-tools": "3.9.0-ultramodern.
|
|
109
|
-
"@modern-js/runtime": "3.9.0-ultramodern.
|
|
108
|
+
"@modern-js/app-tools": "3.9.0-ultramodern.13",
|
|
109
|
+
"@modern-js/runtime": "3.9.0-ultramodern.13",
|
|
110
110
|
"react": "^19.2.8",
|
|
111
111
|
"react-dom": "^19.2.8",
|
|
112
112
|
"react-server-dom-rspack": "0.1.0"
|
|
@@ -117,20 +117,20 @@
|
|
|
117
117
|
}
|
|
118
118
|
},
|
|
119
119
|
"devDependencies": {
|
|
120
|
-
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.9.0-ultramodern.
|
|
121
|
-
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.9.0-ultramodern.
|
|
122
|
-
"@modern-js/server-utils": "npm:@bleedingdev/modern-js-server-utils@3.9.0-ultramodern.
|
|
123
|
-
"@rslib/core": "1.0.
|
|
120
|
+
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.9.0-ultramodern.13",
|
|
121
|
+
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.9.0-ultramodern.13",
|
|
122
|
+
"@modern-js/server-utils": "npm:@bleedingdev/modern-js-server-utils@3.9.0-ultramodern.13",
|
|
123
|
+
"@rslib/core": "1.0.2",
|
|
124
124
|
"@scripts/rstest-config": "2.66.0",
|
|
125
|
-
"@tanstack/history": "1.162.
|
|
125
|
+
"@tanstack/history": "1.162.4",
|
|
126
126
|
"@testing-library/react": "^16.3.3",
|
|
127
127
|
"@tsconfig/strictest": "2.0.8",
|
|
128
|
-
"@types/node": "^26.
|
|
129
|
-
"@types/react": "^19.
|
|
130
|
-
"@types/react-dom": "^19.
|
|
128
|
+
"@types/node": "^26.6.2",
|
|
129
|
+
"@types/react": "^19.3.0",
|
|
130
|
+
"@types/react-dom": "^19.3.0",
|
|
131
131
|
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
132
|
-
"react": "^19.
|
|
133
|
-
"react-dom": "^19.
|
|
132
|
+
"react": "^19.3.0",
|
|
133
|
+
"react-dom": "^19.3.0",
|
|
134
134
|
"react-server-dom-rspack": "0.1.0"
|
|
135
135
|
},
|
|
136
136
|
"sideEffects": [
|
package/src/cli/artifacts.ts
CHANGED
|
@@ -251,5 +251,10 @@ export async function generateTanstackRouteArtifacts(opts: {
|
|
|
251
251
|
internalPlugins: (utils as { INTERNAL_RUNTIME_PLUGINS: unknown })
|
|
252
252
|
.INTERNAL_RUNTIME_PLUGINS as never,
|
|
253
253
|
});
|
|
254
|
-
await cli.init({ ...runOptions, command: 'build' });
|
|
254
|
+
const { appContext } = await cli.init({ ...runOptions, command: 'build' });
|
|
255
|
+
// Preparation owns the artifact writes; there is no dev server or bundler
|
|
256
|
+
// phase after it. Release plugin resources before the headless caller exits.
|
|
257
|
+
// Failed initialization propagates unchanged: it has not returned a context
|
|
258
|
+
// whose lifecycle this caller can close.
|
|
259
|
+
await appContext.hooks.onBeforeExit.call();
|
|
255
260
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// @effect-diagnostics asyncFunction:off strictBooleanExpressions:off
|
|
2
2
|
|
|
3
3
|
import type { NestedRouteForCli, PageRoute } from '@modern-js/types';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
describeRouteTree,
|
|
6
|
+
type RouteDescriptor,
|
|
7
|
+
} from '../../shared/routeDescriptor';
|
|
5
8
|
|
|
6
9
|
import { toTanstackPath } from './shared';
|
|
7
10
|
|
|
@@ -16,6 +19,7 @@ const LOCALE_PARAM_SEGMENTS = new Set([
|
|
|
16
19
|
|
|
17
20
|
type CanonicalAwareRoute = (NestedRouteForCli | PageRoute) & {
|
|
18
21
|
modernCanonicalPath?: string;
|
|
22
|
+
modernLocalisedRoute?: { canonicalPath: string };
|
|
19
23
|
index?: boolean;
|
|
20
24
|
isRoot?: boolean;
|
|
21
25
|
children?: CanonicalAwareRoute[];
|
|
@@ -101,12 +105,18 @@ export function collectCanonicalRoutesForEntry(
|
|
|
101
105
|
}
|
|
102
106
|
};
|
|
103
107
|
|
|
104
|
-
const visit = (
|
|
108
|
+
const visit = (
|
|
109
|
+
descriptor: RouteDescriptor<CanonicalAwareRoute>,
|
|
110
|
+
parentPath: string,
|
|
111
|
+
) => {
|
|
112
|
+
const { source: route, children } = descriptor;
|
|
105
113
|
let currentPath = parentPath;
|
|
106
114
|
|
|
107
|
-
|
|
115
|
+
const canonicalPath =
|
|
116
|
+
route.modernLocalisedRoute?.canonicalPath ?? route.modernCanonicalPath;
|
|
117
|
+
if (typeof canonicalPath === 'string') {
|
|
108
118
|
hasI18nSurface = true;
|
|
109
|
-
currentPath = normalizeJoined(
|
|
119
|
+
currentPath = canonicalPath ? normalizeJoined(canonicalPath) : '';
|
|
110
120
|
} else if (typeof route.path === 'string' && route.path.length > 0) {
|
|
111
121
|
const segments = route.path
|
|
112
122
|
.replace(/\[(.+?)\]/g, ':$1')
|
|
@@ -125,7 +135,6 @@ export function collectCanonicalRoutesForEntry(
|
|
|
125
135
|
: parentPath;
|
|
126
136
|
}
|
|
127
137
|
|
|
128
|
-
const children = route.children;
|
|
129
138
|
if (children && children.length > 0) {
|
|
130
139
|
for (const child of children) {
|
|
131
140
|
visit(child, currentPath);
|
|
@@ -137,13 +146,9 @@ export function collectCanonicalRoutesForEntry(
|
|
|
137
146
|
record(currentPath || '/');
|
|
138
147
|
};
|
|
139
148
|
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const topLevel = rootModern ? (rootModern.children ?? []) : routes;
|
|
144
|
-
|
|
145
|
-
for (const route of topLevel) {
|
|
146
|
-
visit(route as CanonicalAwareRoute, '');
|
|
149
|
+
for (const route of describeRouteTree(routes as CanonicalAwareRoute[])
|
|
150
|
+
.children) {
|
|
151
|
+
visit(route, '');
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
if (!hasI18nSurface || canonicalParams.size === 0) {
|
|
@@ -71,20 +71,6 @@ export function pickRouteSearchContractModules(
|
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
export function isPathlessLayout(route: NestedRouteForCli | PageRoute) {
|
|
75
|
-
const extras = route as RouteExtras;
|
|
76
|
-
return (
|
|
77
|
-
extras.type === 'nested' &&
|
|
78
|
-
typeof extras.index !== 'boolean' &&
|
|
79
|
-
typeof extras.path === 'undefined'
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function isIndexRoute(route: NestedRouteForCli | PageRoute) {
|
|
84
|
-
const extras = route as RouteExtras;
|
|
85
|
-
return extras.type === 'nested' && Boolean(extras.index);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
74
|
export function createRouteStaticDataSnippet(opts: {
|
|
89
75
|
modernRouteId?: string;
|
|
90
76
|
loaderName?: string | null;
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
// @effect-diagnostics asyncFunction:off strictBooleanExpressions:off
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
AppNormalizedConfig,
|
|
5
|
-
AppTools,
|
|
6
|
-
AppToolsContext,
|
|
7
|
-
} from '@modern-js/app-tools';
|
|
8
|
-
import { canonicaliseLocalisedRoutes } from '@modern-js/i18n-runtime-extensions';
|
|
3
|
+
import type { AppToolsContext } from '@modern-js/app-tools';
|
|
9
4
|
import { makeLegalIdentifier } from '@modern-js/runtime/cli';
|
|
10
5
|
import type { NestedRouteForCli, PageRoute } from '@modern-js/types';
|
|
11
6
|
import { upath as path } from '@modern-js/utils';
|
|
12
7
|
|
|
8
|
+
import {
|
|
9
|
+
describeRouteTree,
|
|
10
|
+
type RouteDescriptor,
|
|
11
|
+
} from '../../shared/routeDescriptor';
|
|
12
|
+
|
|
13
13
|
import {
|
|
14
14
|
createRouteStaticDataSnippet,
|
|
15
|
-
isIndexRoute,
|
|
16
|
-
isPathlessLayout,
|
|
17
15
|
normalizeRelativeImport,
|
|
18
16
|
pickModernLoaderModule,
|
|
19
17
|
pickRouteSearchContractModules,
|
|
20
18
|
quote,
|
|
21
19
|
resolveFileNoExt,
|
|
22
|
-
toTanstackPath,
|
|
23
20
|
} from './shared';
|
|
24
21
|
|
|
25
22
|
type RouteForCli = NestedRouteForCli | PageRoute;
|
|
@@ -46,22 +43,15 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
46
43
|
appContext,
|
|
47
44
|
entryName,
|
|
48
45
|
generatedDirName = 'modern-tanstack',
|
|
49
|
-
routes
|
|
46
|
+
routes,
|
|
50
47
|
} = opts;
|
|
51
|
-
const routes: RouteForCli[] = canonicaliseLocalisedRoutes(rawRoutes);
|
|
52
48
|
const outDir = path.join(
|
|
53
49
|
appContext.srcDirectory,
|
|
54
50
|
generatedDirName,
|
|
55
51
|
entryName,
|
|
56
52
|
);
|
|
57
53
|
|
|
58
|
-
const rootModern = routes
|
|
59
|
-
const extras = r as RouteExtras;
|
|
60
|
-
return r && extras.type === 'nested' && extras.isRoot;
|
|
61
|
-
}) as NestedRouteForCli | undefined;
|
|
62
|
-
|
|
63
|
-
const rootExtras = rootModern as RouteExtras | undefined;
|
|
64
|
-
const topLevel = rootModern ? rootExtras?.children || [] : routes;
|
|
54
|
+
const { root: rootModern, children: topLevel } = describeRouteTree(routes);
|
|
65
55
|
|
|
66
56
|
const imports: string[] = [];
|
|
67
57
|
const statements: string[] = [];
|
|
@@ -92,15 +82,11 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
92
82
|
// value carries the internal `@_modern_js_src` alias, which the app's
|
|
93
83
|
// tsconfig does not map — the generated file must use relative
|
|
94
84
|
// imports.
|
|
95
|
-
const
|
|
96
|
-
if (!
|
|
85
|
+
const relImport = await resolveRouteImport(componentPath);
|
|
86
|
+
if (!relImport) {
|
|
97
87
|
return null;
|
|
98
88
|
}
|
|
99
89
|
|
|
100
|
-
const relImport = normalizeRelativeImport(
|
|
101
|
-
path.relative(outDir, resolvedNoExt),
|
|
102
|
-
);
|
|
103
|
-
|
|
104
90
|
const componentName = `component_${componentIndex++}`;
|
|
105
91
|
imports.push(`import ${componentName} from ${quote(relImport)};`);
|
|
106
92
|
return componentName;
|
|
@@ -111,7 +97,7 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
111
97
|
return pendingImportName;
|
|
112
98
|
};
|
|
113
99
|
|
|
114
|
-
const
|
|
100
|
+
const resolveRouteImport = async (aliasedNoExtPath: string) => {
|
|
115
101
|
const prefix = `${appContext.internalSrcAlias}/`;
|
|
116
102
|
let absNoExt: string;
|
|
117
103
|
if (aliasedNoExtPath.startsWith(prefix)) {
|
|
@@ -124,7 +110,10 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
124
110
|
absNoExt = path.join(appContext.srcDirectory, aliasedNoExtPath);
|
|
125
111
|
}
|
|
126
112
|
|
|
127
|
-
|
|
113
|
+
const resolvedNoExt = await resolveFileNoExt(absNoExt);
|
|
114
|
+
return resolvedNoExt
|
|
115
|
+
? normalizeRelativeImport(path.relative(outDir, resolvedNoExt))
|
|
116
|
+
: null;
|
|
128
117
|
};
|
|
129
118
|
|
|
130
119
|
const getImportNamesForLoader = async (
|
|
@@ -143,15 +132,11 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
143
132
|
};
|
|
144
133
|
}
|
|
145
134
|
|
|
146
|
-
const
|
|
147
|
-
if (!
|
|
135
|
+
const relImport = await resolveRouteImport(aliasedNoExtPath);
|
|
136
|
+
if (!relImport) {
|
|
148
137
|
return null;
|
|
149
138
|
}
|
|
150
139
|
|
|
151
|
-
const relImport = normalizeRelativeImport(
|
|
152
|
-
path.relative(outDir, resolvedNoExt),
|
|
153
|
-
);
|
|
154
|
-
|
|
155
140
|
const importName = `loader_${loaderIndex++}`;
|
|
156
141
|
const actionName = hasAction
|
|
157
142
|
? importName.replace(/^loader_/, 'action_')
|
|
@@ -182,14 +167,10 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
182
167
|
return existing;
|
|
183
168
|
}
|
|
184
169
|
|
|
185
|
-
const
|
|
186
|
-
if (!
|
|
170
|
+
const relImport = await resolveRouteImport(aliasedNoExtPath);
|
|
171
|
+
if (!relImport) {
|
|
187
172
|
return null;
|
|
188
173
|
}
|
|
189
|
-
|
|
190
|
-
const relImport = normalizeRelativeImport(
|
|
191
|
-
path.relative(outDir, resolvedNoExt),
|
|
192
|
-
);
|
|
193
174
|
const importName =
|
|
194
175
|
exportName === 'validateSearch'
|
|
195
176
|
? `validateSearch_${validateSearchIndex++}`
|
|
@@ -217,15 +198,8 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
217
198
|
return reserveRouteVarName(`route_${base}`);
|
|
218
199
|
};
|
|
219
200
|
|
|
220
|
-
const
|
|
221
|
-
parentVar: string;
|
|
222
|
-
route: NestedRouteForCli | PageRoute;
|
|
223
|
-
}): Promise<string> => {
|
|
224
|
-
const { parentVar, route } = opts;
|
|
225
|
-
|
|
226
|
-
const varName = createRouteVarName(route);
|
|
201
|
+
const createRouteOptions = async (route: RouteForCli, hasSplat: boolean) => {
|
|
227
202
|
const routeExtras = route as RouteExtras;
|
|
228
|
-
|
|
229
203
|
const loaderInfo = pickModernLoaderModule(route);
|
|
230
204
|
const routeAction = routeExtras.action;
|
|
231
205
|
const loaderImports = loaderInfo
|
|
@@ -251,10 +225,7 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
251
225
|
)
|
|
252
226
|
: null;
|
|
253
227
|
|
|
254
|
-
const
|
|
255
|
-
const hasSplat = typeof rawPath === 'string' && rawPath.includes('*');
|
|
256
|
-
|
|
257
|
-
const routeOpts: string[] = [`getParentRoute: () => ${parentVar},`];
|
|
228
|
+
const routeOpts: string[] = [];
|
|
258
229
|
|
|
259
230
|
const componentName = await getImportNameForComponent(
|
|
260
231
|
routeExtras._component,
|
|
@@ -263,14 +234,6 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
263
234
|
routeOpts.push(`component: ${componentName},`);
|
|
264
235
|
}
|
|
265
236
|
|
|
266
|
-
if (isPathlessLayout(route)) {
|
|
267
|
-
const id = routeExtras.id;
|
|
268
|
-
routeOpts.push(`id: ${quote(id || 'pathless')},`);
|
|
269
|
-
} else {
|
|
270
|
-
const p = isIndexRoute(route) ? '/' : toTanstackPath(rawPath || '');
|
|
271
|
-
routeOpts.push(`path: ${quote(p)},`);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
237
|
if (loaderName) {
|
|
275
238
|
routeOpts.push(
|
|
276
239
|
`loader: modernLoaderToTanstack({ hasSplat: ${hasSplat} }, ${loaderName}),`,
|
|
@@ -292,7 +255,22 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
292
255
|
routeOpts.push(staticDataSnippet);
|
|
293
256
|
}
|
|
294
257
|
|
|
295
|
-
|
|
258
|
+
return routeOpts;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const buildRoute = async (
|
|
262
|
+
descriptor: RouteDescriptor<RouteForCli>,
|
|
263
|
+
parentVar: string,
|
|
264
|
+
): Promise<string> => {
|
|
265
|
+
const { source: route, location, hasSplat, children } = descriptor;
|
|
266
|
+
const varName = createRouteVarName(route);
|
|
267
|
+
const routeOpts = [
|
|
268
|
+
`getParentRoute: () => ${parentVar},`,
|
|
269
|
+
...Object.entries(location).map(
|
|
270
|
+
([key, value]) => `${key}: ${quote(value)},`,
|
|
271
|
+
),
|
|
272
|
+
...(await createRouteOptions(route, hasSplat)),
|
|
273
|
+
];
|
|
296
274
|
const hasChildren = Boolean(children && children.length > 0);
|
|
297
275
|
const routeCtorVarName = hasChildren
|
|
298
276
|
? reserveRouteVarName(`${varName}__base`)
|
|
@@ -305,9 +283,7 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
305
283
|
if (children && children.length > 0) {
|
|
306
284
|
const childVars: string[] = [];
|
|
307
285
|
for (const child of children) {
|
|
308
|
-
childVars.push(
|
|
309
|
-
await buildRoute({ parentVar: routeCtorVarName, route: child }),
|
|
310
|
-
);
|
|
286
|
+
childVars.push(await buildRoute(child, routeCtorVarName));
|
|
311
287
|
}
|
|
312
288
|
statements.push(
|
|
313
289
|
`const ${varName} = ${routeCtorVarName}.addChildren([${childVars.join(', ')}]);`,
|
|
@@ -317,60 +293,14 @@ export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
|
317
293
|
return varName;
|
|
318
294
|
};
|
|
319
295
|
|
|
320
|
-
const rootLoaderInfo = rootModern ? pickModernLoaderModule(rootModern) : null;
|
|
321
|
-
const rootAction = rootExtras?.action;
|
|
322
|
-
const rootLoaderImports = rootLoaderInfo?.loaderPath
|
|
323
|
-
? await getImportNamesForLoader(
|
|
324
|
-
rootLoaderInfo.loaderPath,
|
|
325
|
-
rootLoaderInfo.inline,
|
|
326
|
-
Boolean(
|
|
327
|
-
rootLoaderInfo.inline && rootAction === rootLoaderInfo.loaderPath,
|
|
328
|
-
),
|
|
329
|
-
)
|
|
330
|
-
: null;
|
|
331
|
-
const rootLoaderName = rootLoaderImports?.loaderName || null;
|
|
332
|
-
const rootActionName = rootLoaderImports?.actionName || null;
|
|
333
|
-
const rootSearchContractInfo = rootModern
|
|
334
|
-
? pickRouteSearchContractModules(rootModern)
|
|
335
|
-
: null;
|
|
336
|
-
const rootValidateSearchName = rootSearchContractInfo?.validateSearchPath
|
|
337
|
-
? await getImportNameForSearchContract(
|
|
338
|
-
rootSearchContractInfo.validateSearchPath,
|
|
339
|
-
'validateSearch',
|
|
340
|
-
)
|
|
341
|
-
: null;
|
|
342
|
-
const rootLoaderDepsName = rootSearchContractInfo?.loaderDepsPath
|
|
343
|
-
? await getImportNameForSearchContract(
|
|
344
|
-
rootSearchContractInfo.loaderDepsPath,
|
|
345
|
-
'loaderDeps',
|
|
346
|
-
)
|
|
347
|
-
: null;
|
|
348
|
-
|
|
349
296
|
const topLevelVars: string[] = [];
|
|
350
297
|
for (const route of topLevel) {
|
|
351
|
-
topLevelVars.push(await buildRoute(
|
|
298
|
+
topLevelVars.push(await buildRoute(route, 'rootRoute'));
|
|
352
299
|
}
|
|
353
300
|
|
|
354
|
-
const rootOpts
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
rootExtras?._component,
|
|
358
|
-
);
|
|
359
|
-
if (rootComponentName) {
|
|
360
|
-
rootOpts.push(`component: ${rootComponentName},`);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
if (rootLoaderName) {
|
|
364
|
-
rootOpts.push(
|
|
365
|
-
`loader: modernLoaderToTanstack({ hasSplat: false }, ${rootLoaderName}),`,
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
if (rootValidateSearchName) {
|
|
369
|
-
rootOpts.push(`validateSearch: ${rootValidateSearchName},`);
|
|
370
|
-
}
|
|
371
|
-
if (rootLoaderDepsName) {
|
|
372
|
-
rootOpts.push(`loaderDeps: ${rootLoaderDepsName},`);
|
|
373
|
-
}
|
|
301
|
+
const rootOpts = rootModern
|
|
302
|
+
? await createRouteOptions(rootModern, false)
|
|
303
|
+
: [];
|
|
374
304
|
|
|
375
305
|
const routerGenTs = `// This file is auto-generated by Modern.js. Do not edit manually.
|
|
376
306
|
|
|
@@ -388,13 +318,7 @@ ${imports.join('\n')}
|
|
|
388
318
|
|
|
389
319
|
export const rootRoute = createRootRouteWithContext<ModernRouterContext>()({
|
|
390
320
|
${rootOpts.join('\n ')}
|
|
391
|
-
|
|
392
|
-
createRouteStaticDataSnippet({
|
|
393
|
-
modernRouteId: rootExtras?.id,
|
|
394
|
-
loaderName: rootLoaderName,
|
|
395
|
-
actionName: rootActionName,
|
|
396
|
-
}) || ''
|
|
397
|
-
}
|
|
321
|
+
|
|
398
322
|
});
|
|
399
323
|
|
|
400
324
|
${statements.join('\n\n')}
|
package/src/runtime/lifecycle.ts
CHANGED
|
@@ -98,15 +98,15 @@ type LoaderLikeContext = {
|
|
|
98
98
|
params?: Record<string, string>;
|
|
99
99
|
};
|
|
100
100
|
|
|
101
|
-
function getLoaderSignal(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return
|
|
101
|
+
export function getLoaderSignal(
|
|
102
|
+
ctx: LoaderLikeContext | undefined,
|
|
103
|
+
): AbortSignal {
|
|
104
|
+
const matchSignal = ctx?.abortController?.signal ?? ctx?.signal;
|
|
105
|
+
const requestSignal = ctx?.context?.request?.signal;
|
|
106
|
+
const signals = [matchSignal, requestSignal].filter(
|
|
107
|
+
(signal): signal is AbortSignal => signal instanceof AbortSignal,
|
|
108
|
+
);
|
|
109
|
+
return AbortSignal.any(signals);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
export function getLoaderHref(ctx: LoaderLikeContext | undefined): string {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RouterNavigationCapability,
|
|
3
|
+
RouterNavigationSnapshot,
|
|
4
|
+
} from '@modern-js/runtime-extensions/router-state';
|
|
5
|
+
import type { AnyRouter } from '@tanstack/react-router';
|
|
6
|
+
import { Link } from './prefetchLink';
|
|
7
|
+
|
|
8
|
+
/** Native TanStack navigation, exposed through the provider contract. */
|
|
9
|
+
export function createTanstackNavigation(
|
|
10
|
+
router: AnyRouter,
|
|
11
|
+
): RouterNavigationCapability {
|
|
12
|
+
let location: AnyRouter['state']['location'] | undefined;
|
|
13
|
+
let matches: AnyRouter['state']['matches'] | undefined;
|
|
14
|
+
let snapshot: RouterNavigationSnapshot;
|
|
15
|
+
return {
|
|
16
|
+
Link: Link as RouterNavigationCapability['Link'],
|
|
17
|
+
getSnapshot() {
|
|
18
|
+
const state = router.state;
|
|
19
|
+
if (
|
|
20
|
+
location !== state.location ||
|
|
21
|
+
matches === undefined ||
|
|
22
|
+
matches.length !== state.matches.length ||
|
|
23
|
+
matches.some(
|
|
24
|
+
(match, index) => match.params !== state.matches[index]?.params,
|
|
25
|
+
)
|
|
26
|
+
) {
|
|
27
|
+
location = state.location;
|
|
28
|
+
matches = state.matches;
|
|
29
|
+
snapshot = {
|
|
30
|
+
location: {
|
|
31
|
+
pathname: location.pathname,
|
|
32
|
+
search: location.searchStr,
|
|
33
|
+
hash:
|
|
34
|
+
location.hash !== '' ? `#${location.hash.replace(/^#/, '')}` : '',
|
|
35
|
+
},
|
|
36
|
+
params: Object.assign({}, ...matches.map(match => match.params)),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return snapshot;
|
|
40
|
+
},
|
|
41
|
+
subscribe(listener) {
|
|
42
|
+
const stops = (
|
|
43
|
+
['onBeforeNavigate', 'onBeforeLoad', 'onLoad', 'onResolved'] as const
|
|
44
|
+
).map(event => router.subscribe(event, listener));
|
|
45
|
+
return () => {
|
|
46
|
+
for (const stop of stops) stop();
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
navigate(href, options) {
|
|
50
|
+
return router.navigate({
|
|
51
|
+
to: href,
|
|
52
|
+
replace: options?.replace,
|
|
53
|
+
...(options?.state === undefined
|
|
54
|
+
? {}
|
|
55
|
+
: { state: options.state as never }),
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
createLinkProps(target) {
|
|
59
|
+
const preload =
|
|
60
|
+
target.preload !== undefined
|
|
61
|
+
? target.preload
|
|
62
|
+
: target.prefetch === 'none'
|
|
63
|
+
? false
|
|
64
|
+
: target.prefetch;
|
|
65
|
+
return {
|
|
66
|
+
to: target.pathname,
|
|
67
|
+
...(target.search !== undefined ? { search: target.search } : {}),
|
|
68
|
+
...(target.hash !== undefined && target.hash !== ''
|
|
69
|
+
? { hash: target.hash }
|
|
70
|
+
: {}),
|
|
71
|
+
...(target.hashScrollIntoView === undefined
|
|
72
|
+
? {}
|
|
73
|
+
: { hashScrollIntoView: target.hashScrollIntoView }),
|
|
74
|
+
...(preload === undefined ? {} : { preload }),
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|