@bleedingdev/modern-js-plugin-tanstack 3.2.0-ultramodern.99 → 3.4.0-ultramodern.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/cli/index.js +80 -34
- package/dist/cjs/cli/routeSplitting.js +13 -41
- package/dist/cjs/cli/tanstackTypes.js +114 -200
- package/dist/cjs/cli.js +12 -8
- package/dist/cjs/runtime/basepathRewrite.js +12 -8
- package/dist/cjs/runtime/dataMutation.js +9 -5
- package/dist/cjs/runtime/hooks.js +20 -19
- package/dist/cjs/runtime/hydrationBoundary.js +12 -7
- package/dist/cjs/runtime/index.js +66 -54
- package/dist/cjs/runtime/lifecycle.js +21 -91
- package/dist/cjs/runtime/loaderBridge.js +173 -0
- package/dist/cjs/runtime/outlet.js +58 -0
- package/dist/cjs/runtime/plugin.js +190 -110
- package/dist/cjs/runtime/plugin.node.js +25 -40
- package/dist/cjs/runtime/plugin.worker.js +9 -5
- package/dist/cjs/runtime/pluginCore.js +55 -0
- package/dist/cjs/runtime/prefetchLink.js +10 -6
- package/dist/cjs/runtime/register.js +56 -0
- package/dist/cjs/runtime/routeTree.js +30 -212
- package/dist/cjs/runtime/router.js +41 -0
- package/dist/cjs/runtime/rsc/ClientSlot.js +9 -5
- package/dist/cjs/runtime/rsc/CompositeComponent.js +9 -5
- package/dist/cjs/runtime/rsc/ReplayableStream.js +14 -9
- package/dist/cjs/runtime/rsc/RscNodeRenderer.js +9 -5
- package/dist/cjs/runtime/rsc/SlotContext.js +9 -5
- package/dist/cjs/runtime/rsc/client.js +9 -5
- package/dist/cjs/runtime/rsc/createRscProxy.js +9 -5
- package/dist/cjs/runtime/rsc/index.js +9 -5
- package/dist/cjs/runtime/rsc/payloadRouter.js +44 -6
- package/dist/cjs/runtime/rsc/server.js +9 -5
- package/dist/cjs/runtime/rsc/slotUsageSanitizer.js +9 -5
- package/dist/cjs/runtime/rsc/symbols.js +20 -15
- package/dist/cjs/runtime/state.js +45 -0
- package/dist/cjs/runtime/types.js +13 -9
- package/dist/cjs/runtime/utils.js +9 -11
- package/dist/cjs/runtime.js +9 -5
- package/dist/esm/cli/index.mjs +73 -28
- package/dist/esm/cli/routeSplitting.mjs +1 -30
- package/dist/esm/cli/tanstackTypes.mjs +100 -190
- package/dist/esm/runtime/hooks.mjs +1 -8
- package/dist/esm/runtime/hydrationBoundary.mjs +3 -2
- package/dist/esm/runtime/index.mjs +4 -2
- package/dist/esm/runtime/lifecycle.mjs +1 -82
- package/dist/esm/runtime/loaderBridge.mjs +114 -0
- package/dist/esm/runtime/outlet.mjs +17 -0
- package/dist/esm/runtime/plugin.mjs +183 -107
- package/dist/esm/runtime/plugin.node.mjs +19 -38
- package/dist/esm/runtime/pluginCore.mjs +14 -0
- package/dist/esm/runtime/prefetchLink.mjs +1 -1
- package/dist/esm/runtime/register.mjs +18 -0
- package/dist/esm/runtime/routeTree.mjs +15 -198
- package/dist/esm/runtime/router.mjs +2 -0
- package/dist/esm/runtime/rsc/payloadRouter.mjs +35 -1
- package/dist/esm/runtime/state.mjs +7 -0
- package/dist/esm/runtime/utils.mjs +0 -6
- package/dist/esm-node/cli/index.mjs +73 -28
- package/dist/esm-node/cli/routeSplitting.mjs +1 -30
- package/dist/esm-node/cli/tanstackTypes.mjs +100 -190
- package/dist/esm-node/runtime/hooks.mjs +1 -8
- package/dist/esm-node/runtime/hydrationBoundary.mjs +3 -2
- package/dist/esm-node/runtime/index.mjs +4 -2
- package/dist/esm-node/runtime/lifecycle.mjs +1 -82
- package/dist/esm-node/runtime/loaderBridge.mjs +115 -0
- package/dist/esm-node/runtime/outlet.mjs +18 -0
- package/dist/esm-node/runtime/plugin.mjs +183 -107
- package/dist/esm-node/runtime/plugin.node.mjs +19 -38
- package/dist/esm-node/runtime/pluginCore.mjs +15 -0
- package/dist/esm-node/runtime/prefetchLink.mjs +1 -1
- package/dist/esm-node/runtime/register.mjs +19 -0
- package/dist/esm-node/runtime/routeTree.mjs +15 -198
- package/dist/esm-node/runtime/router.mjs +3 -0
- package/dist/esm-node/runtime/rsc/payloadRouter.mjs +35 -1
- package/dist/esm-node/runtime/state.mjs +8 -0
- package/dist/esm-node/runtime/utils.mjs +0 -6
- package/dist/types/cli/index.d.ts +11 -2
- package/dist/types/cli/routeSplitting.d.ts +6 -15
- package/dist/types/cli/tanstackTypes.d.ts +21 -1
- package/dist/types/runtime/hooks.d.ts +8 -33
- package/dist/types/runtime/index.d.ts +6 -3
- package/dist/types/runtime/lifecycle.d.ts +7 -22
- package/dist/types/runtime/loaderBridge.d.ts +48 -0
- package/dist/types/runtime/outlet.d.ts +2 -0
- package/dist/types/runtime/plugin.d.ts +1 -14
- package/dist/types/runtime/plugin.node.d.ts +1 -14
- package/dist/types/runtime/pluginCore.d.ts +21 -0
- package/dist/types/runtime/register.d.ts +9 -0
- package/dist/types/runtime/routeTree.d.ts +0 -2
- package/dist/types/runtime/router.d.ts +14 -0
- package/dist/types/runtime/state.d.ts +16 -0
- package/dist/types/runtime/types.d.ts +7 -53
- package/package.json +40 -38
- package/rstest.config.mts +6 -0
- package/src/cli/index.ts +146 -24
- package/src/cli/routeSplitting.ts +6 -44
- package/src/cli/tanstackTypes.ts +203 -208
- package/src/runtime/hooks.ts +10 -27
- package/src/runtime/hydrationBoundary.tsx +5 -5
- package/src/runtime/index.tsx +12 -14
- package/src/runtime/lifecycle.ts +16 -151
- package/src/runtime/loaderBridge.ts +257 -0
- package/src/runtime/outlet.tsx +48 -0
- package/src/runtime/plugin.node.tsx +28 -83
- package/src/runtime/plugin.tsx +350 -202
- package/src/runtime/pluginCore.ts +48 -0
- package/src/runtime/prefetchLink.tsx +1 -1
- package/src/runtime/register.ts +58 -0
- package/src/runtime/routeTree.ts +41 -365
- package/src/runtime/router.ts +15 -0
- package/src/runtime/rsc/payloadRouter.ts +45 -2
- package/src/runtime/ssr-shim.d.ts +1 -3
- package/src/runtime/state.ts +29 -0
- package/src/runtime/types.ts +20 -67
- package/src/runtime/utils.tsx +3 -7
- package/tests/router/cli.test.ts +373 -31
- package/tests/router/hooks.test.ts +26 -0
- package/tests/router/loaderBridge.test.ts +211 -0
- package/tests/router/packageSurface.test.ts +24 -0
- package/tests/router/prefetchLink.test.tsx +43 -7
- package/tests/router/register.test.ts +46 -0
- package/tests/router/routeTree.test.ts +176 -139
- package/tests/router/rsc.test.tsx +70 -0
- package/tests/router/tanstackTypes.test.ts +395 -7
- package/dist/cjs/runtime/DefaultNotFound.js +0 -47
- package/dist/esm/runtime/DefaultNotFound.mjs +0 -13
- package/dist/esm-node/runtime/DefaultNotFound.mjs +0 -14
- package/dist/types/runtime/DefaultNotFound.d.ts +0 -2
- package/src/runtime/DefaultNotFound.tsx +0 -15
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { InternalRuntimeContext, getGlobalEnableRsc
|
|
4
|
-
import { merge } from "@modern-js/runtime-utils/merge";
|
|
3
|
+
import { InternalRuntimeContext, getGlobalEnableRsc } from "@modern-js/runtime/context";
|
|
5
4
|
import { normalizePathname } from "@modern-js/runtime-utils/url";
|
|
6
5
|
import { RouterProvider, createBrowserHistory, createHashHistory, createRouter, useLocation, useMatches, useNavigate, useRouter } from "@tanstack/react-router";
|
|
7
|
-
import { RouterClient } from "@tanstack/react-router/ssr/client";
|
|
8
6
|
import { useContext, useMemo } from "react";
|
|
9
7
|
import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
|
|
10
|
-
import {
|
|
8
|
+
import { routerProviderRegistryHooks } from "./hooks.mjs";
|
|
11
9
|
import { wrapTanstackSsrHydrationBoundary } from "./hydrationBoundary.mjs";
|
|
12
10
|
import { applyRouterRuntimeState } from "./lifecycle.mjs";
|
|
11
|
+
import { withModernRouteMatchContext } from "./outlet.mjs";
|
|
12
|
+
import { getFinalRouteConfig, getMergedRouterConfig } from "./pluginCore.mjs";
|
|
13
13
|
import { Link } from "./prefetchLink.mjs";
|
|
14
14
|
import { createRouteTreeFromRouteObjects } from "./routeTree.mjs";
|
|
15
15
|
import { getTanstackRscSerializationAdapters } from "./rsc/client.mjs";
|
|
@@ -42,35 +42,178 @@ function wrapRouterSubscribeWithBlockState(router, getBlockNavState) {
|
|
|
42
42
|
};
|
|
43
43
|
target[BLOCKING_SUBSCRIBE_SYMBOL] = true;
|
|
44
44
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
const routerHydrationRecords = new WeakMap();
|
|
46
|
+
const routeModulesKey = '_routeModules';
|
|
47
|
+
function pickRouteModuleComponent(routeModule, seen = new Set()) {
|
|
48
|
+
if ('function' == typeof routeModule || routeModule && 'object' == typeof routeModule && '$$typeof' in routeModule) return routeModule;
|
|
49
|
+
if (!routeModule || 'object' != typeof routeModule) return;
|
|
50
|
+
if (seen.has(routeModule)) return;
|
|
51
|
+
seen.add(routeModule);
|
|
52
|
+
const module = routeModule;
|
|
53
|
+
for (const candidate of [
|
|
54
|
+
module.default,
|
|
55
|
+
module.Component
|
|
56
|
+
]){
|
|
57
|
+
const component = pickRouteModuleComponent(candidate, seen);
|
|
58
|
+
if (component) return component;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function getCachedRouteModule(routeId) {
|
|
62
|
+
if ("u" < typeof window) return;
|
|
63
|
+
return window[routeModulesKey]?.[routeId];
|
|
64
|
+
}
|
|
65
|
+
function preloadHydratedRouteComponents(router) {
|
|
66
|
+
const preloadableRouter = router;
|
|
67
|
+
const routesById = preloadableRouter.routesById || {};
|
|
68
|
+
const matches = preloadableRouter.stores.matches.get();
|
|
69
|
+
return Promise.all(matches.map((match)=>{
|
|
70
|
+
if (void 0 === match.routeId || '' === match.routeId) return;
|
|
71
|
+
const route = routesById[match.routeId];
|
|
72
|
+
const component = route?.options?.component;
|
|
73
|
+
const preload = component?.load || component?.preload;
|
|
74
|
+
if ('function' != typeof preload) return;
|
|
75
|
+
return Promise.resolve(preload.call(component)).then((routeModule)=>{
|
|
76
|
+
const modernRouteId = route?.options?.staticData?.modernRouteId;
|
|
77
|
+
const cachedRouteModule = 'string' == typeof modernRouteId && '' !== modernRouteId ? getCachedRouteModule(modernRouteId) : void 0;
|
|
78
|
+
const resolvedComponent = pickRouteModuleComponent(cachedRouteModule ?? routeModule);
|
|
79
|
+
if (void 0 !== resolvedComponent && 'string' == typeof modernRouteId && '' !== modernRouteId) route.options.component = withModernRouteMatchContext(resolvedComponent, modernRouteId);
|
|
80
|
+
});
|
|
81
|
+
})).then(()=>void 0);
|
|
82
|
+
}
|
|
83
|
+
function hydrateTanstackRouter(router) {
|
|
84
|
+
return import("@tanstack/react-router/ssr/client").then(({ hydrate })=>hydrate(router));
|
|
85
|
+
}
|
|
86
|
+
function getTanstackSsrHydrationRecord(router) {
|
|
87
|
+
const existingHydrationRecord = routerHydrationRecords.get(router);
|
|
88
|
+
if (void 0 !== existingHydrationRecord) return existingHydrationRecord;
|
|
89
|
+
const hydrationRecord = {
|
|
90
|
+
promise: Promise.resolve(),
|
|
91
|
+
status: 'pending'
|
|
92
|
+
};
|
|
93
|
+
routerHydrationRecords.set(router, hydrationRecord);
|
|
94
|
+
try {
|
|
95
|
+
hydrationRecord.promise = hydrateTanstackRouter(router).then((value)=>preloadHydratedRouteComponents(router).then(()=>value)).then((value)=>{
|
|
96
|
+
hydrationRecord.status = 'fulfilled';
|
|
97
|
+
return value;
|
|
98
|
+
}, (error)=>{
|
|
99
|
+
hydrationRecord.status = 'rejected';
|
|
100
|
+
hydrationRecord.error = error;
|
|
101
|
+
throw error;
|
|
102
|
+
});
|
|
103
|
+
} catch (error) {
|
|
104
|
+
hydrationRecord.status = 'rejected';
|
|
105
|
+
hydrationRecord.error = error;
|
|
106
|
+
hydrationRecord.promise = Promise.reject(error);
|
|
107
|
+
hydrationRecord.promise.catch(()=>{});
|
|
108
|
+
}
|
|
109
|
+
return hydrationRecord;
|
|
110
|
+
}
|
|
111
|
+
function getTanstackSsrHydrationPromise(router) {
|
|
112
|
+
return getTanstackSsrHydrationRecord(router).promise;
|
|
113
|
+
}
|
|
114
|
+
function hasTanstackSsrHydrationRecord(router) {
|
|
115
|
+
return routerHydrationRecords.has(router);
|
|
116
|
+
}
|
|
117
|
+
function ModernRouterClient({ router }) {
|
|
118
|
+
const hydrationRecord = getTanstackSsrHydrationRecord(router);
|
|
119
|
+
if ('rejected' === hydrationRecord.status) throw hydrationRecord.error;
|
|
120
|
+
return /*#__PURE__*/ jsx(RouterProvider, {
|
|
121
|
+
router: router
|
|
52
122
|
});
|
|
53
123
|
}
|
|
54
124
|
const tanstackRouterPlugin = (userConfig = {})=>{
|
|
55
125
|
const plugin = {
|
|
56
126
|
name: '@modern-js/plugin-router-tanstack',
|
|
57
|
-
registryHooks:
|
|
58
|
-
modifyRoutes: modifyRoutes,
|
|
59
|
-
onAfterCreateRouter: onAfterCreateRouter,
|
|
60
|
-
onAfterHydrateRouter: onAfterHydrateRouter,
|
|
61
|
-
onBeforeCreateRouter: onBeforeCreateRouter,
|
|
62
|
-
onBeforeCreateRoutes: onBeforeCreateRoutes,
|
|
63
|
-
onBeforeHydrateRouter: onBeforeHydrateRouter
|
|
64
|
-
},
|
|
127
|
+
registryHooks: routerProviderRegistryHooks,
|
|
65
128
|
setup: (api)=>{
|
|
129
|
+
const hooks = api.getHooks();
|
|
130
|
+
let cachedRouteObjects;
|
|
131
|
+
let cachedRouteTree = null;
|
|
132
|
+
let cachedRouter = null;
|
|
133
|
+
let cachedRouterBasepath = null;
|
|
134
|
+
const getMergedConfig = ()=>getMergedRouterConfig(api, userConfig);
|
|
135
|
+
const getRouteObjects = ()=>{
|
|
136
|
+
if (void 0 !== cachedRouteObjects) return cachedRouteObjects;
|
|
137
|
+
const mergedConfig = getMergedConfig();
|
|
138
|
+
const { createRoutes } = mergedConfig;
|
|
139
|
+
const finalRouteConfig = getFinalRouteConfig(mergedConfig);
|
|
140
|
+
const routeObjects = createRoutes ? createRoutes() : createRouteObjectsFromConfig({
|
|
141
|
+
routesConfig: finalRouteConfig
|
|
142
|
+
}) || [];
|
|
143
|
+
cachedRouteObjects = hooks.modifyRoutes.call(routeObjects);
|
|
144
|
+
return cachedRouteObjects;
|
|
145
|
+
};
|
|
146
|
+
const getRouteTree = ()=>{
|
|
147
|
+
if (cachedRouteTree) return cachedRouteTree;
|
|
148
|
+
const routeObjects = getRouteObjects();
|
|
149
|
+
if (!routeObjects.length) return null;
|
|
150
|
+
cachedRouteTree = createRouteTreeFromRouteObjects(routeObjects, {
|
|
151
|
+
rscPayloadRouter: getGlobalEnableRsc()
|
|
152
|
+
});
|
|
153
|
+
return cachedRouteTree;
|
|
154
|
+
};
|
|
155
|
+
const selectBasePath = (pathname)=>{
|
|
156
|
+
const { serverBase = [] } = getMergedConfig();
|
|
157
|
+
const match = serverBase.find((baseUrl)=>isSegmentPrefix(pathname, baseUrl));
|
|
158
|
+
return match || '/';
|
|
159
|
+
};
|
|
160
|
+
const getClientBasename = (runtimeContext)=>{
|
|
161
|
+
const { basename = '' } = getMergedConfig();
|
|
162
|
+
const baseUrl = selectBasePath(location.pathname).replace(/^\/*/, '/');
|
|
163
|
+
return '/' === baseUrl ? urlJoin(baseUrl, runtimeContext._internalRouterBaseName || basename || '') : baseUrl;
|
|
164
|
+
};
|
|
165
|
+
const getRouter = (runtimeContext, _basename)=>{
|
|
166
|
+
const routeTree = getRouteTree();
|
|
167
|
+
if (!routeTree) return null;
|
|
168
|
+
const lifecycleContext = {
|
|
169
|
+
framework: 'tanstack',
|
|
170
|
+
phase: 'client-create',
|
|
171
|
+
routes: getRouteObjects(),
|
|
172
|
+
runtimeContext,
|
|
173
|
+
basename: _basename
|
|
174
|
+
};
|
|
175
|
+
hooks.onBeforeCreateRouter.call(lifecycleContext);
|
|
176
|
+
if (cachedRouter && cachedRouterBasepath === _basename) {
|
|
177
|
+
wrapRouterSubscribeWithBlockState(cachedRouter, runtimeContext.unstable_getBlockNavState);
|
|
178
|
+
hooks.onAfterCreateRouter.call({
|
|
179
|
+
...lifecycleContext,
|
|
180
|
+
router: cachedRouter,
|
|
181
|
+
runtimeContext
|
|
182
|
+
});
|
|
183
|
+
return cachedRouter;
|
|
184
|
+
}
|
|
185
|
+
const mergedConfig = getMergedConfig();
|
|
186
|
+
const { supportHtml5History = true } = mergedConfig;
|
|
187
|
+
const history = supportHtml5History ? createBrowserHistory() : createHashHistory();
|
|
188
|
+
const rewrite = createModernBasepathRewrite(_basename);
|
|
189
|
+
const serializationAdapters = getGlobalEnableRsc() ? getTanstackRscSerializationAdapters() : void 0;
|
|
190
|
+
cachedRouter = createRouter({
|
|
191
|
+
...getModernTanstackRouterFastDefaults(mergedConfig),
|
|
192
|
+
routeTree,
|
|
193
|
+
basepath: '/',
|
|
194
|
+
rewrite,
|
|
195
|
+
history,
|
|
196
|
+
context: {},
|
|
197
|
+
...serializationAdapters ? {
|
|
198
|
+
serializationAdapters
|
|
199
|
+
} : {}
|
|
200
|
+
});
|
|
201
|
+
cachedRouterBasepath = _basename;
|
|
202
|
+
wrapRouterSubscribeWithBlockState(cachedRouter, runtimeContext.unstable_getBlockNavState);
|
|
203
|
+
hooks.onAfterCreateRouter.call({
|
|
204
|
+
...lifecycleContext,
|
|
205
|
+
router: cachedRouter,
|
|
206
|
+
runtimeContext
|
|
207
|
+
});
|
|
208
|
+
return cachedRouter;
|
|
209
|
+
};
|
|
66
210
|
api.onBeforeRender((context)=>{
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
if ("u" > typeof window && window._SSR_DATA && mergedConfig.unstable_reloadOnURLMismatch) {
|
|
211
|
+
const mergedConfig = getMergedConfig();
|
|
212
|
+
if ("u" > typeof window && void 0 !== window._SSR_DATA && mergedConfig.unstable_reloadOnURLMismatch) {
|
|
70
213
|
const { ssrContext } = context;
|
|
71
214
|
const currentPathname = normalizePathname(window.location.pathname);
|
|
72
|
-
const initialPathname = ssrContext?.request?.pathname
|
|
73
|
-
if (initialPathname && initialPathname !== currentPathname) {
|
|
215
|
+
const initialPathname = 'string' == typeof ssrContext?.request?.pathname ? normalizePathname(ssrContext.request.pathname) : void 0;
|
|
216
|
+
if (void 0 !== initialPathname && '' !== initialPathname && initialPathname !== currentPathname) {
|
|
74
217
|
const errorMsg = `The initial URL ${initialPathname} and the URL ${currentPathname} to be hydrated do not match, reload.`;
|
|
75
218
|
console.error(errorMsg);
|
|
76
219
|
window.location.reload();
|
|
@@ -83,94 +226,26 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
83
226
|
useNavigate: useNavigate,
|
|
84
227
|
useRouter: useRouter
|
|
85
228
|
};
|
|
229
|
+
const hasSSRBootstrap = "u" > typeof window && Boolean(window.$_TSR);
|
|
230
|
+
if (hasSSRBootstrap && getRouteObjects().length > 0) {
|
|
231
|
+
const runtimeContext = context;
|
|
232
|
+
const router = getRouter(runtimeContext, getClientBasename(runtimeContext));
|
|
233
|
+
if (null != router) return getTanstackSsrHydrationPromise(router).then(()=>void 0);
|
|
234
|
+
}
|
|
86
235
|
});
|
|
87
236
|
api.wrapRoot((App)=>{
|
|
88
|
-
|
|
89
|
-
const { serverBase = [], supportHtml5History = true, basename = '', routesConfig, createRoutes } = mergedConfig;
|
|
90
|
-
const finalRouteConfig = {
|
|
91
|
-
routes: getGlobalRoutes(),
|
|
92
|
-
globalApp: getGlobalLayoutApp(),
|
|
93
|
-
...routesConfig
|
|
94
|
-
};
|
|
95
|
-
if (!finalRouteConfig.routes && !createRoutes) return App;
|
|
96
|
-
const hooks = api.getHooks();
|
|
97
|
-
let cachedRouteObjects;
|
|
98
|
-
const getRouteObjects = ()=>{
|
|
99
|
-
if (void 0 !== cachedRouteObjects) return cachedRouteObjects;
|
|
100
|
-
const routeObjects = createRoutes ? createRoutes() : createRouteObjectsFromConfig({
|
|
101
|
-
routesConfig: finalRouteConfig
|
|
102
|
-
}) || [];
|
|
103
|
-
const normalizedRouteObjects = createRoutes ? routeObjects : stripSyntheticNotFoundRoute(routeObjects);
|
|
104
|
-
cachedRouteObjects = hooks.modifyRoutes.call(normalizedRouteObjects);
|
|
105
|
-
return cachedRouteObjects;
|
|
106
|
-
};
|
|
107
|
-
const selectBasePath = (pathname)=>{
|
|
108
|
-
const match = serverBase.find((baseUrl)=>isSegmentPrefix(pathname, baseUrl));
|
|
109
|
-
return match || '/';
|
|
110
|
-
};
|
|
111
|
-
let cachedRouteTree = null;
|
|
112
|
-
let cachedRouter = null;
|
|
113
|
-
let cachedRouterBasepath = null;
|
|
237
|
+
if (0 === getRouteObjects().length) return App;
|
|
114
238
|
const RouterWrapper = ()=>{
|
|
115
239
|
const runtimeContext = useContext(InternalRuntimeContext);
|
|
116
|
-
const
|
|
117
|
-
const
|
|
118
|
-
const routeTree = useMemo(()=>{
|
|
119
|
-
if (cachedRouteTree) return cachedRouteTree;
|
|
120
|
-
const routeObjects = getRouteObjects();
|
|
121
|
-
if (!routeObjects.length) return null;
|
|
122
|
-
cachedRouteTree = createRouteTreeFromRouteObjects(routeObjects, {
|
|
123
|
-
rscPayloadRouter: getGlobalEnableRsc()
|
|
124
|
-
});
|
|
125
|
-
return cachedRouteTree;
|
|
126
|
-
}, []);
|
|
240
|
+
const _basename = getClientBasename(runtimeContext);
|
|
241
|
+
const routeTree = useMemo(()=>getRouteTree(), []);
|
|
127
242
|
if (!routeTree) return App ? /*#__PURE__*/ jsx(App, {}) : null;
|
|
128
|
-
const router = useMemo(()=>
|
|
129
|
-
const lifecycleContext = {
|
|
130
|
-
framework: 'tanstack',
|
|
131
|
-
phase: 'client-create',
|
|
132
|
-
routes: getRouteObjects(),
|
|
133
|
-
runtimeContext,
|
|
134
|
-
basename: _basename
|
|
135
|
-
};
|
|
136
|
-
hooks.onBeforeCreateRouter.call(lifecycleContext);
|
|
137
|
-
if (cachedRouter && cachedRouterBasepath === _basename) {
|
|
138
|
-
wrapRouterSubscribeWithBlockState(cachedRouter, runtimeContext.unstable_getBlockNavState);
|
|
139
|
-
hooks.onAfterCreateRouter.call({
|
|
140
|
-
...lifecycleContext,
|
|
141
|
-
router: cachedRouter,
|
|
142
|
-
runtimeContext
|
|
143
|
-
});
|
|
144
|
-
return cachedRouter;
|
|
145
|
-
}
|
|
146
|
-
const history = supportHtml5History ? createBrowserHistory() : createHashHistory();
|
|
147
|
-
const rewrite = createModernBasepathRewrite(_basename);
|
|
148
|
-
const serializationAdapters = getGlobalEnableRsc() ? getTanstackRscSerializationAdapters() : void 0;
|
|
149
|
-
cachedRouter = createRouter({
|
|
150
|
-
...getModernTanstackRouterFastDefaults(mergedConfig),
|
|
151
|
-
routeTree,
|
|
152
|
-
basepath: '/',
|
|
153
|
-
rewrite,
|
|
154
|
-
history,
|
|
155
|
-
context: {},
|
|
156
|
-
...serializationAdapters ? {
|
|
157
|
-
serializationAdapters
|
|
158
|
-
} : {}
|
|
159
|
-
});
|
|
160
|
-
cachedRouterBasepath = _basename;
|
|
161
|
-
wrapRouterSubscribeWithBlockState(cachedRouter, runtimeContext.unstable_getBlockNavState);
|
|
162
|
-
hooks.onAfterCreateRouter.call({
|
|
163
|
-
...lifecycleContext,
|
|
164
|
-
router: cachedRouter,
|
|
165
|
-
runtimeContext
|
|
166
|
-
});
|
|
167
|
-
return cachedRouter;
|
|
168
|
-
}, [
|
|
243
|
+
const router = useMemo(()=>getRouter(runtimeContext, _basename), [
|
|
169
244
|
_basename,
|
|
170
245
|
routeTree,
|
|
171
|
-
supportHtml5History,
|
|
172
246
|
runtimeContext
|
|
173
247
|
]);
|
|
248
|
+
if (!router) return App ? /*#__PURE__*/ jsx(App, {}) : null;
|
|
174
249
|
const runtimeState = applyRouterRuntimeState(runtimeContext, {
|
|
175
250
|
framework: 'tanstack',
|
|
176
251
|
basename: _basename,
|
|
@@ -184,20 +259,21 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
184
259
|
basename: _basename,
|
|
185
260
|
router
|
|
186
261
|
};
|
|
187
|
-
const hasSSRBootstrap = "u" > typeof window && Boolean(window.$_TSR);
|
|
188
|
-
|
|
262
|
+
const hasSSRBootstrap = "u" > typeof window && (Boolean(window.$_TSR) || hasTanstackSsrHydrationRecord(router));
|
|
263
|
+
const needsRouterClient = hasSSRBootstrap;
|
|
264
|
+
if (needsRouterClient) hooks.onBeforeHydrateRouter.call({
|
|
189
265
|
...lifecycleContext,
|
|
190
266
|
phase: 'hydrate',
|
|
191
267
|
router,
|
|
192
268
|
runtimeContext: runtimeState
|
|
193
269
|
});
|
|
194
|
-
const RouterContent =
|
|
270
|
+
const RouterContent = needsRouterClient ? /*#__PURE__*/ jsx(ModernRouterClient, {
|
|
195
271
|
router: router
|
|
196
272
|
}) : /*#__PURE__*/ jsx(RouterProvider, {
|
|
197
273
|
router: router
|
|
198
274
|
});
|
|
199
275
|
const HydratableRouterContent = wrapTanstackSsrHydrationBoundary(RouterContent, hasSSRBootstrap);
|
|
200
|
-
if (
|
|
276
|
+
if (needsRouterClient) hooks.onAfterHydrateRouter.call({
|
|
201
277
|
...lifecycleContext,
|
|
202
278
|
phase: 'hydrate',
|
|
203
279
|
router,
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { InternalRuntimeContext, getGlobalEnableRsc
|
|
4
|
-
import { merge } from "@modern-js/runtime-utils/merge";
|
|
3
|
+
import { InternalRuntimeContext, getGlobalEnableRsc } from "@modern-js/runtime/context";
|
|
5
4
|
import { createRequestContext, storage } from "@modern-js/runtime-utils/node";
|
|
6
5
|
import { time } from "@modern-js/runtime-utils/time";
|
|
7
6
|
import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants";
|
|
8
7
|
import { RouterProvider, createMemoryHistory, createRouter } from "@tanstack/react-router";
|
|
9
|
-
import { attachRouterServerSsrUtils } from "@tanstack/router-core/ssr/server";
|
|
10
8
|
import { useContext } from "react";
|
|
11
9
|
import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
|
|
12
|
-
import {
|
|
10
|
+
import { routerProviderRegistryHooks } from "./hooks.mjs";
|
|
13
11
|
import { wrapTanstackSsrHydrationBoundary } from "./hydrationBoundary.mjs";
|
|
14
|
-
import { applyRouterServerPrepareResult, createRouterServerSnapshot } from "./lifecycle.mjs";
|
|
12
|
+
import { applyRouterServerPrepareResult, createRouterServerSnapshot, getRouterRuntimeState } from "./lifecycle.mjs";
|
|
13
|
+
import { getFinalRouteConfig, getMergedRouterConfig } from "./pluginCore.mjs";
|
|
15
14
|
import { createRouteTreeFromRouteObjects, getModernRouteIdsFromMatches } from "./routeTree.mjs";
|
|
16
15
|
import { createTanstackRscServerPayload, handleTanstackRscRedirect } from "./rsc/payloadRouter.mjs";
|
|
17
16
|
import { getModernTanstackRouterFastDefaults } from "./types.mjs";
|
|
@@ -29,7 +28,7 @@ function isPreloadableRouteComponent(component) {
|
|
|
29
28
|
return 'function' == typeof preloadable.load || 'function' == typeof preloadable.preload;
|
|
30
29
|
}
|
|
31
30
|
function isReactLazyRouteComponent(component) {
|
|
32
|
-
return
|
|
31
|
+
return null != component && 'object' == typeof component && 'function' == typeof component._init && '_payload' in component;
|
|
33
32
|
}
|
|
34
33
|
async function preloadReactLazyRouteComponent(component) {
|
|
35
34
|
try {
|
|
@@ -96,15 +95,6 @@ function createGetSsrHref(request) {
|
|
|
96
95
|
const url = new URL(request.url);
|
|
97
96
|
return `${url.pathname}${url.search}${url.hash}`;
|
|
98
97
|
}
|
|
99
|
-
function stripSyntheticNotFoundRoute(routes) {
|
|
100
|
-
return routes.filter((route)=>!('*' === route.path && !route.id && !route.loader)).map((route)=>{
|
|
101
|
-
if (!route.children?.length) return route;
|
|
102
|
-
return {
|
|
103
|
-
...route,
|
|
104
|
-
children: stripSyntheticNotFoundRoute(route.children)
|
|
105
|
-
};
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
98
|
function collectRouterErrors(tanstackRouter) {
|
|
109
99
|
const state = tanstackRouter.state;
|
|
110
100
|
const matches = Array.isArray(state.matches) ? state.matches : [];
|
|
@@ -116,29 +106,24 @@ function collectRouterErrors(tanstackRouter) {
|
|
|
116
106
|
}, {});
|
|
117
107
|
return Object.keys(errors).length > 0 ? errors : void 0;
|
|
118
108
|
}
|
|
109
|
+
async function attachServerSsrUtils(router) {
|
|
110
|
+
const { attachRouterServerSsrUtils } = await import("@tanstack/router-core/ssr/server");
|
|
111
|
+
attachRouterServerSsrUtils({
|
|
112
|
+
router,
|
|
113
|
+
manifest: void 0
|
|
114
|
+
});
|
|
115
|
+
}
|
|
119
116
|
const tanstackRouterPlugin = (userConfig = {})=>{
|
|
120
117
|
const plugin = {
|
|
121
118
|
name: '@modern-js/plugin-router-tanstack',
|
|
122
|
-
registryHooks:
|
|
123
|
-
modifyRoutes: modifyRoutes,
|
|
124
|
-
onAfterCreateRouter: onAfterCreateRouter,
|
|
125
|
-
onAfterHydrateRouter: onAfterHydrateRouter,
|
|
126
|
-
onBeforeCreateRouter: onBeforeCreateRouter,
|
|
127
|
-
onBeforeCreateRoutes: onBeforeCreateRoutes,
|
|
128
|
-
onBeforeHydrateRouter: onBeforeHydrateRouter
|
|
129
|
-
},
|
|
119
|
+
registryHooks: routerProviderRegistryHooks,
|
|
130
120
|
setup: (api)=>{
|
|
131
121
|
api.onBeforeRender(async (context, interrupt)=>{
|
|
132
|
-
const
|
|
133
|
-
const mergedConfig = merge(pluginConfig.router || {}, userConfig);
|
|
122
|
+
const mergedConfig = getMergedRouterConfig(api, userConfig);
|
|
134
123
|
const serializationAdapters = getGlobalEnableRsc() ? (await import("./rsc/server.mjs")).getTanstackRscSerializationAdapters() : void 0;
|
|
135
124
|
const enableRsc = getGlobalEnableRsc();
|
|
136
|
-
const { basename = '',
|
|
137
|
-
const finalRouteConfig =
|
|
138
|
-
routes: getGlobalRoutes(),
|
|
139
|
-
globalApp: getGlobalLayoutApp(),
|
|
140
|
-
...routesConfig
|
|
141
|
-
};
|
|
125
|
+
const { basename = '', createRoutes } = mergedConfig;
|
|
126
|
+
const finalRouteConfig = getFinalRouteConfig(mergedConfig);
|
|
142
127
|
if (!finalRouteConfig.routes && !createRoutes) return;
|
|
143
128
|
const hooks = api.getHooks();
|
|
144
129
|
await hooks.onBeforeCreateRoutes.call(context);
|
|
@@ -146,8 +131,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
146
131
|
routesConfig: finalRouteConfig,
|
|
147
132
|
ssrMode: context.ssrContext?.mode
|
|
148
133
|
}) || [];
|
|
149
|
-
const
|
|
150
|
-
const modifiedRouteObjects = hooks.modifyRoutes.call(normalizedRouteObjects);
|
|
134
|
+
const modifiedRouteObjects = hooks.modifyRoutes.call(routeObjects);
|
|
151
135
|
if (!modifiedRouteObjects.length) return;
|
|
152
136
|
const { request, nonce, baseUrl, loaderFailureMode = 'errorBoundary' } = context.ssrContext;
|
|
153
137
|
const _basename = '/' === baseUrl ? urlJoin(baseUrl, basename || '') : baseUrl;
|
|
@@ -195,10 +179,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
195
179
|
} : {}
|
|
196
180
|
});
|
|
197
181
|
const serverRouter = tanstackRouter;
|
|
198
|
-
|
|
199
|
-
router: serverRouter,
|
|
200
|
-
manifest: void 0
|
|
201
|
-
});
|
|
182
|
+
await attachServerSsrUtils(serverRouter);
|
|
202
183
|
const end = time();
|
|
203
184
|
try {
|
|
204
185
|
await tanstackRouter.load({
|
|
@@ -265,7 +246,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
265
246
|
api.wrapRoot((App)=>{
|
|
266
247
|
const getRouteApp = ()=>(props)=>{
|
|
267
248
|
const context = useContext(InternalRuntimeContext);
|
|
268
|
-
const router = context
|
|
249
|
+
const router = getRouterRuntimeState(context)?.instance;
|
|
269
250
|
if (!router) return App ? /*#__PURE__*/ jsx(App, {
|
|
270
251
|
...props
|
|
271
252
|
}) : null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { getGlobalLayoutApp, getGlobalRoutes } from "@modern-js/runtime/context";
|
|
3
|
+
import { merge } from "@modern-js/runtime-utils/merge";
|
|
4
|
+
function getMergedRouterConfig(api, userConfig) {
|
|
5
|
+
const pluginConfig = api.getRuntimeConfig();
|
|
6
|
+
return merge(pluginConfig.router || {}, userConfig);
|
|
7
|
+
}
|
|
8
|
+
function getFinalRouteConfig(mergedConfig) {
|
|
9
|
+
return {
|
|
10
|
+
routes: getGlobalRoutes(),
|
|
11
|
+
globalApp: getGlobalLayoutApp(),
|
|
12
|
+
...mergedConfig.routesConfig
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export { getFinalRouteConfig, getMergedRouterConfig };
|
|
@@ -5,7 +5,7 @@ function resolvePreloadFromPrefetch(prefetch, preload) {
|
|
|
5
5
|
if (void 0 !== preload) return preload;
|
|
6
6
|
if ('none' === prefetch) return false;
|
|
7
7
|
if ('intent' === prefetch || 'render' === prefetch || 'viewport' === prefetch) return prefetch;
|
|
8
|
-
return
|
|
8
|
+
return 'viewport';
|
|
9
9
|
}
|
|
10
10
|
const LinkComponentImpl = (props)=>{
|
|
11
11
|
const { prefetch, preload, ...rest } = props;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { registerRouterProvider } from "@modern-js/runtime/context";
|
|
3
|
+
import { Form, RouteActionResponseError, useFetcher } from "./dataMutation.mjs";
|
|
4
|
+
import { Outlet } from "./outlet.mjs";
|
|
5
|
+
import { tanstackRouterPlugin } from "./plugin.mjs";
|
|
6
|
+
import { Link, NavLink } from "./prefetchLink.mjs";
|
|
7
|
+
const tanstackRouterProviderFactory = (userConfig)=>tanstackRouterPlugin(userConfig);
|
|
8
|
+
registerRouterProvider('tanstack', tanstackRouterProviderFactory);
|
|
9
|
+
const COMPAT_BINDINGS_SLOT = Symbol.for('@modern-js/plugin-tanstack:runtime-compat-bindings');
|
|
10
|
+
const tanstackRouterCompatBindings = {
|
|
11
|
+
Form: Form,
|
|
12
|
+
Link: Link,
|
|
13
|
+
NavLink: NavLink,
|
|
14
|
+
Outlet: Outlet,
|
|
15
|
+
RouteActionResponseError: RouteActionResponseError,
|
|
16
|
+
useFetcher: useFetcher
|
|
17
|
+
};
|
|
18
|
+
globalThis[COMPAT_BINDINGS_SLOT] ??= tanstackRouterCompatBindings;
|
|
19
|
+
export { tanstackRouterCompatBindings };
|