@bleedingdev/modern-js-plugin-tanstack 3.2.0-ultramodern.8 → 3.2.0-ultramodern.81
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/tanstackTypes.js +101 -51
- package/dist/cjs/runtime/plugin.js +4 -5
- package/dist/cjs/runtime/plugin.node.js +25 -10
- package/dist/cjs/runtime/plugin.worker.js +49 -0
- package/dist/cjs/runtime/routeTree.js +40 -4
- package/dist/esm/cli/tanstackTypes.mjs +101 -51
- package/dist/esm/runtime/plugin.mjs +8 -9
- package/dist/esm/runtime/plugin.node.mjs +26 -11
- package/dist/esm/runtime/plugin.worker.mjs +1 -0
- package/dist/esm/runtime/routeTree.mjs +40 -4
- package/dist/esm-node/cli/tanstackTypes.mjs +101 -51
- package/dist/esm-node/runtime/plugin.mjs +8 -9
- package/dist/esm-node/runtime/plugin.node.mjs +26 -11
- package/dist/esm-node/runtime/plugin.worker.mjs +2 -0
- package/dist/esm-node/runtime/routeTree.mjs +40 -4
- package/dist/types/runtime/plugin.worker.d.ts +1 -0
- package/package.json +13 -13
- package/src/cli/tanstackTypes.ts +114 -54
- package/src/runtime/plugin.node.tsx +48 -6
- package/src/runtime/plugin.tsx +3 -4
- package/src/runtime/plugin.worker.tsx +4 -0
- package/src/runtime/routeTree.ts +109 -8
- package/tests/router/routeTree.test.ts +72 -1
- package/tests/router/tanstackTypes.test.ts +64 -0
|
@@ -4,13 +4,14 @@ import { merge } from "@modern-js/runtime-utils/merge";
|
|
|
4
4
|
import { normalizePathname } from "@modern-js/runtime-utils/url";
|
|
5
5
|
import { RouterProvider, createBrowserHistory, createHashHistory, createRouter, useLocation, useMatches, useNavigate, useRouter } from "@tanstack/react-router";
|
|
6
6
|
import { RouterClient } from "@tanstack/react-router/ssr/client";
|
|
7
|
+
import { useContext, useMemo } from "react";
|
|
7
8
|
import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
|
|
8
9
|
import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
|
|
9
10
|
import { applyRouterRuntimeState } from "./lifecycle.mjs";
|
|
11
|
+
import { Link } from "./prefetchLink.mjs";
|
|
10
12
|
import { createRouteTreeFromRouteObjects } from "./routeTree.mjs";
|
|
11
13
|
import { getTanstackRscSerializationAdapters } from "./rsc/client.mjs";
|
|
12
14
|
import { createRouteObjectsFromConfig, urlJoin } from "./utils.mjs";
|
|
13
|
-
import * as __rspack_external_react from "react";
|
|
14
15
|
const BLOCKING_SUBSCRIBE_SYMBOL = Symbol.for('@modern-js/plugin-tanstack:blocking-subscribe');
|
|
15
16
|
const BLOCKING_STATE_SYMBOL = Symbol.for('@modern-js/plugin-tanstack:blocking-state');
|
|
16
17
|
function normalizeBase(b) {
|
|
@@ -73,6 +74,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
context.router = {
|
|
77
|
+
Link: Link,
|
|
76
78
|
useMatches: useMatches,
|
|
77
79
|
useLocation: useLocation,
|
|
78
80
|
useNavigate: useNavigate,
|
|
@@ -107,10 +109,10 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
107
109
|
let cachedRouter = null;
|
|
108
110
|
let cachedRouterBasepath = null;
|
|
109
111
|
const RouterWrapper = ()=>{
|
|
110
|
-
const runtimeContext =
|
|
112
|
+
const runtimeContext = useContext(InternalRuntimeContext);
|
|
111
113
|
const baseUrl = selectBasePath(location.pathname).replace(/^\/*/, '/');
|
|
112
114
|
const _basename = '/' === baseUrl ? urlJoin(baseUrl, runtimeContext._internalRouterBaseName || basename || '') : baseUrl;
|
|
113
|
-
const routeTree =
|
|
115
|
+
const routeTree = useMemo(()=>{
|
|
114
116
|
if (cachedRouteTree) return cachedRouteTree;
|
|
115
117
|
const routeObjects = getRouteObjects();
|
|
116
118
|
if (!routeObjects.length) return null;
|
|
@@ -120,7 +122,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
120
122
|
return cachedRouteTree;
|
|
121
123
|
}, []);
|
|
122
124
|
if (!routeTree) return App ? /*#__PURE__*/ jsx(App, {}) : null;
|
|
123
|
-
const router =
|
|
125
|
+
const router = useMemo(()=>{
|
|
124
126
|
const lifecycleContext = {
|
|
125
127
|
framework: 'tanstack',
|
|
126
128
|
phase: 'client-create',
|
|
@@ -185,11 +187,8 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
185
187
|
router,
|
|
186
188
|
runtimeContext: runtimeState
|
|
187
189
|
});
|
|
188
|
-
const RouterContent = hasSSRBootstrap ? /*#__PURE__*/ jsx(
|
|
189
|
-
|
|
190
|
-
children: /*#__PURE__*/ jsx(RouterClient, {
|
|
191
|
-
router: router
|
|
192
|
-
})
|
|
190
|
+
const RouterContent = hasSSRBootstrap ? /*#__PURE__*/ jsx(RouterClient, {
|
|
191
|
+
router: router
|
|
193
192
|
}) : /*#__PURE__*/ jsx(RouterProvider, {
|
|
194
193
|
router: router
|
|
195
194
|
});
|
|
@@ -5,8 +5,8 @@ import { createRequestContext, storage } from "@modern-js/runtime-utils/node";
|
|
|
5
5
|
import { time } from "@modern-js/runtime-utils/time";
|
|
6
6
|
import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants";
|
|
7
7
|
import { RouterProvider, createMemoryHistory, createRouter } from "@tanstack/react-router";
|
|
8
|
-
import { attachRouterServerSsrUtils } from "@tanstack/
|
|
9
|
-
import {
|
|
8
|
+
import { attachRouterServerSsrUtils } from "@tanstack/router-core/ssr/server";
|
|
9
|
+
import { useContext } from "react";
|
|
10
10
|
import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
|
|
11
11
|
import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
|
|
12
12
|
import { applyRouterServerPrepareResult, createRouterServerSnapshot } from "./lifecycle.mjs";
|
|
@@ -17,12 +17,28 @@ const setTanstackRscServerPayload = (payload)=>{
|
|
|
17
17
|
const storageContext = storage.useContext?.();
|
|
18
18
|
if (storageContext) storageContext.serverPayload = payload;
|
|
19
19
|
};
|
|
20
|
+
function isPromiseLike(value) {
|
|
21
|
+
return Boolean(value && 'function' == typeof value.then);
|
|
22
|
+
}
|
|
20
23
|
function isPreloadableRouteComponent(component) {
|
|
21
24
|
if (!component || 'function' != typeof component) return false;
|
|
22
25
|
const preloadable = component;
|
|
23
26
|
return 'function' == typeof preloadable.load || 'function' == typeof preloadable.preload;
|
|
24
27
|
}
|
|
28
|
+
function isReactLazyRouteComponent(component) {
|
|
29
|
+
return Boolean(component) && 'object' == typeof component && 'function' == typeof component._init && '_payload' in component;
|
|
30
|
+
}
|
|
31
|
+
async function preloadReactLazyRouteComponent(component) {
|
|
32
|
+
try {
|
|
33
|
+
component._init?.(component._payload);
|
|
34
|
+
} catch (thrown) {
|
|
35
|
+
if (!isPromiseLike(thrown)) throw thrown;
|
|
36
|
+
await thrown;
|
|
37
|
+
component._init?.(component._payload);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
25
40
|
async function preloadRouteComponent(component) {
|
|
41
|
+
if (isReactLazyRouteComponent(component)) return void await preloadReactLazyRouteComponent(component);
|
|
26
42
|
if (!isPreloadableRouteComponent(component)) return;
|
|
27
43
|
if ('function' == typeof component.load) return void await component.load({});
|
|
28
44
|
await component.preload?.({});
|
|
@@ -206,10 +222,12 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
206
222
|
await preloadMatchedRouteComponents(serverRouter);
|
|
207
223
|
context.ssrContext?.response.status(tanstackRouter.state.statusCode);
|
|
208
224
|
await serverRouter.serverSsr?.dehydrate?.();
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
225
|
+
if (isRSCNavigation) {
|
|
226
|
+
await waitForRouterSerialization(serverRouter);
|
|
227
|
+
setTanstackRscServerPayload(createTanstackRscServerPayload(serverRouter, {
|
|
228
|
+
omitClientLoaderData: true
|
|
229
|
+
}));
|
|
230
|
+
}
|
|
213
231
|
const ssrScriptTags = serverRouter.serverSsr?.takeBufferedScripts?.();
|
|
214
232
|
const hydrationScripts = routerManagedTagsToHtml(ssrScriptTags);
|
|
215
233
|
const matchedRouteIds = getModernRouteIdsFromMatches(serverRouter);
|
|
@@ -247,11 +265,8 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
247
265
|
if (!router) return App ? /*#__PURE__*/ jsx(App, {
|
|
248
266
|
...props
|
|
249
267
|
}) : null;
|
|
250
|
-
const routerWrapper = /*#__PURE__*/ jsx(
|
|
251
|
-
|
|
252
|
-
children: /*#__PURE__*/ jsx(RouterProvider, {
|
|
253
|
-
router: router
|
|
254
|
-
})
|
|
268
|
+
const routerWrapper = /*#__PURE__*/ jsx(RouterProvider, {
|
|
269
|
+
router: router
|
|
255
270
|
});
|
|
256
271
|
return App ? /*#__PURE__*/ jsx(App, {
|
|
257
272
|
children: routerWrapper
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default, tanstackRouterPlugin } from "./plugin.node.mjs";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createRootRoute, createRoute, notFound, redirect } from "@tanstack/react-router";
|
|
2
|
+
import { createElement } from "react";
|
|
2
3
|
import { DefaultNotFound } from "./DefaultNotFound.mjs";
|
|
3
4
|
import { isTanstackRscPayloadNavigationEnabled, loadTanstackRscRouteData } from "./rsc/payloadRouter.mjs";
|
|
4
5
|
function createTanstackRoute(options) {
|
|
@@ -54,6 +55,33 @@ function normalizeModernLoaderResponse(result) {
|
|
|
54
55
|
}
|
|
55
56
|
return normalizeModernLoaderResult(result);
|
|
56
57
|
}
|
|
58
|
+
function pickRouteModuleComponent(routeModule) {
|
|
59
|
+
if ('function' == typeof routeModule || routeModule && 'object' == typeof routeModule && '$$typeof' in routeModule) return routeModule;
|
|
60
|
+
if (!routeModule || 'object' != typeof routeModule) return;
|
|
61
|
+
const module = routeModule;
|
|
62
|
+
const component = module.default || module.Component;
|
|
63
|
+
if ('function' == typeof component || component && 'object' == typeof component && '$$typeof' in component) return component;
|
|
64
|
+
}
|
|
65
|
+
function createServerLazyImportComponent(lazyImport, fallbackComponent) {
|
|
66
|
+
if ("u" > typeof document) return fallbackComponent;
|
|
67
|
+
let resolvedComponent;
|
|
68
|
+
let pendingLoad;
|
|
69
|
+
const load = async ()=>{
|
|
70
|
+
if (resolvedComponent) return resolvedComponent;
|
|
71
|
+
const routeModule = await lazyImport();
|
|
72
|
+
const component = pickRouteModuleComponent(routeModule);
|
|
73
|
+
if (component) resolvedComponent = component;
|
|
74
|
+
return resolvedComponent;
|
|
75
|
+
};
|
|
76
|
+
const Component = (props)=>{
|
|
77
|
+
if (resolvedComponent) return createElement(resolvedComponent, props);
|
|
78
|
+
pendingLoad ||= load();
|
|
79
|
+
throw pendingLoad;
|
|
80
|
+
};
|
|
81
|
+
Component.load = load;
|
|
82
|
+
Component.preload = load;
|
|
83
|
+
return Component;
|
|
84
|
+
}
|
|
57
85
|
function isAbsoluteUrl(value) {
|
|
58
86
|
try {
|
|
59
87
|
new URL(value);
|
|
@@ -126,7 +154,7 @@ function wrapModernLoader(modernRoute, modernLoader, revalidationState, options
|
|
|
126
154
|
const signal = ctx?.abortController?.signal || ctx?.signal || new AbortController().signal;
|
|
127
155
|
const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
|
|
128
156
|
const href = 'string' == typeof ctx?.location ? ctx.location : ctx?.location?.publicHref || ctx?.location?.href || ctx?.location?.url?.href || '';
|
|
129
|
-
const request = baseRequest ? new Request(baseRequest, {
|
|
157
|
+
const request = void 0 !== baseRequest ? new Request(baseRequest, {
|
|
130
158
|
signal
|
|
131
159
|
}) : createModernRequest(href, signal);
|
|
132
160
|
const params = mapParamsForModernLoader({
|
|
@@ -191,7 +219,7 @@ function wrapRouteObjectLoader(route, revalidationState, options = {}) {
|
|
|
191
219
|
const signal = ctx?.abortController?.signal || ctx?.signal || new AbortController().signal;
|
|
192
220
|
const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
|
|
193
221
|
const href = 'string' == typeof ctx?.location ? ctx.location : ctx?.location?.publicHref || ctx?.location?.href || ctx?.location?.url?.href || '';
|
|
194
|
-
const request = baseRequest ? new Request(baseRequest, {
|
|
222
|
+
const request = void 0 !== baseRequest ? new Request(baseRequest, {
|
|
195
223
|
signal
|
|
196
224
|
}) : createModernRequest(href, signal);
|
|
197
225
|
const params = mapParamsForRouteObjectLoader({
|
|
@@ -228,10 +256,18 @@ function wrapRouteObjectLoader(route, revalidationState, options = {}) {
|
|
|
228
256
|
}
|
|
229
257
|
function toRouteComponent(routeObject) {
|
|
230
258
|
const route = routeObject;
|
|
259
|
+
const lazyImport = 'function' == typeof route.lazyImport ? route.lazyImport : void 0;
|
|
260
|
+
const fallbackComponent = route.Component ? route.Component : route.element ? ()=>route.element : void 0;
|
|
261
|
+
if (lazyImport && fallbackComponent) return createServerLazyImportComponent(lazyImport, fallbackComponent);
|
|
231
262
|
if (route.Component) return route.Component;
|
|
232
263
|
const element = route.element;
|
|
233
264
|
if (element) return ()=>element;
|
|
234
265
|
}
|
|
266
|
+
function toModernRouteComponent(route) {
|
|
267
|
+
const component = route.component || void 0;
|
|
268
|
+
if ('function' == typeof route.lazyImport && component) return createServerLazyImportComponent(route.lazyImport, component);
|
|
269
|
+
return component;
|
|
270
|
+
}
|
|
235
271
|
function toErrorComponent(routeObject) {
|
|
236
272
|
const route = routeObject;
|
|
237
273
|
if (route.ErrorBoundary) return route.ErrorBoundary;
|
|
@@ -312,7 +348,7 @@ function createRouteFromModernRoute(opts) {
|
|
|
312
348
|
const stableFallbackId = modernId || route._component || route.filename || route.data || ('function' == typeof route.loader ? route.id : void 0);
|
|
313
349
|
const pendingComponent = route.loading || route.pendingComponent;
|
|
314
350
|
const errorComponent = route.error || route.errorComponent;
|
|
315
|
-
const component = route
|
|
351
|
+
const component = toModernRouteComponent(route);
|
|
316
352
|
const modernLoader = route.loader;
|
|
317
353
|
const modernAction = route.action;
|
|
318
354
|
const modernShouldRevalidate = route.shouldRevalidate;
|
|
@@ -359,7 +395,7 @@ function createRouteFromModernRoute(opts) {
|
|
|
359
395
|
}
|
|
360
396
|
function createRouteTreeFromModernRoutes(routes, options = {}) {
|
|
361
397
|
const rootModern = routes.find((r)=>r && 'nested' === r.type && r.isRoot);
|
|
362
|
-
const rootComponent = rootModern
|
|
398
|
+
const rootComponent = rootModern ? toModernRouteComponent(rootModern) : void 0;
|
|
363
399
|
const pendingComponent = rootModern?.loading;
|
|
364
400
|
const errorComponent = rootModern?.error;
|
|
365
401
|
const rootLoader = rootModern?.loader;
|
|
@@ -89,6 +89,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
89
89
|
const imports = [];
|
|
90
90
|
const statements = [];
|
|
91
91
|
const loaderImportMap = new Map();
|
|
92
|
+
const usedRouteVarNames = new Set();
|
|
92
93
|
let loaderIndex = 0;
|
|
93
94
|
let routeIndex = 0;
|
|
94
95
|
const getImportNamesForLoader = async (aliasedNoExtPath, inline, hasAction)=>{
|
|
@@ -122,10 +123,17 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
122
123
|
actionName
|
|
123
124
|
};
|
|
124
125
|
};
|
|
126
|
+
const reserveRouteVarName = (preferred)=>{
|
|
127
|
+
let candidate = preferred;
|
|
128
|
+
let suffix = 1;
|
|
129
|
+
while(usedRouteVarNames.has(candidate))candidate = `${preferred}_${suffix++}`;
|
|
130
|
+
usedRouteVarNames.add(candidate);
|
|
131
|
+
return candidate;
|
|
132
|
+
};
|
|
125
133
|
const createRouteVarName = (route)=>{
|
|
126
134
|
const id = route.id;
|
|
127
135
|
const base = id ? makeLegalIdentifier(id) : `r_${routeIndex++}`;
|
|
128
|
-
return `route_${base}
|
|
136
|
+
return reserveRouteVarName(`route_${base}`);
|
|
129
137
|
};
|
|
130
138
|
const buildRoute = async (opts)=>{
|
|
131
139
|
const { parentVar, route } = opts;
|
|
@@ -154,14 +162,16 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
154
162
|
actionName
|
|
155
163
|
});
|
|
156
164
|
if (staticDataSnippet) routeOpts.push(staticDataSnippet);
|
|
157
|
-
statements.push(`const ${varName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
|
|
158
165
|
const children = route.children;
|
|
166
|
+
const hasChildren = Boolean(children && children.length > 0);
|
|
167
|
+
const routeCtorVarName = hasChildren ? reserveRouteVarName(`${varName}__base`) : varName;
|
|
168
|
+
statements.push(`const ${routeCtorVarName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
|
|
159
169
|
if (children && children.length > 0) {
|
|
160
170
|
const childVars = await Promise.all(children.map((child)=>buildRoute({
|
|
161
|
-
parentVar:
|
|
171
|
+
parentVar: routeCtorVarName,
|
|
162
172
|
route: child
|
|
163
173
|
})));
|
|
164
|
-
statements.push(
|
|
174
|
+
statements.push(`const ${varName} = ${routeCtorVarName}.addChildren([${childVars.join(', ')}]);`);
|
|
165
175
|
}
|
|
166
176
|
return varName;
|
|
167
177
|
};
|
|
@@ -208,7 +218,7 @@ function isRedirectResponse(res: Response) {
|
|
|
208
218
|
}
|
|
209
219
|
|
|
210
220
|
function throwTanstackRedirect(location: string) {
|
|
211
|
-
const target = location
|
|
221
|
+
const target = location.length > 0 ? location : '/';
|
|
212
222
|
try {
|
|
213
223
|
void new URL(target);
|
|
214
224
|
throw redirect({ href: target });
|
|
@@ -234,21 +244,87 @@ function createRouteStaticData(opts: {
|
|
|
234
244
|
modernRouteAction?: unknown;
|
|
235
245
|
modernRouteLoader?: unknown;
|
|
236
246
|
}) {
|
|
237
|
-
const staticData:
|
|
247
|
+
const staticData: {
|
|
248
|
+
modernRouteId?: string;
|
|
249
|
+
modernRouteAction?: unknown;
|
|
250
|
+
modernRouteLoader?: unknown;
|
|
251
|
+
} = {};
|
|
238
252
|
|
|
239
|
-
if (opts.modernRouteId) {
|
|
253
|
+
if (typeof opts.modernRouteId === 'string' && opts.modernRouteId.length > 0) {
|
|
240
254
|
staticData.modernRouteId = opts.modernRouteId;
|
|
241
255
|
}
|
|
242
256
|
|
|
243
|
-
if (opts.modernRouteLoader) {
|
|
257
|
+
if (typeof opts.modernRouteLoader !== 'undefined') {
|
|
244
258
|
staticData.modernRouteLoader = opts.modernRouteLoader;
|
|
245
259
|
}
|
|
246
260
|
|
|
247
|
-
if (opts.modernRouteAction) {
|
|
261
|
+
if (typeof opts.modernRouteAction !== 'undefined') {
|
|
248
262
|
staticData.modernRouteAction = opts.modernRouteAction;
|
|
249
263
|
}
|
|
250
264
|
|
|
251
|
-
return
|
|
265
|
+
return staticData;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function getLoaderSignal(ctx: any): AbortSignal {
|
|
269
|
+
const abortSignal = ctx?.abortController?.signal;
|
|
270
|
+
if (abortSignal instanceof AbortSignal) {
|
|
271
|
+
return abortSignal;
|
|
272
|
+
}
|
|
273
|
+
if (ctx?.signal instanceof AbortSignal) {
|
|
274
|
+
return ctx.signal;
|
|
275
|
+
}
|
|
276
|
+
return new AbortController().signal;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function getLoaderHref(ctx: any): string {
|
|
280
|
+
if (typeof ctx?.location === 'string') {
|
|
281
|
+
return ctx.location;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const publicHref = ctx?.location?.publicHref;
|
|
285
|
+
if (typeof publicHref === 'string') {
|
|
286
|
+
return publicHref;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const href = ctx?.location?.href;
|
|
290
|
+
if (typeof href === 'string') {
|
|
291
|
+
return href;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const urlHref = ctx?.location?.url?.href;
|
|
295
|
+
return typeof urlHref === 'string' ? urlHref : '';
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function getLoaderParams(ctx: any): Record<string, string> {
|
|
299
|
+
return typeof ctx?.params === 'object' && ctx.params !== null ? ctx.params : {};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function handleModernLoaderResult<LoaderResult>(result: LoaderResult): LoaderResult {
|
|
303
|
+
if (isResponse(result)) {
|
|
304
|
+
if (isRedirectResponse(result)) {
|
|
305
|
+
const location = result.headers.get('Location') ?? '/';
|
|
306
|
+
throwTanstackRedirect(location);
|
|
307
|
+
}
|
|
308
|
+
if (result.status === 404) {
|
|
309
|
+
throw notFound();
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return result;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function handleModernLoaderError(err: unknown): never {
|
|
317
|
+
if (isResponse(err)) {
|
|
318
|
+
if (isRedirectResponse(err)) {
|
|
319
|
+
const location = err.headers.get('Location') ?? '/';
|
|
320
|
+
throwTanstackRedirect(location);
|
|
321
|
+
}
|
|
322
|
+
if (err.status === 404) {
|
|
323
|
+
throw notFound();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
throw err;
|
|
252
328
|
}
|
|
253
329
|
|
|
254
330
|
function modernLoaderToTanstack<TLoader extends (args: any) => any>(
|
|
@@ -257,57 +333,31 @@ function modernLoaderToTanstack<TLoader extends (args: any) => any>(
|
|
|
257
333
|
) {
|
|
258
334
|
type LoaderResult = Awaited<ReturnType<TLoader>>;
|
|
259
335
|
|
|
260
|
-
return
|
|
336
|
+
return (ctx: any): Promise<LoaderResult> => {
|
|
261
337
|
try {
|
|
262
|
-
const signal
|
|
263
|
-
ctx?.abortController?.signal ||
|
|
264
|
-
ctx?.signal ||
|
|
265
|
-
new AbortController().signal;
|
|
338
|
+
const signal = getLoaderSignal(ctx);
|
|
266
339
|
const baseRequest: Request | undefined =
|
|
267
340
|
ctx?.context?.request instanceof Request ? ctx.context.request : undefined;
|
|
268
341
|
|
|
269
|
-
const href =
|
|
270
|
-
typeof ctx?.location === 'string'
|
|
271
|
-
? ctx.location
|
|
272
|
-
: ctx?.location?.publicHref ||
|
|
273
|
-
ctx?.location?.href ||
|
|
274
|
-
ctx?.location?.url?.href ||
|
|
275
|
-
'';
|
|
342
|
+
const href = getLoaderHref(ctx);
|
|
276
343
|
|
|
277
|
-
const request = baseRequest
|
|
344
|
+
const request = baseRequest !== undefined
|
|
278
345
|
? new Request(baseRequest, { signal })
|
|
279
346
|
: new Request(href, { signal });
|
|
280
347
|
|
|
281
|
-
const params = mapParamsForModernLoader(ctx
|
|
282
|
-
|
|
283
|
-
const result = await (modernLoader as any)({
|
|
284
|
-
request,
|
|
285
|
-
params,
|
|
286
|
-
context: ctx?.context?.requestContext,
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
if (isResponse(result)) {
|
|
290
|
-
if (isRedirectResponse(result)) {
|
|
291
|
-
const location = result.headers.get('Location') || '/';
|
|
292
|
-
throwTanstackRedirect(location);
|
|
293
|
-
}
|
|
294
|
-
if (result.status === 404) {
|
|
295
|
-
throw notFound();
|
|
296
|
-
}
|
|
297
|
-
}
|
|
348
|
+
const params = mapParamsForModernLoader(getLoaderParams(ctx), opts.hasSplat);
|
|
298
349
|
|
|
299
|
-
return
|
|
350
|
+
return Promise.resolve(
|
|
351
|
+
(modernLoader as any)({
|
|
352
|
+
request,
|
|
353
|
+
params,
|
|
354
|
+
context: ctx?.context?.requestContext,
|
|
355
|
+
}),
|
|
356
|
+
)
|
|
357
|
+
.then((result: LoaderResult) => handleModernLoaderResult(result))
|
|
358
|
+
.catch(handleModernLoaderError);
|
|
300
359
|
} catch (err) {
|
|
301
|
-
|
|
302
|
-
if (isRedirectResponse(err)) {
|
|
303
|
-
const location = err.headers.get('Location') || '/';
|
|
304
|
-
throwTanstackRedirect(location);
|
|
305
|
-
}
|
|
306
|
-
if (err.status === 404) {
|
|
307
|
-
throw notFound();
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
throw err;
|
|
360
|
+
handleModernLoaderError(err);
|
|
311
361
|
}
|
|
312
362
|
};
|
|
313
363
|
}
|
|
@@ -5,13 +5,14 @@ import { merge } from "@modern-js/runtime-utils/merge";
|
|
|
5
5
|
import { normalizePathname } from "@modern-js/runtime-utils/url";
|
|
6
6
|
import { RouterProvider, createBrowserHistory, createHashHistory, createRouter, useLocation, useMatches, useNavigate, useRouter } from "@tanstack/react-router";
|
|
7
7
|
import { RouterClient } from "@tanstack/react-router/ssr/client";
|
|
8
|
+
import { useContext, useMemo } from "react";
|
|
8
9
|
import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
|
|
9
10
|
import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
|
|
10
11
|
import { applyRouterRuntimeState } from "./lifecycle.mjs";
|
|
12
|
+
import { Link } from "./prefetchLink.mjs";
|
|
11
13
|
import { createRouteTreeFromRouteObjects } from "./routeTree.mjs";
|
|
12
14
|
import { getTanstackRscSerializationAdapters } from "./rsc/client.mjs";
|
|
13
15
|
import { createRouteObjectsFromConfig, urlJoin } from "./utils.mjs";
|
|
14
|
-
import * as __rspack_external_react from "react";
|
|
15
16
|
const BLOCKING_SUBSCRIBE_SYMBOL = Symbol.for('@modern-js/plugin-tanstack:blocking-subscribe');
|
|
16
17
|
const BLOCKING_STATE_SYMBOL = Symbol.for('@modern-js/plugin-tanstack:blocking-state');
|
|
17
18
|
function normalizeBase(b) {
|
|
@@ -74,6 +75,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
context.router = {
|
|
78
|
+
Link: Link,
|
|
77
79
|
useMatches: useMatches,
|
|
78
80
|
useLocation: useLocation,
|
|
79
81
|
useNavigate: useNavigate,
|
|
@@ -108,10 +110,10 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
108
110
|
let cachedRouter = null;
|
|
109
111
|
let cachedRouterBasepath = null;
|
|
110
112
|
const RouterWrapper = ()=>{
|
|
111
|
-
const runtimeContext =
|
|
113
|
+
const runtimeContext = useContext(InternalRuntimeContext);
|
|
112
114
|
const baseUrl = selectBasePath(location.pathname).replace(/^\/*/, '/');
|
|
113
115
|
const _basename = '/' === baseUrl ? urlJoin(baseUrl, runtimeContext._internalRouterBaseName || basename || '') : baseUrl;
|
|
114
|
-
const routeTree =
|
|
116
|
+
const routeTree = useMemo(()=>{
|
|
115
117
|
if (cachedRouteTree) return cachedRouteTree;
|
|
116
118
|
const routeObjects = getRouteObjects();
|
|
117
119
|
if (!routeObjects.length) return null;
|
|
@@ -121,7 +123,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
121
123
|
return cachedRouteTree;
|
|
122
124
|
}, []);
|
|
123
125
|
if (!routeTree) return App ? /*#__PURE__*/ jsx(App, {}) : null;
|
|
124
|
-
const router =
|
|
126
|
+
const router = useMemo(()=>{
|
|
125
127
|
const lifecycleContext = {
|
|
126
128
|
framework: 'tanstack',
|
|
127
129
|
phase: 'client-create',
|
|
@@ -186,11 +188,8 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
186
188
|
router,
|
|
187
189
|
runtimeContext: runtimeState
|
|
188
190
|
});
|
|
189
|
-
const RouterContent = hasSSRBootstrap ? /*#__PURE__*/ jsx(
|
|
190
|
-
|
|
191
|
-
children: /*#__PURE__*/ jsx(RouterClient, {
|
|
192
|
-
router: router
|
|
193
|
-
})
|
|
191
|
+
const RouterContent = hasSSRBootstrap ? /*#__PURE__*/ jsx(RouterClient, {
|
|
192
|
+
router: router
|
|
194
193
|
}) : /*#__PURE__*/ jsx(RouterProvider, {
|
|
195
194
|
router: router
|
|
196
195
|
});
|
|
@@ -6,8 +6,8 @@ import { createRequestContext, storage } from "@modern-js/runtime-utils/node";
|
|
|
6
6
|
import { time } from "@modern-js/runtime-utils/time";
|
|
7
7
|
import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants";
|
|
8
8
|
import { RouterProvider, createMemoryHistory, createRouter } from "@tanstack/react-router";
|
|
9
|
-
import { attachRouterServerSsrUtils } from "@tanstack/
|
|
10
|
-
import {
|
|
9
|
+
import { attachRouterServerSsrUtils } from "@tanstack/router-core/ssr/server";
|
|
10
|
+
import { useContext } from "react";
|
|
11
11
|
import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
|
|
12
12
|
import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
|
|
13
13
|
import { applyRouterServerPrepareResult, createRouterServerSnapshot } from "./lifecycle.mjs";
|
|
@@ -18,12 +18,28 @@ const setTanstackRscServerPayload = (payload)=>{
|
|
|
18
18
|
const storageContext = storage.useContext?.();
|
|
19
19
|
if (storageContext) storageContext.serverPayload = payload;
|
|
20
20
|
};
|
|
21
|
+
function isPromiseLike(value) {
|
|
22
|
+
return Boolean(value && 'function' == typeof value.then);
|
|
23
|
+
}
|
|
21
24
|
function isPreloadableRouteComponent(component) {
|
|
22
25
|
if (!component || 'function' != typeof component) return false;
|
|
23
26
|
const preloadable = component;
|
|
24
27
|
return 'function' == typeof preloadable.load || 'function' == typeof preloadable.preload;
|
|
25
28
|
}
|
|
29
|
+
function isReactLazyRouteComponent(component) {
|
|
30
|
+
return Boolean(component) && 'object' == typeof component && 'function' == typeof component._init && '_payload' in component;
|
|
31
|
+
}
|
|
32
|
+
async function preloadReactLazyRouteComponent(component) {
|
|
33
|
+
try {
|
|
34
|
+
component._init?.(component._payload);
|
|
35
|
+
} catch (thrown) {
|
|
36
|
+
if (!isPromiseLike(thrown)) throw thrown;
|
|
37
|
+
await thrown;
|
|
38
|
+
component._init?.(component._payload);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
26
41
|
async function preloadRouteComponent(component) {
|
|
42
|
+
if (isReactLazyRouteComponent(component)) return void await preloadReactLazyRouteComponent(component);
|
|
27
43
|
if (!isPreloadableRouteComponent(component)) return;
|
|
28
44
|
if ('function' == typeof component.load) return void await component.load({});
|
|
29
45
|
await component.preload?.({});
|
|
@@ -207,10 +223,12 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
207
223
|
await preloadMatchedRouteComponents(serverRouter);
|
|
208
224
|
context.ssrContext?.response.status(tanstackRouter.state.statusCode);
|
|
209
225
|
await serverRouter.serverSsr?.dehydrate?.();
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
226
|
+
if (isRSCNavigation) {
|
|
227
|
+
await waitForRouterSerialization(serverRouter);
|
|
228
|
+
setTanstackRscServerPayload(createTanstackRscServerPayload(serverRouter, {
|
|
229
|
+
omitClientLoaderData: true
|
|
230
|
+
}));
|
|
231
|
+
}
|
|
214
232
|
const ssrScriptTags = serverRouter.serverSsr?.takeBufferedScripts?.();
|
|
215
233
|
const hydrationScripts = routerManagedTagsToHtml(ssrScriptTags);
|
|
216
234
|
const matchedRouteIds = getModernRouteIdsFromMatches(serverRouter);
|
|
@@ -248,11 +266,8 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
248
266
|
if (!router) return App ? /*#__PURE__*/ jsx(App, {
|
|
249
267
|
...props
|
|
250
268
|
}) : null;
|
|
251
|
-
const routerWrapper = /*#__PURE__*/ jsx(
|
|
252
|
-
|
|
253
|
-
children: /*#__PURE__*/ jsx(RouterProvider, {
|
|
254
|
-
router: router
|
|
255
|
-
})
|
|
269
|
+
const routerWrapper = /*#__PURE__*/ jsx(RouterProvider, {
|
|
270
|
+
router: router
|
|
256
271
|
});
|
|
257
272
|
return App ? /*#__PURE__*/ jsx(App, {
|
|
258
273
|
children: routerWrapper
|