@pracht/core 0.2.5 → 0.2.6
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/README.md +2 -2
- package/dist/{app-Cep0el7c.mjs → app-CUL3q2ZA.mjs} +19 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +144 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,16 +35,16 @@ metadata for the failure phase and matched framework files when available.
|
|
|
35
35
|
### Client
|
|
36
36
|
|
|
37
37
|
- `startApp()` — client-side hydration and runtime
|
|
38
|
+
- `useLocation()` — access the current pathname and search string separately
|
|
38
39
|
- `useRouteData()` — access loader data inside a route component
|
|
39
40
|
- `useRevalidateRoute()` — trigger a revalidation of the current route's data
|
|
40
|
-
- `useSubmitAction()` — submit a form action programmatically
|
|
41
41
|
- `<Form>` — progressive enhancement form component
|
|
42
42
|
|
|
43
43
|
### Types
|
|
44
44
|
|
|
45
45
|
- `LoaderData<T>` — infer the return type of a loader
|
|
46
46
|
- `RouteComponentProps<T>` — props type for route components
|
|
47
|
-
- `LoaderArgs` — argument type passed to loaders
|
|
47
|
+
- `LoaderArgs` — argument type passed to loaders
|
|
48
48
|
|
|
49
49
|
## Rendering Modes
|
|
50
50
|
|
|
@@ -216,7 +216,7 @@ function resolveApiRoutes(files, apiDir = "/src/api") {
|
|
|
216
216
|
file,
|
|
217
217
|
segments: parseRouteSegments(path)
|
|
218
218
|
};
|
|
219
|
-
});
|
|
219
|
+
}).sort(compareResolvedApiRoutes);
|
|
220
220
|
}
|
|
221
221
|
function matchApiRoute(apiRoutes, pathname) {
|
|
222
222
|
const normalizedPathname = normalizeRoutePath(pathname);
|
|
@@ -237,5 +237,23 @@ function createRouteId(path) {
|
|
|
237
237
|
return segment.startsWith(":") ? segment.slice(1) : segment;
|
|
238
238
|
}).join("-").replace(/[^a-zA-Z0-9-]/g, "-");
|
|
239
239
|
}
|
|
240
|
+
function compareResolvedApiRoutes(left, right) {
|
|
241
|
+
const length = Math.max(left.segments.length, right.segments.length);
|
|
242
|
+
for (let index = 0; index < length; index += 1) {
|
|
243
|
+
const leftSegment = left.segments[index];
|
|
244
|
+
const rightSegment = right.segments[index];
|
|
245
|
+
if (!leftSegment) return 1;
|
|
246
|
+
if (!rightSegment) return -1;
|
|
247
|
+
const leftScore = getRouteSegmentSpecificity(leftSegment);
|
|
248
|
+
const rightScore = getRouteSegmentSpecificity(rightSegment);
|
|
249
|
+
if (leftScore !== rightScore) return rightScore - leftScore;
|
|
250
|
+
}
|
|
251
|
+
return left.path.localeCompare(right.path);
|
|
252
|
+
}
|
|
253
|
+
function getRouteSegmentSpecificity(segment) {
|
|
254
|
+
if (segment.type === "static") return 3;
|
|
255
|
+
if (segment.type === "param") return 2;
|
|
256
|
+
return 1;
|
|
257
|
+
}
|
|
240
258
|
//#endregion
|
|
241
259
|
export { matchApiRoute as a, resolveApp as c, group as i, route as l, buildPathFromSegments as n, matchAppRoute as o, defineApp as r, resolveApiRoutes as s, app_exports as t, timeRevalidate as u };
|
package/dist/index.d.mts
CHANGED
|
@@ -334,6 +334,7 @@ declare function readHydrationState<TData = unknown>(): PrachtHydrationState<TDa
|
|
|
334
334
|
declare function useRouteData<TData = unknown>(): TData;
|
|
335
335
|
interface Location {
|
|
336
336
|
pathname: string;
|
|
337
|
+
search: string;
|
|
337
338
|
}
|
|
338
339
|
declare function useLocation(): Location;
|
|
339
340
|
declare function useParams(): RouteParams;
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as matchApiRoute, c as resolveApp, i as group, l as route, n as buildPathFromSegments, o as matchAppRoute, r as defineApp, s as resolveApiRoutes, u as timeRevalidate } from "./app-
|
|
1
|
+
import { a as matchApiRoute, c as resolveApp, i as group, l as route, n as buildPathFromSegments, o as matchAppRoute, r as defineApp, s as resolveApiRoutes, u as timeRevalidate } from "./app-CUL3q2ZA.mjs";
|
|
2
2
|
import { createContext, h, hydrate, options, render } from "preact";
|
|
3
3
|
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
|
|
4
4
|
import { Suspense, lazy } from "preact-suspense";
|
|
@@ -137,7 +137,7 @@ function useRouteData() {
|
|
|
137
137
|
return useContext(RouteDataContext)?.data;
|
|
138
138
|
}
|
|
139
139
|
function useLocation() {
|
|
140
|
-
return
|
|
140
|
+
return parseLocation(useContext(RouteDataContext)?.url ?? (typeof window !== "undefined" ? window.location.pathname + window.location.search : "/"));
|
|
141
141
|
}
|
|
142
142
|
function useParams() {
|
|
143
143
|
return useContext(RouteDataContext)?.params ?? {};
|
|
@@ -200,6 +200,10 @@ async function fetchPrachtRouteState(url) {
|
|
|
200
200
|
type: "redirect"
|
|
201
201
|
};
|
|
202
202
|
const json = await response.json();
|
|
203
|
+
if (json.redirect) return {
|
|
204
|
+
location: json.redirect,
|
|
205
|
+
type: "redirect"
|
|
206
|
+
};
|
|
203
207
|
if (!response.ok) {
|
|
204
208
|
if (json.error) return {
|
|
205
209
|
error: json.error,
|
|
@@ -214,6 +218,7 @@ async function fetchPrachtRouteState(url) {
|
|
|
214
218
|
}
|
|
215
219
|
async function handlePrachtRequest(options) {
|
|
216
220
|
const url = new URL(options.request.url);
|
|
221
|
+
const requestPath = getRequestPath(url);
|
|
217
222
|
const registry = options.registry ?? {};
|
|
218
223
|
const isRouteStateRequest = options.request.headers.get(ROUTE_STATE_REQUEST_HEADER) === "1";
|
|
219
224
|
const exposeDiagnostics = shouldExposeServerErrors(options);
|
|
@@ -315,7 +320,7 @@ async function handlePrachtRequest(options) {
|
|
|
315
320
|
route: match.route,
|
|
316
321
|
url
|
|
317
322
|
});
|
|
318
|
-
if (middlewareResult.response) return
|
|
323
|
+
if (middlewareResult.response) return normalizePageResponse(middlewareResult.response, { isRouteStateRequest });
|
|
319
324
|
routeArgs = {
|
|
320
325
|
...routeArgs,
|
|
321
326
|
context: middlewareResult.context
|
|
@@ -327,7 +332,7 @@ async function handlePrachtRequest(options) {
|
|
|
327
332
|
const { loader, loaderFile: resolvedLoaderFile } = await resolveDataFunctions(match.route, routeModule, registry);
|
|
328
333
|
loaderFile = resolvedLoaderFile;
|
|
329
334
|
const loaderResult = loader ? await loader(routeArgs) : void 0;
|
|
330
|
-
if (loaderResult instanceof Response) return
|
|
335
|
+
if (loaderResult instanceof Response) return normalizePageResponse(loaderResult, { isRouteStateRequest });
|
|
331
336
|
const data = loaderResult;
|
|
332
337
|
if (isRouteStateRequest) return withRouteResponseHeaders(Response.json({ data }), { isRouteStateRequest: true });
|
|
333
338
|
currentPhase = "render";
|
|
@@ -348,7 +353,7 @@ async function handlePrachtRequest(options) {
|
|
|
348
353
|
head,
|
|
349
354
|
body,
|
|
350
355
|
hydrationState: {
|
|
351
|
-
url:
|
|
356
|
+
url: requestPath,
|
|
352
357
|
routeId: match.route.id ?? "",
|
|
353
358
|
data: null,
|
|
354
359
|
error: null,
|
|
@@ -372,13 +377,13 @@ async function handlePrachtRequest(options) {
|
|
|
372
377
|
data,
|
|
373
378
|
params: match.params,
|
|
374
379
|
routeId: match.route.id ?? "",
|
|
375
|
-
url:
|
|
380
|
+
url: requestPath
|
|
376
381
|
}, componentTree);
|
|
377
382
|
return htmlResponse(buildHtmlDocument({
|
|
378
383
|
head,
|
|
379
384
|
body: await (await getRenderToStringAsync())(tree),
|
|
380
385
|
hydrationState: {
|
|
381
|
-
url:
|
|
386
|
+
url: requestPath,
|
|
382
387
|
routeId: match.route.id ?? "",
|
|
383
388
|
data,
|
|
384
389
|
error: null
|
|
@@ -399,10 +404,27 @@ async function handlePrachtRequest(options) {
|
|
|
399
404
|
routeModule,
|
|
400
405
|
shellFile: match.route.shellFile,
|
|
401
406
|
shellModule,
|
|
402
|
-
|
|
407
|
+
requestPath
|
|
403
408
|
});
|
|
404
409
|
}
|
|
405
410
|
}
|
|
411
|
+
function parseLocation(value) {
|
|
412
|
+
try {
|
|
413
|
+
const url = new URL(value, "http://pracht.local");
|
|
414
|
+
return {
|
|
415
|
+
pathname: url.pathname,
|
|
416
|
+
search: url.search
|
|
417
|
+
};
|
|
418
|
+
} catch {
|
|
419
|
+
return {
|
|
420
|
+
pathname: value || "/",
|
|
421
|
+
search: ""
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function getRequestPath(url) {
|
|
426
|
+
return `${url.pathname}${url.search}`;
|
|
427
|
+
}
|
|
406
428
|
/** Strip leading `./` and `/` so all module paths share one canonical form. */
|
|
407
429
|
function normalizeModulePath(path) {
|
|
408
430
|
return path.replace(/^\.?\//, "");
|
|
@@ -553,6 +575,24 @@ function jsonErrorResponse(routeError, options) {
|
|
|
553
575
|
headers
|
|
554
576
|
});
|
|
555
577
|
}
|
|
578
|
+
function jsonRedirectResponse(location, options) {
|
|
579
|
+
const headers = new Headers(options.headers);
|
|
580
|
+
headers.set("content-type", "application/json; charset=utf-8");
|
|
581
|
+
return withRouteResponseHeaders(new Response(JSON.stringify({ redirect: location }), {
|
|
582
|
+
status: 200,
|
|
583
|
+
headers
|
|
584
|
+
}), { isRouteStateRequest: options.isRouteStateRequest });
|
|
585
|
+
}
|
|
586
|
+
function normalizePageResponse(response, options) {
|
|
587
|
+
if (options.isRouteStateRequest && response.status >= 300 && response.status < 400) {
|
|
588
|
+
const location = response.headers.get("location");
|
|
589
|
+
if (location) return jsonRedirectResponse(location, {
|
|
590
|
+
headers: response.headers,
|
|
591
|
+
isRouteStateRequest: true
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
return withRouteResponseHeaders(response, options);
|
|
595
|
+
}
|
|
556
596
|
function renderApiErrorResponse(options) {
|
|
557
597
|
const exposeDetails = shouldExposeServerErrors(options.options);
|
|
558
598
|
const routeError = normalizeRouteError(options.error, { exposeDetails });
|
|
@@ -610,10 +650,10 @@ async function renderRouteErrorResponse(options) {
|
|
|
610
650
|
body: await renderToString(h(PrachtRuntimeProvider, {
|
|
611
651
|
data: null,
|
|
612
652
|
routeId: options.routeId,
|
|
613
|
-
url: options.
|
|
653
|
+
url: options.requestPath
|
|
614
654
|
}, componentTree)),
|
|
615
655
|
hydrationState: {
|
|
616
|
-
url: options.
|
|
656
|
+
url: options.requestPath,
|
|
617
657
|
routeId: options.routeId,
|
|
618
658
|
data: null,
|
|
619
659
|
error: routeErrorWithDiagnostics
|
|
@@ -784,7 +824,7 @@ function serializeJsonForHtml(value) {
|
|
|
784
824
|
return JSON.stringify(value).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
785
825
|
}
|
|
786
826
|
async function prerenderApp(options) {
|
|
787
|
-
const { resolveApp } = await import("./app-
|
|
827
|
+
const { resolveApp } = await import("./app-CUL3q2ZA.mjs").then((n) => n.t);
|
|
788
828
|
const resolved = resolveApp(options.app);
|
|
789
829
|
const results = [];
|
|
790
830
|
const isgManifest = {};
|
|
@@ -846,7 +886,7 @@ async function collectSSGPaths(route, registry) {
|
|
|
846
886
|
console.warn(` Warning: SSG route "${route.path}" has dynamic segments but no getStaticPaths() export, skipping.`);
|
|
847
887
|
return [];
|
|
848
888
|
}
|
|
849
|
-
const { buildPathFromSegments } = await import("./app-
|
|
889
|
+
const { buildPathFromSegments } = await import("./app-CUL3q2ZA.mjs").then((n) => n.t);
|
|
850
890
|
return (await routeModule.getStaticPaths()).map((params) => buildPathFromSegments(route.segments, params));
|
|
851
891
|
}
|
|
852
892
|
//#endregion
|
|
@@ -874,6 +914,13 @@ function prefetchRouteState(url) {
|
|
|
874
914
|
}
|
|
875
915
|
function setupPrefetching(app, warmModules) {
|
|
876
916
|
let hoverTimer = null;
|
|
917
|
+
function getRoutePathname(url) {
|
|
918
|
+
try {
|
|
919
|
+
return new URL(url, window.location.origin).pathname;
|
|
920
|
+
} catch {
|
|
921
|
+
return null;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
877
924
|
function getInternalHref(anchor) {
|
|
878
925
|
const href = anchor.getAttribute("href");
|
|
879
926
|
if (!href || href.startsWith("#")) return null;
|
|
@@ -887,7 +934,9 @@ function setupPrefetching(app, warmModules) {
|
|
|
887
934
|
return url.pathname + url.search;
|
|
888
935
|
}
|
|
889
936
|
function getPrefetchStrategy(pathname) {
|
|
890
|
-
const
|
|
937
|
+
const routePathname = getRoutePathname(pathname);
|
|
938
|
+
if (!routePathname) return "none";
|
|
939
|
+
const match = matchAppRoute(app, routePathname);
|
|
891
940
|
if (!match) return "none";
|
|
892
941
|
if (match.route.prefetch) return match.route.prefetch;
|
|
893
942
|
if (match.route.render === "spa") return "none";
|
|
@@ -904,7 +953,8 @@ function setupPrefetching(app, warmModules) {
|
|
|
904
953
|
hoverTimer = setTimeout(() => {
|
|
905
954
|
prefetchRouteState(href);
|
|
906
955
|
if (warmModules) {
|
|
907
|
-
const
|
|
956
|
+
const pathname = getRoutePathname(href);
|
|
957
|
+
const m = pathname ? matchAppRoute(app, pathname) : void 0;
|
|
908
958
|
if (m) warmModules(m);
|
|
909
959
|
}
|
|
910
960
|
}, 50);
|
|
@@ -925,7 +975,8 @@ function setupPrefetching(app, warmModules) {
|
|
|
925
975
|
if (strategy !== "hover" && strategy !== "intent") return;
|
|
926
976
|
prefetchRouteState(href);
|
|
927
977
|
if (warmModules) {
|
|
928
|
-
const
|
|
978
|
+
const pathname = getRoutePathname(href);
|
|
979
|
+
const m = pathname ? matchAppRoute(app, pathname) : void 0;
|
|
929
980
|
if (m) warmModules(m);
|
|
930
981
|
}
|
|
931
982
|
}, true);
|
|
@@ -938,7 +989,8 @@ function setupPrefetching(app, warmModules) {
|
|
|
938
989
|
if (!href) continue;
|
|
939
990
|
prefetchRouteState(href);
|
|
940
991
|
if (warmModules) {
|
|
941
|
-
const
|
|
992
|
+
const pathname = getRoutePathname(href);
|
|
993
|
+
const m = pathname ? matchAppRoute(app, pathname) : void 0;
|
|
942
994
|
if (m) warmModules(m);
|
|
943
995
|
}
|
|
944
996
|
observer.unobserve(anchor);
|
|
@@ -989,7 +1041,7 @@ async function initClientRouter(options) {
|
|
|
989
1041
|
if (!shellKey) return null;
|
|
990
1042
|
return loadModule(shellModules, shellKey);
|
|
991
1043
|
}
|
|
992
|
-
async function buildRouteTree(match, state, routeModPromise, shellModPromise) {
|
|
1044
|
+
async function buildRouteTree(match, state, currentUrl, routeModPromise, shellModPromise) {
|
|
993
1045
|
const routeMod = await (routeModPromise ?? startRouteImport(match));
|
|
994
1046
|
if (!routeMod) return null;
|
|
995
1047
|
let Shell = null;
|
|
@@ -1007,10 +1059,10 @@ async function initClientRouter(options) {
|
|
|
1007
1059
|
data: state.data,
|
|
1008
1060
|
params: match.params,
|
|
1009
1061
|
routeId: match.route.id ?? "",
|
|
1010
|
-
url:
|
|
1062
|
+
url: currentUrl
|
|
1011
1063
|
}, componentTree));
|
|
1012
1064
|
}
|
|
1013
|
-
async function buildSpaPendingTree(match, shellModPromise) {
|
|
1065
|
+
async function buildSpaPendingTree(match, currentUrl, shellModPromise) {
|
|
1014
1066
|
const resolvedShell = await (shellModPromise ?? startShellImport(match));
|
|
1015
1067
|
if (!resolvedShell) return null;
|
|
1016
1068
|
const Shell = resolvedShell.Shell;
|
|
@@ -1021,16 +1073,40 @@ async function initClientRouter(options) {
|
|
|
1021
1073
|
data: void 0,
|
|
1022
1074
|
params: match.params,
|
|
1023
1075
|
routeId: match.route.id ?? "",
|
|
1024
|
-
url:
|
|
1076
|
+
url: currentUrl
|
|
1025
1077
|
}, componentTree));
|
|
1026
1078
|
}
|
|
1079
|
+
function resolveRedirectTarget(location) {
|
|
1080
|
+
const targetUrl = new URL(location, window.location.href);
|
|
1081
|
+
const fullInternalTarget = targetUrl.pathname + targetUrl.search + targetUrl.hash;
|
|
1082
|
+
const internalPath = targetUrl.pathname + targetUrl.search;
|
|
1083
|
+
const currentPath = window.location.pathname + window.location.search + window.location.hash;
|
|
1084
|
+
const isCurrentLocation = targetUrl.origin === window.location.origin && fullInternalTarget === currentPath;
|
|
1085
|
+
if (targetUrl.origin !== window.location.origin) return {
|
|
1086
|
+
externalUrl: targetUrl.toString(),
|
|
1087
|
+
isCurrentLocation: false
|
|
1088
|
+
};
|
|
1089
|
+
if (targetUrl.hash) return {
|
|
1090
|
+
documentUrl: targetUrl.toString(),
|
|
1091
|
+
isCurrentLocation
|
|
1092
|
+
};
|
|
1093
|
+
return {
|
|
1094
|
+
internalPath,
|
|
1095
|
+
isCurrentLocation
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1027
1098
|
async function navigate(to, opts) {
|
|
1028
|
-
const
|
|
1029
|
-
if (!
|
|
1099
|
+
const target = resolveBrowserRouteTarget(to);
|
|
1100
|
+
if (!target) {
|
|
1030
1101
|
window.location.href = to;
|
|
1031
1102
|
return;
|
|
1032
1103
|
}
|
|
1033
|
-
const
|
|
1104
|
+
const match = matchAppRoute(app, target.pathname);
|
|
1105
|
+
if (!match) {
|
|
1106
|
+
window.location.href = target.browserUrl;
|
|
1107
|
+
return;
|
|
1108
|
+
}
|
|
1109
|
+
const statePromise = getCachedRouteState(target.requestUrl) ?? fetchPrachtRouteState(target.requestUrl);
|
|
1034
1110
|
const routeModPromise = startRouteImport(match);
|
|
1035
1111
|
const shellModPromise = startShellImport(match);
|
|
1036
1112
|
let state = {
|
|
@@ -1041,10 +1117,24 @@ async function initClientRouter(options) {
|
|
|
1041
1117
|
const result = await statePromise;
|
|
1042
1118
|
if (result.type === "redirect") {
|
|
1043
1119
|
if (result.location) {
|
|
1044
|
-
|
|
1120
|
+
const redirect = resolveRedirectTarget(result.location);
|
|
1121
|
+
if (redirect.externalUrl) {
|
|
1122
|
+
window.location.href = redirect.externalUrl;
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
if (redirect.isCurrentLocation) return;
|
|
1126
|
+
if (redirect.documentUrl) {
|
|
1127
|
+
window.location.href = redirect.documentUrl;
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1130
|
+
if (redirect.internalPath) {
|
|
1131
|
+
await navigate(redirect.internalPath, opts);
|
|
1132
|
+
return;
|
|
1133
|
+
}
|
|
1134
|
+
window.location.href = result.location;
|
|
1045
1135
|
return;
|
|
1046
1136
|
}
|
|
1047
|
-
window.location.href =
|
|
1137
|
+
window.location.href = target.browserUrl;
|
|
1048
1138
|
return;
|
|
1049
1139
|
}
|
|
1050
1140
|
if (result.type === "error") state = {
|
|
@@ -1056,16 +1146,16 @@ async function initClientRouter(options) {
|
|
|
1056
1146
|
error: null
|
|
1057
1147
|
};
|
|
1058
1148
|
} catch {
|
|
1059
|
-
window.location.href =
|
|
1149
|
+
window.location.href = target.browserUrl;
|
|
1060
1150
|
return;
|
|
1061
1151
|
}
|
|
1062
|
-
if (!opts?._popstate) if (opts?.replace) history.replaceState(null, "",
|
|
1063
|
-
else history.pushState(null, "",
|
|
1064
|
-
const tree = await buildRouteTree(match, state, routeModPromise, shellModPromise);
|
|
1152
|
+
if (!opts?._popstate) if (opts?.replace) history.replaceState(null, "", target.browserUrl);
|
|
1153
|
+
else history.pushState(null, "", target.browserUrl);
|
|
1154
|
+
const tree = await buildRouteTree(match, state, target.requestUrl, routeModPromise, shellModPromise);
|
|
1065
1155
|
if (tree) {
|
|
1066
1156
|
render(tree, root);
|
|
1067
1157
|
window.scrollTo(0, 0);
|
|
1068
|
-
} else window.location.href =
|
|
1158
|
+
} else window.location.href = target.browserUrl;
|
|
1069
1159
|
}
|
|
1070
1160
|
if (import.meta.env?.DEV) {
|
|
1071
1161
|
const prev = options.__m;
|
|
@@ -1076,7 +1166,10 @@ async function initClientRouter(options) {
|
|
|
1076
1166
|
if (prev) prev(vnode, s);
|
|
1077
1167
|
};
|
|
1078
1168
|
}
|
|
1079
|
-
const
|
|
1169
|
+
const initialTarget = resolveBrowserRouteTarget(options.initialState.url);
|
|
1170
|
+
const initialRequestUrl = initialTarget?.requestUrl ?? options.initialState.url;
|
|
1171
|
+
const initialBrowserUrl = initialTarget?.browserUrl ?? options.initialState.url;
|
|
1172
|
+
const initialMatch = matchAppRoute(app, initialTarget?.pathname ?? options.initialState.url);
|
|
1080
1173
|
if (initialMatch) {
|
|
1081
1174
|
const initialShellPromise = initialMatch.route.render === "spa" && options.initialState.pending ? startShellImport(initialMatch) : null;
|
|
1082
1175
|
let state = {
|
|
@@ -1084,8 +1177,8 @@ async function initClientRouter(options) {
|
|
|
1084
1177
|
error: options.initialState.error ?? null
|
|
1085
1178
|
};
|
|
1086
1179
|
if (initialMatch.route.render === "spa" && options.initialState.pending) {
|
|
1087
|
-
const dataPromise = fetchPrachtRouteState(
|
|
1088
|
-
const pendingTree = await buildSpaPendingTree(initialMatch, initialShellPromise);
|
|
1180
|
+
const dataPromise = fetchPrachtRouteState(initialRequestUrl);
|
|
1181
|
+
const pendingTree = await buildSpaPendingTree(initialMatch, initialRequestUrl, initialShellPromise);
|
|
1089
1182
|
if (pendingTree) hydrate(pendingTree, root);
|
|
1090
1183
|
try {
|
|
1091
1184
|
const result = await dataPromise;
|
|
@@ -1102,11 +1195,11 @@ async function initClientRouter(options) {
|
|
|
1102
1195
|
error: null
|
|
1103
1196
|
};
|
|
1104
1197
|
} catch {
|
|
1105
|
-
window.location.href =
|
|
1198
|
+
window.location.href = initialBrowserUrl;
|
|
1106
1199
|
return;
|
|
1107
1200
|
}
|
|
1108
1201
|
}
|
|
1109
|
-
const tree = await buildRouteTree(initialMatch, state, void 0, initialShellPromise);
|
|
1202
|
+
const tree = await buildRouteTree(initialMatch, state, initialRequestUrl, void 0, initialShellPromise);
|
|
1110
1203
|
if (tree) if (initialMatch.route.render === "spa") render(tree, root);
|
|
1111
1204
|
else {
|
|
1112
1205
|
markHydrating();
|
|
@@ -1132,10 +1225,10 @@ async function initClientRouter(options) {
|
|
|
1132
1225
|
}
|
|
1133
1226
|
if (url.origin !== window.location.origin) return;
|
|
1134
1227
|
e.preventDefault();
|
|
1135
|
-
navigate(url.pathname + url.search);
|
|
1228
|
+
navigate(url.pathname + url.search + url.hash);
|
|
1136
1229
|
});
|
|
1137
1230
|
window.addEventListener("popstate", () => {
|
|
1138
|
-
navigate(window.location.pathname + window.location.search, { _popstate: true });
|
|
1231
|
+
navigate(window.location.pathname + window.location.search + window.location.hash, { _popstate: true });
|
|
1139
1232
|
});
|
|
1140
1233
|
window.__PRACHT_NAVIGATE__ = navigate;
|
|
1141
1234
|
window.__PRACHT_ROUTER_READY__ = true;
|
|
@@ -1200,6 +1293,20 @@ function deserializeRouteError(error) {
|
|
|
1200
1293
|
result.diagnostics = error.diagnostics;
|
|
1201
1294
|
return result;
|
|
1202
1295
|
}
|
|
1296
|
+
function resolveBrowserRouteTarget(to) {
|
|
1297
|
+
if (typeof window === "undefined") return null;
|
|
1298
|
+
try {
|
|
1299
|
+
const url = new URL(to, window.location.href);
|
|
1300
|
+
if (url.origin !== window.location.origin) return null;
|
|
1301
|
+
return {
|
|
1302
|
+
browserUrl: url.pathname + url.search + url.hash,
|
|
1303
|
+
pathname: url.pathname,
|
|
1304
|
+
requestUrl: url.pathname + url.search
|
|
1305
|
+
};
|
|
1306
|
+
} catch {
|
|
1307
|
+
return null;
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1203
1310
|
//#endregion
|
|
1204
1311
|
//#region src/types.ts
|
|
1205
1312
|
var PrachtHttpError = class extends Error {
|