@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.3 → 3.5.0-ultramodern.31
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 +157 -0
- package/dist/cjs/cli/index.js +8 -79
- package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +113 -0
- package/dist/cjs/cli/tanstackTypes/shared.js +130 -0
- package/dist/cjs/cli/tanstackTypes/source.js +251 -0
- package/dist/cjs/cli/tanstackTypes.js +4 -350
- package/dist/cjs/runtime/blockingSubscribe.js +64 -0
- package/dist/cjs/runtime/{pluginCore.js → clientBasepath.js} +12 -19
- package/dist/cjs/runtime/clientHydration.js +129 -0
- package/dist/cjs/runtime/dataMutation.js +11 -176
- package/dist/cjs/runtime/formData.js +116 -0
- package/dist/cjs/runtime/loaderBridge.js +4 -1
- package/dist/cjs/runtime/plugin.js +21 -125
- package/dist/cjs/runtime/plugin.node.js +45 -125
- package/dist/cjs/runtime/pluginShared.js +90 -0
- package/dist/cjs/runtime/prefetchLink.js +15 -2
- package/dist/cjs/runtime/routeTree/components.js +102 -0
- package/dist/cjs/runtime/routeTree/construction.js +152 -0
- package/dist/cjs/runtime/routeTree/index.js +47 -0
- package/dist/cjs/runtime/routeTree/loaders.js +158 -0
- package/dist/cjs/runtime/routeTree/paths.js +57 -0
- package/dist/cjs/runtime/routeTree/staticData.js +63 -0
- package/dist/cjs/runtime/routeTree/tanstackRoutes.js +57 -0
- package/dist/cjs/runtime/routeTree/types.js +18 -0
- package/dist/cjs/runtime/routeTree.js +7 -320
- package/dist/cjs/runtime/rsc/CompositeComponent.js +18 -13
- package/dist/cjs/runtime/rsc/RscNodeRenderer.js +5 -16
- package/dist/cjs/runtime/rsc/client.js +8 -25
- package/dist/cjs/runtime/rsc/flightSerialization.js +132 -0
- package/dist/cjs/runtime/rsc/payloadErrors.js +99 -0
- package/dist/cjs/runtime/rsc/payloadFetch.js +117 -0
- package/dist/cjs/runtime/rsc/payloadRouter.js +21 -142
- package/dist/cjs/runtime/rsc/payloadRoutes.js +106 -0
- package/dist/cjs/runtime/rsc/payloadStorage.js +58 -0
- package/dist/cjs/runtime/rsc/server.js +14 -18
- package/dist/cjs/runtime/rsc/shared.js +71 -0
- package/dist/cjs/runtime/rsc/treeGetter.js +72 -0
- package/dist/cjs/runtime/ssrManagedTags.js +103 -0
- package/dist/cjs/runtime/ssrPreload.js +89 -0
- package/dist/cjs/runtime/ssrTypes.js +18 -0
- package/dist/cjs/runtime/submitAction.js +161 -0
- package/dist/cjs/runtime/utils.js +49 -86
- package/dist/esm/cli/artifacts.mjs +103 -0
- package/dist/esm/cli/index.mjs +4 -78
- package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +75 -0
- package/dist/esm/cli/tanstackTypes/shared.mjs +68 -0
- package/dist/esm/cli/tanstackTypes/source.mjs +203 -0
- package/dist/esm/cli/tanstackTypes.mjs +2 -339
- package/dist/esm/runtime/blockingSubscribe.mjs +19 -0
- package/dist/esm/runtime/clientBasepath.mjs +10 -0
- package/dist/esm/runtime/clientHydration.mjs +70 -0
- package/dist/esm/runtime/dataMutation.mjs +2 -167
- package/dist/esm/runtime/formData.mjs +63 -0
- package/dist/esm/runtime/loaderBridge.mjs +4 -1
- package/dist/esm/runtime/plugin.mjs +14 -118
- package/dist/esm/runtime/plugin.node.mjs +41 -121
- package/dist/esm/runtime/pluginShared.mjs +40 -0
- package/dist/esm/runtime/prefetchLink.mjs +18 -5
- package/dist/esm/runtime/routeTree/components.mjs +55 -0
- package/dist/esm/runtime/routeTree/construction.mjs +111 -0
- package/dist/esm/runtime/routeTree/index.mjs +2 -0
- package/dist/esm/runtime/routeTree/loaders.mjs +117 -0
- package/dist/esm/runtime/routeTree/paths.mjs +16 -0
- package/dist/esm/runtime/routeTree/staticData.mjs +22 -0
- package/dist/esm/runtime/routeTree/tanstackRoutes.mjs +13 -0
- package/dist/esm/runtime/routeTree/types.mjs +0 -0
- package/dist/esm/runtime/routeTree.mjs +1 -318
- package/dist/esm/runtime/rsc/CompositeComponent.mjs +18 -13
- package/dist/esm/runtime/rsc/RscNodeRenderer.mjs +4 -15
- package/dist/esm/runtime/rsc/client.mjs +6 -26
- package/dist/esm/runtime/rsc/flightSerialization.mjs +88 -0
- package/dist/esm/runtime/rsc/payloadErrors.mjs +49 -0
- package/dist/esm/runtime/rsc/payloadFetch.mjs +61 -0
- package/dist/esm/runtime/rsc/payloadRouter.mjs +12 -133
- package/dist/esm/runtime/rsc/payloadRoutes.mjs +50 -0
- package/dist/esm/runtime/rsc/payloadStorage.mjs +14 -0
- package/dist/esm/runtime/rsc/server.mjs +17 -21
- package/dist/esm/runtime/rsc/shared.mjs +21 -0
- package/dist/esm/runtime/rsc/treeGetter.mjs +34 -0
- package/dist/esm/runtime/ssrManagedTags.mjs +53 -0
- package/dist/esm/runtime/ssrPreload.mjs +51 -0
- package/dist/esm/runtime/ssrTypes.mjs +0 -0
- package/dist/esm/runtime/submitAction.mjs +120 -0
- package/dist/esm/runtime/utils.mjs +47 -75
- package/dist/esm-node/cli/artifacts.mjs +104 -0
- package/dist/esm-node/cli/index.mjs +4 -78
- package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +76 -0
- package/dist/esm-node/cli/tanstackTypes/shared.mjs +69 -0
- package/dist/esm-node/cli/tanstackTypes/source.mjs +204 -0
- package/dist/esm-node/cli/tanstackTypes.mjs +2 -339
- package/dist/esm-node/runtime/blockingSubscribe.mjs +20 -0
- package/dist/esm-node/runtime/clientBasepath.mjs +11 -0
- package/dist/esm-node/runtime/clientHydration.mjs +71 -0
- package/dist/esm-node/runtime/dataMutation.mjs +2 -167
- package/dist/esm-node/runtime/formData.mjs +64 -0
- package/dist/esm-node/runtime/loaderBridge.mjs +4 -1
- package/dist/esm-node/runtime/plugin.mjs +14 -118
- package/dist/esm-node/runtime/plugin.node.mjs +41 -121
- package/dist/esm-node/runtime/pluginShared.mjs +41 -0
- package/dist/esm-node/runtime/prefetchLink.mjs +18 -5
- package/dist/esm-node/runtime/routeTree/components.mjs +56 -0
- package/dist/esm-node/runtime/routeTree/construction.mjs +112 -0
- package/dist/esm-node/runtime/routeTree/index.mjs +3 -0
- package/dist/esm-node/runtime/routeTree/loaders.mjs +118 -0
- package/dist/esm-node/runtime/routeTree/paths.mjs +17 -0
- package/dist/esm-node/runtime/routeTree/staticData.mjs +23 -0
- package/dist/esm-node/runtime/routeTree/tanstackRoutes.mjs +14 -0
- package/dist/esm-node/runtime/routeTree/types.mjs +1 -0
- package/dist/esm-node/runtime/routeTree.mjs +1 -318
- package/dist/esm-node/runtime/rsc/CompositeComponent.mjs +18 -13
- package/dist/esm-node/runtime/rsc/RscNodeRenderer.mjs +4 -15
- package/dist/esm-node/runtime/rsc/client.mjs +6 -26
- package/dist/esm-node/runtime/rsc/flightSerialization.mjs +89 -0
- package/dist/esm-node/runtime/rsc/payloadErrors.mjs +50 -0
- package/dist/esm-node/runtime/rsc/payloadFetch.mjs +62 -0
- package/dist/esm-node/runtime/rsc/payloadRouter.mjs +12 -133
- package/dist/esm-node/runtime/rsc/payloadRoutes.mjs +51 -0
- package/dist/esm-node/runtime/rsc/payloadStorage.mjs +15 -0
- package/dist/esm-node/runtime/rsc/server.mjs +17 -21
- package/dist/esm-node/runtime/rsc/shared.mjs +22 -0
- package/dist/esm-node/runtime/rsc/treeGetter.mjs +35 -0
- package/dist/esm-node/runtime/ssrManagedTags.mjs +54 -0
- package/dist/esm-node/runtime/ssrPreload.mjs +52 -0
- package/dist/esm-node/runtime/ssrTypes.mjs +1 -0
- package/dist/esm-node/runtime/submitAction.mjs +121 -0
- package/dist/esm-node/runtime/utils.mjs +47 -75
- package/dist/types/cli/artifacts.d.ts +33 -0
- package/dist/types/cli/index.d.ts +2 -22
- package/dist/types/cli/tanstackTypes/canonicalRoutes.d.ts +22 -0
- package/dist/types/cli/tanstackTypes/shared.d.ts +20 -0
- package/dist/types/cli/tanstackTypes/source.d.ts +10 -0
- package/dist/types/cli/tanstackTypes.d.ts +3 -31
- package/dist/types/runtime/blockingSubscribe.d.ts +3 -0
- package/dist/types/runtime/clientBasepath.d.ts +1 -0
- package/dist/types/runtime/clientHydration.d.ts +19 -0
- package/dist/types/runtime/dataMutation.d.ts +3 -12
- package/dist/types/runtime/formData.d.ts +23 -0
- package/dist/types/runtime/plugin.d.ts +1 -1
- package/dist/types/runtime/plugin.node.d.ts +1 -1
- package/dist/types/runtime/pluginShared.d.ts +39 -0
- package/dist/types/runtime/routeTree/components.d.ts +7 -0
- package/dist/types/runtime/routeTree/construction.d.ts +5 -0
- package/dist/types/runtime/routeTree/index.d.ts +2 -0
- package/dist/types/runtime/routeTree/loaders.d.ts +4 -0
- package/dist/types/runtime/routeTree/paths.d.ts +3 -0
- package/dist/types/runtime/routeTree/staticData.d.ts +19 -0
- package/dist/types/runtime/routeTree/tanstackRoutes.d.ts +4 -0
- package/dist/types/runtime/routeTree/types.d.ts +75 -0
- package/dist/types/runtime/routeTree.d.ts +1 -9
- package/dist/types/runtime/rsc/CompositeComponent.d.ts +1 -2
- package/dist/types/runtime/rsc/RscNodeRenderer.d.ts +2 -3
- package/dist/types/runtime/rsc/client.d.ts +2 -0
- package/dist/types/runtime/rsc/flightSerialization.d.ts +3 -0
- package/dist/types/runtime/rsc/payloadErrors.d.ts +6 -0
- package/dist/types/runtime/rsc/payloadFetch.d.ts +10 -0
- package/dist/types/runtime/rsc/payloadRouter.d.ts +2 -10
- package/dist/types/runtime/rsc/payloadRoutes.d.ts +43 -0
- package/dist/types/runtime/rsc/payloadStorage.d.ts +5 -0
- package/dist/types/runtime/rsc/shared.d.ts +19 -0
- package/dist/types/runtime/rsc/treeGetter.d.ts +1 -0
- package/dist/types/runtime/ssrManagedTags.d.ts +7 -0
- package/dist/types/runtime/ssrPreload.d.ts +2 -0
- package/dist/types/runtime/ssrTypes.d.ts +43 -0
- package/dist/types/runtime/state.d.ts +1 -1
- package/dist/types/runtime/submitAction.d.ts +14 -0
- package/dist/types/runtime/types.d.ts +4 -9
- package/dist/types/runtime/utils.d.ts +4 -24
- package/package.json +30 -8
- package/rstest.config.mts +3 -0
- package/src/cli/artifacts.ts +255 -0
- package/src/cli/index.ts +7 -185
- package/src/cli/tanstackTypes/canonicalRoutes.ts +157 -0
- package/src/cli/tanstackTypes/shared.ts +119 -0
- package/src/cli/tanstackTypes/source.ts +405 -0
- package/src/cli/tanstackTypes.ts +4 -647
- package/src/runtime/blockingSubscribe.ts +48 -0
- package/src/runtime/clientBasepath.ts +12 -0
- package/src/runtime/clientHydration.ts +151 -0
- package/src/runtime/dataMutation.tsx +9 -306
- package/src/runtime/formData.ts +153 -0
- package/src/runtime/loaderBridge.ts +8 -3
- package/src/runtime/plugin.node.tsx +76 -291
- package/src/runtime/plugin.tsx +21 -257
- package/src/runtime/pluginShared.ts +112 -0
- package/src/runtime/prefetchLink.tsx +78 -15
- package/src/runtime/routeTree/components.ts +130 -0
- package/src/runtime/routeTree/construction.ts +238 -0
- package/src/runtime/routeTree/index.ts +7 -0
- package/src/runtime/routeTree/loaders.ts +232 -0
- package/src/runtime/routeTree/paths.ts +36 -0
- package/src/runtime/routeTree/staticData.ts +66 -0
- package/src/runtime/routeTree/tanstackRoutes.ts +36 -0
- package/src/runtime/routeTree/types.ts +87 -0
- package/src/runtime/routeTree.ts +5 -750
- package/src/runtime/rsc/CompositeComponent.tsx +29 -20
- package/src/runtime/rsc/RscNodeRenderer.tsx +9 -27
- package/src/runtime/rsc/client.tsx +12 -40
- package/src/runtime/rsc/flightSerialization.ts +158 -0
- package/src/runtime/rsc/payloadErrors.ts +73 -0
- package/src/runtime/rsc/payloadFetch.ts +97 -0
- package/src/runtime/rsc/payloadRouter.ts +29 -234
- package/src/runtime/rsc/payloadRoutes.ts +122 -0
- package/src/runtime/rsc/payloadStorage.ts +35 -0
- package/src/runtime/rsc/server.tsx +20 -29
- package/src/runtime/rsc/shared.ts +70 -0
- package/src/runtime/rsc/treeGetter.tsx +52 -0
- package/src/runtime/ssrManagedTags.ts +107 -0
- package/src/runtime/ssrPreload.ts +125 -0
- package/src/runtime/ssrTypes.ts +51 -0
- package/src/runtime/state.ts +4 -2
- package/src/runtime/submitAction.ts +194 -0
- package/src/runtime/types.ts +6 -13
- package/src/runtime/utils.tsx +76 -110
- package/src/types/react-server-dom-rspack.d.ts +56 -0
- package/tests/castRatchet.test.ts +85 -0
- package/tests/router/cli.test.ts +7 -0
- package/tests/router/dataMutation.test.tsx +59 -0
- package/tests/router/fixtures/router-gen.golden.txt +72 -0
- package/tests/router/generateRouteArtifacts.test.ts +106 -0
- package/tests/router/loaderBridge.test.ts +21 -0
- package/tests/router/prefetchLink.test.tsx +106 -59
- package/tests/router/prefetchLinkPreload.test.tsx +85 -0
- package/tests/router/routeTree.test.ts +46 -11
- package/tests/router/rsc.test.tsx +189 -0
- package/tests/router/ssrPreload.test.ts +30 -0
- package/tests/router/tanstackTypes.test.ts +254 -1
- package/dist/esm/runtime/pluginCore.mjs +0 -14
- package/dist/esm-node/runtime/pluginCore.mjs +0 -15
- package/dist/types/runtime/pluginCore.d.ts +0 -21
- package/src/runtime/pluginCore.ts +0 -48
package/src/cli/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @effect-diagnostics asyncFunction:off nodeBuiltinImport:off strictBooleanExpressions:off
|
|
1
|
+
// @effect-diagnostics asyncFunction:off nodeBuiltinImport:off strictBooleanExpressions:off processEnv:off processEnvInEffect:off
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import type {
|
|
4
4
|
AppNormalizedConfig,
|
|
@@ -18,15 +18,17 @@ import {
|
|
|
18
18
|
fs,
|
|
19
19
|
NESTED_ROUTE_SPEC_FILE,
|
|
20
20
|
} from '@modern-js/utils';
|
|
21
|
+
import { writeTanstackRouterTypesForEntries } from './artifacts';
|
|
21
22
|
import {
|
|
22
23
|
createTanstackRsbuildRouteSplittingProfile,
|
|
23
24
|
type TanstackRouteCodeSplittingOption,
|
|
24
25
|
} from './routeSplitting';
|
|
25
|
-
import {
|
|
26
|
-
collectCanonicalRoutesForEntry,
|
|
27
|
-
generateTanstackRouterTypesSourceForEntry,
|
|
28
|
-
} from './tanstackTypes';
|
|
29
26
|
|
|
27
|
+
export {
|
|
28
|
+
generateTanstackRouteArtifacts,
|
|
29
|
+
writeTanstackRegisterFile,
|
|
30
|
+
writeTanstackRouterTypesForEntries,
|
|
31
|
+
} from './artifacts';
|
|
30
32
|
export type {
|
|
31
33
|
TanstackRouteCodeSplittingOption,
|
|
32
34
|
TanstackRsbuildRouteSplittingProfile,
|
|
@@ -113,186 +115,6 @@ function getRuntimeRouterCli(): RuntimeRouterCliHelpers {
|
|
|
113
115
|
);
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
async function writeFileIfChanged(filePath: string, content: string) {
|
|
117
|
-
try {
|
|
118
|
-
const previous = (await fs.pathExists(filePath))
|
|
119
|
-
? await fs.readFile(filePath, 'utf-8')
|
|
120
|
-
: null;
|
|
121
|
-
if (previous === content) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
} catch {
|
|
125
|
-
// Fall through and rewrite the generated file.
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
await fs.outputFile(filePath, content, 'utf-8');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function createRegisterDtsContent(opts: {
|
|
132
|
-
entries: string[];
|
|
133
|
-
runtimeModule: string;
|
|
134
|
-
canonicalRoutes?: Record<string, string> | null;
|
|
135
|
-
i18nRuntimeModule?: string;
|
|
136
|
-
}) {
|
|
137
|
-
const importStatements = opts.entries
|
|
138
|
-
.map(
|
|
139
|
-
(entryName, index) =>
|
|
140
|
-
`import type { router as router${index} } from './${entryName}/router.gen';`,
|
|
141
|
-
)
|
|
142
|
-
.join('\n');
|
|
143
|
-
const routerUnionType = opts.entries
|
|
144
|
-
.map((_, index) => `typeof router${index}`)
|
|
145
|
-
.join(' | ');
|
|
146
|
-
|
|
147
|
-
const canonicalEntries = Object.entries(opts.canonicalRoutes ?? {});
|
|
148
|
-
const canonicalRoutesAugmentation =
|
|
149
|
-
canonicalEntries.length > 0
|
|
150
|
-
? `
|
|
151
|
-
declare module '${opts.i18nRuntimeModule || '@modern-js/plugin-i18n/runtime'}' {
|
|
152
|
-
interface UltramodernCanonicalRoutes {
|
|
153
|
-
${canonicalEntries
|
|
154
|
-
.map(([routePath, paramsType]) => ` '${routePath}': ${paramsType};`)
|
|
155
|
-
.join('\n')}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
`
|
|
159
|
-
: '';
|
|
160
|
-
|
|
161
|
-
return `// This file is auto-generated by Modern.js. Do not edit manually.
|
|
162
|
-
|
|
163
|
-
${importStatements}
|
|
164
|
-
|
|
165
|
-
declare module '${opts.runtimeModule}' {
|
|
166
|
-
interface Register {
|
|
167
|
-
router: ${routerUnionType};
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
${canonicalRoutesAugmentation}`;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export async function writeTanstackRegisterFile(opts: {
|
|
174
|
-
entries: string[];
|
|
175
|
-
generatedDirName?: string;
|
|
176
|
-
runtimeModule?: string;
|
|
177
|
-
srcDirectory: string;
|
|
178
|
-
canonicalRoutes?: Record<string, string> | null;
|
|
179
|
-
i18nRuntimeModule?: string;
|
|
180
|
-
}) {
|
|
181
|
-
const {
|
|
182
|
-
entries,
|
|
183
|
-
generatedDirName = DEFAULT_GENERATED_DIR_NAME,
|
|
184
|
-
runtimeModule = '@modern-js/plugin-tanstack/runtime',
|
|
185
|
-
srcDirectory,
|
|
186
|
-
canonicalRoutes,
|
|
187
|
-
i18nRuntimeModule,
|
|
188
|
-
} = opts;
|
|
189
|
-
|
|
190
|
-
if (entries.length === 0) {
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const registerDtsPath = path.join(
|
|
195
|
-
srcDirectory,
|
|
196
|
-
generatedDirName,
|
|
197
|
-
'register.gen.d.ts',
|
|
198
|
-
);
|
|
199
|
-
|
|
200
|
-
await writeFileIfChanged(
|
|
201
|
-
registerDtsPath,
|
|
202
|
-
createRegisterDtsContent({
|
|
203
|
-
entries,
|
|
204
|
-
runtimeModule,
|
|
205
|
-
canonicalRoutes,
|
|
206
|
-
i18nRuntimeModule,
|
|
207
|
-
}),
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
export async function writeTanstackRouterTypesForEntries(opts: {
|
|
212
|
-
appContext: AppToolsContext;
|
|
213
|
-
generatedDirName?: string;
|
|
214
|
-
routesByEntry: Record<string, (NestedRouteForCli | PageRoute)[]>;
|
|
215
|
-
/**
|
|
216
|
-
* Whether `@modern-js/plugin-i18n` is actually installed in the app. The
|
|
217
|
-
* `register.gen.d.ts` augmentation of '@modern-js/plugin-i18n/runtime' is
|
|
218
|
-
* only emitted when this is true — otherwise apps with a hand-rolled
|
|
219
|
-
* `/:lang/` param would fail typechecking on an unresolvable module.
|
|
220
|
-
*/
|
|
221
|
-
i18nPluginInstalled?: boolean;
|
|
222
|
-
}) {
|
|
223
|
-
const {
|
|
224
|
-
appContext,
|
|
225
|
-
generatedDirName = DEFAULT_GENERATED_DIR_NAME,
|
|
226
|
-
routesByEntry,
|
|
227
|
-
i18nPluginInstalled = false,
|
|
228
|
-
} = opts;
|
|
229
|
-
|
|
230
|
-
const entryNames = Object.keys(routesByEntry);
|
|
231
|
-
|
|
232
|
-
await Promise.all(
|
|
233
|
-
entryNames.map(async entryName => {
|
|
234
|
-
const { routerGenTs } = await generateTanstackRouterTypesSourceForEntry({
|
|
235
|
-
appContext,
|
|
236
|
-
entryName,
|
|
237
|
-
generatedDirName,
|
|
238
|
-
routes: routesByEntry[entryName],
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
await writeFileIfChanged(
|
|
242
|
-
path.join(
|
|
243
|
-
appContext.srcDirectory,
|
|
244
|
-
generatedDirName,
|
|
245
|
-
entryName,
|
|
246
|
-
'router.gen.ts',
|
|
247
|
-
),
|
|
248
|
-
routerGenTs,
|
|
249
|
-
);
|
|
250
|
-
}),
|
|
251
|
-
);
|
|
252
|
-
|
|
253
|
-
const mainEntryName = appContext.entrypoints?.find(
|
|
254
|
-
entrypoint => entrypoint.isMainEntry,
|
|
255
|
-
)?.entryName;
|
|
256
|
-
const registerEntries = entryNames.sort((a, b) => {
|
|
257
|
-
if (mainEntryName && a === mainEntryName) {
|
|
258
|
-
return -1;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (mainEntryName && b === mainEntryName) {
|
|
262
|
-
return 1;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
return a.localeCompare(b);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// Merge the canonical (language-agnostic) route maps of every entry so the
|
|
269
|
-
// typed i18n Link covers all routes the app can navigate to. Only relevant
|
|
270
|
-
// when plugin-i18n is actually installed — without it the emitted module
|
|
271
|
-
// augmentation would reference an unresolvable module.
|
|
272
|
-
let canonicalRoutes: Record<string, string> | null = null;
|
|
273
|
-
if (i18nPluginInstalled) {
|
|
274
|
-
for (const entryName of registerEntries) {
|
|
275
|
-
const entryCanonicalRoutes = collectCanonicalRoutesForEntry(
|
|
276
|
-
routesByEntry[entryName],
|
|
277
|
-
{ localeParamHeuristic: true },
|
|
278
|
-
);
|
|
279
|
-
if (entryCanonicalRoutes) {
|
|
280
|
-
canonicalRoutes = {
|
|
281
|
-
...entryCanonicalRoutes,
|
|
282
|
-
...(canonicalRoutes ?? {}),
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
await writeTanstackRegisterFile({
|
|
289
|
-
entries: registerEntries,
|
|
290
|
-
generatedDirName,
|
|
291
|
-
srcDirectory: appContext.srcDirectory,
|
|
292
|
-
canonicalRoutes,
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
|
|
296
118
|
export function tanstackRouterPlugin(
|
|
297
119
|
options: TanstackRouterPluginOptions = {},
|
|
298
120
|
): CliPlugin<AppTools> {
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// @effect-diagnostics asyncFunction:off strictBooleanExpressions:off
|
|
2
|
+
|
|
3
|
+
import type { NestedRouteForCli, PageRoute } from '@modern-js/types';
|
|
4
|
+
import { MAIN_ENTRY_NAME } from '@modern-js/utils';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
import { toTanstackPath } from './shared';
|
|
8
|
+
|
|
9
|
+
const LOCALE_PARAM_SEGMENTS = new Set([
|
|
10
|
+
':lang',
|
|
11
|
+
':locale',
|
|
12
|
+
':language',
|
|
13
|
+
'$lang',
|
|
14
|
+
'$locale',
|
|
15
|
+
'$language',
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
type CanonicalAwareRoute = (NestedRouteForCli | PageRoute) & {
|
|
19
|
+
modernCanonicalPath?: string;
|
|
20
|
+
index?: boolean;
|
|
21
|
+
isRoot?: boolean;
|
|
22
|
+
children?: CanonicalAwareRoute[];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function paramsTypeForCanonicalPath(canonicalPath: string): string {
|
|
26
|
+
const fields: string[] = [];
|
|
27
|
+
|
|
28
|
+
for (const segment of canonicalPath.split('/')) {
|
|
29
|
+
if (!segment) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (segment === '*' || segment === '$') {
|
|
33
|
+
fields.push(`'_splat'?: string`);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (segment.startsWith('{-$') && segment.endsWith('}')) {
|
|
37
|
+
fields.push(`${JSON.stringify(segment.slice(3, -1))}?: string`);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (segment.startsWith('$')) {
|
|
41
|
+
fields.push(`${JSON.stringify(segment.slice(1))}: string`);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (segment.startsWith(':')) {
|
|
45
|
+
const optional = segment.endsWith('?');
|
|
46
|
+
const name = segment.slice(1, optional ? undefined : segment.length);
|
|
47
|
+
fields.push(
|
|
48
|
+
`${JSON.stringify(optional ? name.slice(0, -1) : name)}${
|
|
49
|
+
optional ? '?' : ''
|
|
50
|
+
}: string`,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return fields.length > 0
|
|
56
|
+
? `{ ${fields.join('; ')} }`
|
|
57
|
+
: 'Record<string, never>';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type CollectCanonicalRoutesOptions = {
|
|
61
|
+
/**
|
|
62
|
+
* Whether a leading `:lang`/`:locale`/`:language` route param may be
|
|
63
|
+
* treated as an i18n locale prefix. This MUST only be enabled when
|
|
64
|
+
* `@modern-js/plugin-i18n` is actually installed: the emitted
|
|
65
|
+
* `declare module '@modern-js/plugin-i18n/runtime'` augmentation breaks
|
|
66
|
+
* typechecking (TS2664) for apps that hand-roll a `/:lang/` param without
|
|
67
|
+
* the plugin. Routes carrying `modernCanonicalPath` metadata are always
|
|
68
|
+
* honored — only plugin-i18n produces them.
|
|
69
|
+
*/
|
|
70
|
+
localeParamHeuristic?: boolean;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Derive the canonical (language-agnostic) route map for an entry: the
|
|
75
|
+
* leading locale param is stripped and localized physical variants (routes
|
|
76
|
+
* carrying `modernCanonicalPath` metadata from `@modern-js/plugin-i18n`)
|
|
77
|
+
* collapse to their canonical pattern. Returns `null` when the entry has no
|
|
78
|
+
* i18n routing surface (no locale param and no localized variants), so plain
|
|
79
|
+
* TanStack apps never get a `@modern-js/plugin-i18n` module augmentation.
|
|
80
|
+
*/
|
|
81
|
+
export function collectCanonicalRoutesForEntry(
|
|
82
|
+
routes: (NestedRouteForCli | PageRoute)[],
|
|
83
|
+
options: CollectCanonicalRoutesOptions = {},
|
|
84
|
+
): Record<string, string> | null {
|
|
85
|
+
const { localeParamHeuristic = true } = options;
|
|
86
|
+
const canonicalParams = new Map<string, string>();
|
|
87
|
+
let hasI18nSurface = false;
|
|
88
|
+
|
|
89
|
+
const normalizeJoined = (joined: string): string => {
|
|
90
|
+
const collapsed = joined.replace(/\/+/g, '/');
|
|
91
|
+
const withLeading = collapsed.startsWith('/') ? collapsed : `/${collapsed}`;
|
|
92
|
+
return withLeading.length > 1
|
|
93
|
+
? withLeading.replace(/\/+$/, '')
|
|
94
|
+
: withLeading;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const record = (canonicalPath: string) => {
|
|
98
|
+
const normalized = normalizeJoined(canonicalPath || '/');
|
|
99
|
+
const key = toTanstackPath(normalized);
|
|
100
|
+
if (!canonicalParams.has(key)) {
|
|
101
|
+
canonicalParams.set(key, paramsTypeForCanonicalPath(normalized));
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const visit = (route: CanonicalAwareRoute, parentPath: string) => {
|
|
106
|
+
let currentPath = parentPath;
|
|
107
|
+
|
|
108
|
+
if (typeof route.modernCanonicalPath === 'string') {
|
|
109
|
+
hasI18nSurface = true;
|
|
110
|
+
currentPath = normalizeJoined(route.modernCanonicalPath);
|
|
111
|
+
} else if (typeof route.path === 'string' && route.path.length > 0) {
|
|
112
|
+
const segments = route.path
|
|
113
|
+
.replace(/\[(.+?)\]/g, ':$1')
|
|
114
|
+
.split('/')
|
|
115
|
+
.filter(Boolean);
|
|
116
|
+
if (
|
|
117
|
+
localeParamHeuristic &&
|
|
118
|
+
parentPath === '' &&
|
|
119
|
+
LOCALE_PARAM_SEGMENTS.has(segments[0])
|
|
120
|
+
) {
|
|
121
|
+
hasI18nSurface = true;
|
|
122
|
+
segments.shift();
|
|
123
|
+
}
|
|
124
|
+
currentPath = segments.length
|
|
125
|
+
? normalizeJoined(`${parentPath}/${segments.join('/')}`)
|
|
126
|
+
: parentPath;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const children = route.children;
|
|
130
|
+
if (children && children.length > 0) {
|
|
131
|
+
for (const child of children) {
|
|
132
|
+
visit(child, currentPath);
|
|
133
|
+
}
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Leaf page or index route: a navigable target.
|
|
138
|
+
record(currentPath || '/');
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const rootModern = routes.find(
|
|
142
|
+
route => (route as CanonicalAwareRoute).isRoot,
|
|
143
|
+
) as CanonicalAwareRoute | undefined;
|
|
144
|
+
const topLevel = rootModern ? (rootModern.children ?? []) : routes;
|
|
145
|
+
|
|
146
|
+
for (const route of topLevel) {
|
|
147
|
+
visit(route as CanonicalAwareRoute, '');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!hasI18nSurface || canonicalParams.size === 0) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return Object.fromEntries(
|
|
155
|
+
[...canonicalParams.entries()].sort(([a], [b]) => a.localeCompare(b)),
|
|
156
|
+
);
|
|
157
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// @effect-diagnostics asyncFunction:off strictBooleanExpressions:off
|
|
2
|
+
|
|
3
|
+
import { getPathWithoutExt } from '@modern-js/runtime/cli';
|
|
4
|
+
import type { NestedRouteForCli, PageRoute } from '@modern-js/types';
|
|
5
|
+
import { findExists, formatImportPath, slash } from '@modern-js/utils';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
const JS_OR_TS_EXTS = [
|
|
9
|
+
'.js',
|
|
10
|
+
'.jsx',
|
|
11
|
+
'.ts',
|
|
12
|
+
'.tsx',
|
|
13
|
+
'.mjs',
|
|
14
|
+
'.mts',
|
|
15
|
+
'.cjs',
|
|
16
|
+
'.cts',
|
|
17
|
+
] as const;
|
|
18
|
+
|
|
19
|
+
export function toTanstackPath(pathname: string): string {
|
|
20
|
+
return pathname
|
|
21
|
+
.split('/')
|
|
22
|
+
.map(segment => {
|
|
23
|
+
if (!segment) {
|
|
24
|
+
return segment;
|
|
25
|
+
}
|
|
26
|
+
if (segment === '*') {
|
|
27
|
+
return '$';
|
|
28
|
+
}
|
|
29
|
+
if (segment.startsWith(':')) {
|
|
30
|
+
const name = segment.slice(1);
|
|
31
|
+
if (name.endsWith('?')) {
|
|
32
|
+
return `{-$${name.slice(0, -1)}}`;
|
|
33
|
+
}
|
|
34
|
+
return `$${name}`;
|
|
35
|
+
}
|
|
36
|
+
return segment;
|
|
37
|
+
})
|
|
38
|
+
.join('/');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function resolveFileNoExt(inputNoExtPath: string) {
|
|
42
|
+
const file = findExists(JS_OR_TS_EXTS.map(ext => `${inputNoExtPath}${ext}`));
|
|
43
|
+
return file ? getPathWithoutExt(file) : null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function quote(str: string) {
|
|
47
|
+
return JSON.stringify(str);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function normalizeRelativeImport(p: string) {
|
|
51
|
+
const normalized = formatImportPath(slash(p));
|
|
52
|
+
if (normalized.startsWith('.')) {
|
|
53
|
+
return normalized;
|
|
54
|
+
}
|
|
55
|
+
return `./${normalized}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function pickModernLoaderModule(route: NestedRouteForCli | PageRoute) {
|
|
59
|
+
const loaderPath = (route as any).data || (route as any).loader;
|
|
60
|
+
if (!loaderPath || typeof loaderPath !== 'string') {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const inline = Boolean((route as any).data);
|
|
65
|
+
return { loaderPath, inline };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function pickRouteSearchContractModules(
|
|
69
|
+
route: NestedRouteForCli | PageRoute,
|
|
70
|
+
) {
|
|
71
|
+
const validateSearchPath = (route as any).validateSearch;
|
|
72
|
+
const loaderDepsPath = (route as any).loaderDeps;
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
validateSearchPath:
|
|
76
|
+
typeof validateSearchPath === 'string' ? validateSearchPath : null,
|
|
77
|
+
loaderDepsPath: typeof loaderDepsPath === 'string' ? loaderDepsPath : null,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function isPathlessLayout(route: NestedRouteForCli | PageRoute) {
|
|
82
|
+
return (
|
|
83
|
+
(route as any).type === 'nested' &&
|
|
84
|
+
typeof (route as any).index !== 'boolean' &&
|
|
85
|
+
typeof (route as any).path === 'undefined'
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function isIndexRoute(route: NestedRouteForCli | PageRoute) {
|
|
90
|
+
return (route as any).type === 'nested' && Boolean((route as any).index);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function createRouteStaticDataSnippet(opts: {
|
|
94
|
+
modernRouteId?: string;
|
|
95
|
+
loaderName?: string | null;
|
|
96
|
+
actionName?: string | null;
|
|
97
|
+
}) {
|
|
98
|
+
const staticDataLines: string[] = [];
|
|
99
|
+
|
|
100
|
+
if (opts.modernRouteId) {
|
|
101
|
+
staticDataLines.push(`modernRouteId: ${quote(opts.modernRouteId)},`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (opts.loaderName) {
|
|
105
|
+
staticDataLines.push(`modernRouteLoader: ${opts.loaderName},`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (opts.actionName) {
|
|
109
|
+
staticDataLines.push(`modernRouteAction: ${opts.actionName},`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!staticDataLines.length) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return `staticData: createRouteStaticData({\n ${staticDataLines.join(
|
|
117
|
+
'\n ',
|
|
118
|
+
)}\n }),`;
|
|
119
|
+
}
|