vinext 0.1.6 → 0.1.8
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/build/client-build-config.d.ts +4 -6
- package/dist/build/client-build-config.js +27 -7
- package/dist/build/prerender.js +1 -2
- package/dist/check.d.ts +18 -0
- package/dist/check.js +37 -17
- package/dist/cli.js +2 -2
- package/dist/config/next-config.d.ts +2 -1
- package/dist/config/next-config.js +3 -0
- package/dist/config/server-external-packages.d.ts +4 -0
- package/dist/config/server-external-packages.js +91 -0
- package/dist/deploy.d.ts +7 -0
- package/dist/deploy.js +25 -18
- package/dist/entries/app-rsc-entry.d.ts +2 -1
- package/dist/entries/app-rsc-entry.js +89 -20
- package/dist/entries/app-rsc-manifest.js +8 -0
- package/dist/entries/pages-client-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +1 -0
- package/dist/index.js +87 -34
- package/dist/init.js +2 -1
- package/dist/plugins/middleware-server-only.d.ts +8 -6
- package/dist/plugins/middleware-server-only.js +8 -7
- package/dist/plugins/og-assets.js +6 -6
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/remove-console.js +1 -1
- package/dist/plugins/strip-server-exports.js +2 -1
- package/dist/routing/app-route-graph.d.ts +6 -2
- package/dist/routing/app-route-graph.js +61 -13
- package/dist/routing/app-router.d.ts +5 -0
- package/dist/routing/app-router.js +5 -0
- package/dist/routing/file-matcher.d.ts +5 -0
- package/dist/routing/file-matcher.js +7 -1
- package/dist/server/app-action-request.d.ts +4 -0
- package/dist/server/app-action-request.js +9 -0
- package/dist/server/app-bfcache-identity.d.ts +12 -2
- package/dist/server/app-bfcache-identity.js +52 -23
- package/dist/server/app-browser-entry.js +42 -147
- package/dist/server/app-browser-history-controller.d.ts +2 -1
- package/dist/server/app-browser-history-controller.js +6 -2
- package/dist/server/app-browser-server-action-client.d.ts +32 -0
- package/dist/server/app-browser-server-action-client.js +128 -0
- package/dist/server/app-fallback-renderer.d.ts +3 -1
- package/dist/server/app-fallback-renderer.js +6 -2
- package/dist/server/app-history-state.d.ts +1 -2
- package/dist/server/app-history-state.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +3 -0
- package/dist/server/app-page-boundary-render.js +14 -3
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +8 -2
- package/dist/server/app-page-dispatch.d.ts +33 -4
- package/dist/server/app-page-dispatch.js +62 -90
- package/dist/server/app-page-element-builder.d.ts +7 -1
- package/dist/server/app-page-element-builder.js +56 -19
- package/dist/server/app-page-head.d.ts +16 -1
- package/dist/server/app-page-head.js +44 -22
- package/dist/server/app-page-method.js +1 -1
- package/dist/server/app-page-params.d.ts +2 -1
- package/dist/server/app-page-params.js +8 -1
- package/dist/server/app-page-ppr-runtime.d.ts +7 -0
- package/dist/server/app-page-ppr-runtime.js +70 -0
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +1 -1
- package/dist/server/app-page-render.d.ts +4 -1
- package/dist/server/app-page-render.js +8 -3
- package/dist/server/app-page-request.d.ts +8 -1
- package/dist/server/app-page-request.js +23 -11
- package/dist/server/app-page-route-wiring.d.ts +6 -1
- package/dist/server/app-page-route-wiring.js +30 -8
- package/dist/server/app-page-search-params-observation.d.ts +4 -2
- package/dist/server/app-page-search-params-observation.js +11 -7
- package/dist/server/app-page-stream.js +2 -1
- package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
- package/dist/server/app-route-handler-cache.js +1 -1
- package/dist/server/app-route-handler-dispatch.js +3 -2
- package/dist/server/app-route-handler-execution.js +5 -3
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +1 -6
- package/dist/server/app-route-module-loader.d.ts +2 -0
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-router-entry.js +7 -6
- package/dist/server/app-rsc-errors.d.ts +12 -1
- package/dist/server/app-rsc-errors.js +29 -3
- package/dist/server/app-rsc-handler.d.ts +15 -13
- package/dist/server/app-rsc-handler.js +28 -33
- package/dist/server/app-rsc-response-finalizer.js +5 -1
- package/dist/server/app-rsc-route-matching.d.ts +7 -0
- package/dist/server/app-rsc-route-matching.js +36 -3
- package/dist/server/app-segment-config.d.ts +1 -0
- package/dist/server/app-segment-config.js +32 -2
- package/dist/server/app-server-action-execution.d.ts +4 -0
- package/dist/server/app-server-action-execution.js +42 -11
- package/dist/server/app-ssr-entry.js +11 -6
- package/dist/server/app-static-generation.d.ts +1 -0
- package/dist/server/app-static-generation.js +1 -0
- package/dist/server/headers.d.ts +3 -1
- package/dist/server/headers.js +3 -1
- package/dist/server/metadata-route-response.d.ts +1 -1
- package/dist/server/prod-server.js +15 -6
- package/dist/server/worker-utils.d.ts +2 -1
- package/dist/server/worker-utils.js +7 -1
- package/dist/shims/dynamic.js +1 -1
- package/dist/shims/error-boundary.d.ts +19 -1
- package/dist/shims/error-boundary.js +11 -1
- package/dist/shims/headers.d.ts +3 -1
- package/dist/shims/headers.js +16 -5
- package/dist/shims/link.js +16 -12
- package/dist/shims/metadata.d.ts +3 -2
- package/dist/shims/metadata.js +8 -4
- package/dist/shims/router.js +13 -2
- package/dist/typegen.js +6 -5
- package/dist/utils/path.d.ts +2 -1
- package/dist/utils/path.js +1 -1
- package/dist/utils/project.d.ts +4 -0
- package/dist/utils/project.js +5 -1
- package/package.json +7 -3
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
|
|
1
|
+
import { VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RSC_REDIRECT_HEADER } from "./headers.js";
|
|
3
2
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
4
3
|
import { APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI } from "./app-rsc-render-mode.js";
|
|
5
4
|
import { getMountedSlotIdsHeader, resolveVisitedResponseInterceptionContext } from "./app-elements.js";
|
|
@@ -14,7 +13,7 @@ import { DevRecoveryBoundary, GlobalErrorBoundary, RedirectBoundary } from "../s
|
|
|
14
13
|
import { beginAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
15
14
|
import { AppRouterScrollCommitProvider } from "../shims/app-router-scroll.js";
|
|
16
15
|
import { BfcacheStateKeyMapContext, ElementsContext, Slot } from "../shims/slot.js";
|
|
17
|
-
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl,
|
|
16
|
+
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, getVinextRscCompatibilityId } from "./app-rsc-cache-busting.js";
|
|
18
17
|
import { getNavigationRuntime, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
|
|
19
18
|
import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
|
|
20
19
|
import "../client/instrumentation-client.js";
|
|
@@ -25,26 +24,23 @@ import { blockDangerousStreamedRscRedirect } from "./app-browser-rsc-redirect.js
|
|
|
25
24
|
import { navigationPlanner } from "./navigation-planner.js";
|
|
26
25
|
import { __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, getClientNavigationRenderContext, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, setClientParams, setMountedSlotsHeader, setPendingPathname, useRouter } from "../shims/navigation.js";
|
|
27
26
|
import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
|
|
28
|
-
import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot
|
|
27
|
+
import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot } from "./app-browser-action-result.js";
|
|
29
28
|
import { createClientReuseManifestHeaderFromVisibleAppState } from "./app-browser-client-reuse-manifest.js";
|
|
30
29
|
import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
|
|
31
|
-
import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, isCacheRestorableAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl
|
|
30
|
+
import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, isCacheRestorableAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl } from "./app-browser-state.js";
|
|
32
31
|
import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch } from "./app-browser-navigation-controller.js";
|
|
33
|
-
import { applyServerActionResultDecision } from "./app-browser-server-action-navigation.js";
|
|
34
32
|
import { consumeInitialFormState, createVinextHydrateRootOptions, hydrateRootInTransition } from "./app-browser-hydration.js";
|
|
35
33
|
import { AppBrowserHistoryController } from "./app-browser-history-controller.js";
|
|
36
34
|
import { createVisitedResponseCacheEntry, isVisitedResponseCacheEntryFresh } from "./app-visited-response-cache.js";
|
|
37
35
|
import { createPopstateRestoreHandler, restoreSynchronousPopstateScrollPosition } from "./app-browser-popstate.js";
|
|
38
36
|
import { createDevOnCaughtError, createOnUncaughtError, createProdOnCaughtError, prodOnRecoverableError } from "./app-browser-error.js";
|
|
39
|
-
import { dismissOverlay } from "./dev-error-overlay-store.js";
|
|
40
|
-
import { devOnCaughtError, installDevErrorOverlay, installViteHmrErrorHandler, reportInitialDevServerErrors } from "./dev-error-overlay.js";
|
|
41
|
-
import { throwOnServerActionNotFound } from "./server-action-not-found.js";
|
|
42
37
|
import { createOptimisticRouteTemplate, getOptimisticPrefetchSourceKey, getOptimisticRouteTemplateKey, resolveOptimisticNavigationPayload } from "./app-optimistic-routing.js";
|
|
43
38
|
import { removeStylesheetLinksCoveredByInlineCss } from "./app-inline-css-client.js";
|
|
44
39
|
import { createElement, startTransition, use, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
45
40
|
import { flushSync } from "react-dom";
|
|
46
|
-
import { createFromFetch, createFromReadableStream,
|
|
41
|
+
import { createFromFetch, createFromReadableStream, setServerCallback } from "@vitejs/plugin-rsc/browser";
|
|
47
42
|
import { createRoot, hydrateRoot } from "react-dom/client";
|
|
43
|
+
import { hasServerActions, loadServerActionClient } from "virtual:vinext-app-capabilities";
|
|
48
44
|
//#region src/server/app-browser-entry.ts
|
|
49
45
|
function toActionType(kind) {
|
|
50
46
|
return kind === "traverse" ? "traverse" : "navigate";
|
|
@@ -94,10 +90,14 @@ const browserNavigationController = createAppBrowserNavigationController({
|
|
|
94
90
|
getRouteManifest: getBrowserRouteManifest,
|
|
95
91
|
syncHistoryStatePreviousNextUrl: (previousNextUrl, bfcacheIds) => historyController.syncCurrentHistoryStatePreviousNextUrl(previousNextUrl, bfcacheIds)
|
|
96
92
|
});
|
|
97
|
-
const discardedServerActionRefreshScheduler = createDiscardedServerActionRefreshScheduler({ runRefresh() {
|
|
93
|
+
const discardedServerActionRefreshScheduler = hasServerActions ? createDiscardedServerActionRefreshScheduler({ runRefresh() {
|
|
98
94
|
clearClientNavigationCaches();
|
|
99
95
|
getNavigationRuntime()?.functions.navigate?.(window.location.href, 0, "refresh", void 0, void 0, true);
|
|
100
|
-
} })
|
|
96
|
+
} }) : {
|
|
97
|
+
markNavigationSettled() {},
|
|
98
|
+
markNavigationStart() {},
|
|
99
|
+
schedule() {}
|
|
100
|
+
};
|
|
101
101
|
const NavigationCommitSignal = browserNavigationController.NavigationCommitSignal;
|
|
102
102
|
const ACTION_HTTP_FALLBACK_ROBOTS_META_ATTR = "data-vinext-action-http-fallback";
|
|
103
103
|
function syncServerActionHttpFallbackHead(status) {
|
|
@@ -303,52 +303,6 @@ async function renderNavigationPayload(payload, navigationSnapshot, targetHref,
|
|
|
303
303
|
visibleCommitMode
|
|
304
304
|
});
|
|
305
305
|
}
|
|
306
|
-
function resolveActionRedirectTarget(response) {
|
|
307
|
-
const actionRedirect = response.headers.get(ACTION_REDIRECT_HEADER);
|
|
308
|
-
if (!actionRedirect) return null;
|
|
309
|
-
if (isDangerousScheme(actionRedirect)) {
|
|
310
|
-
console.error(DANGEROUS_URL_BLOCK_MESSAGE);
|
|
311
|
-
return null;
|
|
312
|
-
}
|
|
313
|
-
try {
|
|
314
|
-
let redirectUrl;
|
|
315
|
-
if (actionRedirect.startsWith("/") || /^[a-z]+:/i.test(actionRedirect)) redirectUrl = new URL(actionRedirect, window.location.href);
|
|
316
|
-
else {
|
|
317
|
-
const baseParsed = new URL(window.location.href);
|
|
318
|
-
let baseDir = baseParsed.pathname;
|
|
319
|
-
if (!baseDir.endsWith("/")) baseDir = baseDir + "/";
|
|
320
|
-
redirectUrl = new URL(actionRedirect, `${baseParsed.origin}${baseDir}${baseParsed.search}`);
|
|
321
|
-
}
|
|
322
|
-
if (redirectUrl.origin !== window.location.origin) {
|
|
323
|
-
browserNavigationController.performHardNavigation(actionRedirect);
|
|
324
|
-
return null;
|
|
325
|
-
}
|
|
326
|
-
const statusHeader = response.headers.get(ACTION_REDIRECT_STATUS_HEADER);
|
|
327
|
-
const status = statusHeader ? parseInt(statusHeader, 10) : 307;
|
|
328
|
-
return {
|
|
329
|
-
href: redirectUrl.href,
|
|
330
|
-
type: response.headers.get("x-action-redirect-type") ?? "push",
|
|
331
|
-
status
|
|
332
|
-
};
|
|
333
|
-
} catch {
|
|
334
|
-
browserNavigationController.performHardNavigation(actionRedirect);
|
|
335
|
-
return null;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
var ServerActionRedirectError = class extends Error {
|
|
339
|
-
digest;
|
|
340
|
-
handled = true;
|
|
341
|
-
constructor(target) {
|
|
342
|
-
super("NEXT_REDIRECT");
|
|
343
|
-
const redirectUrl = new URL(target.href, window.location.href);
|
|
344
|
-
const redirectHref = redirectUrl.pathname + redirectUrl.search + redirectUrl.hash;
|
|
345
|
-
const redirectType = target.type === "push" ? "push" : "replace";
|
|
346
|
-
this.digest = `NEXT_REDIRECT;${redirectType};${encodeURIComponent(redirectHref)};${target.status};`;
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
function createServerActionRedirectError(target) {
|
|
350
|
-
return new ServerActionRedirectError(target);
|
|
351
|
-
}
|
|
352
306
|
async function commitSameUrlNavigatePayload(nextElements, actionInitiation, returnValue, revalidation = "none") {
|
|
353
307
|
const navigationSnapshot = createClientNavigationRenderSnapshot(actionInitiation.href, actionInitiation.routerState.navigationSnapshot.params);
|
|
354
308
|
return browserNavigationController.commitSameUrlNavigatePayload(nextElements, navigationSnapshot, returnValue, actionInitiation.routerState, {
|
|
@@ -709,112 +663,53 @@ function applyRuntimeRscBootstrap(rsc) {
|
|
|
709
663
|
if (rsc.nav) restoreHydrationNavigationContext(rsc.nav.pathname, rsc.nav.searchParams, params);
|
|
710
664
|
}
|
|
711
665
|
function registerServerActionCallback() {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
const temporaryReferences = createTemporaryReferenceSet();
|
|
666
|
+
setServerCallback((id, args) => {
|
|
667
|
+
const releaseCacheInvalidationGuard = historyController.beginCacheInvalidationGuard();
|
|
715
668
|
const actionInitiation = createActionInitiationSnapshot();
|
|
716
|
-
|
|
717
|
-
const body = await encodeReply(args, { temporaryReferences });
|
|
718
|
-
const { headers } = resolveServerActionRequestState({
|
|
719
|
-
actionId: id,
|
|
669
|
+
return loadServerActionClient().then(({ invokeClientServerAction }) => invokeClientServerAction(id, args, actionInitiation, {
|
|
720
670
|
basePath: __basePath,
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
if (hasActionRedirect && !actionRedirectTarget) return;
|
|
733
|
-
const actionResultFacts = createServerActionResultFacts({
|
|
734
|
-
actionRedirectHref: actionRedirectTarget?.href ?? null,
|
|
735
|
-
actionRedirectType: actionRedirectTarget?.type ?? null,
|
|
736
|
-
clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
|
|
737
|
-
compatibilityIdHeader: fetchResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
|
|
738
|
-
contentTypeHeader: fetchResponse.headers.get("content-type"),
|
|
739
|
-
currentHref: actionInitiation.href,
|
|
740
|
-
origin: window.location.origin,
|
|
741
|
-
responseUrl: fetchResponse.url
|
|
742
|
-
});
|
|
743
|
-
const fetchResponseIsRsc = actionResultFacts.isRscContentType;
|
|
744
|
-
if (applyServerActionResultDecision(navigationPlanner.classifyServerActionResult(actionResultFacts), clearClientNavigationCaches, (url, historyMode) => browserNavigationController.performHardNavigation(url, historyMode))) return;
|
|
745
|
-
const revalidation = parseServerActionRevalidationHeader(fetchResponse.headers);
|
|
746
|
-
if (revalidation !== "none") clearClientNavigationCaches();
|
|
747
|
-
const invalidResponseError = await readInvalidServerActionResponseError(fetchResponse.clone(), actionRedirectTarget !== null);
|
|
748
|
-
if (invalidResponseError) throw invalidResponseError;
|
|
749
|
-
if (actionRedirectTarget && !fetchResponseIsRsc) {
|
|
750
|
-
browserNavigationController.performHardNavigation(actionRedirectTarget.href);
|
|
751
|
-
return;
|
|
752
|
-
}
|
|
753
|
-
const flightResponse = fetchResponse.status === 303 ? new Response(fetchResponse.body, {
|
|
754
|
-
headers: fetchResponse.headers,
|
|
755
|
-
status: 200,
|
|
756
|
-
statusText: "OK"
|
|
757
|
-
}) : fetchResponse;
|
|
758
|
-
const result = await createFromFetch(Promise.resolve(flightResponse), { temporaryReferences });
|
|
759
|
-
if (revalidation === "none" && shouldClearClientNavigationCachesForServerActionResult(result, revalidation)) clearClientNavigationCaches();
|
|
760
|
-
if (actionRedirectTarget) {
|
|
761
|
-
if (isServerActionResult(result) && result.root !== void 0) {
|
|
762
|
-
const decoded = AppElementsWire.decode(result.root);
|
|
763
|
-
const hashIdx = actionRedirectTarget.href.indexOf("#");
|
|
764
|
-
const actionScrollIntent = beginAppRouterScrollIntent((hashIdx !== -1 ? actionRedirectTarget.href.slice(hashIdx) : "") || null);
|
|
765
|
-
if (actionRedirectTarget.type === "push") saveScrollPosition();
|
|
766
|
-
renderNavigationPayload(Promise.resolve(decoded), createClientNavigationRenderSnapshot(actionRedirectTarget.href, actionInitiation.routerState.navigationSnapshot.params), actionRedirectTarget.href, actionInitiation.navigationId, actionRedirectTarget.type === "push" ? "push" : "replace", {}, null, null, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, actionRedirectTarget.type === "push" ? "navigate" : "replace", "server-action", null, actionScrollIntent).catch(() => {
|
|
767
|
-
browserNavigationController.performHardNavigation(actionRedirectTarget.href);
|
|
671
|
+
clearClientNavigationCaches,
|
|
672
|
+
clientRscCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
|
|
673
|
+
commitSameUrlNavigatePayload,
|
|
674
|
+
navigationPlanner,
|
|
675
|
+
performHardNavigation: (url, historyMode) => browserNavigationController.performHardNavigation(url, historyMode),
|
|
676
|
+
renderRedirectPayload(elements, target, actionInitiation) {
|
|
677
|
+
const hashIdx = target.href.indexOf("#");
|
|
678
|
+
const actionScrollIntent = beginAppRouterScrollIntent((hashIdx !== -1 ? target.href.slice(hashIdx) : "") || null);
|
|
679
|
+
if (target.type === "push") saveScrollPosition();
|
|
680
|
+
renderNavigationPayload(Promise.resolve(elements), createClientNavigationRenderSnapshot(target.href, actionInitiation.routerState.navigationSnapshot.params), target.href, actionInitiation.navigationId, target.type === "push" ? "push" : "replace", {}, null, null, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, target.type === "push" ? "navigate" : "replace", "server-action", null, actionScrollIntent).catch(() => {
|
|
681
|
+
browserNavigationController.performHardNavigation(target.href);
|
|
768
682
|
});
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}
|
|
774
|
-
syncServerActionHttpFallbackHead(isServerActionResult(result) && result.root !== void 0 ? null : fetchResponse.status);
|
|
775
|
-
if (isServerActionResult(result)) {
|
|
776
|
-
if (result.root !== void 0) {
|
|
777
|
-
const returnValue = result.returnValue && !result.returnValue.ok ? {
|
|
778
|
-
ok: false,
|
|
779
|
-
data: normalizeServerActionThrownValue(result.returnValue.data, fetchResponse.status)
|
|
780
|
-
} : result.returnValue;
|
|
781
|
-
return commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result.root)), actionInitiation, returnValue, revalidation);
|
|
782
|
-
}
|
|
783
|
-
if (result.returnValue) {
|
|
784
|
-
if (!result.returnValue.ok) throw normalizeServerActionThrownValue(result.returnValue.data, fetchResponse.status);
|
|
785
|
-
return result.returnValue.data;
|
|
786
|
-
}
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
return commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result)), actionInitiation, void 0, revalidation);
|
|
790
|
-
};
|
|
791
|
-
setServerCallback((id, args) => {
|
|
792
|
-
const releaseCacheInvalidationGuard = historyController.beginCacheInvalidationGuard();
|
|
793
|
-
return Promise.resolve().then(() => serverActionCallback(id, args)).finally(releaseCacheInvalidationGuard);
|
|
683
|
+
},
|
|
684
|
+
syncCurrentHistoryState: (previousNextUrl, bfcacheIds) => historyController.syncCurrentHistoryStatePreviousNextUrl(previousNextUrl, bfcacheIds),
|
|
685
|
+
syncServerActionHttpFallbackHead
|
|
686
|
+
})).finally(releaseCacheInvalidationGuard);
|
|
794
687
|
});
|
|
795
688
|
}
|
|
796
689
|
async function main() {
|
|
797
690
|
if (!claimInitialAppRouterBootstrap()) return;
|
|
798
|
-
registerServerActionCallback();
|
|
691
|
+
if (hasServerActions) registerServerActionCallback();
|
|
799
692
|
installAppNavigationFailureListeners();
|
|
693
|
+
let devErrorOverlay = null;
|
|
800
694
|
if (import.meta.env.DEV) {
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
695
|
+
devErrorOverlay = await import("./dev-error-overlay.js");
|
|
696
|
+
devErrorOverlay.installDevErrorOverlay();
|
|
697
|
+
devErrorOverlay.installViteHmrErrorHandler(import.meta.hot);
|
|
698
|
+
devErrorOverlay.reportInitialDevServerErrors();
|
|
804
699
|
}
|
|
805
700
|
const rscStream = await readInitialRscStream();
|
|
806
701
|
if (rscStream === null) return;
|
|
807
|
-
bootstrapHydration(rscStream);
|
|
702
|
+
bootstrapHydration(rscStream, devErrorOverlay);
|
|
808
703
|
}
|
|
809
|
-
function bootstrapHydration(rscStream) {
|
|
704
|
+
function bootstrapHydration(rscStream, devErrorOverlay) {
|
|
810
705
|
const root = decodeAppElementsPromise(createFromReadableStream(rscStream));
|
|
811
706
|
const initialNavigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
|
|
812
707
|
historyController.writeBootstrapHistoryMetadata();
|
|
813
708
|
const onUncaughtError = createOnUncaughtError();
|
|
814
709
|
const formState = consumeInitialFormState(getVinextBrowserGlobal());
|
|
815
|
-
const hydrateRootOptions = import.meta.env.DEV ? createVinextHydrateRootOptions({
|
|
710
|
+
const hydrateRootOptions = import.meta.env.DEV && devErrorOverlay ? createVinextHydrateRootOptions({
|
|
816
711
|
formState,
|
|
817
|
-
onCaughtError: createDevOnCaughtError(devOnCaughtError, onUncaughtError),
|
|
712
|
+
onCaughtError: createDevOnCaughtError(devErrorOverlay.devOnCaughtError, onUncaughtError),
|
|
818
713
|
onUncaughtError
|
|
819
714
|
}) : createVinextHydrateRootOptions({
|
|
820
715
|
formState,
|
|
@@ -1141,7 +1036,7 @@ function bootstrapHydration(rscStream) {
|
|
|
1141
1036
|
restorePopstateScrollPosition
|
|
1142
1037
|
}, event.state);
|
|
1143
1038
|
});
|
|
1144
|
-
if (import.meta.hot) {
|
|
1039
|
+
if (import.meta.env.DEV && import.meta.hot) {
|
|
1145
1040
|
const applyRscHmrUpdate = async (updateId) => {
|
|
1146
1041
|
if (updateId !== latestRscHmrUpdateId) return;
|
|
1147
1042
|
if (document.documentElement.id === "__next_error__") {
|
|
@@ -1157,7 +1052,7 @@ function bootstrapHydration(rscStream) {
|
|
|
1157
1052
|
if (!browserNavigationController.hasBrowserRouterState()) return;
|
|
1158
1053
|
clearClientNavigationCaches();
|
|
1159
1054
|
const navigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
|
|
1160
|
-
dismissOverlay();
|
|
1055
|
+
devErrorOverlay?.dismissOverlay();
|
|
1161
1056
|
const hmrHeaders = createRscRequestHeaders();
|
|
1162
1057
|
await browserNavigationController.hmrReplaceTree(decodeAppElementsPromise(createFromFetch(fetch(await createRscRequestUrl(window.location.pathname + window.location.search, hmrHeaders), { headers: hmrHeaders }))), navigationSnapshot);
|
|
1163
1058
|
};
|
|
@@ -45,6 +45,7 @@ type CommitNavigationHistoryOptions = {
|
|
|
45
45
|
targetHistoryIndex?: number | null;
|
|
46
46
|
stageClientParams: () => void;
|
|
47
47
|
};
|
|
48
|
+
declare function createCanonicalBrowserHistoryHref(href: string): string;
|
|
48
49
|
/**
|
|
49
50
|
* Owns App Router browser-history metadata and traversal bookkeeping behind a
|
|
50
51
|
* typed seam: traversal index allocation/commit, push/replace/traverse/hash-only
|
|
@@ -101,4 +102,4 @@ declare class AppBrowserHistoryController {
|
|
|
101
102
|
restoreHistorySnapshot(options: RestoreHistorySnapshotOptions): boolean;
|
|
102
103
|
}
|
|
103
104
|
//#endregion
|
|
104
|
-
export { AppBrowserHistoryController, RestorableSnapshotCandidate };
|
|
105
|
+
export { AppBrowserHistoryController, RestorableSnapshotCandidate, createCanonicalBrowserHistoryHref };
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { RestorableClientStateController, createHistoryStateWithNavigationMetadata, readHistoryStateBfcacheIds, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
2
2
|
//#region src/server/app-browser-history-controller.ts
|
|
3
|
+
function createCanonicalBrowserHistoryHref(href) {
|
|
4
|
+
const url = new URL(href);
|
|
5
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
6
|
+
}
|
|
3
7
|
function stripVinextScrollState(state) {
|
|
4
8
|
if (!state || typeof state !== "object") return state;
|
|
5
9
|
const nextState = {};
|
|
@@ -166,7 +170,7 @@ var AppBrowserHistoryController = class {
|
|
|
166
170
|
this.#replaceHistoryState(createHistoryStateWithNavigationMetadata(this.#readHistoryState(), {
|
|
167
171
|
previousNextUrl: null,
|
|
168
172
|
traversalIndex: this.#currentHistoryTraversalIndex
|
|
169
|
-
}), this.#readCurrentHref());
|
|
173
|
+
}), createCanonicalBrowserHistoryHref(this.#readCurrentHref()));
|
|
170
174
|
}
|
|
171
175
|
/** History write performed on the first committed (hydrated) render. */
|
|
172
176
|
writeHydratedHistoryMetadata(options) {
|
|
@@ -207,4 +211,4 @@ function areBfcacheIdMapsEqual(a, b) {
|
|
|
207
211
|
return aEntries.every(([key, value]) => b[key] === value);
|
|
208
212
|
}
|
|
209
213
|
//#endregion
|
|
210
|
-
export { AppBrowserHistoryController };
|
|
214
|
+
export { AppBrowserHistoryController, createCanonicalBrowserHistoryHref };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AppElements, AppWireElements } from "./app-elements-wire.js";
|
|
2
|
+
import { navigationPlanner } from "./navigation-planner.js";
|
|
3
|
+
import { AppBrowserServerActionResult, ServerActionRevalidationKind } from "./app-browser-action-result.js";
|
|
4
|
+
import { AppRouterState } from "./app-browser-state.js";
|
|
5
|
+
|
|
6
|
+
//#region src/server/app-browser-server-action-client.d.ts
|
|
7
|
+
type ServerActionResult = AppBrowserServerActionResult<AppWireElements>;
|
|
8
|
+
type ClientServerActionInitiation = {
|
|
9
|
+
href: string;
|
|
10
|
+
navigationId: number;
|
|
11
|
+
path: string;
|
|
12
|
+
routerState: AppRouterState;
|
|
13
|
+
};
|
|
14
|
+
type ActionRedirectTarget = {
|
|
15
|
+
href: string;
|
|
16
|
+
type: string;
|
|
17
|
+
status: number;
|
|
18
|
+
};
|
|
19
|
+
type ClientServerActionDeps = {
|
|
20
|
+
basePath: string;
|
|
21
|
+
clearClientNavigationCaches(): void;
|
|
22
|
+
clientRscCompatibilityId: string | null;
|
|
23
|
+
commitSameUrlNavigatePayload(elements: Promise<AppElements>, actionInitiation: ClientServerActionInitiation, returnValue: ServerActionResult["returnValue"] | undefined, revalidation: ServerActionRevalidationKind): Promise<unknown>;
|
|
24
|
+
navigationPlanner: typeof navigationPlanner;
|
|
25
|
+
performHardNavigation(url: string, historyMode?: "assign" | "replace"): void;
|
|
26
|
+
renderRedirectPayload(elements: AppElements, target: ActionRedirectTarget, actionInitiation: ClientServerActionInitiation): void;
|
|
27
|
+
syncCurrentHistoryState(previousNextUrl: string | null, bfcacheIds: Readonly<Record<string, string>>): void;
|
|
28
|
+
syncServerActionHttpFallbackHead(status: number | null): void;
|
|
29
|
+
};
|
|
30
|
+
declare function invokeClientServerAction(id: string, args: unknown[], actionInitiation: ClientServerActionInitiation, deps: ClientServerActionDeps): Promise<unknown>;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { ClientServerActionDeps, ClientServerActionInitiation, invokeClientServerAction };
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER } from "./headers.js";
|
|
2
|
+
import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
|
|
3
|
+
import { AppElementsWire } from "./app-elements-wire.js";
|
|
4
|
+
import "./app-elements.js";
|
|
5
|
+
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createServerActionRequestUrl } from "./app-rsc-cache-busting.js";
|
|
6
|
+
import { createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult } from "./app-browser-action-result.js";
|
|
7
|
+
import { resolveServerActionRequestState } from "./app-browser-state.js";
|
|
8
|
+
import { applyServerActionResultDecision } from "./app-browser-server-action-navigation.js";
|
|
9
|
+
import { throwOnServerActionNotFound } from "./server-action-not-found.js";
|
|
10
|
+
import { createFromFetch, createTemporaryReferenceSet, encodeReply } from "@vitejs/plugin-rsc/browser";
|
|
11
|
+
//#region src/server/app-browser-server-action-client.ts
|
|
12
|
+
function resolveActionRedirectTarget(response, performHardNavigation) {
|
|
13
|
+
const actionRedirect = response.headers.get(ACTION_REDIRECT_HEADER);
|
|
14
|
+
if (!actionRedirect) return null;
|
|
15
|
+
if (isDangerousScheme(actionRedirect)) {
|
|
16
|
+
console.error(DANGEROUS_URL_BLOCK_MESSAGE);
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
let redirectUrl;
|
|
21
|
+
if (actionRedirect.startsWith("/") || /^[a-z]+:/i.test(actionRedirect)) redirectUrl = new URL(actionRedirect, window.location.href);
|
|
22
|
+
else {
|
|
23
|
+
const baseParsed = new URL(window.location.href);
|
|
24
|
+
let baseDir = baseParsed.pathname;
|
|
25
|
+
if (!baseDir.endsWith("/")) baseDir += "/";
|
|
26
|
+
redirectUrl = new URL(actionRedirect, `${baseParsed.origin}${baseDir}${baseParsed.search}`);
|
|
27
|
+
}
|
|
28
|
+
if (redirectUrl.origin !== window.location.origin) {
|
|
29
|
+
performHardNavigation(actionRedirect);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const statusHeader = response.headers.get(ACTION_REDIRECT_STATUS_HEADER);
|
|
33
|
+
return {
|
|
34
|
+
href: redirectUrl.href,
|
|
35
|
+
type: response.headers.get("x-action-redirect-type") ?? "push",
|
|
36
|
+
status: statusHeader ? parseInt(statusHeader, 10) : 307
|
|
37
|
+
};
|
|
38
|
+
} catch {
|
|
39
|
+
performHardNavigation(actionRedirect);
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
var ServerActionRedirectError = class extends Error {
|
|
44
|
+
digest;
|
|
45
|
+
handled = true;
|
|
46
|
+
constructor(target) {
|
|
47
|
+
super("NEXT_REDIRECT");
|
|
48
|
+
const redirectUrl = new URL(target.href, window.location.href);
|
|
49
|
+
const redirectHref = redirectUrl.pathname + redirectUrl.search + redirectUrl.hash;
|
|
50
|
+
const redirectType = target.type === "push" ? "push" : "replace";
|
|
51
|
+
this.digest = `NEXT_REDIRECT;${redirectType};${encodeURIComponent(redirectHref)};${target.status};`;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
async function invokeClientServerAction(id, args, actionInitiation, deps) {
|
|
55
|
+
deps.syncServerActionHttpFallbackHead(null);
|
|
56
|
+
const temporaryReferences = createTemporaryReferenceSet();
|
|
57
|
+
deps.syncCurrentHistoryState(actionInitiation.routerState.previousNextUrl, actionInitiation.routerState.bfcacheIds);
|
|
58
|
+
const body = await encodeReply(args, { temporaryReferences });
|
|
59
|
+
const headers = resolveServerActionRequestState({
|
|
60
|
+
actionId: id,
|
|
61
|
+
basePath: deps.basePath,
|
|
62
|
+
elements: actionInitiation.routerState.elements,
|
|
63
|
+
previousNextUrl: actionInitiation.routerState.previousNextUrl
|
|
64
|
+
}).headers;
|
|
65
|
+
const fetchResponse = await fetch(createServerActionRequestUrl(actionInitiation.path), {
|
|
66
|
+
method: "POST",
|
|
67
|
+
headers,
|
|
68
|
+
body
|
|
69
|
+
});
|
|
70
|
+
throwOnServerActionNotFound(fetchResponse, id);
|
|
71
|
+
const hasActionRedirect = fetchResponse.headers.has(ACTION_REDIRECT_HEADER);
|
|
72
|
+
const actionRedirectTarget = resolveActionRedirectTarget(fetchResponse, (url, historyMode) => deps.performHardNavigation(url, historyMode));
|
|
73
|
+
if (hasActionRedirect && !actionRedirectTarget) return void 0;
|
|
74
|
+
const actionResultFacts = createServerActionResultFacts({
|
|
75
|
+
actionRedirectHref: actionRedirectTarget?.href ?? null,
|
|
76
|
+
actionRedirectType: actionRedirectTarget?.type ?? null,
|
|
77
|
+
clientCompatibilityId: deps.clientRscCompatibilityId,
|
|
78
|
+
compatibilityIdHeader: fetchResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
|
|
79
|
+
contentTypeHeader: fetchResponse.headers.get("content-type"),
|
|
80
|
+
currentHref: actionInitiation.href,
|
|
81
|
+
origin: window.location.origin,
|
|
82
|
+
responseUrl: fetchResponse.url
|
|
83
|
+
});
|
|
84
|
+
const fetchResponseIsRsc = actionResultFacts.isRscContentType;
|
|
85
|
+
if (applyServerActionResultDecision(deps.navigationPlanner.classifyServerActionResult(actionResultFacts), () => deps.clearClientNavigationCaches(), (url, historyMode) => deps.performHardNavigation(url, historyMode))) return;
|
|
86
|
+
const revalidation = parseServerActionRevalidationHeader(fetchResponse.headers);
|
|
87
|
+
if (revalidation !== "none") deps.clearClientNavigationCaches();
|
|
88
|
+
const invalidResponseError = await readInvalidServerActionResponseError(fetchResponse.clone(), actionRedirectTarget !== null);
|
|
89
|
+
if (invalidResponseError) throw invalidResponseError;
|
|
90
|
+
if (actionRedirectTarget && !fetchResponseIsRsc) {
|
|
91
|
+
deps.performHardNavigation(actionRedirectTarget.href);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const flightResponse = fetchResponse.status === 303 ? new Response(fetchResponse.body, {
|
|
95
|
+
headers: fetchResponse.headers,
|
|
96
|
+
status: 200,
|
|
97
|
+
statusText: "OK"
|
|
98
|
+
}) : fetchResponse;
|
|
99
|
+
const result = await createFromFetch(Promise.resolve(flightResponse), { temporaryReferences });
|
|
100
|
+
if (revalidation === "none" && shouldClearClientNavigationCachesForServerActionResult(result, revalidation)) deps.clearClientNavigationCaches();
|
|
101
|
+
if (actionRedirectTarget) {
|
|
102
|
+
if (isServerActionResult(result) && result.root !== void 0) {
|
|
103
|
+
deps.renderRedirectPayload(AppElementsWire.decode(result.root), actionRedirectTarget, actionInitiation);
|
|
104
|
+
throw new ServerActionRedirectError(actionRedirectTarget);
|
|
105
|
+
}
|
|
106
|
+
deps.performHardNavigation(actionRedirectTarget.href);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const hasSameUrlRerenderPayload = isServerActionResult(result) && result.root !== void 0;
|
|
110
|
+
deps.syncServerActionHttpFallbackHead(hasSameUrlRerenderPayload ? null : fetchResponse.status);
|
|
111
|
+
if (isServerActionResult(result)) {
|
|
112
|
+
if (result.root !== void 0) {
|
|
113
|
+
const returnValue = result.returnValue && !result.returnValue.ok ? {
|
|
114
|
+
ok: false,
|
|
115
|
+
data: normalizeServerActionThrownValue(result.returnValue.data, fetchResponse.status)
|
|
116
|
+
} : result.returnValue;
|
|
117
|
+
return deps.commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result.root)), actionInitiation, returnValue, revalidation);
|
|
118
|
+
}
|
|
119
|
+
if (result.returnValue) {
|
|
120
|
+
if (!result.returnValue.ok) throw normalizeServerActionThrownValue(result.returnValue.data, fetchResponse.status);
|
|
121
|
+
return result.returnValue.data;
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
return deps.commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result)), actionInitiation, void 0, revalidation);
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
export { invokeClientServerAction };
|
|
@@ -4,6 +4,7 @@ import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
|
4
4
|
import { AppPageParams } from "./app-page-boundary.js";
|
|
5
5
|
import { AppPageFontPreload } from "./app-page-execution.js";
|
|
6
6
|
import { AppPageMiddlewareContext } from "./app-page-response.js";
|
|
7
|
+
import { ApplyAppPageFileBasedMetadata } from "./app-page-head.js";
|
|
7
8
|
import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
8
9
|
import { AppPageBoundaryRoute } from "./app-page-boundary-render.js";
|
|
9
10
|
import { ReactNode } from "react";
|
|
@@ -27,6 +28,7 @@ type AppFallbackRendererFontProviders = {
|
|
|
27
28
|
getFontStyles: () => string[];
|
|
28
29
|
};
|
|
29
30
|
type AppFallbackRendererOptions<TModule extends AppPageModule = AppPageModule> = {
|
|
31
|
+
applyFileBasedMetadata?: ApplyAppPageFileBasedMetadata;
|
|
30
32
|
clearRequestContext: () => void;
|
|
31
33
|
createRscOnErrorHandler: (request: Request, pathname: string, routePath: string) => AppPageBoundaryOnError;
|
|
32
34
|
fontProviders: AppFallbackRendererFontProviders;
|
|
@@ -73,7 +75,7 @@ type AppFallbackRendererCallContext = {
|
|
|
73
75
|
sourcePageSegments?: readonly string[] | null;
|
|
74
76
|
};
|
|
75
77
|
type AppFallbackRenderer<TModule extends AppPageModule = AppPageModule> = {
|
|
76
|
-
renderErrorBoundary: (route: AppPageBoundaryRoute<TModule> | null, error: unknown, isRscRequest: boolean, request: Request, matchedParams: AppPageParams | undefined, scriptNonce: string | undefined, middlewareContext: AppPageMiddlewareContext, callContext?: AppFallbackRendererCallContext) => Promise<Response | null>;
|
|
78
|
+
renderErrorBoundary: (route: AppPageBoundaryRoute<TModule> | null, error: unknown, isRscRequest: boolean, request: Request, matchedParams: AppPageParams | undefined, scriptNonce: string | undefined, middlewareContext: AppPageMiddlewareContext, callContext?: AppFallbackRendererCallContext, errorOrigin?: "rsc" | "ssr") => Promise<Response | null>;
|
|
77
79
|
renderHttpAccessFallback: (route: AppPageBoundaryRoute<TModule> | null, statusCode: number, isRscRequest: boolean, request: Request, opts: {
|
|
78
80
|
boundaryComponent?: AppPageComponent | null;
|
|
79
81
|
boundaryModule?: TModule | null;
|
|
@@ -7,7 +7,7 @@ const EMPTY_MW_CTX = {
|
|
|
7
7
|
status: null
|
|
8
8
|
};
|
|
9
9
|
function createAppFallbackRenderer(options) {
|
|
10
|
-
const { basePath = "", clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, loadGlobalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader, trailingSlash } = options;
|
|
10
|
+
const { applyFileBasedMetadata, basePath = "", clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, loadGlobalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader, trailingSlash } = options;
|
|
11
11
|
const { rootForbiddenModule, rootLayouts, rootNotFoundModule, rootUnauthorizedModule } = rootBoundaries;
|
|
12
12
|
const effectiveGlobalErrorModule = globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE;
|
|
13
13
|
const effectiveRootNotFoundModule = rootNotFoundModule ?? DEFAULT_NOT_FOUND_MODULE;
|
|
@@ -23,6 +23,7 @@ function createAppFallbackRenderer(options) {
|
|
|
23
23
|
const globalNotFoundModule = await resolveGlobalNotFoundModule();
|
|
24
24
|
const globalNotFoundComponent = globalNotFoundModule?.default ?? null;
|
|
25
25
|
if (globalNotFoundComponent) return renderAppPageHttpAccessFallback({
|
|
26
|
+
applyFileBasedMetadata,
|
|
26
27
|
boundaryComponent: globalNotFoundComponent,
|
|
27
28
|
boundaryModule: globalNotFoundModule ?? null,
|
|
28
29
|
buildFontLinkHeader: fontProviders.buildFontLinkHeader,
|
|
@@ -57,6 +58,7 @@ function createAppFallbackRenderer(options) {
|
|
|
57
58
|
});
|
|
58
59
|
}
|
|
59
60
|
return renderAppPageHttpAccessFallback({
|
|
61
|
+
applyFileBasedMetadata,
|
|
60
62
|
basePath,
|
|
61
63
|
trailingSlash,
|
|
62
64
|
boundaryComponent: opts?.boundaryComponent ?? null,
|
|
@@ -95,8 +97,9 @@ function createAppFallbackRenderer(options) {
|
|
|
95
97
|
renderNotFound(route, isRscRequest, request, matchedParams, scriptNonce, middlewareContext, callContext) {
|
|
96
98
|
return this.renderHttpAccessFallback(route, 404, isRscRequest, request, { matchedParams }, scriptNonce, middlewareContext, callContext);
|
|
97
99
|
},
|
|
98
|
-
renderErrorBoundary(route, error, isRscRequest, request, matchedParams, scriptNonce, middlewareContext, callContext) {
|
|
100
|
+
renderErrorBoundary(route, error, isRscRequest, request, matchedParams, scriptNonce, middlewareContext, callContext, errorOrigin = "rsc") {
|
|
99
101
|
return renderAppPageErrorBoundary({
|
|
102
|
+
applyFileBasedMetadata,
|
|
100
103
|
basePath,
|
|
101
104
|
trailingSlash,
|
|
102
105
|
buildFontLinkHeader: fontProviders.buildFontLinkHeader,
|
|
@@ -105,6 +108,7 @@ function createAppFallbackRenderer(options) {
|
|
|
105
108
|
return buildRscOnErrorHandler(request, pathname, routePath);
|
|
106
109
|
},
|
|
107
110
|
error,
|
|
111
|
+
errorOrigin,
|
|
108
112
|
getFontLinks: fontProviders.getFontLinks,
|
|
109
113
|
getFontPreloads: fontProviders.getFontPreloads,
|
|
110
114
|
getFontStyles: fontProviders.getFontStyles,
|
|
@@ -63,7 +63,6 @@ declare function createHistoryStateWithNavigationMetadata(state: unknown, metada
|
|
|
63
63
|
}): HistoryStateRecord | null;
|
|
64
64
|
declare function createExternalHistoryStatePreservingMetadata(callerState: unknown, currentHistoryState: unknown): unknown;
|
|
65
65
|
declare function readHistoryStatePreviousNextUrl(state: unknown): string | null;
|
|
66
|
-
declare function isBfcacheSegmentId(id: string): boolean;
|
|
67
66
|
declare function readHistoryStateBfcacheIds(state: unknown): BfcacheIdMap | null;
|
|
68
67
|
declare function readHistoryStateBfcacheVersion(state: unknown): number | null;
|
|
69
68
|
/**
|
|
@@ -83,4 +82,4 @@ declare function resolveHistoryTraversalIntent(options: {
|
|
|
83
82
|
historyState: unknown;
|
|
84
83
|
}): HistoryTraversalIntent;
|
|
85
84
|
//#endregion
|
|
86
|
-
export { BfcacheIdMap, HistoryStateSnapshotCache, HistoryTraversalIntent, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl,
|
|
85
|
+
export { BfcacheIdMap, HistoryStateSnapshotCache, HistoryTraversalIntent, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent };
|
|
@@ -220,4 +220,4 @@ function resolveHistoryTraversalIntent(options) {
|
|
|
220
220
|
};
|
|
221
221
|
}
|
|
222
222
|
//#endregion
|
|
223
|
-
export { HistoryStateSnapshotCache, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl,
|
|
223
|
+
export { HistoryStateSnapshotCache, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent };
|
|
@@ -4,6 +4,7 @@ import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
|
4
4
|
import { AppPageParams } from "./app-page-boundary.js";
|
|
5
5
|
import { AppPageFontPreload } from "./app-page-execution.js";
|
|
6
6
|
import { AppPageMiddlewareContext } from "./app-page-response.js";
|
|
7
|
+
import { ApplyAppPageFileBasedMetadata } from "./app-page-head.js";
|
|
7
8
|
import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
8
9
|
import { ComponentType, ReactNode } from "react";
|
|
9
10
|
|
|
@@ -27,6 +28,7 @@ type AppPageBoundaryRoute<TModule extends AppPageModule = AppPageModule> = {
|
|
|
27
28
|
unauthorized?: TModule | null;
|
|
28
29
|
};
|
|
29
30
|
type AppPageBoundaryRenderCommonOptions<TModule extends AppPageModule = AppPageModule> = {
|
|
31
|
+
applyFileBasedMetadata?: ApplyAppPageFileBasedMetadata;
|
|
30
32
|
buildFontLinkHeader: (preloads: readonly AppPageFontPreload[] | null | undefined) => string;
|
|
31
33
|
clearRequestContext: () => void;
|
|
32
34
|
createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;
|
|
@@ -73,6 +75,7 @@ type RenderAppPageHttpAccessFallbackOptions<TModule extends AppPageModule = AppP
|
|
|
73
75
|
} & AppPageBoundaryRenderCommonOptions<TModule>;
|
|
74
76
|
type RenderAppPageErrorBoundaryOptions<TModule extends AppPageModule = AppPageModule> = {
|
|
75
77
|
error: unknown;
|
|
78
|
+
errorOrigin?: "rsc" | "ssr";
|
|
76
79
|
matchedParams?: AppPageParams | null;
|
|
77
80
|
route?: AppPageBoundaryRoute<TModule> | null;
|
|
78
81
|
sanitizeErrorForClient: (error: Error) => Error;
|