@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.9 → 3.5.0-ultramodern.91
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 +123 -0
- package/dist/cjs/cli/tanstackTypes/source.js +255 -0
- package/dist/cjs/cli/tanstackTypes.js +4 -350
- package/dist/cjs/runtime/blockingSubscribe.js +57 -0
- package/dist/cjs/runtime/{pluginCore.js → clientBasepath.js} +12 -19
- package/dist/cjs/runtime/clientHydration.js +118 -0
- package/dist/cjs/runtime/dataMutation.js +11 -176
- package/dist/cjs/runtime/formData.js +116 -0
- package/dist/cjs/runtime/loaderBridge.js +7 -11
- package/dist/cjs/runtime/plugin.js +21 -125
- package/dist/cjs/runtime/plugin.node.js +45 -125
- package/dist/cjs/runtime/pluginShared.js +87 -0
- package/dist/cjs/runtime/prefetchLink.js +15 -2
- package/dist/cjs/runtime/register.js +3 -16
- 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/router.js +15 -2
- package/dist/cjs/runtime/rsc/CompositeComponent.js +18 -13
- package/dist/cjs/runtime/rsc/ReplayableStream.js +0 -4
- 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 +105 -0
- package/dist/cjs/runtime/rsc/payloadRouter.js +21 -142
- package/dist/cjs/runtime/rsc/payloadRoutes.js +94 -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 +68 -0
- package/dist/cjs/runtime/rsc/slotUsageSanitizer.js +1 -0
- package/dist/cjs/runtime/rsc/treeGetter.js +72 -0
- package/dist/cjs/runtime/shared/isAbsoluteUrl.js +47 -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/state.js +1 -1
- 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 +8 -82
- package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +75 -0
- package/dist/esm/cli/tanstackTypes/shared.mjs +61 -0
- package/dist/esm/cli/tanstackTypes/source.mjs +207 -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 +71 -0
- package/dist/esm/runtime/dataMutation.mjs +2 -167
- package/dist/esm/runtime/formData.mjs +63 -0
- package/dist/esm/runtime/loaderBridge.mjs +5 -9
- 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/register.mjs +1 -14
- 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/router.mjs +16 -2
- package/dist/esm/runtime/rsc/CompositeComponent.mjs +18 -13
- package/dist/esm/runtime/rsc/ReplayableStream.mjs +1 -1
- 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 +55 -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/slotUsageSanitizer.mjs +1 -0
- package/dist/esm/runtime/rsc/treeGetter.mjs +34 -0
- package/dist/esm/runtime/shared/isAbsoluteUrl.mjs +9 -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/state.mjs +1 -1
- 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 +8 -82
- package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +76 -0
- package/dist/esm-node/cli/tanstackTypes/shared.mjs +62 -0
- package/dist/esm-node/cli/tanstackTypes/source.mjs +208 -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 +72 -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 +5 -9
- 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/register.mjs +1 -14
- 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/router.mjs +16 -2
- package/dist/esm-node/runtime/rsc/CompositeComponent.mjs +18 -13
- package/dist/esm-node/runtime/rsc/ReplayableStream.mjs +1 -1
- 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 +56 -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/slotUsageSanitizer.mjs +1 -0
- package/dist/esm-node/runtime/rsc/treeGetter.mjs +35 -0
- package/dist/esm-node/runtime/shared/isAbsoluteUrl.mjs +10 -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/state.mjs +1 -1
- 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 +12 -0
- package/dist/types/cli/tanstackTypes.d.ts +3 -31
- package/dist/types/runtime/blockingSubscribe.d.ts +1 -0
- package/dist/types/runtime/clientBasepath.d.ts +1 -0
- package/dist/types/runtime/clientHydration.d.ts +10 -0
- package/dist/types/runtime/dataMutation.d.ts +3 -12
- package/dist/types/runtime/formData.d.ts +24 -0
- package/dist/types/runtime/loaderBridge.d.ts +2 -1
- 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 +38 -0
- package/dist/types/runtime/register.d.ts +10 -9
- 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 +76 -0
- package/dist/types/runtime/routeTree.d.ts +1 -9
- package/dist/types/runtime/router.d.ts +6 -7
- package/dist/types/runtime/rsc/CompositeComponent.d.ts +1 -2
- package/dist/types/runtime/rsc/ReplayableStream.d.ts +3 -2
- package/dist/types/runtime/rsc/RscNodeRenderer.d.ts +2 -3
- package/dist/types/runtime/rsc/SlotContext.d.ts +2 -1
- 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 +8 -0
- package/dist/types/runtime/rsc/payloadRouter.d.ts +2 -10
- package/dist/types/runtime/rsc/payloadRoutes.d.ts +40 -0
- package/dist/types/runtime/rsc/payloadStorage.d.ts +5 -0
- package/dist/types/runtime/rsc/shared.d.ts +18 -0
- package/dist/types/runtime/rsc/treeGetter.d.ts +1 -0
- package/dist/types/runtime/shared/isAbsoluteUrl.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 +44 -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 -10
- package/dist/types/runtime/utils.d.ts +4 -24
- package/package.json +37 -17
- package/rstest.config.mts +23 -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 +113 -0
- package/src/cli/tanstackTypes/source.ts +414 -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 +149 -0
- package/src/runtime/dataMutation.tsx +9 -306
- package/src/runtime/formData.ts +153 -0
- package/src/runtime/loaderBridge.ts +11 -12
- 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/register.ts +10 -42
- 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/router.ts +35 -7
- package/src/runtime/rsc/CompositeComponent.tsx +29 -20
- package/src/runtime/rsc/ReplayableStream.ts +2 -2
- package/src/runtime/rsc/RscNodeRenderer.tsx +9 -27
- package/src/runtime/rsc/SlotContext.tsx +1 -1
- 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 +92 -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/slotUsageSanitizer.ts +4 -0
- package/src/runtime/rsc/treeGetter.tsx +52 -0
- package/src/runtime/shared/isAbsoluteUrl.ts +8 -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 +9 -3
- package/src/runtime/submitAction.ts +201 -0
- package/src/runtime/types.ts +4 -18
- 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/realm-isolation.test.ts +114 -0
- package/tests/router/cli.test.ts +7 -0
- package/tests/router/clientHydration.test.tsx +61 -0
- package/tests/router/dataMutation.test.tsx +59 -0
- package/tests/router/fixtures/legacyRuntimeRouter.ts +10 -0
- package/tests/router/fixtures/router-gen.golden.txt +71 -0
- package/tests/router/fixtures/router-gen.oxlint.json +5 -0
- package/tests/router/flightSerialization.roundtrip.test.tsx +137 -0
- package/tests/router/generateRouteArtifacts.test.ts +106 -0
- package/tests/router/hooks.test.ts +14 -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/register.test.ts +1 -39
- package/tests/router/routeTree.test.ts +51 -11
- package/tests/router/routerCompatibility.test.ts +245 -0
- package/tests/router/rsc.test.tsx +189 -0
- package/tests/router/rscPayloadRouterMatrix.test.ts +197 -0
- package/tests/router/slotUsageSanitizer.test.ts +23 -0
- package/tests/router/ssrPreload.test.ts +30 -0
- package/tests/router/tanstackTypes.test.ts +298 -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/tanstackTypes.ts
CHANGED
|
@@ -1,648 +1,5 @@
|
|
|
1
|
-
// @effect-diagnostics asyncFunction:off
|
|
2
|
-
import type { AppToolsContext } from '@modern-js/app-tools';
|
|
3
|
-
import { getPathWithoutExt, makeLegalIdentifier } 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';
|
|
1
|
+
// @effect-diagnostics asyncFunction:off strictBooleanExpressions:off
|
|
7
2
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
'.ts',
|
|
12
|
-
'.tsx',
|
|
13
|
-
'.mjs',
|
|
14
|
-
'.mts',
|
|
15
|
-
'.cjs',
|
|
16
|
-
'.cts',
|
|
17
|
-
] as const;
|
|
18
|
-
|
|
19
|
-
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
|
-
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
|
-
function quote(str: string) {
|
|
47
|
-
return JSON.stringify(str);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function normalizeRelativeImport(p: string) {
|
|
51
|
-
const normalized = formatImportPath(slash(p));
|
|
52
|
-
if (normalized.startsWith('.')) {
|
|
53
|
-
return normalized;
|
|
54
|
-
}
|
|
55
|
-
return `./${normalized}`;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
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
|
-
function pickRouteSearchContractModules(route: NestedRouteForCli | PageRoute) {
|
|
69
|
-
const validateSearchPath = (route as any).validateSearch;
|
|
70
|
-
const loaderDepsPath = (route as any).loaderDeps;
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
validateSearchPath:
|
|
74
|
-
typeof validateSearchPath === 'string' ? validateSearchPath : null,
|
|
75
|
-
loaderDepsPath: typeof loaderDepsPath === 'string' ? loaderDepsPath : null,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function isPathlessLayout(route: NestedRouteForCli | PageRoute) {
|
|
80
|
-
return (
|
|
81
|
-
(route as any).type === 'nested' &&
|
|
82
|
-
typeof (route as any).index !== 'boolean' &&
|
|
83
|
-
typeof (route as any).path === 'undefined'
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function isIndexRoute(route: NestedRouteForCli | PageRoute) {
|
|
88
|
-
return (route as any).type === 'nested' && Boolean((route as any).index);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function createRouteStaticDataSnippet(opts: {
|
|
92
|
-
modernRouteId?: string;
|
|
93
|
-
loaderName?: string | null;
|
|
94
|
-
actionName?: string | null;
|
|
95
|
-
}) {
|
|
96
|
-
const staticDataLines: string[] = [];
|
|
97
|
-
|
|
98
|
-
if (opts.modernRouteId) {
|
|
99
|
-
staticDataLines.push(`modernRouteId: ${quote(opts.modernRouteId)},`);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (opts.loaderName) {
|
|
103
|
-
staticDataLines.push(`modernRouteLoader: ${opts.loaderName},`);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (opts.actionName) {
|
|
107
|
-
staticDataLines.push(`modernRouteAction: ${opts.actionName},`);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (!staticDataLines.length) {
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return `staticData: createRouteStaticData({\n ${staticDataLines.join(
|
|
115
|
-
'\n ',
|
|
116
|
-
)}\n }),`;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const LOCALE_PARAM_SEGMENTS = new Set([
|
|
120
|
-
':lang',
|
|
121
|
-
':locale',
|
|
122
|
-
':language',
|
|
123
|
-
'$lang',
|
|
124
|
-
'$locale',
|
|
125
|
-
'$language',
|
|
126
|
-
]);
|
|
127
|
-
|
|
128
|
-
type CanonicalAwareRoute = (NestedRouteForCli | PageRoute) & {
|
|
129
|
-
modernCanonicalPath?: string;
|
|
130
|
-
index?: boolean;
|
|
131
|
-
isRoot?: boolean;
|
|
132
|
-
children?: CanonicalAwareRoute[];
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
function paramsTypeForCanonicalPath(canonicalPath: string): string {
|
|
136
|
-
const fields: string[] = [];
|
|
137
|
-
|
|
138
|
-
for (const segment of canonicalPath.split('/')) {
|
|
139
|
-
if (!segment) {
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
if (segment === '*' || segment === '$') {
|
|
143
|
-
fields.push(`'_splat'?: string`);
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
if (segment.startsWith('{-$') && segment.endsWith('}')) {
|
|
147
|
-
fields.push(`${JSON.stringify(segment.slice(3, -1))}?: string`);
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
if (segment.startsWith('$')) {
|
|
151
|
-
fields.push(`${JSON.stringify(segment.slice(1))}: string`);
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
if (segment.startsWith(':')) {
|
|
155
|
-
const optional = segment.endsWith('?');
|
|
156
|
-
const name = segment.slice(1, optional ? undefined : segment.length);
|
|
157
|
-
fields.push(
|
|
158
|
-
`${JSON.stringify(optional ? name.slice(0, -1) : name)}${
|
|
159
|
-
optional ? '?' : ''
|
|
160
|
-
}: string`,
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return fields.length > 0
|
|
166
|
-
? `{ ${fields.join('; ')} }`
|
|
167
|
-
: 'Record<string, never>';
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export type CollectCanonicalRoutesOptions = {
|
|
171
|
-
/**
|
|
172
|
-
* Whether a leading `:lang`/`:locale`/`:language` route param may be
|
|
173
|
-
* treated as an i18n locale prefix. This MUST only be enabled when
|
|
174
|
-
* `@modern-js/plugin-i18n` is actually installed: the emitted
|
|
175
|
-
* `declare module '@modern-js/plugin-i18n/runtime'` augmentation breaks
|
|
176
|
-
* typechecking (TS2664) for apps that hand-roll a `/:lang/` param without
|
|
177
|
-
* the plugin. Routes carrying `modernCanonicalPath` metadata are always
|
|
178
|
-
* honored — only plugin-i18n produces them.
|
|
179
|
-
*/
|
|
180
|
-
localeParamHeuristic?: boolean;
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Derive the canonical (language-agnostic) route map for an entry: the
|
|
185
|
-
* leading locale param is stripped and localized physical variants (routes
|
|
186
|
-
* carrying `modernCanonicalPath` metadata from `@modern-js/plugin-i18n`)
|
|
187
|
-
* collapse to their canonical pattern. Returns `null` when the entry has no
|
|
188
|
-
* i18n routing surface (no locale param and no localized variants), so plain
|
|
189
|
-
* TanStack apps never get a `@modern-js/plugin-i18n` module augmentation.
|
|
190
|
-
*/
|
|
191
|
-
export function collectCanonicalRoutesForEntry(
|
|
192
|
-
routes: (NestedRouteForCli | PageRoute)[],
|
|
193
|
-
options: CollectCanonicalRoutesOptions = {},
|
|
194
|
-
): Record<string, string> | null {
|
|
195
|
-
const { localeParamHeuristic = true } = options;
|
|
196
|
-
const canonicalParams = new Map<string, string>();
|
|
197
|
-
let hasI18nSurface = false;
|
|
198
|
-
|
|
199
|
-
const normalizeJoined = (joined: string): string => {
|
|
200
|
-
const collapsed = joined.replace(/\/+/g, '/');
|
|
201
|
-
const withLeading = collapsed.startsWith('/') ? collapsed : `/${collapsed}`;
|
|
202
|
-
return withLeading.length > 1
|
|
203
|
-
? withLeading.replace(/\/+$/, '')
|
|
204
|
-
: withLeading;
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const record = (canonicalPath: string) => {
|
|
208
|
-
const normalized = normalizeJoined(canonicalPath || '/');
|
|
209
|
-
const key = toTanstackPath(normalized);
|
|
210
|
-
if (!canonicalParams.has(key)) {
|
|
211
|
-
canonicalParams.set(key, paramsTypeForCanonicalPath(normalized));
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
const visit = (route: CanonicalAwareRoute, parentPath: string) => {
|
|
216
|
-
let currentPath = parentPath;
|
|
217
|
-
|
|
218
|
-
if (typeof route.modernCanonicalPath === 'string') {
|
|
219
|
-
hasI18nSurface = true;
|
|
220
|
-
currentPath = normalizeJoined(route.modernCanonicalPath);
|
|
221
|
-
} else if (typeof route.path === 'string' && route.path.length > 0) {
|
|
222
|
-
const segments = route.path
|
|
223
|
-
.replace(/\[(.+?)\]/g, ':$1')
|
|
224
|
-
.split('/')
|
|
225
|
-
.filter(Boolean);
|
|
226
|
-
if (
|
|
227
|
-
localeParamHeuristic &&
|
|
228
|
-
parentPath === '' &&
|
|
229
|
-
LOCALE_PARAM_SEGMENTS.has(segments[0])
|
|
230
|
-
) {
|
|
231
|
-
hasI18nSurface = true;
|
|
232
|
-
segments.shift();
|
|
233
|
-
}
|
|
234
|
-
currentPath = segments.length
|
|
235
|
-
? normalizeJoined(`${parentPath}/${segments.join('/')}`)
|
|
236
|
-
: parentPath;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const children = route.children;
|
|
240
|
-
if (children && children.length > 0) {
|
|
241
|
-
for (const child of children) {
|
|
242
|
-
visit(child, currentPath);
|
|
243
|
-
}
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Leaf page or index route: a navigable target.
|
|
248
|
-
record(currentPath || '/');
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
const rootModern = routes.find(
|
|
252
|
-
route => (route as CanonicalAwareRoute).isRoot,
|
|
253
|
-
) as CanonicalAwareRoute | undefined;
|
|
254
|
-
const topLevel = rootModern ? (rootModern.children ?? []) : routes;
|
|
255
|
-
|
|
256
|
-
for (const route of topLevel) {
|
|
257
|
-
visit(route as CanonicalAwareRoute, '');
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (!hasI18nSurface || canonicalParams.size === 0) {
|
|
261
|
-
return null;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return Object.fromEntries(
|
|
265
|
-
[...canonicalParams.entries()].sort(([a], [b]) => a.localeCompare(b)),
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
export async function generateTanstackRouterTypesSourceForEntry(opts: {
|
|
270
|
-
appContext: AppToolsContext;
|
|
271
|
-
entryName: string;
|
|
272
|
-
generatedDirName?: string;
|
|
273
|
-
routes: (NestedRouteForCli | PageRoute)[];
|
|
274
|
-
}): Promise<{
|
|
275
|
-
routerGenTs: string;
|
|
276
|
-
}> {
|
|
277
|
-
const {
|
|
278
|
-
appContext,
|
|
279
|
-
entryName,
|
|
280
|
-
generatedDirName = 'modern-tanstack',
|
|
281
|
-
routes,
|
|
282
|
-
} = opts;
|
|
283
|
-
const outDir = path.join(
|
|
284
|
-
appContext.srcDirectory,
|
|
285
|
-
generatedDirName,
|
|
286
|
-
entryName,
|
|
287
|
-
);
|
|
288
|
-
|
|
289
|
-
const rootModern = routes.find(
|
|
290
|
-
r => r && (r as any).type === 'nested' && (r as any).isRoot,
|
|
291
|
-
) as NestedRouteForCli | undefined;
|
|
292
|
-
|
|
293
|
-
const topLevel = rootModern
|
|
294
|
-
? ((rootModern as any).children as Array<NestedRouteForCli | PageRoute>) ||
|
|
295
|
-
[]
|
|
296
|
-
: routes;
|
|
297
|
-
|
|
298
|
-
const imports: string[] = [];
|
|
299
|
-
const statements: string[] = [];
|
|
300
|
-
|
|
301
|
-
const loaderImportMap = new Map<string, string>();
|
|
302
|
-
const componentImportMap = new Map<string, Promise<string | null>>();
|
|
303
|
-
const searchContractImportMap = new Map<string, string>();
|
|
304
|
-
const usedRouteVarNames = new Set<string>();
|
|
305
|
-
let loaderIndex = 0;
|
|
306
|
-
let componentIndex = 0;
|
|
307
|
-
let validateSearchIndex = 0;
|
|
308
|
-
let loaderDepsIndex = 0;
|
|
309
|
-
let routeIndex = 0;
|
|
310
|
-
|
|
311
|
-
const getImportNameForComponent = (
|
|
312
|
-
componentPath: unknown,
|
|
313
|
-
): Promise<string | null> => {
|
|
314
|
-
if (typeof componentPath !== 'string' || componentPath.length === 0) {
|
|
315
|
-
return Promise.resolve(null);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Cache the in-flight promise: sibling routes sharing a component module
|
|
319
|
-
// are generated concurrently and must reuse one import.
|
|
320
|
-
let pendingImportName = componentImportMap.get(componentPath);
|
|
321
|
-
if (!pendingImportName) {
|
|
322
|
-
pendingImportName = (async () => {
|
|
323
|
-
// Resolve through the same machinery as loaders: the raw `_component`
|
|
324
|
-
// value carries the internal `@_modern_js_src` alias, which the app's
|
|
325
|
-
// tsconfig does not map — the generated file must use relative
|
|
326
|
-
// imports.
|
|
327
|
-
const resolvedNoExt = await resolveRouteModuleNoExt(componentPath);
|
|
328
|
-
if (!resolvedNoExt) {
|
|
329
|
-
return null;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
const relImport = normalizeRelativeImport(
|
|
333
|
-
path.relative(outDir, resolvedNoExt),
|
|
334
|
-
);
|
|
335
|
-
|
|
336
|
-
const componentName = `component_${componentIndex++}`;
|
|
337
|
-
imports.push(`import ${componentName} from ${quote(relImport)};`);
|
|
338
|
-
return componentName;
|
|
339
|
-
})();
|
|
340
|
-
componentImportMap.set(componentPath, pendingImportName);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
return pendingImportName;
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
const resolveRouteModuleNoExt = async (aliasedNoExtPath: string) => {
|
|
347
|
-
const prefix = `${appContext.internalSrcAlias}/`;
|
|
348
|
-
let absNoExt: string;
|
|
349
|
-
if (aliasedNoExtPath.startsWith(prefix)) {
|
|
350
|
-
const rel = aliasedNoExtPath.slice(prefix.length);
|
|
351
|
-
absNoExt = path.join(appContext.srcDirectory, rel);
|
|
352
|
-
} else if (path.isAbsolute(aliasedNoExtPath)) {
|
|
353
|
-
absNoExt = aliasedNoExtPath;
|
|
354
|
-
} else {
|
|
355
|
-
// Unknown format; treat as already relative to src.
|
|
356
|
-
absNoExt = path.join(appContext.srcDirectory, aliasedNoExtPath);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
return resolveFileNoExt(absNoExt);
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
const getImportNamesForLoader = async (
|
|
363
|
-
aliasedNoExtPath: string,
|
|
364
|
-
inline: boolean,
|
|
365
|
-
hasAction: boolean,
|
|
366
|
-
) => {
|
|
367
|
-
const key = `${
|
|
368
|
-
inline ? 'inline' : 'default'
|
|
369
|
-
}:${hasAction ? 'action' : 'loader'}:${aliasedNoExtPath}`;
|
|
370
|
-
const existing = loaderImportMap.get(key);
|
|
371
|
-
if (existing) {
|
|
372
|
-
return {
|
|
373
|
-
loaderName: existing,
|
|
374
|
-
actionName: hasAction ? existing.replace(/^loader_/, 'action_') : null,
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
const resolvedNoExt = await resolveRouteModuleNoExt(aliasedNoExtPath);
|
|
379
|
-
if (!resolvedNoExt) {
|
|
380
|
-
return null;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
const relImport = normalizeRelativeImport(
|
|
384
|
-
path.relative(outDir, resolvedNoExt),
|
|
385
|
-
);
|
|
386
|
-
|
|
387
|
-
const importName = `loader_${loaderIndex++}`;
|
|
388
|
-
const actionName = hasAction
|
|
389
|
-
? importName.replace(/^loader_/, 'action_')
|
|
390
|
-
: null;
|
|
391
|
-
if (inline) {
|
|
392
|
-
const specifiers = [`loader as ${importName}`];
|
|
393
|
-
if (actionName) {
|
|
394
|
-
specifiers.push(`action as ${actionName}`);
|
|
395
|
-
}
|
|
396
|
-
imports.push(
|
|
397
|
-
`import { ${specifiers.join(', ')} } from ${quote(relImport)};`,
|
|
398
|
-
);
|
|
399
|
-
} else {
|
|
400
|
-
imports.push(`import ${importName} from ${quote(relImport)};`);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
loaderImportMap.set(key, importName);
|
|
404
|
-
return { loaderName: importName, actionName };
|
|
405
|
-
};
|
|
406
|
-
|
|
407
|
-
const getImportNameForSearchContract = async (
|
|
408
|
-
aliasedNoExtPath: string,
|
|
409
|
-
exportName: 'validateSearch' | 'loaderDeps',
|
|
410
|
-
) => {
|
|
411
|
-
const key = `${exportName}:${aliasedNoExtPath}`;
|
|
412
|
-
const existing = searchContractImportMap.get(key);
|
|
413
|
-
if (existing) {
|
|
414
|
-
return existing;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
const resolvedNoExt = await resolveRouteModuleNoExt(aliasedNoExtPath);
|
|
418
|
-
if (!resolvedNoExt) {
|
|
419
|
-
return null;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
const relImport = normalizeRelativeImport(
|
|
423
|
-
path.relative(outDir, resolvedNoExt),
|
|
424
|
-
);
|
|
425
|
-
const importName =
|
|
426
|
-
exportName === 'validateSearch'
|
|
427
|
-
? `validateSearch_${validateSearchIndex++}`
|
|
428
|
-
: `loaderDeps_${loaderDepsIndex++}`;
|
|
429
|
-
imports.push(
|
|
430
|
-
`import { ${exportName} as ${importName} } from ${quote(relImport)};`,
|
|
431
|
-
);
|
|
432
|
-
searchContractImportMap.set(key, importName);
|
|
433
|
-
return importName;
|
|
434
|
-
};
|
|
435
|
-
|
|
436
|
-
const reserveRouteVarName = (preferred: string) => {
|
|
437
|
-
let candidate = preferred;
|
|
438
|
-
let suffix = 1;
|
|
439
|
-
while (usedRouteVarNames.has(candidate)) {
|
|
440
|
-
candidate = `${preferred}_${suffix++}`;
|
|
441
|
-
}
|
|
442
|
-
usedRouteVarNames.add(candidate);
|
|
443
|
-
return candidate;
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
const createRouteVarName = (route: NestedRouteForCli | PageRoute) => {
|
|
447
|
-
const id = (route as any).id as string | undefined;
|
|
448
|
-
const base = id ? makeLegalIdentifier(id) : `r_${routeIndex++}`;
|
|
449
|
-
return reserveRouteVarName(`route_${base}`);
|
|
450
|
-
};
|
|
451
|
-
|
|
452
|
-
const buildRoute = async (opts: {
|
|
453
|
-
parentVar: string;
|
|
454
|
-
route: NestedRouteForCli | PageRoute;
|
|
455
|
-
}): Promise<string> => {
|
|
456
|
-
const { parentVar, route } = opts;
|
|
457
|
-
|
|
458
|
-
const varName = createRouteVarName(route);
|
|
459
|
-
|
|
460
|
-
const loaderInfo = pickModernLoaderModule(route);
|
|
461
|
-
const routeAction = (route as any).action;
|
|
462
|
-
const loaderImports = loaderInfo
|
|
463
|
-
? await getImportNamesForLoader(
|
|
464
|
-
loaderInfo.loaderPath,
|
|
465
|
-
loaderInfo.inline,
|
|
466
|
-
Boolean(loaderInfo.inline && routeAction === loaderInfo.loaderPath),
|
|
467
|
-
)
|
|
468
|
-
: null;
|
|
469
|
-
const loaderName = loaderImports?.loaderName || null;
|
|
470
|
-
const actionName = loaderImports?.actionName || null;
|
|
471
|
-
const searchContractInfo = pickRouteSearchContractModules(route);
|
|
472
|
-
const validateSearchName = searchContractInfo.validateSearchPath
|
|
473
|
-
? await getImportNameForSearchContract(
|
|
474
|
-
searchContractInfo.validateSearchPath,
|
|
475
|
-
'validateSearch',
|
|
476
|
-
)
|
|
477
|
-
: null;
|
|
478
|
-
const loaderDepsName = searchContractInfo.loaderDepsPath
|
|
479
|
-
? await getImportNameForSearchContract(
|
|
480
|
-
searchContractInfo.loaderDepsPath,
|
|
481
|
-
'loaderDeps',
|
|
482
|
-
)
|
|
483
|
-
: null;
|
|
484
|
-
|
|
485
|
-
const rawPath = (route as any).path as string | undefined;
|
|
486
|
-
const hasSplat = typeof rawPath === 'string' && rawPath.includes('*');
|
|
487
|
-
|
|
488
|
-
const routeOpts: string[] = [`getParentRoute: () => ${parentVar},`];
|
|
489
|
-
|
|
490
|
-
const componentName = await getImportNameForComponent(
|
|
491
|
-
(route as any)._component,
|
|
492
|
-
);
|
|
493
|
-
if (componentName) {
|
|
494
|
-
routeOpts.push(`component: ${componentName},`);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
if (isPathlessLayout(route)) {
|
|
498
|
-
const id = (route as any).id as string | undefined;
|
|
499
|
-
routeOpts.push(`id: ${quote(id || 'pathless')},`);
|
|
500
|
-
} else {
|
|
501
|
-
const p = isIndexRoute(route) ? '/' : toTanstackPath(rawPath || '');
|
|
502
|
-
routeOpts.push(`path: ${quote(p)},`);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
if (loaderName) {
|
|
506
|
-
routeOpts.push(
|
|
507
|
-
`loader: modernLoaderToTanstack({ hasSplat: ${hasSplat} }, ${loaderName}),`,
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
if (validateSearchName) {
|
|
511
|
-
routeOpts.push(`validateSearch: ${validateSearchName},`);
|
|
512
|
-
}
|
|
513
|
-
if (loaderDepsName) {
|
|
514
|
-
routeOpts.push(`loaderDeps: ${loaderDepsName},`);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
const staticDataSnippet = createRouteStaticDataSnippet({
|
|
518
|
-
modernRouteId: (route as any).id as string | undefined,
|
|
519
|
-
loaderName,
|
|
520
|
-
actionName,
|
|
521
|
-
});
|
|
522
|
-
if (staticDataSnippet) {
|
|
523
|
-
routeOpts.push(staticDataSnippet);
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
const children = (route as any).children as
|
|
527
|
-
| Array<NestedRouteForCli | PageRoute>
|
|
528
|
-
| undefined;
|
|
529
|
-
const hasChildren = Boolean(children && children.length > 0);
|
|
530
|
-
const routeCtorVarName = hasChildren
|
|
531
|
-
? reserveRouteVarName(`${varName}__base`)
|
|
532
|
-
: varName;
|
|
533
|
-
|
|
534
|
-
statements.push(
|
|
535
|
-
`const ${routeCtorVarName} = createRoute({\n ${routeOpts.join('\n ')}\n});`,
|
|
536
|
-
);
|
|
537
|
-
|
|
538
|
-
if (children && children.length > 0) {
|
|
539
|
-
const childVars = await Promise.all(
|
|
540
|
-
children.map(child =>
|
|
541
|
-
buildRoute({ parentVar: routeCtorVarName, route: child }),
|
|
542
|
-
),
|
|
543
|
-
);
|
|
544
|
-
statements.push(
|
|
545
|
-
`const ${varName} = ${routeCtorVarName}.addChildren([${childVars.join(', ')}]);`,
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
return varName;
|
|
550
|
-
};
|
|
551
|
-
|
|
552
|
-
const rootLoaderInfo = rootModern ? pickModernLoaderModule(rootModern) : null;
|
|
553
|
-
const rootAction = (rootModern as any)?.action;
|
|
554
|
-
const rootLoaderImports = rootLoaderInfo?.loaderPath
|
|
555
|
-
? await getImportNamesForLoader(
|
|
556
|
-
rootLoaderInfo.loaderPath,
|
|
557
|
-
rootLoaderInfo.inline,
|
|
558
|
-
Boolean(
|
|
559
|
-
rootLoaderInfo.inline && rootAction === rootLoaderInfo.loaderPath,
|
|
560
|
-
),
|
|
561
|
-
)
|
|
562
|
-
: null;
|
|
563
|
-
const rootLoaderName = rootLoaderImports?.loaderName || null;
|
|
564
|
-
const rootActionName = rootLoaderImports?.actionName || null;
|
|
565
|
-
const rootSearchContractInfo = rootModern
|
|
566
|
-
? pickRouteSearchContractModules(rootModern)
|
|
567
|
-
: null;
|
|
568
|
-
const rootValidateSearchName = rootSearchContractInfo?.validateSearchPath
|
|
569
|
-
? await getImportNameForSearchContract(
|
|
570
|
-
rootSearchContractInfo.validateSearchPath,
|
|
571
|
-
'validateSearch',
|
|
572
|
-
)
|
|
573
|
-
: null;
|
|
574
|
-
const rootLoaderDepsName = rootSearchContractInfo?.loaderDepsPath
|
|
575
|
-
? await getImportNameForSearchContract(
|
|
576
|
-
rootSearchContractInfo.loaderDepsPath,
|
|
577
|
-
'loaderDeps',
|
|
578
|
-
)
|
|
579
|
-
: null;
|
|
580
|
-
|
|
581
|
-
const topLevelVars = await Promise.all(
|
|
582
|
-
topLevel.map(route => buildRoute({ parentVar: 'rootRoute', route })),
|
|
583
|
-
);
|
|
584
|
-
|
|
585
|
-
const rootOpts: string[] = [];
|
|
586
|
-
|
|
587
|
-
const rootComponentName = await getImportNameForComponent(
|
|
588
|
-
(rootModern as any)?._component,
|
|
589
|
-
);
|
|
590
|
-
if (rootComponentName) {
|
|
591
|
-
rootOpts.push(`component: ${rootComponentName},`);
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
if (rootLoaderName) {
|
|
595
|
-
rootOpts.push(
|
|
596
|
-
`loader: modernLoaderToTanstack({ hasSplat: false }, ${rootLoaderName}),`,
|
|
597
|
-
);
|
|
598
|
-
}
|
|
599
|
-
if (rootValidateSearchName) {
|
|
600
|
-
rootOpts.push(`validateSearch: ${rootValidateSearchName},`);
|
|
601
|
-
}
|
|
602
|
-
if (rootLoaderDepsName) {
|
|
603
|
-
rootOpts.push(`loaderDeps: ${rootLoaderDepsName},`);
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
const routerGenTs = `/* eslint-disable */
|
|
607
|
-
// This file is auto-generated by Modern.js. Do not edit manually.
|
|
608
|
-
|
|
609
|
-
import {
|
|
610
|
-
createMemoryHistory,
|
|
611
|
-
createRootRouteWithContext,
|
|
612
|
-
createRoute,
|
|
613
|
-
createRouter,
|
|
614
|
-
createRouteStaticData,
|
|
615
|
-
type ModernRouterContext,
|
|
616
|
-
modernLoaderToTanstack,
|
|
617
|
-
modernTanstackRouterFastDefaults,
|
|
618
|
-
} from '@modern-js/plugin-tanstack/runtime';
|
|
619
|
-
|
|
620
|
-
${imports.join('\n')}
|
|
621
|
-
|
|
622
|
-
export const rootRoute = createRootRouteWithContext<ModernRouterContext>()({
|
|
623
|
-
${rootOpts.join('\n ')}
|
|
624
|
-
${
|
|
625
|
-
createRouteStaticDataSnippet({
|
|
626
|
-
modernRouteId: (rootModern as any)?.id as string | undefined,
|
|
627
|
-
loaderName: rootLoaderName,
|
|
628
|
-
actionName: rootActionName,
|
|
629
|
-
}) || ''
|
|
630
|
-
}
|
|
631
|
-
});
|
|
632
|
-
|
|
633
|
-
${statements.join('\n\n')}
|
|
634
|
-
|
|
635
|
-
export const routeTree = rootRoute.addChildren([${topLevelVars.join(', ')}]);
|
|
636
|
-
|
|
637
|
-
export const router = createRouter({
|
|
638
|
-
...modernTanstackRouterFastDefaults,
|
|
639
|
-
routeTree,
|
|
640
|
-
history: createMemoryHistory({
|
|
641
|
-
initialEntries: ['/'],
|
|
642
|
-
}),
|
|
643
|
-
context: {} as ModernRouterContext,
|
|
644
|
-
});
|
|
645
|
-
`;
|
|
646
|
-
|
|
647
|
-
return { routerGenTs };
|
|
648
|
-
}
|
|
3
|
+
export type { CollectCanonicalRoutesOptions } from './tanstackTypes/canonicalRoutes';
|
|
4
|
+
export { collectCanonicalRoutesForEntry } from './tanstackTypes/canonicalRoutes';
|
|
5
|
+
export { generateTanstackRouterTypesSourceForEntry } from './tanstackTypes/source';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// @effect-diagnostics strictBooleanExpressions:off
|
|
2
|
+
|
|
3
|
+
const BLOCKING_SUBSCRIBE_SYMBOL = Symbol.for(
|
|
4
|
+
'@modern-js/plugin-tanstack:blocking-subscribe',
|
|
5
|
+
);
|
|
6
|
+
const BLOCKING_STATE_SYMBOL = Symbol.for(
|
|
7
|
+
'@modern-js/plugin-tanstack:blocking-state',
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
type TanstackRouterWithSubscribe = {
|
|
11
|
+
[BLOCKING_STATE_SYMBOL]?: () => boolean;
|
|
12
|
+
[BLOCKING_SUBSCRIBE_SYMBOL]?: boolean;
|
|
13
|
+
subscribe?: (
|
|
14
|
+
eventType: string,
|
|
15
|
+
listener: (...args: unknown[]) => void,
|
|
16
|
+
) => () => void;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export function wrapRouterSubscribeWithBlockState(
|
|
20
|
+
router: unknown,
|
|
21
|
+
getBlockNavState?: () => boolean,
|
|
22
|
+
) {
|
|
23
|
+
if (!router || typeof router !== 'object') {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const target = router as TanstackRouterWithSubscribe;
|
|
28
|
+
target[BLOCKING_STATE_SYMBOL] = getBlockNavState;
|
|
29
|
+
if (
|
|
30
|
+
target[BLOCKING_SUBSCRIBE_SYMBOL] ||
|
|
31
|
+
typeof target.subscribe !== 'function'
|
|
32
|
+
) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const originSubscribe = target.subscribe.bind(target);
|
|
37
|
+
target.subscribe = (eventType, listener) => {
|
|
38
|
+
const wrappedListener = (...args: unknown[]) => {
|
|
39
|
+
const blockRoute = target[BLOCKING_STATE_SYMBOL]?.() || false;
|
|
40
|
+
if (blockRoute) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
return listener(...args);
|
|
44
|
+
};
|
|
45
|
+
return originSubscribe(eventType, wrappedListener);
|
|
46
|
+
};
|
|
47
|
+
target[BLOCKING_SUBSCRIBE_SYMBOL] = true;
|
|
48
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
function normalizeBase(b: string) {
|
|
2
|
+
if (b.length > 1 && b.endsWith('/')) {
|
|
3
|
+
return b.slice(0, -1);
|
|
4
|
+
}
|
|
5
|
+
return b || '/';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function isSegmentPrefix(pathname: string, base: string) {
|
|
9
|
+
const b = normalizeBase(base);
|
|
10
|
+
const p = pathname || '/';
|
|
11
|
+
return p === b || p.startsWith(`${b}/`);
|
|
12
|
+
}
|