vinext 0.1.1 → 0.1.2
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 -5
- package/dist/build/client-build-config.d.ts +7 -1
- package/dist/build/client-build-config.js +9 -1
- package/dist/check.js +4 -3
- package/dist/client/navigation-runtime.d.ts +3 -2
- package/dist/client/window-next.d.ts +6 -4
- package/dist/config/config-matchers.d.ts +11 -4
- package/dist/config/config-matchers.js +15 -2
- package/dist/config/next-config.d.ts +13 -0
- package/dist/config/next-config.js +2 -0
- package/dist/deploy.js +9 -2
- package/dist/entries/app-rsc-entry.js +7 -1
- package/dist/entries/pages-client-entry.js +1 -1
- package/dist/entries/pages-server-entry.js +7 -6
- package/dist/index.d.ts +0 -2
- package/dist/index.js +86 -78
- package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
- package/dist/plugins/dynamic-preload-metadata.js +415 -0
- package/dist/plugins/og-assets.js +2 -2
- package/dist/plugins/optimize-imports.d.ts +8 -4
- package/dist/plugins/optimize-imports.js +16 -12
- package/dist/plugins/sass.d.ts +53 -24
- package/dist/plugins/sass.js +249 -1
- package/dist/plugins/wasm-module-import.d.ts +15 -0
- package/dist/plugins/wasm-module-import.js +50 -0
- package/dist/routing/app-route-graph.d.ts +23 -1
- package/dist/routing/app-route-graph.js +47 -8
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/app-browser-entry.js +108 -213
- package/dist/server/app-browser-error.d.ts +4 -1
- package/dist/server/app-browser-error.js +7 -1
- package/dist/server/app-browser-history-controller.d.ts +104 -0
- package/dist/server/app-browser-history-controller.js +210 -0
- package/dist/server/app-browser-navigation-controller.d.ts +3 -2
- package/dist/server/app-browser-navigation-controller.js +10 -7
- package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
- package/dist/server/app-browser-rsc-redirect.js +30 -8
- package/dist/server/app-browser-state.js +4 -7
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -1
- package/dist/server/app-fallback-renderer.js +3 -1
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-optimistic-routing.js +22 -1
- package/dist/server/app-page-boundary-render.d.ts +2 -1
- package/dist/server/app-page-boundary-render.js +4 -2
- package/dist/server/app-page-cache.js +9 -7
- package/dist/server/app-page-dispatch.d.ts +8 -0
- package/dist/server/app-page-dispatch.js +18 -5
- package/dist/server/app-page-element-builder.d.ts +22 -2
- package/dist/server/app-page-element-builder.js +37 -8
- package/dist/server/app-page-execution.d.ts +1 -1
- package/dist/server/app-page-execution.js +32 -17
- package/dist/server/app-page-render.d.ts +1 -1
- package/dist/server/app-page-render.js +7 -14
- package/dist/server/app-page-request.d.ts +1 -0
- package/dist/server/app-page-request.js +3 -2
- package/dist/server/app-page-response.js +1 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +8 -7
- package/dist/server/app-page-stream.d.ts +1 -6
- package/dist/server/app-page-stream.js +1 -4
- package/dist/server/app-route-handler-response.js +11 -10
- package/dist/server/app-route-handler-runtime.js +12 -1
- package/dist/server/app-rsc-handler.js +1 -1
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-server-action-execution.d.ts +11 -0
- package/dist/server/app-server-action-execution.js +5 -2
- package/dist/server/app-ssr-entry.js +2 -2
- package/dist/server/app-ssr-stream.js +9 -1
- package/dist/server/dev-lockfile.js +2 -1
- package/dist/server/dev-server.js +43 -12
- package/dist/server/headers.d.ts +8 -1
- package/dist/server/headers.js +8 -1
- package/dist/server/instrumentation-runtime.d.ts +6 -0
- package/dist/server/instrumentation-runtime.js +8 -0
- package/dist/server/isr-decision.d.ts +79 -0
- package/dist/server/isr-decision.js +70 -0
- package/dist/server/metadata-route-response.js +5 -3
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +11 -7
- package/dist/server/middleware.js +1 -0
- package/dist/server/navigation-planner.d.ts +62 -1
- package/dist/server/navigation-planner.js +188 -0
- package/dist/server/navigation-trace.d.ts +11 -1
- package/dist/server/navigation-trace.js +11 -1
- package/dist/server/normalize-path.d.ts +0 -8
- package/dist/server/normalize-path.js +3 -1
- package/dist/server/otel-tracer-extension.d.ts +45 -0
- package/dist/server/otel-tracer-extension.js +89 -0
- package/dist/server/pages-api-route.d.ts +14 -3
- package/dist/server/pages-api-route.js +6 -1
- package/dist/server/pages-asset-tags.d.ts +15 -4
- package/dist/server/pages-asset-tags.js +18 -12
- package/dist/server/pages-data-route.js +5 -1
- package/dist/server/pages-node-compat.d.ts +3 -11
- package/dist/server/pages-node-compat.js +174 -121
- package/dist/server/pages-page-data.d.ts +28 -0
- package/dist/server/pages-page-data.js +61 -17
- package/dist/server/pages-page-handler.d.ts +1 -0
- package/dist/server/pages-page-handler.js +22 -6
- package/dist/server/pages-page-response.d.ts +45 -1
- package/dist/server/pages-page-response.js +66 -5
- package/dist/server/pages-readiness.d.ts +1 -1
- package/dist/server/pages-request-pipeline.d.ts +15 -1
- package/dist/server/pages-request-pipeline.js +23 -2
- package/dist/server/prod-server.d.ts +39 -1
- package/dist/server/prod-server.js +98 -34
- package/dist/shims/cache-runtime.js +9 -2
- package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
- package/dist/shims/dynamic-preload-chunks.js +77 -0
- package/dist/shims/dynamic.d.ts +4 -0
- package/dist/shims/dynamic.js +4 -2
- package/dist/shims/error-boundary.d.ts +4 -4
- package/dist/shims/error.js +37 -11
- package/dist/shims/fetch-cache.d.ts +9 -1
- package/dist/shims/fetch-cache.js +11 -1
- package/dist/shims/head.js +6 -1
- package/dist/shims/headers.d.ts +16 -2
- package/dist/shims/headers.js +37 -1
- package/dist/shims/image-config.js +7 -1
- package/dist/shims/internal/app-route-detection.d.ts +6 -3
- package/dist/shims/internal/app-route-detection.js +10 -6
- package/dist/shims/internal/app-router-context.d.ts +5 -0
- package/dist/shims/metadata.d.ts +6 -2
- package/dist/shims/metadata.js +32 -14
- package/dist/shims/navigation.d.ts +7 -16
- package/dist/shims/navigation.js +33 -16
- package/dist/shims/router.js +28 -1
- package/dist/shims/script-nonce-context.d.ts +1 -1
- package/dist/shims/script-nonce-context.js +11 -3
- package/dist/shims/server.d.ts +17 -1
- package/dist/shims/server.js +31 -6
- package/dist/shims/slot.js +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/typegen.js +1 -0
- package/dist/utils/client-build-manifest.js +15 -5
- package/dist/utils/client-runtime-metadata.d.ts +45 -0
- package/dist/utils/client-runtime-metadata.js +63 -0
- package/dist/utils/hash.d.ts +17 -1
- package/dist/utils/hash.js +36 -1
- package/dist/utils/lazy-chunks.d.ts +27 -1
- package/dist/utils/lazy-chunks.js +65 -1
- package/dist/utils/manifest-paths.d.ts +20 -2
- package/dist/utils/manifest-paths.js +38 -3
- package/dist/utils/path.d.ts +2 -1
- package/dist/utils/path.js +5 -1
- package/package.json +2 -2
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { VINEXT_MOUNTED_SLOTS_HEADER } from "./headers.js";
|
|
2
2
|
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
3
3
|
import { encodeCacheTag } from "../utils/encode-cache-tag.js";
|
|
4
|
+
import { applyCdnResponseHeaders } from "./cache-control.js";
|
|
5
|
+
import { decideIsr } from "./isr-decision.js";
|
|
4
6
|
import { buildAppPageCacheValue } from "./isr-cache.js";
|
|
5
7
|
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
6
8
|
import { readStreamAsText } from "../utils/text-stream.js";
|
|
7
|
-
import { applyCdnResponseHeaders, buildCachedRevalidateCacheControl } from "./cache-control.js";
|
|
8
9
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
9
10
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
10
11
|
import { hasCompleteNegativeRequestApiProof } from "./cache-proof.js";
|
|
@@ -52,9 +53,6 @@ function buildAppPageCacheTags(pathname, extraTags) {
|
|
|
52
53
|
for (const tag of extraTags) if (!tags.includes(tag)) tags.push(tag);
|
|
53
54
|
return tags.map(encodeCacheTag);
|
|
54
55
|
}
|
|
55
|
-
function buildAppPageCacheControl(cacheState, revalidateSeconds, expireSeconds) {
|
|
56
|
-
return buildCachedRevalidateCacheControl(cacheState, revalidateSeconds, expireSeconds);
|
|
57
|
-
}
|
|
58
56
|
function buildAppPageCachedHeaders(options) {
|
|
59
57
|
const headers = new Headers({
|
|
60
58
|
"Content-Type": options.contentType,
|
|
@@ -87,9 +85,13 @@ function resolveAppPageCacheWritePolicy(options) {
|
|
|
87
85
|
}
|
|
88
86
|
function buildAppPageCachedResponse(cachedValue, options) {
|
|
89
87
|
const status = options.middlewareStatus ?? (cachedValue.status || 200);
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
const { cacheControl } = decideIsr({
|
|
89
|
+
cacheState: options.cacheState,
|
|
90
|
+
kind: "app-page",
|
|
91
|
+
revalidateSeconds: options.revalidateSeconds,
|
|
92
|
+
expireSeconds: options.expireSeconds,
|
|
93
|
+
cacheControlMeta: options.cacheControl
|
|
94
|
+
});
|
|
93
95
|
if (options.isRscRequest) {
|
|
94
96
|
if (!cachedValue.rscData) return null;
|
|
95
97
|
const rscHeaders = buildAppPageCachedHeaders({
|
|
@@ -51,6 +51,12 @@ type AppPageModule = {
|
|
|
51
51
|
dynamic?: unknown;
|
|
52
52
|
revalidate?: unknown;
|
|
53
53
|
};
|
|
54
|
+
type AppPageDispatchSlot = {
|
|
55
|
+
default?: AppPageModule | null;
|
|
56
|
+
page?: AppPageModule | null;
|
|
57
|
+
slotPatternParts?: readonly string[] | null;
|
|
58
|
+
slotParamNames?: readonly string[] | null;
|
|
59
|
+
};
|
|
54
60
|
type AppPageDispatchRoute = {
|
|
55
61
|
__buildTimeClassifications?: LayoutClassificationOptions["buildTimeClassifications"];
|
|
56
62
|
__buildTimeReasons?: LayoutClassificationOptions["buildTimeReasons"];
|
|
@@ -67,6 +73,7 @@ type AppPageDispatchRoute = {
|
|
|
67
73
|
params: readonly string[];
|
|
68
74
|
pattern: string;
|
|
69
75
|
routeSegments: readonly string[];
|
|
76
|
+
slots?: Readonly<Record<string, AppPageDispatchSlot>>;
|
|
70
77
|
unauthorized?: AppPageModule | null;
|
|
71
78
|
unauthorizeds?: readonly (AppPageModule | null | undefined)[];
|
|
72
79
|
};
|
|
@@ -87,6 +94,7 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
|
|
|
87
94
|
buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker) => Promise<AppPageElement>;
|
|
88
95
|
clientReuseManifest?: ClientReuseManifestParseResult;
|
|
89
96
|
cleanPathname: string;
|
|
97
|
+
displayPathname?: string;
|
|
90
98
|
clearRequestContext: () => void;
|
|
91
99
|
createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;
|
|
92
100
|
debugClassification?: (layoutId: string, reason: ClassificationReason) => void;
|
|
@@ -18,9 +18,10 @@ import { resolveAppPageParentHttpAccessBoundary, resolveAppPageParentHttpAccessB
|
|
|
18
18
|
import { isAppSsrRenderResult } from "./app-page-stream.js";
|
|
19
19
|
import { createAppLayoutParamAccessTracker, isAppLayoutObservationUnsafeForStaticReuse } from "./app-layout-param-observation.js";
|
|
20
20
|
import { resolveAppPageMethodResponse } from "./app-page-method.js";
|
|
21
|
+
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
22
|
+
import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
|
|
21
23
|
import { buildAppPageElement, resolveAppPageIntercept, resolveAppPageInterceptionRerenderTarget, validateAppPageDynamicParams } from "./app-page-request.js";
|
|
22
24
|
import { renderAppPageLifecycle } from "./app-page-render.js";
|
|
23
|
-
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
24
25
|
import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
|
|
25
26
|
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
26
27
|
import React from "react";
|
|
@@ -124,7 +125,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
|
|
|
124
125
|
ensureFetchPatch();
|
|
125
126
|
setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], options.routeSegments));
|
|
126
127
|
options.setNavigationContext({
|
|
127
|
-
pathname: options.cleanPathname,
|
|
128
|
+
pathname: options.displayPathname ?? options.cleanPathname,
|
|
128
129
|
searchParams: new URLSearchParams(),
|
|
129
130
|
params: options.params
|
|
130
131
|
});
|
|
@@ -183,10 +184,11 @@ async function dispatchAppPageInner(options) {
|
|
|
183
184
|
routeKind: "page",
|
|
184
185
|
routePattern: route.pattern
|
|
185
186
|
}));
|
|
187
|
+
const staticNavigationParams = resolveAppPageNavigationParams(route, options.params, options.cleanPathname, null);
|
|
186
188
|
options.setNavigationContext({
|
|
187
|
-
pathname: options.cleanPathname,
|
|
189
|
+
pathname: options.displayPathname ?? options.cleanPathname,
|
|
188
190
|
searchParams: new URLSearchParams(),
|
|
189
|
-
params:
|
|
191
|
+
params: staticNavigationParams
|
|
190
192
|
});
|
|
191
193
|
}
|
|
192
194
|
if (shouldReadAppPageCache({
|
|
@@ -233,9 +235,11 @@ async function dispatchAppPageInner(options) {
|
|
|
233
235
|
return toInterceptOptions(options.interceptionContext, intercept);
|
|
234
236
|
}
|
|
235
237
|
});
|
|
238
|
+
revalidationTarget.navigationParams = resolveAppPageNavigationParams(revalidationTarget.route, revalidationTarget.navigationParams, options.cleanPathname, revalidationTarget.interceptOpts);
|
|
236
239
|
await options.ensureRouteLoaded?.(revalidationTarget.route);
|
|
237
240
|
return runAppPageRevalidationContext({
|
|
238
241
|
cleanPathname: options.cleanPathname,
|
|
242
|
+
displayPathname: options.displayPathname,
|
|
239
243
|
currentFetchCacheMode: options.resolveRouteFetchCacheMode?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? options.fetchCache ?? null : null),
|
|
240
244
|
draftModeSecret: options.draftModeSecret,
|
|
241
245
|
dynamicConfig,
|
|
@@ -352,6 +356,9 @@ async function dispatchAppPageInner(options) {
|
|
|
352
356
|
},
|
|
353
357
|
isRscRequest: options.isRscRequest,
|
|
354
358
|
layoutParamAccess,
|
|
359
|
+
resolveNavigationParams(sourceRoute, navigationParams, pathname, interceptOpts) {
|
|
360
|
+
return resolveAppPageNavigationParams(sourceRoute, navigationParams, pathname, interceptOpts);
|
|
361
|
+
},
|
|
355
362
|
renderInterceptResponse(sourceRoute, interceptElement) {
|
|
356
363
|
const interceptOnError = options.createRscOnErrorHandler(options.cleanPathname, sourceRoute.pattern);
|
|
357
364
|
const interceptStream = options.renderToReadableStream(interceptElement, { onError: interceptOnError });
|
|
@@ -387,6 +394,12 @@ async function dispatchAppPageInner(options) {
|
|
|
387
394
|
resolveSpecialError: resolveAppPageSpecialError
|
|
388
395
|
});
|
|
389
396
|
if (pageBuildResult.response) return pageBuildResult.response;
|
|
397
|
+
const navigationParams = resolveAppPageNavigationParams(route, options.params, options.cleanPathname, interceptResult.interceptOpts);
|
|
398
|
+
options.setNavigationContext({
|
|
399
|
+
pathname: options.displayPathname ?? options.cleanPathname,
|
|
400
|
+
searchParams: options.searchParams,
|
|
401
|
+
params: navigationParams
|
|
402
|
+
});
|
|
390
403
|
const layoutClassifications = getEffectiveLayoutClassifications(route, options.debugClassification);
|
|
391
404
|
return renderAppPageLifecycle({
|
|
392
405
|
basePath: options.basePath,
|
|
@@ -442,6 +455,7 @@ async function dispatchAppPageInner(options) {
|
|
|
442
455
|
layoutCount: route.layouts.length,
|
|
443
456
|
loadSsrHandler: options.loadSsrHandler,
|
|
444
457
|
middlewareContext: options.middlewareContext,
|
|
458
|
+
navigationParams,
|
|
445
459
|
params: options.params,
|
|
446
460
|
layoutParamAccess,
|
|
447
461
|
rootParams: options.rootParams,
|
|
@@ -495,7 +509,6 @@ async function dispatchAppPageInner(options) {
|
|
|
495
509
|
return renderPageSpecialError(options, specialError);
|
|
496
510
|
},
|
|
497
511
|
renderToReadableStream: options.renderToReadableStream,
|
|
498
|
-
routeHasLocalBoundary: Boolean(route.error?.default || route.errors?.some((errorModule) => errorModule?.default)),
|
|
499
512
|
routePattern: route.pattern,
|
|
500
513
|
runWithSuppressedHookWarning(probe) {
|
|
501
514
|
return options.runWithSuppressedHookWarning(probe);
|
|
@@ -49,9 +49,28 @@ type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TEr
|
|
|
49
49
|
* Configured next.config `basePath`. Threaded through `resolveAppPageHead`
|
|
50
50
|
* so file-based metadata route URLs emitted in <head> are prefixed.
|
|
51
51
|
*/
|
|
52
|
-
basePath?: string; /**
|
|
52
|
+
basePath?: string; /** Configured next.config `trailingSlash`, threaded into canonical URL rendering. */
|
|
53
|
+
trailingSlash?: boolean; /** Serialized next.config `htmlLimitedBots` regexp source. */
|
|
53
54
|
htmlLimitedBots?: string;
|
|
54
55
|
};
|
|
56
|
+
type AppPageNavigationParamModule = {
|
|
57
|
+
default?: unknown;
|
|
58
|
+
};
|
|
59
|
+
type AppPageNavigationParamSlot = {
|
|
60
|
+
default?: AppPageNavigationParamModule | null;
|
|
61
|
+
page?: AppPageNavigationParamModule | null;
|
|
62
|
+
slotPatternParts?: readonly string[] | null;
|
|
63
|
+
slotParamNames?: readonly string[] | null;
|
|
64
|
+
};
|
|
65
|
+
type AppPageNavigationParamRoute = {
|
|
66
|
+
params?: readonly string[] | null;
|
|
67
|
+
slots?: Readonly<Record<string, AppPageNavigationParamSlot>> | null;
|
|
68
|
+
};
|
|
69
|
+
type AppPageNavigationParamInterceptOptions = {
|
|
70
|
+
interceptPage?: unknown;
|
|
71
|
+
interceptParams?: AppPageParams | null;
|
|
72
|
+
interceptSlotKey?: string | null;
|
|
73
|
+
};
|
|
55
74
|
/**
|
|
56
75
|
* Build the App Router element tree for a matched route.
|
|
57
76
|
*
|
|
@@ -69,5 +88,6 @@ type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TEr
|
|
|
69
88
|
* {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.
|
|
70
89
|
*/
|
|
71
90
|
declare function buildPageElements<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule>(options: BuildPageElementsOptions<TModule, TErrorModule>): Promise<AppElements>;
|
|
91
|
+
declare function resolveAppPageNavigationParams(route: AppPageNavigationParamRoute, routeParams: AppPageParams, routePath: string, opts?: AppPageNavigationParamInterceptOptions | null): AppPageParams;
|
|
72
92
|
//#endregion
|
|
73
|
-
export { AppPageBuildRoute, type AppPageErrorModule, AppPageInterceptOptions, AppPagePageRequest, type AppPageRouteWiringRoute, BuildPageElementsOptions, buildPageElements };
|
|
93
|
+
export { AppPageBuildRoute, type AppPageErrorModule, AppPageInterceptOptions, AppPagePageRequest, type AppPageRouteWiringRoute, BuildPageElementsOptions, buildPageElements, resolveAppPageNavigationParams };
|
|
@@ -8,8 +8,8 @@ import { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from "./app-
|
|
|
8
8
|
import { makeObservedAppPageSearchParamsThenable } from "./app-page-search-params-observation.js";
|
|
9
9
|
import { buildAppPageElements, createAppPageTreePath } from "./app-page-route-wiring.js";
|
|
10
10
|
import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
|
|
11
|
-
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
12
11
|
import "./app-rsc-route-matching.js";
|
|
12
|
+
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
13
13
|
import { createElement } from "react";
|
|
14
14
|
//#region src/server/app-page-element-builder.ts
|
|
15
15
|
/**
|
|
@@ -118,7 +118,8 @@ async function buildPageElements(options) {
|
|
|
118
118
|
route,
|
|
119
119
|
searchParams: pageSearchParamsThenable,
|
|
120
120
|
slotOverrides,
|
|
121
|
-
renderMode
|
|
121
|
+
renderMode,
|
|
122
|
+
trailingSlash: options.trailingSlash
|
|
122
123
|
});
|
|
123
124
|
}
|
|
124
125
|
/**
|
|
@@ -142,6 +143,18 @@ function buildSlotOverrides(route, routeParams, routePath, opts) {
|
|
|
142
143
|
pageModule: opts.interceptPage,
|
|
143
144
|
params: opts.interceptParams || routeParams
|
|
144
145
|
};
|
|
146
|
+
const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
|
|
147
|
+
for (const [slotKey, params] of Object.entries(slotParamOverrides ?? {})) {
|
|
148
|
+
const existing = overrides[slotKey];
|
|
149
|
+
overrides[slotKey] = existing ? {
|
|
150
|
+
...existing,
|
|
151
|
+
params
|
|
152
|
+
} : { params };
|
|
153
|
+
}
|
|
154
|
+
return Object.keys(overrides).length > 0 ? overrides : null;
|
|
155
|
+
}
|
|
156
|
+
function resolveSlotParamOverrides(route, routePath) {
|
|
157
|
+
const overrides = {};
|
|
145
158
|
const slots = route.slots;
|
|
146
159
|
if (slots) {
|
|
147
160
|
let urlParts = null;
|
|
@@ -154,19 +167,35 @@ function buildSlotOverrides(route, routeParams, routePath, opts) {
|
|
|
154
167
|
if (urlParts === null) urlParts = routePath.split("/").filter(Boolean);
|
|
155
168
|
const matched = matchRoutePattern(urlParts, patternParts);
|
|
156
169
|
if (!matched) continue;
|
|
157
|
-
|
|
158
|
-
overrides[slotKey] = existing ? {
|
|
159
|
-
...existing,
|
|
160
|
-
params: matched
|
|
161
|
-
} : { params: matched };
|
|
170
|
+
overrides[slotKey] = matched;
|
|
162
171
|
}
|
|
163
172
|
}
|
|
164
173
|
return Object.keys(overrides).length > 0 ? overrides : null;
|
|
165
174
|
}
|
|
175
|
+
function mergeAppPageParams(target, source) {
|
|
176
|
+
for (const [key, value] of Object.entries(source)) target[key] = value;
|
|
177
|
+
}
|
|
178
|
+
function isDefaultExportModule(module) {
|
|
179
|
+
return typeof module === "object" && module !== null;
|
|
180
|
+
}
|
|
181
|
+
function hasDefaultExport(module) {
|
|
182
|
+
if (!isDefaultExportModule(module)) return false;
|
|
183
|
+
return module?.default !== null && module?.default !== void 0;
|
|
184
|
+
}
|
|
185
|
+
function resolveAppPageNavigationParams(route, routeParams, routePath, opts) {
|
|
186
|
+
const navigationParams = { ...routeParams };
|
|
187
|
+
const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
|
|
188
|
+
for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {
|
|
189
|
+
const isInterceptedSlot = opts?.interceptSlotKey === slotKey && opts.interceptSlotKey !== "__vinext_page_intercept" && hasDefaultExport(opts.interceptPage);
|
|
190
|
+
if (!isInterceptedSlot && !hasDefaultExport(slot.page) && !hasDefaultExport(slot.default)) continue;
|
|
191
|
+
mergeAppPageParams(navigationParams, isInterceptedSlot ? opts?.interceptParams ?? routeParams : slotParamOverrides?.[slotKey] ?? routeParams);
|
|
192
|
+
}
|
|
193
|
+
return navigationParams;
|
|
194
|
+
}
|
|
166
195
|
function collectParamNameSet(params) {
|
|
167
196
|
const set = /* @__PURE__ */ new Set();
|
|
168
197
|
if (params) for (const name of params) set.add(name);
|
|
169
198
|
return set;
|
|
170
199
|
}
|
|
171
200
|
//#endregion
|
|
172
|
-
export { buildPageElements };
|
|
201
|
+
export { buildPageElements, resolveAppPageNavigationParams };
|
|
@@ -103,7 +103,7 @@ type LayoutClassificationOptions = {
|
|
|
103
103
|
* unsafe even if the older dynamic scope did not report dynamic usage.
|
|
104
104
|
*/
|
|
105
105
|
isLayoutObservationDynamic?: (layoutId: string) => boolean; /** Runs a function with isolated dynamic usage tracking per layout. */
|
|
106
|
-
runWithIsolatedDynamicScope: <T>(fn: () => T) => Promise<{
|
|
106
|
+
runWithIsolatedDynamicScope: <T>(fn: () => T | Promise<T>) => Promise<{
|
|
107
107
|
result: T;
|
|
108
108
|
dynamicDetected: boolean;
|
|
109
109
|
}>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { addBasePathToPathname } from "../utils/base-path.js";
|
|
2
2
|
import { VINEXT_RSC_REDIRECT_HEADER } from "./headers.js";
|
|
3
|
+
import { runWithConnectionProbe } from "../shims/headers.js";
|
|
3
4
|
import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, createRscRedirectLocation } from "./app-rsc-cache-busting.js";
|
|
4
5
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
5
6
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
@@ -180,10 +181,15 @@ async function buildAppPageSpecialErrorResponse(options) {
|
|
|
180
181
|
}
|
|
181
182
|
if (options.renderFallbackPage) {
|
|
182
183
|
const fallbackResponse = await options.renderFallbackPage(options.specialError.statusCode);
|
|
183
|
-
if (fallbackResponse) return mergeAppPageSpecialErrorHeaders(fallbackResponse,
|
|
184
|
+
if (fallbackResponse) return mergeAppPageSpecialErrorHeaders(options.specialError.fromMetadata === true && options.serveStreamingMetadata !== false ? new Response(fallbackResponse.body, {
|
|
185
|
+
headers: fallbackResponse.headers,
|
|
186
|
+
status: 200,
|
|
187
|
+
statusText: fallbackResponse.statusText
|
|
188
|
+
}) : fallbackResponse, options.middlewareContext);
|
|
184
189
|
}
|
|
185
190
|
options.clearRequestContext();
|
|
186
|
-
|
|
191
|
+
const responseStatus = options.specialError.fromMetadata === true && options.serveStreamingMetadata !== false ? 200 : options.specialError.statusCode;
|
|
192
|
+
return mergeAppPageSpecialErrorHeaders(new Response(getAppPageStatusText(options.specialError.statusCode), { status: responseStatus }), options.middlewareContext);
|
|
187
193
|
}
|
|
188
194
|
/** See `LayoutFlags` type docblock in app-elements.ts for lifecycle. */
|
|
189
195
|
async function probeAppPageLayouts(options) {
|
|
@@ -210,7 +216,10 @@ async function probeAppPageLayouts(options) {
|
|
|
210
216
|
if (cls) {
|
|
211
217
|
const layoutId = cls.getLayoutId(layoutIndex);
|
|
212
218
|
try {
|
|
213
|
-
const { dynamicDetected } = await cls.runWithIsolatedDynamicScope(() =>
|
|
219
|
+
const { dynamicDetected } = await cls.runWithIsolatedDynamicScope(async () => {
|
|
220
|
+
const outcome = await runWithConnectionProbe(() => options.probeLayoutAt(layoutIndex));
|
|
221
|
+
return outcome.completed ? outcome.result : null;
|
|
222
|
+
});
|
|
214
223
|
const observationDynamic = cls.isLayoutObservationDynamic?.(layoutId) === true;
|
|
215
224
|
const layoutDynamic = dynamicDetected || observationDynamic;
|
|
216
225
|
layoutFlags[layoutId] = layoutDynamic ? "d" : "s";
|
|
@@ -239,25 +248,31 @@ async function probeAppPageLayouts(options) {
|
|
|
239
248
|
};
|
|
240
249
|
}
|
|
241
250
|
async function probeLayoutForErrors(options, layoutIndex) {
|
|
242
|
-
|
|
243
|
-
const layoutResult = options.probeLayoutAt(layoutIndex);
|
|
244
|
-
if (isPromiseLike(layoutResult)) await layoutResult;
|
|
245
|
-
} catch (error) {
|
|
246
|
-
return options.onLayoutError(error, layoutIndex);
|
|
247
|
-
}
|
|
248
|
-
return null;
|
|
249
|
-
}
|
|
250
|
-
async function probeAppPageComponent(options) {
|
|
251
|
-
return options.runWithSuppressedHookWarning(async () => {
|
|
251
|
+
const outcome = await runWithConnectionProbe(async () => {
|
|
252
252
|
try {
|
|
253
|
-
const
|
|
254
|
-
if (isPromiseLike(
|
|
255
|
-
else Promise.resolve(pageResult).catch(() => {});
|
|
253
|
+
const layoutResult = options.probeLayoutAt(layoutIndex);
|
|
254
|
+
if (isPromiseLike(layoutResult)) await layoutResult;
|
|
256
255
|
} catch (error) {
|
|
257
|
-
return options.
|
|
256
|
+
return options.onLayoutError(error, layoutIndex);
|
|
258
257
|
}
|
|
259
258
|
return null;
|
|
260
259
|
});
|
|
260
|
+
return outcome.completed ? outcome.result : null;
|
|
261
|
+
}
|
|
262
|
+
async function probeAppPageComponent(options) {
|
|
263
|
+
return options.runWithSuppressedHookWarning(async () => {
|
|
264
|
+
const outcome = await runWithConnectionProbe(async () => {
|
|
265
|
+
try {
|
|
266
|
+
const pageResult = options.probePage();
|
|
267
|
+
if (isPromiseLike(pageResult)) if (options.awaitAsyncResult) await pageResult;
|
|
268
|
+
else Promise.resolve(pageResult).catch(() => {});
|
|
269
|
+
} catch (error) {
|
|
270
|
+
return options.onError(error);
|
|
271
|
+
}
|
|
272
|
+
return null;
|
|
273
|
+
});
|
|
274
|
+
return outcome.completed ? outcome.result : null;
|
|
275
|
+
});
|
|
261
276
|
}
|
|
262
277
|
async function readAppPageBinaryStream(stream) {
|
|
263
278
|
const reader = stream.getReader();
|
|
@@ -68,6 +68,7 @@ type RenderAppPageLifecycleOptions = {
|
|
|
68
68
|
layoutCount: number;
|
|
69
69
|
loadSsrHandler: () => Promise<AppPageSsrHandler>;
|
|
70
70
|
middlewareContext: AppPageMiddlewareContext;
|
|
71
|
+
navigationParams: Record<string, unknown>;
|
|
71
72
|
params: Record<string, unknown>;
|
|
72
73
|
rootParams?: RootParams;
|
|
73
74
|
peekRenderObservationState?: () => AppPageRenderObservationState;
|
|
@@ -82,7 +83,6 @@ type RenderAppPageLifecycleOptions = {
|
|
|
82
83
|
renderToReadableStream: (element: ReactNode | AppOutgoingElements, options: {
|
|
83
84
|
onError: AppPageBoundaryOnError;
|
|
84
85
|
}) => ReadableStream<Uint8Array>;
|
|
85
|
-
routeHasLocalBoundary: boolean;
|
|
86
86
|
routePattern: string;
|
|
87
87
|
runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;
|
|
88
88
|
scriptNonce?: string;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { NO_STORE_CACHE_CONTROL } from "./cache-control.js";
|
|
1
2
|
import { createArtifactCompatibilityEnvelope, createArtifactCompatibilityGraphVersion } from "./artifact-compatibility.js";
|
|
2
3
|
import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
|
|
3
4
|
import "./app-elements.js";
|
|
4
5
|
import { runWithFetchDedupe } from "../shims/fetch-cache.js";
|
|
5
|
-
import { NO_STORE_CACHE_CONTROL } from "./cache-control.js";
|
|
6
6
|
import { buildAppPageHtmlResponse, buildAppPageRscResponse, resolveAppPageHtmlResponsePolicy, resolveAppPageRscResponsePolicy } from "./app-page-response.js";
|
|
7
7
|
import { buildAppPageFontLinkHeader, readAppPageBinaryStream, resolveAppPageSpecialError, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
|
|
8
8
|
import { probeAppPageBeforeRender } from "./app-page-probe.js";
|
|
@@ -10,7 +10,7 @@ import { DEFAULT_CACHE_VARIANT_BUDGET, buildCacheVariantWithRouteBudget, buildRe
|
|
|
10
10
|
import { createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope, createEmptyAppPageRenderObservationState } from "./app-page-render-observation.js";
|
|
11
11
|
import { finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse } from "./app-page-cache.js";
|
|
12
12
|
import { createStaticLayoutClientReuseArtifactCompatibility, createStaticLayoutClientReusePayloadHash, createStaticLayoutClientReuseRouteId } from "./static-layout-client-reuse-proof.js";
|
|
13
|
-
import { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery
|
|
13
|
+
import { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery } from "./app-page-stream.js";
|
|
14
14
|
import { getStaticLayoutObservationSkipRejection } from "./app-layout-param-observation.js";
|
|
15
15
|
import { hasDigest } from "./app-rsc-errors.js";
|
|
16
16
|
import { createClientReuseSkipTransportPlan, crossCheckClientReuseManifestEntryWithCache } from "./skip-cache-proof.js";
|
|
@@ -293,7 +293,7 @@ async function renderAppPageLifecycle(options) {
|
|
|
293
293
|
cleanPathname: options.cleanPathname,
|
|
294
294
|
completeness: "partial",
|
|
295
295
|
output: rscOutputScope,
|
|
296
|
-
params: options.
|
|
296
|
+
params: options.navigationParams,
|
|
297
297
|
state: options.peekRenderObservationState?.() ?? createEmptyAppPageRenderObservationState()
|
|
298
298
|
});
|
|
299
299
|
const skipDisposition = options.skipDisposition ?? createRenderLifecycleSkipDisposition({
|
|
@@ -349,7 +349,7 @@ async function renderAppPageLifecycle(options) {
|
|
|
349
349
|
isEdgeRuntime: options.isEdgeRuntime,
|
|
350
350
|
middlewareContext: options.middlewareContext,
|
|
351
351
|
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
352
|
-
params: options.
|
|
352
|
+
params: options.navigationParams,
|
|
353
353
|
policy: rscResponsePolicy,
|
|
354
354
|
timing: buildResponseTiming({
|
|
355
355
|
compileEnd,
|
|
@@ -371,7 +371,7 @@ async function renderAppPageLifecycle(options) {
|
|
|
371
371
|
cleanPathname: options.cleanPathname,
|
|
372
372
|
completeness: "complete",
|
|
373
373
|
output: rscOutputScope,
|
|
374
|
-
params: options.
|
|
374
|
+
params: options.navigationParams,
|
|
375
375
|
state: input.state
|
|
376
376
|
});
|
|
377
377
|
},
|
|
@@ -448,13 +448,6 @@ async function renderAppPageLifecycle(options) {
|
|
|
448
448
|
}
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
|
-
if (shouldRerenderAppPageWithGlobalError({
|
|
452
|
-
capturedError: rscErrorTracker.getCapturedError(),
|
|
453
|
-
hasLocalBoundary: options.routeHasLocalBoundary
|
|
454
|
-
})) {
|
|
455
|
-
const cleanResponse = await options.renderErrorBoundaryResponse(rscErrorTracker.getCapturedError());
|
|
456
|
-
if (cleanResponse) return cleanResponse;
|
|
457
|
-
}
|
|
458
451
|
if (options.isPrerender === true) {
|
|
459
452
|
await settleCapturedRscRenderForCacheMetadata(htmlRender.capturedRscData);
|
|
460
453
|
({expireSeconds, revalidateSeconds} = applyRequestCacheLife({
|
|
@@ -516,7 +509,7 @@ async function renderAppPageLifecycle(options) {
|
|
|
516
509
|
cleanPathname: options.cleanPathname,
|
|
517
510
|
completeness: "complete",
|
|
518
511
|
output: htmlOutputScope,
|
|
519
|
-
params: options.
|
|
512
|
+
params: options.navigationParams,
|
|
520
513
|
state: input.state
|
|
521
514
|
});
|
|
522
515
|
},
|
|
@@ -528,7 +521,7 @@ async function renderAppPageLifecycle(options) {
|
|
|
528
521
|
cleanPathname: options.cleanPathname,
|
|
529
522
|
completeness: "complete",
|
|
530
523
|
output: rscOutputScope,
|
|
531
|
-
params: options.
|
|
524
|
+
params: options.navigationParams,
|
|
532
525
|
state: input.state
|
|
533
526
|
});
|
|
534
527
|
},
|
|
@@ -87,6 +87,7 @@ type ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement> = {
|
|
|
87
87
|
getSourceRoute: (sourceRouteIndex: number) => Awaitable<TRoute | undefined>;
|
|
88
88
|
isRscRequest: boolean;
|
|
89
89
|
layoutParamAccess?: AppLayoutParamAccessTracker;
|
|
90
|
+
resolveNavigationParams: (route: TRoute, params: AppPageParams, pathname: string, interceptOpts: TInterceptOpts) => AppPageParams;
|
|
90
91
|
renderInterceptResponse: (route: TRoute, element: TElement) => Promise<Response> | Response;
|
|
91
92
|
searchParams: URLSearchParams;
|
|
92
93
|
setNavigationContext: (context: {
|
|
@@ -155,13 +155,14 @@ async function resolveAppPageIntercept(options) {
|
|
|
155
155
|
});
|
|
156
156
|
if (interceptState.kind === "source-route") {
|
|
157
157
|
const renderRoute = interceptState.sourceRoute;
|
|
158
|
+
const interceptOpts = options.toInterceptOpts(interceptState.intercept);
|
|
158
159
|
const renderParams = pickRouteParams(interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute));
|
|
159
160
|
options.setNavigationContext({
|
|
160
|
-
params: interceptState.intercept.matchedParams,
|
|
161
|
+
params: options.resolveNavigationParams(renderRoute, interceptState.intercept.matchedParams, options.cleanPathname, interceptOpts),
|
|
161
162
|
pathname: options.cleanPathname,
|
|
162
163
|
searchParams: options.searchParams
|
|
163
164
|
});
|
|
164
|
-
const interceptElement = await options.buildPageElement(renderRoute, renderParams,
|
|
165
|
+
const interceptElement = await options.buildPageElement(renderRoute, renderParams, interceptOpts, options.searchParams, options.layoutParamAccess);
|
|
165
166
|
return {
|
|
166
167
|
interceptOpts: void 0,
|
|
167
168
|
response: await options.renderInterceptResponse(renderRoute, interceptElement)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_PARAMS_HEADER, VINEXT_TIMING_HEADER } from "./headers.js";
|
|
2
2
|
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
3
|
-
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
4
3
|
import { NO_STORE_CACHE_CONTROL, STATIC_CACHE_CONTROL, buildRevalidateCacheControl } from "./cache-control.js";
|
|
4
|
+
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
5
5
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
6
6
|
//#region src/server/app-page-response.ts
|
|
7
7
|
function applyTimingHeader(headers, timing) {
|
|
@@ -113,6 +113,7 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
|
|
|
113
113
|
resolvedMetadata: Metadata | null;
|
|
114
114
|
resolvedMetadataPathname?: string;
|
|
115
115
|
resolvedViewport: Viewport;
|
|
116
|
+
trailingSlash?: boolean;
|
|
116
117
|
rootForbiddenModule?: TModule | null;
|
|
117
118
|
rootNotFoundModule?: TModule | null;
|
|
118
119
|
rootUnauthorizedModule?: TModule | null;
|
|
@@ -142,6 +143,7 @@ declare function createAppPageLayoutEntries<TModule extends AppPageModule, TErro
|
|
|
142
143
|
forbiddens?: readonly (TModule | null | undefined)[] | null;
|
|
143
144
|
unauthorizeds?: readonly (TModule | null | undefined)[] | null;
|
|
144
145
|
}): AppPageLayoutEntry<TModule, TErrorModule>[];
|
|
146
|
+
declare function createAppPageRouteBodyMetadata(metadata: Metadata | null, pathname: string, metadataPlacement: "body" | "head", trailingSlash?: boolean): ReactNode;
|
|
145
147
|
declare function buildAppPageElements<TModule extends AppPageModule, TErrorModule extends AppPageErrorModule>(options: BuildAppPageElementsOptions<TModule, TErrorModule>): AppElements;
|
|
146
148
|
//#endregion
|
|
147
|
-
export { AppPageErrorModule, AppPageModule, AppPageRouteWiringRoute, AppPageSlotOverride, buildAppPageElements, createAppPageLayoutEntries, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
|
|
149
|
+
export { AppPageErrorModule, AppPageModule, AppPageRouteWiringRoute, AppPageSlotOverride, buildAppPageElements, createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
|
|
@@ -139,21 +139,22 @@ function createAppPageSlotBindings(route, layoutEntries, resolveSlotOverride, op
|
|
|
139
139
|
}
|
|
140
140
|
return normalizeAppElementsSlotBindings(bindings, { layoutIds: layoutEntries.map((entry) => entry.id) });
|
|
141
141
|
}
|
|
142
|
-
function createAppPageRouteHead(metadata, viewport, pathname, metadataPlacement) {
|
|
142
|
+
function createAppPageRouteHead(metadata, viewport, pathname, metadataPlacement, trailingSlash) {
|
|
143
143
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
144
144
|
/* @__PURE__ */ jsx("meta", { charSet: "utf-8" }),
|
|
145
145
|
metadata && metadataPlacement === "head" ? /* @__PURE__ */ jsx(MetadataHead, {
|
|
146
146
|
metadata,
|
|
147
|
-
pathname
|
|
147
|
+
pathname,
|
|
148
|
+
trailingSlash
|
|
148
149
|
}) : null,
|
|
149
150
|
/* @__PURE__ */ jsx(ViewportHead, { viewport })
|
|
150
151
|
] });
|
|
151
152
|
}
|
|
152
|
-
function createAppPageRouteBodyMetadata(metadata, pathname, metadataPlacement) {
|
|
153
|
+
function createAppPageRouteBodyMetadata(metadata, pathname, metadataPlacement, trailingSlash) {
|
|
153
154
|
if (!metadata || metadataPlacement !== "body") return null;
|
|
154
155
|
return /* @__PURE__ */ jsx("div", {
|
|
155
156
|
hidden: true,
|
|
156
|
-
dangerouslySetInnerHTML: { __html: renderMetadataToHtml(metadata, pathname) }
|
|
157
|
+
dangerouslySetInnerHTML: { __html: renderMetadataToHtml(metadata, pathname, { trailingSlash }) }
|
|
157
158
|
});
|
|
158
159
|
}
|
|
159
160
|
function buildAppPageElements(options) {
|
|
@@ -431,12 +432,12 @@ function buildAppPageElements(options) {
|
|
|
431
432
|
children: routeChildren
|
|
432
433
|
});
|
|
433
434
|
elements[routeId] = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
434
|
-
createAppPageRouteHead(options.resolvedMetadata, options.resolvedViewport, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement),
|
|
435
|
+
createAppPageRouteHead(options.resolvedMetadata, options.resolvedViewport, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash),
|
|
435
436
|
routeChildren,
|
|
436
|
-
createAppPageRouteBodyMetadata(options.resolvedMetadata, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement)
|
|
437
|
+
createAppPageRouteBodyMetadata(options.resolvedMetadata, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash)
|
|
437
438
|
] });
|
|
438
439
|
registerAppElementRenderDependencies(elements, renderDependenciesByElementId);
|
|
439
440
|
return elements;
|
|
440
441
|
}
|
|
441
442
|
//#endregion
|
|
442
|
-
export { buildAppPageElements, createAppPageLayoutEntries, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
|
|
443
|
+
export { buildAppPageElements, createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
|
|
@@ -129,10 +129,6 @@ type AppPageRscErrorTracker = {
|
|
|
129
129
|
getCapturedSpecialError: () => unknown;
|
|
130
130
|
onRenderError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
|
|
131
131
|
};
|
|
132
|
-
type ShouldRerenderAppPageWithGlobalErrorOptions = {
|
|
133
|
-
capturedError: unknown;
|
|
134
|
-
hasLocalBoundary: boolean;
|
|
135
|
-
};
|
|
136
132
|
declare function createAppPageFontData(options: CreateAppPageFontDataOptions): AppPageFontData;
|
|
137
133
|
declare function renderAppPageHtmlStream(options: RenderAppPageHtmlStreamOptions): Promise<AppSsrRenderResult>;
|
|
138
134
|
/**
|
|
@@ -146,6 +142,5 @@ declare function deferUntilStreamConsumed(stream: ReadableStream<Uint8Array>, on
|
|
|
146
142
|
declare function renderAppPageHtmlResponse(options: RenderAppPageHtmlResponseOptions): Promise<Response>;
|
|
147
143
|
declare function renderAppPageHtmlStreamWithRecovery<TSpecialError>(options: RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError>): Promise<AppPageHtmlStreamRecoveryResult>;
|
|
148
144
|
declare function createAppPageRscErrorTracker(baseOnError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown): AppPageRscErrorTracker;
|
|
149
|
-
declare function shouldRerenderAppPageWithGlobalError(options: ShouldRerenderAppPageWithGlobalErrorOptions): boolean;
|
|
150
145
|
//#endregion
|
|
151
|
-
export { AppPageFontData, AppPageSsrHandler, AppSsrRenderResult, buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, isAppSsrRenderResult, renderAppPageHtmlResponse, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery
|
|
146
|
+
export { AppPageFontData, AppPageSsrHandler, AppSsrRenderResult, buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, isAppSsrRenderResult, renderAppPageHtmlResponse, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery };
|
|
@@ -166,8 +166,5 @@ function createAppPageRscErrorTracker(baseOnError) {
|
|
|
166
166
|
}
|
|
167
167
|
};
|
|
168
168
|
}
|
|
169
|
-
function shouldRerenderAppPageWithGlobalError(options) {
|
|
170
|
-
return Boolean(options.capturedError) && !options.hasLocalBoundary;
|
|
171
|
-
}
|
|
172
169
|
//#endregion
|
|
173
|
-
export { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, isAppSsrRenderResult, renderAppPageHtmlResponse, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery
|
|
170
|
+
export { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, isAppSsrRenderResult, renderAppPageHtmlResponse, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import "./headers.js";
|
|
2
2
|
import { processMiddlewareHeaders } from "./request-pipeline.js";
|
|
3
3
|
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
4
|
-
import {
|
|
4
|
+
import { applyCdnResponseHeaders } from "./cache-control.js";
|
|
5
|
+
import { buildAppRouteMissIsrCacheControl, decideIsr } from "./isr-decision.js";
|
|
5
6
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
6
7
|
import { getSetCookieName } from "./cookie-utils.js";
|
|
7
8
|
//#region src/server/app-route-handler-response.ts
|
|
@@ -11,11 +12,6 @@ function hasMiddlewareHeader(headers) {
|
|
|
11
12
|
for (const key of headers.keys()) if (key.startsWith("x-middleware-")) return true;
|
|
12
13
|
return false;
|
|
13
14
|
}
|
|
14
|
-
function buildRouteHandlerCacheControl(cacheState, revalidateSeconds, expireSeconds) {
|
|
15
|
-
if (revalidateSeconds === 0) return NEVER_CACHE_CONTROL;
|
|
16
|
-
if (revalidateSeconds === Infinity) return STATIC_CACHE_CONTROL;
|
|
17
|
-
return buildCachedRevalidateCacheControl(cacheState, revalidateSeconds, expireSeconds);
|
|
18
|
-
}
|
|
19
15
|
function applyRouteHandlerMiddlewareContext(response, middlewareContext) {
|
|
20
16
|
if (!middlewareContext.headers && middlewareContext.status == null) return response;
|
|
21
17
|
const responseHeaders = new Headers(response.headers);
|
|
@@ -35,9 +31,14 @@ function buildRouteHandlerCachedResponse(cachedValue, options) {
|
|
|
35
31
|
for (const [key, value] of Object.entries(cachedValue.headers)) if (Array.isArray(value)) for (const entry of value) headers.append(key, entry);
|
|
36
32
|
else headers.set(key, value);
|
|
37
33
|
setCacheStateHeaders(headers, options.cacheState);
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
const { cacheControl } = decideIsr({
|
|
35
|
+
cacheState: options.cacheState,
|
|
36
|
+
kind: "app-route",
|
|
37
|
+
revalidateSeconds: options.revalidateSeconds,
|
|
38
|
+
expireSeconds: options.expireSeconds,
|
|
39
|
+
cacheControlMeta: options.cacheControl
|
|
40
|
+
});
|
|
41
|
+
applyCdnResponseHeaders(headers, { cacheControl });
|
|
41
42
|
return new Response(options.isHead ? null : cachedValue.body, {
|
|
42
43
|
status: cachedValue.status,
|
|
43
44
|
headers
|
|
@@ -45,7 +46,7 @@ function buildRouteHandlerCachedResponse(cachedValue, options) {
|
|
|
45
46
|
}
|
|
46
47
|
function applyRouteHandlerRevalidateHeader(response, revalidateSeconds, expireSeconds, tags) {
|
|
47
48
|
applyCdnResponseHeaders(response.headers, {
|
|
48
|
-
cacheControl:
|
|
49
|
+
cacheControl: buildAppRouteMissIsrCacheControl(revalidateSeconds, expireSeconds),
|
|
49
50
|
tags
|
|
50
51
|
});
|
|
51
52
|
}
|