@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.30 → 3.5.0-ultramodern.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/cli/artifacts.js +157 -0
- package/dist/cjs/cli/index.js +6 -103
- package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +113 -0
- package/dist/cjs/cli/tanstackTypes/shared.js +130 -0
- package/dist/cjs/cli/tanstackTypes/source.js +251 -0
- package/dist/cjs/cli/tanstackTypes.js +4 -350
- package/dist/cjs/runtime/blockingSubscribe.js +64 -0
- package/dist/cjs/runtime/{pluginCore.js → clientBasepath.js} +12 -19
- package/dist/cjs/runtime/clientHydration.js +129 -0
- package/dist/cjs/runtime/dataMutation.js +11 -176
- package/dist/cjs/runtime/formData.js +116 -0
- package/dist/cjs/runtime/loaderBridge.js +4 -1
- package/dist/cjs/runtime/plugin.js +21 -125
- package/dist/cjs/runtime/plugin.node.js +38 -119
- package/dist/cjs/runtime/pluginShared.js +90 -0
- package/dist/cjs/runtime/routeTree/components.js +102 -0
- package/dist/cjs/runtime/routeTree/construction.js +152 -0
- package/dist/cjs/runtime/routeTree/index.js +47 -0
- package/dist/cjs/runtime/routeTree/loaders.js +158 -0
- package/dist/cjs/runtime/routeTree/paths.js +57 -0
- package/dist/cjs/runtime/routeTree/staticData.js +63 -0
- package/dist/cjs/runtime/routeTree/tanstackRoutes.js +57 -0
- package/dist/cjs/runtime/routeTree/types.js +18 -0
- package/dist/cjs/runtime/routeTree.js +7 -320
- package/dist/cjs/runtime/rsc/CompositeComponent.js +18 -13
- package/dist/cjs/runtime/rsc/RscNodeRenderer.js +5 -16
- package/dist/cjs/runtime/rsc/client.js +8 -25
- package/dist/cjs/runtime/rsc/flightSerialization.js +132 -0
- package/dist/cjs/runtime/rsc/payloadErrors.js +99 -0
- package/dist/cjs/runtime/rsc/payloadFetch.js +117 -0
- package/dist/cjs/runtime/rsc/payloadRouter.js +21 -142
- package/dist/cjs/runtime/rsc/payloadRoutes.js +106 -0
- package/dist/cjs/runtime/rsc/payloadStorage.js +58 -0
- package/dist/cjs/runtime/rsc/server.js +14 -18
- package/dist/cjs/runtime/rsc/shared.js +71 -0
- package/dist/cjs/runtime/rsc/treeGetter.js +72 -0
- package/dist/cjs/runtime/ssrManagedTags.js +103 -0
- package/dist/cjs/runtime/ssrPreload.js +89 -0
- package/dist/cjs/runtime/ssrTypes.js +18 -0
- package/dist/cjs/runtime/submitAction.js +161 -0
- package/dist/cjs/runtime/utils.js +49 -86
- package/dist/esm/cli/artifacts.mjs +103 -0
- package/dist/esm/cli/index.mjs +4 -101
- package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +75 -0
- package/dist/esm/cli/tanstackTypes/shared.mjs +68 -0
- package/dist/esm/cli/tanstackTypes/source.mjs +203 -0
- package/dist/esm/cli/tanstackTypes.mjs +2 -339
- package/dist/esm/runtime/blockingSubscribe.mjs +19 -0
- package/dist/esm/runtime/clientBasepath.mjs +10 -0
- package/dist/esm/runtime/clientHydration.mjs +70 -0
- package/dist/esm/runtime/dataMutation.mjs +2 -167
- package/dist/esm/runtime/formData.mjs +63 -0
- package/dist/esm/runtime/loaderBridge.mjs +4 -1
- package/dist/esm/runtime/plugin.mjs +14 -118
- package/dist/esm/runtime/plugin.node.mjs +33 -114
- package/dist/esm/runtime/pluginShared.mjs +40 -0
- package/dist/esm/runtime/routeTree/components.mjs +55 -0
- package/dist/esm/runtime/routeTree/construction.mjs +111 -0
- package/dist/esm/runtime/routeTree/index.mjs +2 -0
- package/dist/esm/runtime/routeTree/loaders.mjs +117 -0
- package/dist/esm/runtime/routeTree/paths.mjs +16 -0
- package/dist/esm/runtime/routeTree/staticData.mjs +22 -0
- package/dist/esm/runtime/routeTree/tanstackRoutes.mjs +13 -0
- package/dist/esm/runtime/routeTree/types.mjs +0 -0
- package/dist/esm/runtime/routeTree.mjs +1 -318
- package/dist/esm/runtime/rsc/CompositeComponent.mjs +18 -13
- package/dist/esm/runtime/rsc/RscNodeRenderer.mjs +4 -15
- package/dist/esm/runtime/rsc/client.mjs +6 -26
- package/dist/esm/runtime/rsc/flightSerialization.mjs +88 -0
- package/dist/esm/runtime/rsc/payloadErrors.mjs +49 -0
- package/dist/esm/runtime/rsc/payloadFetch.mjs +61 -0
- package/dist/esm/runtime/rsc/payloadRouter.mjs +12 -133
- package/dist/esm/runtime/rsc/payloadRoutes.mjs +50 -0
- package/dist/esm/runtime/rsc/payloadStorage.mjs +14 -0
- package/dist/esm/runtime/rsc/server.mjs +17 -21
- package/dist/esm/runtime/rsc/shared.mjs +21 -0
- package/dist/esm/runtime/rsc/treeGetter.mjs +34 -0
- package/dist/esm/runtime/ssrManagedTags.mjs +53 -0
- package/dist/esm/runtime/ssrPreload.mjs +51 -0
- package/dist/esm/runtime/ssrTypes.mjs +0 -0
- package/dist/esm/runtime/submitAction.mjs +120 -0
- package/dist/esm/runtime/utils.mjs +47 -75
- package/dist/esm-node/cli/artifacts.mjs +104 -0
- package/dist/esm-node/cli/index.mjs +4 -101
- package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +76 -0
- package/dist/esm-node/cli/tanstackTypes/shared.mjs +69 -0
- package/dist/esm-node/cli/tanstackTypes/source.mjs +204 -0
- package/dist/esm-node/cli/tanstackTypes.mjs +2 -339
- package/dist/esm-node/runtime/blockingSubscribe.mjs +20 -0
- package/dist/esm-node/runtime/clientBasepath.mjs +11 -0
- package/dist/esm-node/runtime/clientHydration.mjs +71 -0
- package/dist/esm-node/runtime/dataMutation.mjs +2 -167
- package/dist/esm-node/runtime/formData.mjs +64 -0
- package/dist/esm-node/runtime/loaderBridge.mjs +4 -1
- package/dist/esm-node/runtime/plugin.mjs +14 -118
- package/dist/esm-node/runtime/plugin.node.mjs +33 -114
- package/dist/esm-node/runtime/pluginShared.mjs +41 -0
- package/dist/esm-node/runtime/routeTree/components.mjs +56 -0
- package/dist/esm-node/runtime/routeTree/construction.mjs +112 -0
- package/dist/esm-node/runtime/routeTree/index.mjs +3 -0
- package/dist/esm-node/runtime/routeTree/loaders.mjs +118 -0
- package/dist/esm-node/runtime/routeTree/paths.mjs +17 -0
- package/dist/esm-node/runtime/routeTree/staticData.mjs +23 -0
- package/dist/esm-node/runtime/routeTree/tanstackRoutes.mjs +14 -0
- package/dist/esm-node/runtime/routeTree/types.mjs +1 -0
- package/dist/esm-node/runtime/routeTree.mjs +1 -318
- package/dist/esm-node/runtime/rsc/CompositeComponent.mjs +18 -13
- package/dist/esm-node/runtime/rsc/RscNodeRenderer.mjs +4 -15
- package/dist/esm-node/runtime/rsc/client.mjs +6 -26
- package/dist/esm-node/runtime/rsc/flightSerialization.mjs +89 -0
- package/dist/esm-node/runtime/rsc/payloadErrors.mjs +50 -0
- package/dist/esm-node/runtime/rsc/payloadFetch.mjs +62 -0
- package/dist/esm-node/runtime/rsc/payloadRouter.mjs +12 -133
- package/dist/esm-node/runtime/rsc/payloadRoutes.mjs +51 -0
- package/dist/esm-node/runtime/rsc/payloadStorage.mjs +15 -0
- package/dist/esm-node/runtime/rsc/server.mjs +17 -21
- package/dist/esm-node/runtime/rsc/shared.mjs +22 -0
- package/dist/esm-node/runtime/rsc/treeGetter.mjs +35 -0
- package/dist/esm-node/runtime/ssrManagedTags.mjs +54 -0
- package/dist/esm-node/runtime/ssrPreload.mjs +52 -0
- package/dist/esm-node/runtime/ssrTypes.mjs +1 -0
- package/dist/esm-node/runtime/submitAction.mjs +121 -0
- package/dist/esm-node/runtime/utils.mjs +47 -75
- package/dist/types/cli/artifacts.d.ts +33 -0
- package/dist/types/cli/index.d.ts +2 -33
- package/dist/types/cli/tanstackTypes/canonicalRoutes.d.ts +22 -0
- package/dist/types/cli/tanstackTypes/shared.d.ts +20 -0
- package/dist/types/cli/tanstackTypes/source.d.ts +10 -0
- package/dist/types/cli/tanstackTypes.d.ts +3 -31
- package/dist/types/runtime/blockingSubscribe.d.ts +3 -0
- package/dist/types/runtime/clientBasepath.d.ts +1 -0
- package/dist/types/runtime/clientHydration.d.ts +19 -0
- package/dist/types/runtime/dataMutation.d.ts +3 -12
- package/dist/types/runtime/formData.d.ts +23 -0
- package/dist/types/runtime/plugin.d.ts +1 -1
- package/dist/types/runtime/plugin.node.d.ts +1 -1
- package/dist/types/runtime/{pluginCore.d.ts → pluginShared.d.ts} +14 -0
- package/dist/types/runtime/routeTree/components.d.ts +7 -0
- package/dist/types/runtime/routeTree/construction.d.ts +5 -0
- package/dist/types/runtime/routeTree/index.d.ts +2 -0
- package/dist/types/runtime/routeTree/loaders.d.ts +4 -0
- package/dist/types/runtime/routeTree/paths.d.ts +3 -0
- package/dist/types/runtime/routeTree/staticData.d.ts +19 -0
- package/dist/types/runtime/routeTree/tanstackRoutes.d.ts +4 -0
- package/dist/types/runtime/routeTree/types.d.ts +75 -0
- package/dist/types/runtime/routeTree.d.ts +1 -9
- package/dist/types/runtime/rsc/CompositeComponent.d.ts +1 -2
- package/dist/types/runtime/rsc/RscNodeRenderer.d.ts +2 -3
- package/dist/types/runtime/rsc/client.d.ts +2 -0
- package/dist/types/runtime/rsc/flightSerialization.d.ts +3 -0
- package/dist/types/runtime/rsc/payloadErrors.d.ts +6 -0
- package/dist/types/runtime/rsc/payloadFetch.d.ts +10 -0
- package/dist/types/runtime/rsc/payloadRouter.d.ts +2 -10
- package/dist/types/runtime/rsc/payloadRoutes.d.ts +43 -0
- package/dist/types/runtime/rsc/payloadStorage.d.ts +5 -0
- package/dist/types/runtime/rsc/shared.d.ts +19 -0
- package/dist/types/runtime/rsc/treeGetter.d.ts +1 -0
- package/dist/types/runtime/ssrManagedTags.d.ts +7 -0
- package/dist/types/runtime/ssrPreload.d.ts +2 -0
- package/dist/types/runtime/ssrTypes.d.ts +43 -0
- package/dist/types/runtime/state.d.ts +1 -1
- package/dist/types/runtime/submitAction.d.ts +14 -0
- package/dist/types/runtime/types.d.ts +3 -46
- package/dist/types/runtime/utils.d.ts +1 -22
- package/package.json +30 -9
- package/rstest.config.mts +1 -0
- package/src/cli/artifacts.ts +255 -0
- package/src/cli/index.ts +6 -246
- package/src/cli/tanstackTypes/canonicalRoutes.ts +157 -0
- package/src/cli/tanstackTypes/shared.ts +119 -0
- package/src/cli/tanstackTypes/source.ts +405 -0
- package/src/cli/tanstackTypes.ts +4 -647
- package/src/runtime/blockingSubscribe.ts +48 -0
- package/src/runtime/clientBasepath.ts +12 -0
- package/src/runtime/clientHydration.ts +151 -0
- package/src/runtime/dataMutation.tsx +9 -306
- package/src/runtime/formData.ts +153 -0
- package/src/runtime/loaderBridge.ts +8 -3
- package/src/runtime/plugin.node.tsx +60 -284
- package/src/runtime/plugin.tsx +21 -257
- package/src/runtime/pluginShared.ts +112 -0
- package/src/runtime/routeTree/components.ts +130 -0
- package/src/runtime/routeTree/construction.ts +238 -0
- package/src/runtime/routeTree/index.ts +7 -0
- package/src/runtime/routeTree/loaders.ts +232 -0
- package/src/runtime/routeTree/paths.ts +36 -0
- package/src/runtime/routeTree/staticData.ts +66 -0
- package/src/runtime/routeTree/tanstackRoutes.ts +36 -0
- package/src/runtime/routeTree/types.ts +87 -0
- package/src/runtime/routeTree.ts +5 -750
- package/src/runtime/rsc/CompositeComponent.tsx +29 -20
- package/src/runtime/rsc/RscNodeRenderer.tsx +9 -27
- package/src/runtime/rsc/client.tsx +12 -40
- package/src/runtime/rsc/flightSerialization.ts +158 -0
- package/src/runtime/rsc/payloadErrors.ts +73 -0
- package/src/runtime/rsc/payloadFetch.ts +97 -0
- package/src/runtime/rsc/payloadRouter.ts +29 -234
- package/src/runtime/rsc/payloadRoutes.ts +122 -0
- package/src/runtime/rsc/payloadStorage.ts +35 -0
- package/src/runtime/rsc/server.tsx +20 -29
- package/src/runtime/rsc/shared.ts +70 -0
- package/src/runtime/rsc/treeGetter.tsx +52 -0
- package/src/runtime/ssrManagedTags.ts +107 -0
- package/src/runtime/ssrPreload.ts +125 -0
- package/src/runtime/ssrTypes.ts +51 -0
- package/src/runtime/state.ts +4 -2
- package/src/runtime/submitAction.ts +194 -0
- package/src/runtime/types.ts +14 -51
- package/src/runtime/utils.tsx +72 -108
- package/src/types/react-server-dom-rspack.d.ts +56 -0
- package/tests/castRatchet.test.ts +85 -0
- package/tests/router/dataMutation.test.tsx +59 -0
- package/tests/router/fixtures/router-gen.golden.txt +72 -0
- package/tests/router/loaderBridge.test.ts +21 -0
- package/tests/router/routeTree.test.ts +51 -11
- package/tests/router/rsc.test.tsx +189 -0
- package/tests/router/ssrPreload.test.ts +30 -0
- package/tests/router/tanstackTypes.test.ts +254 -1
- package/dist/esm/runtime/pluginCore.mjs +0 -14
- package/dist/esm-node/runtime/pluginCore.mjs +0 -15
- package/src/runtime/pluginCore.ts +0 -56
|
@@ -2,173 +2,8 @@ import "node:module";
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useRouter } from "@tanstack/react-router";
|
|
4
4
|
import { useCallback, useRef, useState } from "react";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
super(`Route action failed with status ${response.status}`);
|
|
8
|
-
this.name = 'RouteActionResponseError';
|
|
9
|
-
this.response = response;
|
|
10
|
-
this.data = data;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
function formDataToUrlSearchParams(formData) {
|
|
14
|
-
const searchParams = new URLSearchParams();
|
|
15
|
-
formData.forEach((value, key)=>{
|
|
16
|
-
if ('string' == typeof value) searchParams.append(key, value);
|
|
17
|
-
});
|
|
18
|
-
return searchParams;
|
|
19
|
-
}
|
|
20
|
-
function formDataToTextPlain(formData) {
|
|
21
|
-
return Array.from(formData.entries()).map(([key, value])=>`${key}=${String(value)}`).join('\n');
|
|
22
|
-
}
|
|
23
|
-
function toFormData(target) {
|
|
24
|
-
if (target instanceof HTMLFormElement) return new FormData(target);
|
|
25
|
-
if (target instanceof FormData) return target;
|
|
26
|
-
if (target instanceof URLSearchParams) {
|
|
27
|
-
const formData = new FormData();
|
|
28
|
-
target.forEach((value, key)=>{
|
|
29
|
-
formData.append(key, value);
|
|
30
|
-
});
|
|
31
|
-
return formData;
|
|
32
|
-
}
|
|
33
|
-
const formData = new FormData();
|
|
34
|
-
Object.entries(target).forEach(([key, value])=>{
|
|
35
|
-
if (null == value) return;
|
|
36
|
-
formData.append(key, String(value));
|
|
37
|
-
});
|
|
38
|
-
return formData;
|
|
39
|
-
}
|
|
40
|
-
function getSubmitter(event) {
|
|
41
|
-
const nativeEvent = event.nativeEvent;
|
|
42
|
-
const submitter = nativeEvent?.submitter;
|
|
43
|
-
if (submitter instanceof HTMLButtonElement || submitter instanceof HTMLInputElement) return submitter;
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
function createFormDataFromSubmit({ form, submitter }) {
|
|
47
|
-
if (submitter) try {
|
|
48
|
-
return new FormData(form, submitter);
|
|
49
|
-
} catch {}
|
|
50
|
-
return new FormData(form);
|
|
51
|
-
}
|
|
52
|
-
function resolveSubmitOptionsFromForm({ form, submitter, action, method, encType }) {
|
|
53
|
-
const resolvedAction = submitter?.getAttribute('formaction') || action || form.getAttribute('action') || '.';
|
|
54
|
-
const resolvedMethod = (submitter?.getAttribute('formmethod') || method || form.getAttribute('method') || 'get').toLowerCase();
|
|
55
|
-
const resolvedEncType = submitter?.getAttribute('formenctype') || encType || form.getAttribute('enctype') || 'application/x-www-form-urlencoded';
|
|
56
|
-
return {
|
|
57
|
-
action: resolvedAction,
|
|
58
|
-
method: resolvedMethod,
|
|
59
|
-
encType: resolvedEncType
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
function resolveRouteHandlers(router, actionTo) {
|
|
63
|
-
const builtLocation = router.buildLocation({
|
|
64
|
-
to: actionTo
|
|
65
|
-
});
|
|
66
|
-
const href = router.getParsedLocationHref(builtLocation);
|
|
67
|
-
const matchedRoutes = router.getMatchedRoutes(builtLocation.pathname);
|
|
68
|
-
const routeStaticData = matchedRoutes.foundRoute?.options?.staticData;
|
|
69
|
-
const action = routeStaticData?.modernRouteAction;
|
|
70
|
-
const loader = routeStaticData?.modernRouteLoader;
|
|
71
|
-
return {
|
|
72
|
-
action,
|
|
73
|
-
loader,
|
|
74
|
-
href,
|
|
75
|
-
params: matchedRoutes.routeParams || {}
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
function isRedirectResponse(value) {
|
|
79
|
-
if (!(value instanceof Response)) return false;
|
|
80
|
-
return [
|
|
81
|
-
301,
|
|
82
|
-
302,
|
|
83
|
-
303,
|
|
84
|
-
307,
|
|
85
|
-
308
|
|
86
|
-
].includes(value.status);
|
|
87
|
-
}
|
|
88
|
-
async function parseResponseData(response) {
|
|
89
|
-
if (204 === response.status) return null;
|
|
90
|
-
const contentType = response.headers.get('Content-Type') || '';
|
|
91
|
-
if (contentType.includes('application/json')) return response.json();
|
|
92
|
-
return response.text();
|
|
93
|
-
}
|
|
94
|
-
async function parseResponseResultOrThrow(response) {
|
|
95
|
-
const parsed = await parseResponseData(response);
|
|
96
|
-
if (!response.ok) throw new RouteActionResponseError(response, parsed);
|
|
97
|
-
return parsed;
|
|
98
|
-
}
|
|
99
|
-
async function submitRouteAction({ router, target, options = {}, isFetcher = false, onInvalidateStart }) {
|
|
100
|
-
const method = (options.method || 'post').toLowerCase();
|
|
101
|
-
const encType = options.encType || 'application/x-www-form-urlencoded';
|
|
102
|
-
const actionTo = options.action || '.';
|
|
103
|
-
const formData = toFormData(target);
|
|
104
|
-
const resolved = resolveRouteHandlers(router, actionTo);
|
|
105
|
-
if ('get' === method) {
|
|
106
|
-
const search = formDataToUrlSearchParams(formData).toString();
|
|
107
|
-
const requestUrl = new URL(resolved.href, window.location.origin);
|
|
108
|
-
requestUrl.search = search;
|
|
109
|
-
if (isFetcher && resolved.loader) {
|
|
110
|
-
const result = await resolved.loader({
|
|
111
|
-
request: new Request(requestUrl, {
|
|
112
|
-
method: 'GET'
|
|
113
|
-
}),
|
|
114
|
-
params: resolved.params
|
|
115
|
-
});
|
|
116
|
-
if (result instanceof Response) {
|
|
117
|
-
const redirectTo = result.headers.get('X-Modernjs-Redirect') || result.headers.get('Location');
|
|
118
|
-
if (redirectTo || isRedirectResponse(result)) {
|
|
119
|
-
await router.navigate({
|
|
120
|
-
to: redirectTo || '/'
|
|
121
|
-
});
|
|
122
|
-
return parseResponseData(result);
|
|
123
|
-
}
|
|
124
|
-
return parseResponseResultOrThrow(result);
|
|
125
|
-
}
|
|
126
|
-
return result;
|
|
127
|
-
}
|
|
128
|
-
await router.navigate({
|
|
129
|
-
href: search ? `${resolved.href}?${search}` : resolved.href
|
|
130
|
-
});
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
if (!resolved.action) throw new Error(`No route action found for "${actionTo}"`);
|
|
134
|
-
const headers = new Headers();
|
|
135
|
-
let body = null;
|
|
136
|
-
if (encType.includes('application/json')) {
|
|
137
|
-
headers.set('Content-Type', 'application/json');
|
|
138
|
-
body = JSON.stringify(Object.fromEntries(formDataToUrlSearchParams(formData).entries()));
|
|
139
|
-
} else if (encType.includes('text/plain')) {
|
|
140
|
-
headers.set('Content-Type', 'text/plain;charset=UTF-8');
|
|
141
|
-
body = formDataToTextPlain(formData);
|
|
142
|
-
} else if (encType.includes('application/x-www-form-urlencoded')) {
|
|
143
|
-
headers.set('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8');
|
|
144
|
-
body = formDataToUrlSearchParams(formData);
|
|
145
|
-
} else body = formData;
|
|
146
|
-
const request = new Request(new URL(resolved.href, window.location.origin), {
|
|
147
|
-
method: method.toUpperCase(),
|
|
148
|
-
headers,
|
|
149
|
-
body
|
|
150
|
-
});
|
|
151
|
-
const result = await resolved.action({
|
|
152
|
-
request,
|
|
153
|
-
params: resolved.params
|
|
154
|
-
});
|
|
155
|
-
if (result instanceof Response) {
|
|
156
|
-
const redirectTo = result.headers.get('X-Modernjs-Redirect') || result.headers.get('Location');
|
|
157
|
-
if (redirectTo || isRedirectResponse(result)) {
|
|
158
|
-
await router.navigate({
|
|
159
|
-
to: redirectTo || '/'
|
|
160
|
-
});
|
|
161
|
-
return parseResponseData(result);
|
|
162
|
-
}
|
|
163
|
-
const parsed = isFetcher ? await parseResponseResultOrThrow(result) : await parseResponseData(result);
|
|
164
|
-
onInvalidateStart?.();
|
|
165
|
-
await router.invalidate();
|
|
166
|
-
return parsed;
|
|
167
|
-
}
|
|
168
|
-
onInvalidateStart?.();
|
|
169
|
-
await router.invalidate();
|
|
170
|
-
return result;
|
|
171
|
-
}
|
|
5
|
+
import { createFormDataFromSubmit, getSubmitter, resolveSubmitOptionsFromForm } from "./formData.mjs";
|
|
6
|
+
import { RouteActionResponseError, submitRouteAction } from "./submitAction.mjs";
|
|
172
7
|
function Form({ action, method = 'get', encType, reloadDocument, onSubmit, ...rest }) {
|
|
173
8
|
const router = useRouter();
|
|
174
9
|
const handleSubmit = useCallback(async (event)=>{
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
function formDataToUrlSearchParams(formData) {
|
|
3
|
+
const searchParams = new URLSearchParams();
|
|
4
|
+
formData.forEach((value, key)=>{
|
|
5
|
+
if ('string' == typeof value) searchParams.append(key, value);
|
|
6
|
+
});
|
|
7
|
+
return searchParams;
|
|
8
|
+
}
|
|
9
|
+
function formDataToTextPlain(formData) {
|
|
10
|
+
return Array.from(formData.entries()).map(([key, value])=>`${key}=${String(value)}`).join('\n');
|
|
11
|
+
}
|
|
12
|
+
function toFormData(target) {
|
|
13
|
+
if (target instanceof HTMLFormElement) return new FormData(target);
|
|
14
|
+
if (target instanceof FormData) return target;
|
|
15
|
+
if (target instanceof URLSearchParams) {
|
|
16
|
+
const formData = new FormData();
|
|
17
|
+
target.forEach((value, key)=>{
|
|
18
|
+
formData.append(key, value);
|
|
19
|
+
});
|
|
20
|
+
return formData;
|
|
21
|
+
}
|
|
22
|
+
const formData = new FormData();
|
|
23
|
+
Object.entries(target).forEach(([key, value])=>{
|
|
24
|
+
if (null == value) return;
|
|
25
|
+
formData.append(key, String(value));
|
|
26
|
+
});
|
|
27
|
+
return formData;
|
|
28
|
+
}
|
|
29
|
+
function getSubmitter(event) {
|
|
30
|
+
const nativeEvent = event.nativeEvent;
|
|
31
|
+
const submitter = nativeEvent?.submitter;
|
|
32
|
+
if (submitter instanceof HTMLButtonElement || submitter instanceof HTMLInputElement) return submitter;
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function appendSubmitterValue(formData, form, submitter) {
|
|
36
|
+
if (submitter.form !== form || submitter.disabled) return;
|
|
37
|
+
if (submitter instanceof HTMLInputElement && 'image' === submitter.type) {
|
|
38
|
+
const namePrefix = submitter.name ? `${submitter.name}.` : '';
|
|
39
|
+
formData.append(`${namePrefix}x`, '0');
|
|
40
|
+
formData.append(`${namePrefix}y`, '0');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!submitter.name || 'button' === submitter.type || 'reset' === submitter.type) return;
|
|
44
|
+
formData.append(submitter.name, submitter.value);
|
|
45
|
+
}
|
|
46
|
+
function createFormDataFromSubmit({ form, submitter }) {
|
|
47
|
+
if (submitter) try {
|
|
48
|
+
return new FormData(form, submitter);
|
|
49
|
+
} catch {}
|
|
50
|
+
const formData = new FormData(form);
|
|
51
|
+
if (submitter) appendSubmitterValue(formData, form, submitter);
|
|
52
|
+
return formData;
|
|
53
|
+
}
|
|
54
|
+
function resolveSubmitOptionsFromForm({ form, submitter, action, method, encType }) {
|
|
55
|
+
const resolvedAction = submitter?.getAttribute('formaction') || action || form.getAttribute('action') || '.';
|
|
56
|
+
const resolvedMethod = (submitter?.getAttribute('formmethod') || method || form.getAttribute('method') || 'get').toLowerCase();
|
|
57
|
+
const resolvedEncType = submitter?.getAttribute('formenctype') || encType || form.getAttribute('enctype') || 'application/x-www-form-urlencoded';
|
|
58
|
+
return {
|
|
59
|
+
action: resolvedAction,
|
|
60
|
+
method: resolvedMethod,
|
|
61
|
+
encType: resolvedEncType
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export { createFormDataFromSubmit, formDataToTextPlain, formDataToUrlSearchParams, getSubmitter, resolveSubmitOptionsFromForm, toFormData };
|
|
@@ -96,7 +96,10 @@ function modernLoaderToTanstack(opts, modernLoader) {
|
|
|
96
96
|
const signal = getLoaderSignal(ctx);
|
|
97
97
|
const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
|
|
98
98
|
const href = getLoaderHref(ctx);
|
|
99
|
-
const request = void 0 !== baseRequest ? new Request(baseRequest, {
|
|
99
|
+
const request = void 0 !== baseRequest && '' !== href ? new Request(new URL(href, baseRequest.url).href, {
|
|
100
|
+
headers: baseRequest.headers,
|
|
101
|
+
signal
|
|
102
|
+
}) : void 0 !== baseRequest ? new Request(baseRequest, {
|
|
100
103
|
signal
|
|
101
104
|
}) : new Request(href, {
|
|
102
105
|
signal
|
|
@@ -5,123 +5,18 @@ import { normalizePathname } from "@modern-js/runtime-utils/url";
|
|
|
5
5
|
import { RouterProvider, createBrowserHistory, createHashHistory, createRouter, useLocation, useNavigate, useRouter } from "@tanstack/react-router";
|
|
6
6
|
import { useContext, useMemo } from "react";
|
|
7
7
|
import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
|
|
8
|
+
import { wrapRouterSubscribeWithBlockState } from "./blockingSubscribe.mjs";
|
|
9
|
+
import { isSegmentPrefix } from "./clientBasepath.mjs";
|
|
10
|
+
import { ModernRouterClient, getTanstackSsrHydrationPromise, hasTanstackSsrHydrationRecord } from "./clientHydration.mjs";
|
|
8
11
|
import { routerProviderRegistryHooks } from "./hooks.mjs";
|
|
9
12
|
import { wrapTanstackSsrHydrationBoundary } from "./hydrationBoundary.mjs";
|
|
10
13
|
import { applyRouterRuntimeState } from "./lifecycle.mjs";
|
|
11
|
-
import {
|
|
12
|
-
import { getFinalRouteConfig, getMergedRouterConfig } from "./pluginCore.mjs";
|
|
14
|
+
import { createTanstackRouteObjects, getMergedRouterConfig, getTanstackRouteConfig, joinBasename } from "./pluginShared.mjs";
|
|
13
15
|
import { Link } from "./prefetchLink.mjs";
|
|
14
16
|
import { useMatches } from "./routeHooks.mjs";
|
|
15
17
|
import { createRouteTreeFromRouteObjects } from "./routeTree.mjs";
|
|
16
18
|
import { getTanstackRscSerializationAdapters } from "./rsc/client.mjs";
|
|
17
19
|
import { getModernTanstackRouterFastDefaults } from "./types.mjs";
|
|
18
|
-
import { createRouteObjectsFromConfig, urlJoin } from "./utils.mjs";
|
|
19
|
-
const BLOCKING_SUBSCRIBE_SYMBOL = Symbol.for('@modern-js/plugin-tanstack:blocking-subscribe');
|
|
20
|
-
const BLOCKING_STATE_SYMBOL = Symbol.for('@modern-js/plugin-tanstack:blocking-state');
|
|
21
|
-
function normalizeBase(b) {
|
|
22
|
-
if (b.length > 1 && b.endsWith('/')) return b.slice(0, -1);
|
|
23
|
-
return b || '/';
|
|
24
|
-
}
|
|
25
|
-
function isSegmentPrefix(pathname, base) {
|
|
26
|
-
const b = normalizeBase(base);
|
|
27
|
-
const p = pathname || '/';
|
|
28
|
-
return p === b || p.startsWith(`${b}/`);
|
|
29
|
-
}
|
|
30
|
-
function wrapRouterSubscribeWithBlockState(router, getBlockNavState) {
|
|
31
|
-
if (!router || 'object' != typeof router) return;
|
|
32
|
-
const target = router;
|
|
33
|
-
target[BLOCKING_STATE_SYMBOL] = getBlockNavState;
|
|
34
|
-
if (target[BLOCKING_SUBSCRIBE_SYMBOL] || 'function' != typeof target.subscribe) return;
|
|
35
|
-
const originSubscribe = target.subscribe.bind(target);
|
|
36
|
-
target.subscribe = (eventType, listener)=>{
|
|
37
|
-
const wrappedListener = (...args)=>{
|
|
38
|
-
const blockRoute = target[BLOCKING_STATE_SYMBOL]?.() || false;
|
|
39
|
-
if (blockRoute) return;
|
|
40
|
-
return listener(...args);
|
|
41
|
-
};
|
|
42
|
-
return originSubscribe(eventType, wrappedListener);
|
|
43
|
-
};
|
|
44
|
-
target[BLOCKING_SUBSCRIBE_SYMBOL] = true;
|
|
45
|
-
}
|
|
46
|
-
const routerHydrationRecords = new WeakMap();
|
|
47
|
-
const routeModulesKey = '_routeModules';
|
|
48
|
-
function pickRouteModuleComponent(routeModule, seen = new Set()) {
|
|
49
|
-
if ('function' == typeof routeModule || routeModule && 'object' == typeof routeModule && '$$typeof' in routeModule) return routeModule;
|
|
50
|
-
if (!routeModule || 'object' != typeof routeModule) return;
|
|
51
|
-
if (seen.has(routeModule)) return;
|
|
52
|
-
seen.add(routeModule);
|
|
53
|
-
const module = routeModule;
|
|
54
|
-
for (const candidate of [
|
|
55
|
-
module.default,
|
|
56
|
-
module.Component
|
|
57
|
-
]){
|
|
58
|
-
const component = pickRouteModuleComponent(candidate, seen);
|
|
59
|
-
if (component) return component;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
function getCachedRouteModule(routeId) {
|
|
63
|
-
if ("u" < typeof window) return;
|
|
64
|
-
return window[routeModulesKey]?.[routeId];
|
|
65
|
-
}
|
|
66
|
-
function preloadHydratedRouteComponents(router) {
|
|
67
|
-
const preloadableRouter = router;
|
|
68
|
-
const routesById = preloadableRouter.routesById || {};
|
|
69
|
-
const matches = preloadableRouter.stores.matches.get();
|
|
70
|
-
return Promise.all(matches.map((match)=>{
|
|
71
|
-
if (void 0 === match.routeId || '' === match.routeId) return;
|
|
72
|
-
const route = routesById[match.routeId];
|
|
73
|
-
const component = route?.options?.component;
|
|
74
|
-
const preload = component?.load || component?.preload;
|
|
75
|
-
if ('function' != typeof preload) return;
|
|
76
|
-
return Promise.resolve(preload.call(component)).then((routeModule)=>{
|
|
77
|
-
const modernRouteId = route?.options?.staticData?.modernRouteId;
|
|
78
|
-
const cachedRouteModule = 'string' == typeof modernRouteId && '' !== modernRouteId ? getCachedRouteModule(modernRouteId) : void 0;
|
|
79
|
-
const resolvedComponent = pickRouteModuleComponent(cachedRouteModule ?? routeModule);
|
|
80
|
-
if (void 0 !== resolvedComponent && 'string' == typeof modernRouteId && '' !== modernRouteId) route.options.component = withModernRouteMatchContext(resolvedComponent, modernRouteId);
|
|
81
|
-
});
|
|
82
|
-
})).then(()=>void 0);
|
|
83
|
-
}
|
|
84
|
-
function hydrateTanstackRouter(router) {
|
|
85
|
-
return import("@tanstack/react-router/ssr/client").then(({ hydrate })=>hydrate(router));
|
|
86
|
-
}
|
|
87
|
-
function getTanstackSsrHydrationRecord(router) {
|
|
88
|
-
const existingHydrationRecord = routerHydrationRecords.get(router);
|
|
89
|
-
if (void 0 !== existingHydrationRecord) return existingHydrationRecord;
|
|
90
|
-
const hydrationRecord = {
|
|
91
|
-
promise: Promise.resolve(),
|
|
92
|
-
status: 'pending'
|
|
93
|
-
};
|
|
94
|
-
routerHydrationRecords.set(router, hydrationRecord);
|
|
95
|
-
try {
|
|
96
|
-
hydrationRecord.promise = hydrateTanstackRouter(router).then((value)=>preloadHydratedRouteComponents(router).then(()=>value)).then((value)=>{
|
|
97
|
-
hydrationRecord.status = 'fulfilled';
|
|
98
|
-
return value;
|
|
99
|
-
}, (error)=>{
|
|
100
|
-
hydrationRecord.status = 'rejected';
|
|
101
|
-
hydrationRecord.error = error;
|
|
102
|
-
throw error;
|
|
103
|
-
});
|
|
104
|
-
} catch (error) {
|
|
105
|
-
hydrationRecord.status = 'rejected';
|
|
106
|
-
hydrationRecord.error = error;
|
|
107
|
-
hydrationRecord.promise = Promise.reject(error);
|
|
108
|
-
hydrationRecord.promise.catch(()=>{});
|
|
109
|
-
}
|
|
110
|
-
return hydrationRecord;
|
|
111
|
-
}
|
|
112
|
-
function getTanstackSsrHydrationPromise(router) {
|
|
113
|
-
return getTanstackSsrHydrationRecord(router).promise;
|
|
114
|
-
}
|
|
115
|
-
function hasTanstackSsrHydrationRecord(router) {
|
|
116
|
-
return routerHydrationRecords.has(router);
|
|
117
|
-
}
|
|
118
|
-
function ModernRouterClient({ router }) {
|
|
119
|
-
const hydrationRecord = getTanstackSsrHydrationRecord(router);
|
|
120
|
-
if ('rejected' === hydrationRecord.status) throw hydrationRecord.error;
|
|
121
|
-
return /*#__PURE__*/ jsx(RouterProvider, {
|
|
122
|
-
router: router
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
20
|
const tanstackRouterPlugin = (userConfig = {})=>{
|
|
126
21
|
const plugin = {
|
|
127
22
|
name: '@modern-js/plugin-router-tanstack',
|
|
@@ -135,13 +30,10 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
135
30
|
const getMergedConfig = ()=>getMergedRouterConfig(api, userConfig);
|
|
136
31
|
const getRouteObjects = ()=>{
|
|
137
32
|
if (void 0 !== cachedRouteObjects) return cachedRouteObjects;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
routesConfig: finalRouteConfig
|
|
143
|
-
}) || [];
|
|
144
|
-
cachedRouteObjects = hooks.modifyRoutes.call(routeObjects);
|
|
33
|
+
cachedRouteObjects = createTanstackRouteObjects({
|
|
34
|
+
hooks,
|
|
35
|
+
routeConfig: getTanstackRouteConfig(api, userConfig)
|
|
36
|
+
});
|
|
145
37
|
return cachedRouteObjects;
|
|
146
38
|
};
|
|
147
39
|
const getRouteTree = ()=>{
|
|
@@ -161,7 +53,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
161
53
|
const getClientBasename = (runtimeContext)=>{
|
|
162
54
|
const { basename = '' } = getMergedConfig();
|
|
163
55
|
const baseUrl = selectBasePath(location.pathname).replace(/^\/*/, '/');
|
|
164
|
-
return '/' === baseUrl ?
|
|
56
|
+
return '/' === baseUrl ? joinBasename(baseUrl, runtimeContext._internalRouterBaseName || basename || '') : baseUrl;
|
|
165
57
|
};
|
|
166
58
|
const getRouter = (runtimeContext, _basename)=>{
|
|
167
59
|
const routeTree = getRouteTree();
|
|
@@ -188,8 +80,12 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
188
80
|
const history = supportHtml5History ? createBrowserHistory() : createHashHistory();
|
|
189
81
|
const rewrite = createModernBasepathRewrite(_basename);
|
|
190
82
|
const serializationAdapters = getGlobalEnableRsc() ? getTanstackRscSerializationAdapters() : void 0;
|
|
83
|
+
const routerFastDefaults = getModernTanstackRouterFastDefaults(mergedConfig);
|
|
191
84
|
cachedRouter = createRouter({
|
|
192
|
-
...
|
|
85
|
+
...routerFastDefaults,
|
|
86
|
+
...serializationAdapters ? {
|
|
87
|
+
defaultStructuralSharing: false
|
|
88
|
+
} : {},
|
|
193
89
|
routeTree,
|
|
194
90
|
basepath: '/',
|
|
195
91
|
rewrite,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { InternalRuntimeContext, getGlobalEnableRsc } from "@modern-js/runtime/context";
|
|
4
|
-
import { createRequestContext
|
|
4
|
+
import { createRequestContext } 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";
|
|
@@ -10,131 +10,35 @@ import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
|
|
|
10
10
|
import { routerProviderRegistryHooks } from "./hooks.mjs";
|
|
11
11
|
import { wrapTanstackSsrHydrationBoundary } from "./hydrationBoundary.mjs";
|
|
12
12
|
import { applyRouterServerPrepareResult, createRouterServerSnapshot, getRouterRuntimeState } from "./lifecycle.mjs";
|
|
13
|
-
import {
|
|
13
|
+
import { createTanstackRouteObjects, getTanstackRouteConfig, joinBasename } from "./pluginShared.mjs";
|
|
14
14
|
import { createRouteTreeFromRouteObjects, getModernRouteIdsFromMatches } from "./routeTree.mjs";
|
|
15
15
|
import { createTanstackRscServerPayload, handleTanstackRscRedirect } from "./rsc/payloadRouter.mjs";
|
|
16
|
+
import { getTanstackRscRouter, setTanstackRscRouter, setTanstackRscServerPayload } from "./rsc/payloadStorage.mjs";
|
|
17
|
+
import { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml, waitForRouterSerialization } from "./ssrManagedTags.mjs";
|
|
18
|
+
import { preloadMatchedRouteComponents } from "./ssrPreload.mjs";
|
|
16
19
|
import { getModernTanstackRouterFastDefaults } from "./types.mjs";
|
|
17
|
-
import { createRouteObjectsFromConfig, urlJoin } from "./utils.mjs";
|
|
18
|
-
const setTanstackRscServerPayload = (payload)=>{
|
|
19
|
-
const storageContext = storage.useContext?.();
|
|
20
|
-
if (storageContext) storageContext.serverPayload = payload;
|
|
21
|
-
};
|
|
22
|
-
function isPromiseLike(value) {
|
|
23
|
-
return Boolean(value && 'function' == typeof value.then);
|
|
24
|
-
}
|
|
25
|
-
function isPreloadableRouteComponent(component) {
|
|
26
|
-
if (!component || 'function' != typeof component) return false;
|
|
27
|
-
const preloadable = component;
|
|
28
|
-
return 'function' == typeof preloadable.load || 'function' == typeof preloadable.preload;
|
|
29
|
-
}
|
|
30
|
-
function isReactLazyRouteComponent(component) {
|
|
31
|
-
return null != component && 'object' == typeof component && 'function' == typeof component._init && '_payload' in component;
|
|
32
|
-
}
|
|
33
|
-
async function preloadReactLazyRouteComponent(component) {
|
|
34
|
-
try {
|
|
35
|
-
component._init?.(component._payload);
|
|
36
|
-
} catch (thrown) {
|
|
37
|
-
if (!isPromiseLike(thrown)) throw thrown;
|
|
38
|
-
await thrown;
|
|
39
|
-
component._init?.(component._payload);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
async function preloadRouteComponent(component) {
|
|
43
|
-
if (isReactLazyRouteComponent(component)) return void await preloadReactLazyRouteComponent(component);
|
|
44
|
-
if (!isPreloadableRouteComponent(component)) return;
|
|
45
|
-
if ('function' == typeof component.load) return void await component.load({});
|
|
46
|
-
await component.preload?.({});
|
|
47
|
-
}
|
|
48
|
-
async function preloadMatchedRouteComponents(tanstackRouter) {
|
|
49
|
-
const matches = Array.isArray(tanstackRouter.state.matches) ? tanstackRouter.state.matches : [];
|
|
50
|
-
const routesById = tanstackRouter.routesById || {};
|
|
51
|
-
await Promise.all(matches.map(async (match)=>{
|
|
52
|
-
const routeId = 'string' == typeof match.routeId ? match.routeId : 'string' == typeof match.route?.id ? match.route.id : void 0;
|
|
53
|
-
const route = routeId ? routesById[routeId] : match.route;
|
|
54
|
-
const options = route?.options;
|
|
55
|
-
if (!options) return;
|
|
56
|
-
await Promise.all([
|
|
57
|
-
preloadRouteComponent(options.component),
|
|
58
|
-
preloadRouteComponent(options.pendingComponent),
|
|
59
|
-
preloadRouteComponent(options.errorComponent),
|
|
60
|
-
preloadRouteComponent(options.notFoundComponent)
|
|
61
|
-
]);
|
|
62
|
-
}));
|
|
63
|
-
}
|
|
64
|
-
async function waitForRouterSerialization(tanstackRouter) {
|
|
65
|
-
const serverSsr = tanstackRouter.serverSsr;
|
|
66
|
-
if (!serverSsr || 'function' != typeof serverSsr.onSerializationFinished || serverSsr.isSerializationFinished?.()) return;
|
|
67
|
-
await new Promise((resolve)=>{
|
|
68
|
-
serverSsr.onSerializationFinished?.(resolve);
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
function htmlEscapeAttr(value) {
|
|
72
|
-
return value.replace(/&/g, '&').replace(/"/g, '"');
|
|
73
|
-
}
|
|
74
|
-
function routerManagedTagToHtml(tag) {
|
|
75
|
-
if (!tag || 'object' != typeof tag) return '';
|
|
76
|
-
const managedTag = tag;
|
|
77
|
-
if (!managedTag || "script" !== managedTag.tag) return '';
|
|
78
|
-
const attrs = managedTag.attrs || {};
|
|
79
|
-
const attrsStr = Object.entries(attrs).filter(([, v])=>null != v && false !== v).map(([k, v])=>{
|
|
80
|
-
const name = 'className' === k ? 'class' : k;
|
|
81
|
-
if (true === v) return name;
|
|
82
|
-
return `${name}="${htmlEscapeAttr(String(v))}"`;
|
|
83
|
-
}).join(' ');
|
|
84
|
-
const open = attrsStr.length ? `<script ${attrsStr}>` : "<script>";
|
|
85
|
-
const children = 'string' == typeof managedTag.children ? managedTag.children : '';
|
|
86
|
-
return `${open}${children}</script>`;
|
|
87
|
-
}
|
|
88
|
-
function routerManagedTagsToHtml(tags) {
|
|
89
|
-
const normalizedTags = Array.isArray(tags) ? tags : [
|
|
90
|
-
tags
|
|
91
|
-
];
|
|
92
|
-
return normalizedTags.map(routerManagedTagToHtml).filter(Boolean);
|
|
93
|
-
}
|
|
94
|
-
function createGetSsrHref(request) {
|
|
95
|
-
const url = new URL(request.url);
|
|
96
|
-
return `${url.pathname}${url.search}${url.hash}`;
|
|
97
|
-
}
|
|
98
|
-
function collectRouterErrors(tanstackRouter) {
|
|
99
|
-
const state = tanstackRouter.state;
|
|
100
|
-
const matches = Array.isArray(state.matches) ? state.matches : [];
|
|
101
|
-
const errors = matches.reduce((acc, match)=>{
|
|
102
|
-
if (!match.error) return acc;
|
|
103
|
-
const routeId = 'string' == typeof match.routeId ? match.routeId : 'string' == typeof match.route?.id ? match.route.id : `match-${Object.keys(acc).length}`;
|
|
104
|
-
acc[routeId] = match.error;
|
|
105
|
-
return acc;
|
|
106
|
-
}, {});
|
|
107
|
-
return Object.keys(errors).length > 0 ? errors : void 0;
|
|
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
|
-
}
|
|
116
20
|
const tanstackRouterPlugin = (userConfig = {})=>{
|
|
117
21
|
const plugin = {
|
|
118
22
|
name: '@modern-js/plugin-router-tanstack',
|
|
119
23
|
registryHooks: routerProviderRegistryHooks,
|
|
120
24
|
setup: (api)=>{
|
|
121
25
|
api.onBeforeRender(async (context, interrupt)=>{
|
|
122
|
-
const
|
|
26
|
+
const routeConfig = getTanstackRouteConfig(api, userConfig);
|
|
27
|
+
const { mergedConfig } = routeConfig;
|
|
123
28
|
const serializationAdapters = getGlobalEnableRsc() ? (await import("./rsc/server.mjs")).getTanstackRscSerializationAdapters() : void 0;
|
|
124
29
|
const enableRsc = getGlobalEnableRsc();
|
|
125
|
-
const { basename = ''
|
|
126
|
-
|
|
127
|
-
if (!finalRouteConfig.routes && !createRoutes) return;
|
|
30
|
+
const { basename = '' } = mergedConfig;
|
|
31
|
+
if (!routeConfig.hasConfiguredRoutes) return;
|
|
128
32
|
const hooks = api.getHooks();
|
|
129
33
|
await hooks.onBeforeCreateRoutes.call(context);
|
|
130
|
-
const
|
|
131
|
-
|
|
34
|
+
const modifiedRouteObjects = createTanstackRouteObjects({
|
|
35
|
+
hooks,
|
|
36
|
+
routeConfig,
|
|
132
37
|
ssrMode: context.ssrContext?.mode
|
|
133
|
-
})
|
|
134
|
-
const modifiedRouteObjects = hooks.modifyRoutes.call(routeObjects);
|
|
38
|
+
});
|
|
135
39
|
if (!modifiedRouteObjects.length) return;
|
|
136
40
|
const { request, nonce, baseUrl, loaderFailureMode = 'errorBoundary' } = context.ssrContext;
|
|
137
|
-
const _basename = '/' === baseUrl ?
|
|
41
|
+
const _basename = '/' === baseUrl ? joinBasename(baseUrl, basename || '') : baseUrl;
|
|
138
42
|
const rawRequest = request.raw;
|
|
139
43
|
const initialHref = createGetSsrHref(rawRequest);
|
|
140
44
|
const isRSCNavigation = enableRsc && 'true' === rawRequest.headers.get('x-rsc-tree');
|
|
@@ -180,6 +84,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
180
84
|
} : {}
|
|
181
85
|
});
|
|
182
86
|
const serverRouter = tanstackRouter;
|
|
87
|
+
if (enableRsc) setTanstackRscRouter(serverRouter);
|
|
183
88
|
await attachServerSsrUtils(serverRouter);
|
|
184
89
|
const end = time();
|
|
185
90
|
try {
|
|
@@ -208,10 +113,10 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
208
113
|
await preloadMatchedRouteComponents(serverRouter);
|
|
209
114
|
context.ssrContext?.response?.status(tanstackRouter.state.statusCode);
|
|
210
115
|
await serverRouter.serverSsr?.dehydrate?.();
|
|
211
|
-
if (
|
|
212
|
-
await waitForRouterSerialization(serverRouter);
|
|
116
|
+
if (enableRsc) {
|
|
117
|
+
if (isRSCNavigation) await waitForRouterSerialization(serverRouter);
|
|
213
118
|
setTanstackRscServerPayload(createTanstackRscServerPayload(serverRouter, {
|
|
214
|
-
omitClientLoaderData:
|
|
119
|
+
omitClientLoaderData: isRSCNavigation
|
|
215
120
|
}));
|
|
216
121
|
}
|
|
217
122
|
const ssrScriptTags = serverRouter.serverSsr?.takeBufferedScripts?.();
|
|
@@ -245,7 +150,20 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
245
150
|
});
|
|
246
151
|
});
|
|
247
152
|
api.wrapRoot((App)=>{
|
|
248
|
-
const getRouteApp = ()=>
|
|
153
|
+
const getRouteApp = ()=>{
|
|
154
|
+
if (getGlobalEnableRsc()) return (props)=>{
|
|
155
|
+
const router = getTanstackRscRouter();
|
|
156
|
+
if (!router) return App ? /*#__PURE__*/ jsx(App, {
|
|
157
|
+
...props
|
|
158
|
+
}) : null;
|
|
159
|
+
const routerWrapper = wrapTanstackSsrHydrationBoundary(/*#__PURE__*/ jsx(RouterProvider, {
|
|
160
|
+
router: router
|
|
161
|
+
}), true);
|
|
162
|
+
return App ? /*#__PURE__*/ jsx(App, {
|
|
163
|
+
children: routerWrapper
|
|
164
|
+
}) : routerWrapper;
|
|
165
|
+
};
|
|
166
|
+
return (props)=>{
|
|
249
167
|
const context = useContext(InternalRuntimeContext);
|
|
250
168
|
const router = getRouterRuntimeState(context)?.instance;
|
|
251
169
|
if (!router) return App ? /*#__PURE__*/ jsx(App, {
|
|
@@ -258,6 +176,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
258
176
|
children: routerWrapper
|
|
259
177
|
}) : routerWrapper;
|
|
260
178
|
};
|
|
179
|
+
};
|
|
261
180
|
return getRouteApp();
|
|
262
181
|
});
|
|
263
182
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { getGlobalLayoutApp, getGlobalRoutes } from "@modern-js/runtime/context";
|
|
3
|
+
import { merge } from "@modern-js/runtime-utils/merge";
|
|
4
|
+
import { createTanstackRouteObjectsFromConfig } from "./utils.mjs";
|
|
5
|
+
function getMergedRouterConfig(api, userConfig) {
|
|
6
|
+
const pluginConfig = api.getRuntimeConfig();
|
|
7
|
+
return merge(pluginConfig.router || {}, userConfig);
|
|
8
|
+
}
|
|
9
|
+
function getFinalRouteConfig(mergedConfig) {
|
|
10
|
+
return {
|
|
11
|
+
routes: getGlobalRoutes(),
|
|
12
|
+
globalApp: getGlobalLayoutApp(),
|
|
13
|
+
...mergedConfig.routesConfig
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function getTanstackRouteConfig(api, userConfig) {
|
|
17
|
+
const mergedConfig = getMergedRouterConfig(api, userConfig);
|
|
18
|
+
const finalRouteConfig = getFinalRouteConfig(mergedConfig);
|
|
19
|
+
return {
|
|
20
|
+
mergedConfig,
|
|
21
|
+
finalRouteConfig,
|
|
22
|
+
hasConfiguredRoutes: Boolean(finalRouteConfig.routes) || Boolean(mergedConfig.createRoutes)
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function createTanstackRouteObjects({ hooks, routeConfig, ssrMode }) {
|
|
26
|
+
const { mergedConfig, finalRouteConfig } = routeConfig;
|
|
27
|
+
const routeObjects = mergedConfig.createRoutes ? mergedConfig.createRoutes() : createTanstackRouteObjectsFromConfig({
|
|
28
|
+
routesConfig: finalRouteConfig,
|
|
29
|
+
ssrMode
|
|
30
|
+
}) || [];
|
|
31
|
+
return hooks.modifyRoutes.call(routeObjects);
|
|
32
|
+
}
|
|
33
|
+
function joinBasename(baseUrl, basename) {
|
|
34
|
+
const base = baseUrl || '/';
|
|
35
|
+
const normalizedBase = base.startsWith('/') ? base : `/${base}`;
|
|
36
|
+
const trimmedBase = normalizedBase.length > 1 ? normalizedBase.replace(/\/+$/g, '') : normalizedBase;
|
|
37
|
+
const trimmedBasename = basename.replace(/^\/+|\/+$/g, '');
|
|
38
|
+
if (!trimmedBasename) return trimmedBase || '/';
|
|
39
|
+
return `${trimmedBase}/${trimmedBasename}`.replace(/\/{2,}/g, '/');
|
|
40
|
+
}
|
|
41
|
+
export { createTanstackRouteObjects, getFinalRouteConfig, getMergedRouterConfig, getTanstackRouteConfig, joinBasename };
|