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