@qzsy/vinext 0.1.11 → 0.1.122
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/check.d.ts +8 -0
- package/dist/check.js +20 -9
- package/dist/cli.js +2 -2
- package/dist/deploy.js +10 -11
- package/dist/entries/app-rsc-entry.js +37 -8
- 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 +12 -8
- 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/routing/app-route-graph.d.ts +6 -2
- package/dist/routing/app-route-graph.js +60 -12
- 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-browser-history-controller.d.ts +2 -1
- package/dist/server/app-browser-history-controller.js +6 -2
- package/dist/server/app-fallback-renderer.d.ts +1 -1
- package/dist/server/app-fallback-renderer.js +2 -1
- package/dist/server/app-page-boundary-render.d.ts +1 -0
- package/dist/server/app-page-boundary-render.js +12 -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 +11 -3
- package/dist/server/app-page-dispatch.js +54 -15
- package/dist/server/app-page-element-builder.d.ts +5 -1
- package/dist/server/app-page-element-builder.js +55 -19
- package/dist/server/app-page-head.d.ts +12 -0
- package/dist/server/app-page-head.js +42 -19
- package/dist/server/app-page-params.d.ts +2 -1
- package/dist/server/app-page-params.js +8 -1
- 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-route-handler-dispatch.js +1 -0
- package/dist/server/app-route-handler-execution.js +2 -1
- 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.js +7 -1
- package/dist/server/app-rsc-handler.js +4 -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 +41 -10
- 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/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/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/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 +23 -24
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { ThenableParams, ThenableParamsObserver } from "../shims/thenable-params.js";
|
|
1
2
|
import { AppPageSearchParams } from "./app-page-head.js";
|
|
2
|
-
import { ThenableParams } from "../shims/thenable-params.js";
|
|
3
3
|
|
|
4
4
|
//#region src/server/app-page-search-params-observation.d.ts
|
|
5
5
|
type AppPageSearchParamsObservationOptions = {
|
|
6
|
+
markDynamic?: boolean;
|
|
6
7
|
observeReactPromiseStatus?: boolean;
|
|
7
8
|
};
|
|
9
|
+
declare function createAppPageSearchParamsObserver(options?: AppPageSearchParamsObservationOptions): ThenableParamsObserver;
|
|
8
10
|
declare function makeObservedAppPageSearchParamsThenable(pageSearchParams: AppPageSearchParams, options?: AppPageSearchParamsObservationOptions): ThenableParams<AppPageSearchParams>;
|
|
9
11
|
//#endregion
|
|
10
|
-
export { makeObservedAppPageSearchParamsThenable };
|
|
12
|
+
export { createAppPageSearchParamsObserver, makeObservedAppPageSearchParamsThenable };
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import { markDynamicUsage, markRenderRequestApiUsage, throwIfInsideCacheScope } from "../shims/headers.js";
|
|
1
|
+
import { markDynamicUsage, markRenderRequestApiUsage, throwIfInsideCacheScope, throwIfStaticGenerationAccessError } from "../shims/headers.js";
|
|
2
2
|
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
3
3
|
//#region src/server/app-page-search-params-observation.ts
|
|
4
|
-
function markAppPageSearchParamsAccess() {
|
|
4
|
+
function markAppPageSearchParamsAccess(markDynamic) {
|
|
5
|
+
throwIfStaticGenerationAccessError();
|
|
5
6
|
throwIfInsideCacheScope("searchParams");
|
|
6
|
-
markDynamicUsage();
|
|
7
|
+
if (markDynamic) markDynamicUsage();
|
|
7
8
|
markRenderRequestApiUsage("searchParams");
|
|
8
9
|
}
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
markAppPageSearchParamsAccess();
|
|
10
|
+
function createAppPageSearchParamsObserver(options = {}) {
|
|
11
|
+
return { observeParamAccess() {
|
|
12
|
+
markAppPageSearchParamsAccess(options.markDynamic !== false);
|
|
12
13
|
} };
|
|
14
|
+
}
|
|
15
|
+
function makeObservedAppPageSearchParamsThenable(pageSearchParams, options = {}) {
|
|
16
|
+
const observer = createAppPageSearchParamsObserver(options);
|
|
13
17
|
if (options.observeReactPromiseStatus === true) return makeThenableParams(pageSearchParams, {
|
|
14
18
|
...observer,
|
|
15
19
|
observeReactPromiseStatus: true
|
|
@@ -17,4 +21,4 @@ function makeObservedAppPageSearchParamsThenable(pageSearchParams, options = {})
|
|
|
17
21
|
return makeThenableParams(pageSearchParams, observer);
|
|
18
22
|
}
|
|
19
23
|
//#endregion
|
|
20
|
-
export { makeObservedAppPageSearchParamsThenable };
|
|
24
|
+
export { createAppPageSearchParamsObserver, makeObservedAppPageSearchParamsThenable };
|
|
@@ -24,6 +24,7 @@ function buildRouteHandlerPageCacheTags(pathname, extraTags, routeSegments) {
|
|
|
24
24
|
async function runInRouteHandlerRevalidationContext(options, renderFn) {
|
|
25
25
|
await runWithRequestContext(createRequestContext({
|
|
26
26
|
headersContext: createStaticGenerationHeadersContext({
|
|
27
|
+
draftModeEnabled: false,
|
|
27
28
|
draftModeSecret: options.draftModeSecret,
|
|
28
29
|
dynamicConfig: options.dynamicConfig,
|
|
29
30
|
routeKind: "route",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { setHeadersContext } from "../shims/headers.js";
|
|
1
|
+
import { isDraftModeRequest, setHeadersContext } from "../shims/headers.js";
|
|
2
2
|
import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
|
|
3
3
|
import { applyRouteHandlerMiddlewareContext, applyRouteHandlerRevalidateHeader, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, finalizeRouteHandlerResponse, markRouteHandlerCacheMiss } from "./app-route-handler-response.js";
|
|
4
4
|
import { createTrackedAppRouteRequest, markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
|
|
@@ -8,6 +8,7 @@ import { resolveAppRouteHandlerSpecialError, shouldApplyAppRouteHandlerRevalidat
|
|
|
8
8
|
function configureAppRouteStaticGenerationContext(options) {
|
|
9
9
|
if (options.dynamicConfig === "force-static" || options.dynamicConfig === "error") {
|
|
10
10
|
setHeadersContext(createStaticGenerationHeadersContext({
|
|
11
|
+
draftModeEnabled: options.draftModeSecret !== void 0 && isDraftModeRequest(options.request, options.draftModeSecret),
|
|
11
12
|
draftModeSecret: options.draftModeSecret,
|
|
12
13
|
dynamicConfig: options.dynamicConfig,
|
|
13
14
|
routeKind: "route",
|
|
@@ -36,11 +36,13 @@ type LazyLoadableSlot = {
|
|
|
36
36
|
page?: unknown;
|
|
37
37
|
default?: unknown;
|
|
38
38
|
layout?: unknown;
|
|
39
|
+
configLayouts?: readonly unknown[];
|
|
39
40
|
loading?: unknown;
|
|
40
41
|
error?: unknown;
|
|
41
42
|
__loadPage?: LazyModuleThunk | null;
|
|
42
43
|
__loadDefault?: LazyModuleThunk | null;
|
|
43
44
|
__loadLayout?: LazyModuleThunk | null;
|
|
45
|
+
__loadConfigLayouts?: LazyModuleLoaderArray | null;
|
|
44
46
|
__loadLoading?: LazyModuleThunk | null;
|
|
45
47
|
__loadError?: LazyModuleThunk | null; /** Hydrated only after an intercept matches, not with the slot's base modules. */
|
|
46
48
|
intercepts?: LazyLoadableIntercept[];
|
|
@@ -61,6 +61,7 @@ function ensureAppRouteModulesLoaded(route) {
|
|
|
61
61
|
pushFieldLoad(loads, slot, "page", slot.__loadPage);
|
|
62
62
|
pushFieldLoad(loads, slot, "default", slot.__loadDefault);
|
|
63
63
|
pushFieldLoad(loads, slot, "layout", slot.__loadLayout);
|
|
64
|
+
pushArrayLoads(loads, slot.configLayouts, slot.__loadConfigLayouts);
|
|
64
65
|
pushFieldLoad(loads, slot, "loading", slot.__loadLoading);
|
|
65
66
|
pushFieldLoad(loads, slot, "error", slot.__loadError);
|
|
66
67
|
}
|
|
@@ -5,7 +5,7 @@ import { badRequestResponse, notFoundResponse, notFoundStaticAssetResponse } fro
|
|
|
5
5
|
import { isOpenRedirectShaped } from "./open-redirect.js";
|
|
6
6
|
import { bufferRequestBodyForHeaderClone, cloneRequestWithHeaders, filterInternalHeaders } from "./request-pipeline.js";
|
|
7
7
|
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
8
|
-
import { resolveStaticAssetSignal } from "./worker-utils.js";
|
|
8
|
+
import { finalizeMissingStaticAssetResponse, resolveStaticAssetSignal } from "./worker-utils.js";
|
|
9
9
|
import { readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
|
|
10
10
|
import rscHandler, { __assetPrefix, __basePath } from "virtual:vinext-rsc-entry";
|
|
11
11
|
import { registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
|
|
@@ -24,7 +24,7 @@ async function handleRequest(request, env, ctx) {
|
|
|
24
24
|
} catch {
|
|
25
25
|
return badRequestResponse();
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
const missingBuildAsset = isNextStaticPath(url.pathname, __workerBasePath, __workerAssetPathPrefix);
|
|
28
28
|
{
|
|
29
29
|
request = await bufferRequestBodyForHeaderClone(request);
|
|
30
30
|
const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(request);
|
|
@@ -36,14 +36,15 @@ async function handleRequest(request, env, ctx) {
|
|
|
36
36
|
const handleFn = () => rscHandler(request, ctx);
|
|
37
37
|
const result = await (ctx ? runWithExecutionContext(ctx, handleFn) : handleFn());
|
|
38
38
|
if (result instanceof Response) {
|
|
39
|
+
let response = result;
|
|
39
40
|
if (env?.ASSETS) {
|
|
40
41
|
const assetFetcher = env.ASSETS;
|
|
41
|
-
const assetResponse = await resolveStaticAssetSignal(
|
|
42
|
-
if (assetResponse)
|
|
42
|
+
const assetResponse = await resolveStaticAssetSignal(response, { fetchAsset: (path) => Promise.resolve(assetFetcher.fetch(new Request(new URL(path, request.url)))) });
|
|
43
|
+
if (assetResponse) response = assetResponse;
|
|
43
44
|
}
|
|
44
|
-
return
|
|
45
|
+
return finalizeMissingStaticAssetResponse(response, missingBuildAsset);
|
|
45
46
|
}
|
|
46
|
-
if (result === null || result === void 0) return notFoundResponse();
|
|
47
|
+
if (result === null || result === void 0) return missingBuildAsset ? notFoundStaticAssetResponse() : notFoundResponse();
|
|
47
48
|
return new Response(String(result), { status: 200 });
|
|
48
49
|
}
|
|
49
50
|
//#endregion
|
|
@@ -53,7 +53,13 @@ function createRscOnErrorHandler(options) {
|
|
|
53
53
|
}
|
|
54
54
|
if (options.requestInfo && options.errorContext && error) options.reportRequestError(error instanceof Error ? error : new Error(getThrownValueMessage(error)), options.requestInfo, options.errorContext);
|
|
55
55
|
if (hasDigest(error)) return String(error.digest);
|
|
56
|
-
if (
|
|
56
|
+
if (error) {
|
|
57
|
+
const digest = errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
|
|
58
|
+
if (error instanceof Error) try {
|
|
59
|
+
Object.assign(error, { digest });
|
|
60
|
+
} catch {}
|
|
61
|
+
return digest;
|
|
62
|
+
}
|
|
57
63
|
};
|
|
58
64
|
}
|
|
59
65
|
//#endregion
|
|
@@ -208,7 +208,10 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
208
208
|
if (isImageOptimizationPath(cleanPathname)) {
|
|
209
209
|
const imageRedirect = resolveDevImageRedirect(url, [...options.imageConfig?.deviceSizes ?? DEFAULT_DEVICE_SIZES, ...options.imageConfig?.imageSizes ?? DEFAULT_IMAGE_SIZES], options.imageConfig?.qualities, { isDev: options.isDev });
|
|
210
210
|
if (!imageRedirect) return new Response("Invalid image optimization parameters", { status: 400 });
|
|
211
|
-
return
|
|
211
|
+
return new Response(null, {
|
|
212
|
+
status: 302,
|
|
213
|
+
headers: { Location: imageRedirect }
|
|
214
|
+
});
|
|
212
215
|
}
|
|
213
216
|
if (options.handleMetadataRouteRequest) {
|
|
214
217
|
const metadataRouteResponse = await options.handleMetadataRouteRequest(cleanPathname);
|
|
@@ -31,6 +31,8 @@ type AppRscInterceptForMatching = {
|
|
|
31
31
|
sourceMatchPattern?: string;
|
|
32
32
|
sourcePageSegments?: readonly string[];
|
|
33
33
|
interceptLayouts: readonly unknown[];
|
|
34
|
+
interceptLayoutSegments?: readonly (readonly string[])[];
|
|
35
|
+
interceptBranchSegments?: readonly string[];
|
|
34
36
|
__loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
|
|
35
37
|
page: unknown;
|
|
36
38
|
__pageLoader?: (() => Promise<unknown>) | null;
|
|
@@ -46,6 +48,8 @@ type AppRscSiblingInterceptForMatching = {
|
|
|
46
48
|
sourcePageSegments?: readonly string[];
|
|
47
49
|
slotId: string | null;
|
|
48
50
|
interceptLayouts: readonly unknown[];
|
|
51
|
+
interceptLayoutSegments?: readonly (readonly string[])[];
|
|
52
|
+
interceptBranchSegments?: readonly string[];
|
|
49
53
|
__loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
|
|
50
54
|
page: unknown;
|
|
51
55
|
__pageLoader?: (() => Promise<unknown>) | null;
|
|
@@ -59,6 +63,7 @@ type AppRscRouteForMatching = {
|
|
|
59
63
|
};
|
|
60
64
|
type AppRscInterceptMatch = AppRscInterceptLookupEntry & {
|
|
61
65
|
matchedParams: AppRscRouteParams;
|
|
66
|
+
sourceMatchedParams: AppRscRouteParams;
|
|
62
67
|
};
|
|
63
68
|
type AppRscInterceptLoadState = {
|
|
64
69
|
page: unknown;
|
|
@@ -74,6 +79,8 @@ type AppRscInterceptLookupEntry = {
|
|
|
74
79
|
sourceMatchPatternParts: string[] | null;
|
|
75
80
|
sourcePageSegments: readonly string[] | null;
|
|
76
81
|
interceptLayouts: readonly unknown[];
|
|
82
|
+
interceptLayoutSegments?: readonly (readonly string[])[];
|
|
83
|
+
interceptBranchSegments?: readonly string[];
|
|
77
84
|
__loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
|
|
78
85
|
page: unknown;
|
|
79
86
|
__pageLoader?: (() => Promise<unknown>) | null;
|
|
@@ -36,12 +36,13 @@ function createAppRscRouteMatcher(routes) {
|
|
|
36
36
|
const sourceRoute = routes[concreteSourceRouteIndex];
|
|
37
37
|
const matchedSourceParams = matchedSourceRoute && entry.sourceMatchPatternParts !== null ? matchedSourceRoute.params : sourceRoute ? matchAppRscRoutePattern(sourceParts, sourceRoute.patternParts) : null;
|
|
38
38
|
if (matchedSourceParams === null && entry.sourceMatchPatternParts === null) continue;
|
|
39
|
-
const sourceParams = matchedSourceParams ?? createRouteParams();
|
|
39
|
+
const sourceParams = matchedSourceParams && entry.sourceMatchPatternParts !== null ? pickPatternParams(matchedSourceParams, entry.sourceMatchPatternParts) : matchedSourceParams ?? createRouteParams();
|
|
40
40
|
return {
|
|
41
41
|
...entry,
|
|
42
42
|
page: entry.__loadState.page,
|
|
43
43
|
sourceRouteIndex: concreteSourceRouteIndex,
|
|
44
|
-
matchedParams: mergeMatchedParams(sourceParams, params)
|
|
44
|
+
matchedParams: mergeMatchedParams(sourceParams, params),
|
|
45
|
+
sourceMatchedParams: matchedSourceParams ?? createRouteParams()
|
|
45
46
|
};
|
|
46
47
|
}
|
|
47
48
|
return null;
|
|
@@ -64,6 +65,24 @@ function matchInterceptSource(sourceParts, entry) {
|
|
|
64
65
|
if (patternParts.length === 0) return true;
|
|
65
66
|
return matchRoutePatternPrefix(sourceParts, patternParts);
|
|
66
67
|
}
|
|
68
|
+
function interceptSegmentPrecedence(segment) {
|
|
69
|
+
if (!segment.startsWith(":")) return 0;
|
|
70
|
+
if (segment.endsWith("*")) return 3;
|
|
71
|
+
if (segment.endsWith("+")) return 2;
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
function compareInterceptTargetPatterns(a, b) {
|
|
75
|
+
const sharedLength = Math.min(a.targetPatternParts.length, b.targetPatternParts.length);
|
|
76
|
+
for (let index = 0; index < sharedLength; index++) {
|
|
77
|
+
const aSegment = a.targetPatternParts[index];
|
|
78
|
+
const bSegment = b.targetPatternParts[index];
|
|
79
|
+
const precedence = interceptSegmentPrecedence(aSegment) - interceptSegmentPrecedence(bSegment);
|
|
80
|
+
if (precedence !== 0) return precedence;
|
|
81
|
+
if (aSegment !== bSegment) return aSegment.localeCompare(bSegment);
|
|
82
|
+
}
|
|
83
|
+
const lengthDifference = a.targetPatternParts.length - b.targetPatternParts.length;
|
|
84
|
+
return lengthDifference !== 0 ? lengthDifference : a.targetPattern.localeCompare(b.targetPattern);
|
|
85
|
+
}
|
|
67
86
|
function createInterceptLookup(routes) {
|
|
68
87
|
const patternToIndex = new Map(routes.map((r, i) => [r.pattern, i]));
|
|
69
88
|
const interceptLookup = [];
|
|
@@ -85,6 +104,8 @@ function createInterceptLookup(routes) {
|
|
|
85
104
|
sourceMatchPatternParts,
|
|
86
105
|
sourcePageSegments: intercept.sourcePageSegments ?? null,
|
|
87
106
|
interceptLayouts: intercept.interceptLayouts,
|
|
107
|
+
interceptLayoutSegments: intercept.interceptLayoutSegments,
|
|
108
|
+
interceptBranchSegments: intercept.interceptBranchSegments,
|
|
88
109
|
__loadInterceptLayouts: intercept.__loadInterceptLayouts,
|
|
89
110
|
page: intercept.page,
|
|
90
111
|
__pageLoader: intercept.__pageLoader,
|
|
@@ -110,6 +131,8 @@ function createInterceptLookup(routes) {
|
|
|
110
131
|
sourceMatchPatternParts,
|
|
111
132
|
sourcePageSegments: intercept.sourcePageSegments ?? null,
|
|
112
133
|
interceptLayouts: intercept.interceptLayouts,
|
|
134
|
+
interceptLayoutSegments: intercept.interceptLayoutSegments,
|
|
135
|
+
interceptBranchSegments: intercept.interceptBranchSegments,
|
|
113
136
|
__loadInterceptLayouts: intercept.__loadInterceptLayouts,
|
|
114
137
|
page: intercept.page,
|
|
115
138
|
__pageLoader: intercept.__pageLoader,
|
|
@@ -122,7 +145,7 @@ function createInterceptLookup(routes) {
|
|
|
122
145
|
});
|
|
123
146
|
}
|
|
124
147
|
}
|
|
125
|
-
return interceptLookup;
|
|
148
|
+
return interceptLookup.sort(compareInterceptTargetPatterns);
|
|
126
149
|
}
|
|
127
150
|
function matchAppRscRoutePattern(urlParts, patternParts) {
|
|
128
151
|
return matchRoutePattern(urlParts, patternParts);
|
|
@@ -130,5 +153,15 @@ function matchAppRscRoutePattern(urlParts, patternParts) {
|
|
|
130
153
|
function mergeMatchedParams(sourceParams, targetParams) {
|
|
131
154
|
return Object.assign(createRouteParams(), sourceParams, targetParams);
|
|
132
155
|
}
|
|
156
|
+
function pickPatternParams(params, patternParts) {
|
|
157
|
+
const picked = createRouteParams();
|
|
158
|
+
for (const patternPart of patternParts) {
|
|
159
|
+
if (!patternPart.startsWith(":")) continue;
|
|
160
|
+
const paramName = patternPart.endsWith("+") || patternPart.endsWith("*") ? patternPart.slice(1, -1) : patternPart.slice(1);
|
|
161
|
+
const value = params[paramName];
|
|
162
|
+
if (value !== void 0) picked[paramName] = value;
|
|
163
|
+
}
|
|
164
|
+
return picked;
|
|
165
|
+
}
|
|
133
166
|
//#endregion
|
|
134
167
|
export { SIBLING_PAGE_INTERCEPT_SLOT_KEY, createAppRscRouteMatcher, matchAppRscRoutePattern };
|
|
@@ -22,6 +22,7 @@ type ResolveAppPageSegmentConfigOptions = {
|
|
|
22
22
|
layouts?: readonly (AppRouteSegmentConfigModule | null | undefined)[];
|
|
23
23
|
page?: AppRouteSegmentConfigModule | null;
|
|
24
24
|
parallelPages?: readonly (AppRouteSegmentConfigModule | null | undefined)[];
|
|
25
|
+
parallelSegments?: readonly (AppRouteSegmentConfigModule | null | undefined)[];
|
|
25
26
|
};
|
|
26
27
|
/**
|
|
27
28
|
* Resolve the route segment config that applies to an App page route.
|
|
@@ -59,9 +59,13 @@ function resolveAppPageSegmentConfig(options) {
|
|
|
59
59
|
let hasOnlyCache = false;
|
|
60
60
|
let hasOnlyNoStore = false;
|
|
61
61
|
let hasParentDefaultNoStore = false;
|
|
62
|
+
let hasForceDynamic = false;
|
|
62
63
|
for (const segment of segments) {
|
|
63
64
|
if (!segment) continue;
|
|
64
|
-
if (isRouteSegmentDynamic(segment.dynamic))
|
|
65
|
+
if (isRouteSegmentDynamic(segment.dynamic)) {
|
|
66
|
+
if (segment.dynamic === "force-dynamic") hasForceDynamic = true;
|
|
67
|
+
config.dynamicConfig = hasForceDynamic ? "force-dynamic" : segment.dynamic;
|
|
68
|
+
}
|
|
65
69
|
if (isRouteSegmentRuntime(segment.runtime)) config.runtime = segment.runtime;
|
|
66
70
|
if (segment.dynamicParams === false) config.dynamicParamsConfig = false;
|
|
67
71
|
else if (segment.dynamicParams === true && config.dynamicParamsConfig !== false) config.dynamicParamsConfig = true;
|
|
@@ -72,7 +76,7 @@ function resolveAppPageSegmentConfig(options) {
|
|
|
72
76
|
if (fetchCache === "force-no-store") hasForceNoStore = true;
|
|
73
77
|
if (fetchCache === "only-cache") hasOnlyCache = true;
|
|
74
78
|
if (fetchCache === "only-no-store") hasOnlyNoStore = true;
|
|
75
|
-
if (
|
|
79
|
+
if (hasForceCache && hasForceNoStore || !hasForceCache && !hasForceNoStore && hasOnlyCache && hasOnlyNoStore) throw new Error(describeFetchCacheConflict(fetchCache));
|
|
76
80
|
if (fetchCache === "default-no-store") hasParentDefaultNoStore = true;
|
|
77
81
|
if (hasForceCache) config.fetchCache = "force-cache";
|
|
78
82
|
else if (hasForceNoStore) config.fetchCache = "force-no-store";
|
|
@@ -82,6 +86,32 @@ function resolveAppPageSegmentConfig(options) {
|
|
|
82
86
|
}
|
|
83
87
|
config.revalidateSeconds = resolveRevalidateSeconds(config.revalidateSeconds, segment.revalidate);
|
|
84
88
|
}
|
|
89
|
+
for (const segment of options.parallelSegments ?? []) {
|
|
90
|
+
if (!segment) continue;
|
|
91
|
+
if (segment.dynamic === "force-dynamic") {
|
|
92
|
+
hasForceDynamic = true;
|
|
93
|
+
config.dynamicConfig = "force-dynamic";
|
|
94
|
+
} else if (config.dynamicConfig === void 0 && isRouteSegmentDynamic(segment.dynamic)) config.dynamicConfig = segment.dynamic;
|
|
95
|
+
if (segment.dynamicParams === false) config.dynamicParamsConfig = false;
|
|
96
|
+
else if (segment.dynamicParams === true && config.dynamicParamsConfig === void 0) config.dynamicParamsConfig = true;
|
|
97
|
+
if (config.runtime === void 0 && isRouteSegmentRuntime(segment.runtime)) config.runtime = segment.runtime;
|
|
98
|
+
if (isRouteSegmentFetchCache(segment.fetchCache)) {
|
|
99
|
+
const fetchCache = segment.fetchCache;
|
|
100
|
+
if (hasParentDefaultNoStore && (fetchCache === "auto" || isCacheFetchCacheMode(fetchCache))) throw new Error(describeFetchCacheConflict(fetchCache));
|
|
101
|
+
if (fetchCache === "force-cache") hasForceCache = true;
|
|
102
|
+
if (fetchCache === "force-no-store") hasForceNoStore = true;
|
|
103
|
+
if (fetchCache === "only-cache") hasOnlyCache = true;
|
|
104
|
+
if (fetchCache === "only-no-store") hasOnlyNoStore = true;
|
|
105
|
+
if (hasForceCache && hasForceNoStore || !hasForceCache && !hasForceNoStore && hasOnlyCache && hasOnlyNoStore) throw new Error(describeFetchCacheConflict(fetchCache));
|
|
106
|
+
if (fetchCache === "default-no-store") hasParentDefaultNoStore = true;
|
|
107
|
+
if (hasForceCache) config.fetchCache = "force-cache";
|
|
108
|
+
else if (hasForceNoStore) config.fetchCache = "force-no-store";
|
|
109
|
+
else if (hasOnlyCache) config.fetchCache = "only-cache";
|
|
110
|
+
else if (hasOnlyNoStore) config.fetchCache = "only-no-store";
|
|
111
|
+
else if (config.fetchCache === void 0) config.fetchCache = fetchCache;
|
|
112
|
+
}
|
|
113
|
+
config.revalidateSeconds = resolveRevalidateSeconds(config.revalidateSeconds, segment.revalidate);
|
|
114
|
+
}
|
|
85
115
|
for (const segment of [options.page, ...options.parallelPages ?? []]) {
|
|
86
116
|
if (!segment) continue;
|
|
87
117
|
config.dynamicStaleTimeSeconds = resolveDynamicStaleTimeSeconds(config.dynamicStaleTimeSeconds, segment.unstable_dynamicStaleTime);
|
|
@@ -76,6 +76,7 @@ type AppServerActionMatch<TRoute extends AppServerActionRoute> = {
|
|
|
76
76
|
};
|
|
77
77
|
type AppServerActionIntercept<TPage = unknown> = {
|
|
78
78
|
matchedParams: AppPageParams;
|
|
79
|
+
sourceMatchedParams?: AppPageParams;
|
|
79
80
|
page: TPage;
|
|
80
81
|
slotId?: string | null;
|
|
81
82
|
slotKey: string;
|
|
@@ -91,6 +92,8 @@ type BuildServerActionPageElementOptions<TRoute extends AppServerActionRoute, TI
|
|
|
91
92
|
route: TRoute;
|
|
92
93
|
searchParams: URLSearchParams;
|
|
93
94
|
renderMode: AppRscRenderMode;
|
|
95
|
+
observeMetadataSearchParamsAccess?: boolean;
|
|
96
|
+
observePageSearchParamsAccess?: boolean;
|
|
94
97
|
};
|
|
95
98
|
type AppServerActionRscModel<TElement> = {
|
|
96
99
|
/**
|
|
@@ -148,6 +151,7 @@ type HandleServerActionRscRequestOptions<TElement, TRoute extends AppServerActio
|
|
|
148
151
|
createRscOnErrorHandler: (request: Request, pathname: string, pattern: string) => (error: unknown) => unknown;
|
|
149
152
|
createTemporaryReferenceSet: () => TTemporaryReferences;
|
|
150
153
|
decodeReply: (body: string | FormData, options: DecodeServerActionReplyOptions<TTemporaryReferences>) => Promise<unknown[]> | unknown[];
|
|
154
|
+
draftModeSecret: string;
|
|
151
155
|
/**
|
|
152
156
|
* Hydrate a route's lazy page/route-handler modules before reading
|
|
153
157
|
* `route.page` / `route.routeHandler` on action redirect targets and
|
|
@@ -5,7 +5,7 @@ import { isExternalUrl } from "../config/config-matchers.js";
|
|
|
5
5
|
import { internalServerErrorResponse, payloadTooLargeResponse } from "./http-error-responses.js";
|
|
6
6
|
import { validateCsrfOrigin, validateServerActionPayload } from "./request-pipeline.js";
|
|
7
7
|
import { APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI } from "./app-rsc-render-mode.js";
|
|
8
|
-
import { headersContextFromRequest, setHeadersContext } from "../shims/headers.js";
|
|
8
|
+
import { headersContextFromRequest, isDraftModeRequest, setHeadersContext } from "../shims/headers.js";
|
|
9
9
|
import { getAndClearActionRevalidationKind } from "../shims/cache-request-state.js";
|
|
10
10
|
import { setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
|
|
11
11
|
import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
|
|
@@ -20,7 +20,18 @@ import { buildAppPageTags } from "./implicit-tags.js";
|
|
|
20
20
|
import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
|
|
21
21
|
import { resolveAppPageActionRerenderTarget } from "./app-page-request.js";
|
|
22
22
|
import { getSetCookieName } from "./cookie-utils.js";
|
|
23
|
+
import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
|
|
23
24
|
//#region src/server/app-server-action-execution.ts
|
|
25
|
+
function prepareActionPageRerenderContext(options) {
|
|
26
|
+
if (options.dynamicConfig === "force-static" || options.dynamicConfig === "error") setHeadersContext(createStaticGenerationHeadersContext({
|
|
27
|
+
draftModeEnabled: isDraftModeRequest(options.request, options.draftModeSecret),
|
|
28
|
+
draftModeSecret: options.draftModeSecret,
|
|
29
|
+
dynamicConfig: options.dynamicConfig,
|
|
30
|
+
routeKind: "page",
|
|
31
|
+
routePattern: options.routePattern
|
|
32
|
+
}));
|
|
33
|
+
return options.dynamicConfig === "force-static" ? new URLSearchParams() : options.searchParams;
|
|
34
|
+
}
|
|
24
35
|
/**
|
|
25
36
|
* Matches Next.js' server action argument cap to prevent stack overflow in
|
|
26
37
|
* Function.prototype.apply when decoding hostile action payloads.
|
|
@@ -623,14 +634,22 @@ async function handleServerActionRscRequest(options) {
|
|
|
623
634
|
url: redirectTarget
|
|
624
635
|
});
|
|
625
636
|
setHeadersContext(headersContextFromRequest(redirectRenderRequest));
|
|
637
|
+
const redirectDynamicConfig = options.resolveRouteDynamicConfig?.(targetMatch.route);
|
|
638
|
+
const redirectSearchParams = prepareActionPageRerenderContext({
|
|
639
|
+
draftModeSecret: options.draftModeSecret,
|
|
640
|
+
dynamicConfig: redirectDynamicConfig,
|
|
641
|
+
request: redirectRenderRequest,
|
|
642
|
+
routePattern: targetMatch.route.pattern,
|
|
643
|
+
searchParams: redirectTarget.searchParams
|
|
644
|
+
});
|
|
626
645
|
const redirectNavigationParams = resolveAppPageNavigationParams(targetMatch.route, targetMatch.params, targetPathname, null);
|
|
627
646
|
options.setNavigationContext({
|
|
628
647
|
pathname: targetPathname,
|
|
629
|
-
searchParams:
|
|
648
|
+
searchParams: redirectSearchParams,
|
|
630
649
|
params: redirectNavigationParams
|
|
631
650
|
});
|
|
632
651
|
setCurrentFetchCacheMode(options.resolveRouteFetchCacheMode?.(targetMatch.route) ?? null);
|
|
633
|
-
setCurrentForceDynamicFetchDefault(
|
|
652
|
+
setCurrentForceDynamicFetchDefault(redirectDynamicConfig === "force-dynamic");
|
|
634
653
|
setCurrentFetchSoftTags(buildServerActionPageTags(targetMatch.route, targetPathname));
|
|
635
654
|
const element = options.buildPageElement({
|
|
636
655
|
cleanPathname: targetPathname,
|
|
@@ -640,8 +659,10 @@ async function handleServerActionRscRequest(options) {
|
|
|
640
659
|
params: targetMatch.params,
|
|
641
660
|
request: redirectRenderRequest,
|
|
642
661
|
route: targetMatch.route,
|
|
643
|
-
searchParams:
|
|
644
|
-
renderMode: APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI
|
|
662
|
+
searchParams: redirectSearchParams,
|
|
663
|
+
renderMode: APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI,
|
|
664
|
+
observeMetadataSearchParamsAccess: redirectDynamicConfig !== "force-static",
|
|
665
|
+
observePageSearchParamsAccess: redirectDynamicConfig !== "force-static"
|
|
645
666
|
});
|
|
646
667
|
const onRenderError = options.createRscOnErrorHandler(redirectRenderRequest, targetPathname, targetMatch.route.pattern);
|
|
647
668
|
return createServerActionRscResponse(await options.renderToReadableStream({
|
|
@@ -702,14 +723,22 @@ async function handleServerActionRscRequest(options) {
|
|
|
702
723
|
toInterceptOpts: options.toInterceptOpts
|
|
703
724
|
});
|
|
704
725
|
const resolvedActionNavigationParams = resolveAppPageNavigationParams(actionRerenderTarget.route, actionRerenderTarget.navigationParams, options.cleanPathname, actionRerenderTarget.interceptOpts);
|
|
726
|
+
await options.ensureRouteLoaded?.(actionRerenderTarget.route);
|
|
727
|
+
const actionRerenderDynamicConfig = options.resolveRouteDynamicConfig?.(actionRerenderTarget.route);
|
|
728
|
+
const actionRerenderSearchParams = prepareActionPageRerenderContext({
|
|
729
|
+
draftModeSecret: options.draftModeSecret,
|
|
730
|
+
dynamicConfig: actionRerenderDynamicConfig,
|
|
731
|
+
request: options.request,
|
|
732
|
+
routePattern: actionRerenderTarget.route.pattern,
|
|
733
|
+
searchParams: options.searchParams
|
|
734
|
+
});
|
|
705
735
|
options.setNavigationContext({
|
|
706
736
|
pathname: options.cleanPathname,
|
|
707
|
-
searchParams:
|
|
737
|
+
searchParams: actionRerenderSearchParams,
|
|
708
738
|
params: resolvedActionNavigationParams
|
|
709
739
|
});
|
|
710
|
-
await options.ensureRouteLoaded?.(actionRerenderTarget.route);
|
|
711
740
|
setCurrentFetchCacheMode(options.resolveRouteFetchCacheMode?.(actionRerenderTarget.route) ?? null);
|
|
712
|
-
setCurrentForceDynamicFetchDefault(
|
|
741
|
+
setCurrentForceDynamicFetchDefault(actionRerenderDynamicConfig === "force-dynamic");
|
|
713
742
|
setCurrentFetchSoftTags(buildServerActionPageTags(actionRerenderTarget.route, options.cleanPathname));
|
|
714
743
|
element = options.buildPageElement({
|
|
715
744
|
cleanPathname: options.cleanPathname,
|
|
@@ -719,8 +748,10 @@ async function handleServerActionRscRequest(options) {
|
|
|
719
748
|
params: actionRerenderTarget.params,
|
|
720
749
|
request: options.request,
|
|
721
750
|
route: actionRerenderTarget.route,
|
|
722
|
-
searchParams:
|
|
723
|
-
renderMode: APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI
|
|
751
|
+
searchParams: actionRerenderSearchParams,
|
|
752
|
+
renderMode: APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI,
|
|
753
|
+
observeMetadataSearchParamsAccess: actionRerenderDynamicConfig !== "force-static",
|
|
754
|
+
observePageSearchParamsAccess: actionRerenderDynamicConfig !== "force-static"
|
|
724
755
|
});
|
|
725
756
|
errorPattern = actionRerenderTarget.route.pattern;
|
|
726
757
|
} else {
|
|
@@ -3,6 +3,7 @@ import { HeadersContext } from "../shims/headers.js";
|
|
|
3
3
|
//#region src/server/app-static-generation.d.ts
|
|
4
4
|
type AppStaticGenerationRouteKind = "page" | "route";
|
|
5
5
|
type CreateStaticGenerationHeadersContextOptions = {
|
|
6
|
+
draftModeEnabled?: boolean;
|
|
6
7
|
draftModeSecret?: string;
|
|
7
8
|
dynamicConfig?: string;
|
|
8
9
|
routeKind: AppStaticGenerationRouteKind;
|
|
@@ -9,6 +9,7 @@ function createStaticGenerationHeadersContext(options) {
|
|
|
9
9
|
const context = {
|
|
10
10
|
headers: new Headers(),
|
|
11
11
|
cookies: /* @__PURE__ */ new Map(),
|
|
12
|
+
draftModeEnabled: options.draftModeEnabled,
|
|
12
13
|
draftModeSecret: options.draftModeSecret
|
|
13
14
|
};
|
|
14
15
|
if (options.dynamicConfig === "force-static") context.forceStatic = true;
|
package/dist/server/headers.d.ts
CHANGED
|
@@ -97,6 +97,8 @@ declare const NEXT_ROUTER_STATE_TREE_HEADER = "Next-Router-State-Tree";
|
|
|
97
97
|
declare const NEXT_ROUTER_PREFETCH_HEADER = "Next-Router-Prefetch";
|
|
98
98
|
declare const NEXT_ROUTER_SEGMENT_PREFETCH_HEADER = "Next-Router-Segment-Prefetch";
|
|
99
99
|
declare const NEXT_URL_HEADER = "Next-Url";
|
|
100
|
+
declare const NEXT_REQUEST_ID_HEADER = "x-nextjs-request-id";
|
|
101
|
+
declare const NEXT_HTML_REQUEST_ID_HEADER = "x-nextjs-html-request-id";
|
|
100
102
|
/** Lowercase flight header variants used in middleware forwarding. */
|
|
101
103
|
declare const FLIGHT_HEADERS: readonly string[];
|
|
102
104
|
/**
|
|
@@ -111,4 +113,4 @@ declare const INTERNAL_HEADERS: string[];
|
|
|
111
113
|
/** Vinext-only internal headers stripped alongside Next.js protocol internals. */
|
|
112
114
|
declare const VINEXT_INTERNAL_HEADERS: string[];
|
|
113
115
|
//#endregion
|
|
114
|
-
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
|
116
|
+
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
package/dist/server/headers.js
CHANGED
|
@@ -101,6 +101,8 @@ const NEXT_ROUTER_STATE_TREE_HEADER = "Next-Router-State-Tree";
|
|
|
101
101
|
const NEXT_ROUTER_PREFETCH_HEADER = "Next-Router-Prefetch";
|
|
102
102
|
const NEXT_ROUTER_SEGMENT_PREFETCH_HEADER = "Next-Router-Segment-Prefetch";
|
|
103
103
|
const NEXT_URL_HEADER = "Next-Url";
|
|
104
|
+
const NEXT_REQUEST_ID_HEADER = "x-nextjs-request-id";
|
|
105
|
+
const NEXT_HTML_REQUEST_ID_HEADER = "x-nextjs-html-request-id";
|
|
104
106
|
/** Lowercase flight header variants used in middleware forwarding. */
|
|
105
107
|
const FLIGHT_HEADERS = [
|
|
106
108
|
"rsc",
|
|
@@ -133,4 +135,4 @@ const INTERNAL_HEADERS = [
|
|
|
133
135
|
/** Vinext-only internal headers stripped alongside Next.js protocol internals. */
|
|
134
136
|
const VINEXT_INTERNAL_HEADERS = [VINEXT_PRERENDER_ROUTE_PARAMS_HEADER];
|
|
135
137
|
//#endregion
|
|
136
|
-
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
|
138
|
+
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
|
@@ -819,13 +819,12 @@ async function startAppRouterServer(options) {
|
|
|
819
819
|
return;
|
|
820
820
|
}
|
|
821
821
|
}
|
|
822
|
+
let missingBuildAsset = false;
|
|
822
823
|
{
|
|
823
824
|
const assetLookupPath = resolveAppRouterAssetPath(pathname, appAssetPathPrefix, appRouterAssetPrefix);
|
|
824
825
|
if (assetLookupPath) {
|
|
825
826
|
if (await tryServeStatic(req, res, clientDir, assetLookupPath, compress, staticCache)) return;
|
|
826
|
-
|
|
827
|
-
res.end("Not Found");
|
|
828
|
-
return;
|
|
827
|
+
missingBuildAsset = true;
|
|
829
828
|
}
|
|
830
829
|
}
|
|
831
830
|
if (isImageOptimizationPath(pathname)) {
|
|
@@ -868,6 +867,12 @@ async function startAppRouterServer(options) {
|
|
|
868
867
|
await sendWebResponse(notFoundResponse({ headers: toWebHeaders(staticResponseHeaders) }), req, res, compress);
|
|
869
868
|
return;
|
|
870
869
|
}
|
|
870
|
+
if (missingBuildAsset && response.status === 404) {
|
|
871
|
+
cancelResponseBody(response);
|
|
872
|
+
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
|
|
873
|
+
res.end("Not Found");
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
871
876
|
await sendWebResponse(response, req, res, compress);
|
|
872
877
|
} catch (e) {
|
|
873
878
|
console.error("[vinext] Server error:", e);
|
|
@@ -1000,11 +1005,9 @@ async function startPagesRouterServer(options) {
|
|
|
1000
1005
|
}
|
|
1001
1006
|
const staticLookupPath = stripBasePath(pathname, basePath);
|
|
1002
1007
|
const pagesAssetLookup = resolveAppRouterAssetPath(pathname, pagesAssetPathPrefix, assetPrefix);
|
|
1008
|
+
const missingBuildAsset = pagesAssetLookup !== null;
|
|
1003
1009
|
if (pagesAssetLookup) {
|
|
1004
1010
|
if (await tryServeStatic(req, res, clientDir, pagesAssetLookup, compress, staticCache)) return;
|
|
1005
|
-
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
|
|
1006
|
-
res.end("Not Found");
|
|
1007
|
-
return;
|
|
1008
1011
|
}
|
|
1009
1012
|
if (isImageOptimizationPath(pathname) || isImageOptimizationPath(staticLookupPath)) {
|
|
1010
1013
|
const params = parseImageParams(new URL(rawUrl, "http://localhost"), allowedImageWidths, pagesImageConfig?.qualities);
|
|
@@ -1089,6 +1092,12 @@ async function startPagesRouterServer(options) {
|
|
|
1089
1092
|
if (result.type === "handled") return;
|
|
1090
1093
|
if (result.type === "response") {
|
|
1091
1094
|
const { response } = result;
|
|
1095
|
+
if (missingBuildAsset && response.status === 404) {
|
|
1096
|
+
cancelResponseBody(response);
|
|
1097
|
+
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
|
|
1098
|
+
res.end("Not Found");
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1092
1101
|
if (isVinextStreamedHtmlResponse(response) || !response.body || result.defaultContentType === void 0) {
|
|
1093
1102
|
await sendWebResponse(response, req, res, compress);
|
|
1094
1103
|
return;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
//#region src/server/worker-utils.d.ts
|
|
2
|
+
declare function finalizeMissingStaticAssetResponse(response: Response, missingBuildAsset: boolean): Response;
|
|
2
3
|
declare function mergeHeaders(response: Response, extraHeaders: Record<string, string | string[]>, statusOverride?: number): Response;
|
|
3
4
|
declare function resolveStaticAssetSignal(signalResponse: Response, options: {
|
|
4
5
|
fetchAsset(path: string): Promise<Response>;
|
|
5
6
|
}): Promise<Response | null>;
|
|
6
7
|
//#endregion
|
|
7
|
-
export { mergeHeaders, resolveStaticAssetSignal };
|
|
8
|
+
export { finalizeMissingStaticAssetResponse, mergeHeaders, resolveStaticAssetSignal };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { VINEXT_STATIC_FILE_HEADER } from "./headers.js";
|
|
2
|
+
import { notFoundStaticAssetResponse } from "./http-error-responses.js";
|
|
2
3
|
//#region src/server/worker-utils.ts
|
|
3
4
|
/**
|
|
4
5
|
* Shared utilities for Cloudflare Worker entries.
|
|
@@ -29,6 +30,11 @@ function cancelResponseBody(response) {
|
|
|
29
30
|
if (!body || body.locked) return;
|
|
30
31
|
body.cancel().catch(() => {});
|
|
31
32
|
}
|
|
33
|
+
function finalizeMissingStaticAssetResponse(response, missingBuildAsset) {
|
|
34
|
+
if (!missingBuildAsset || response.status !== 404) return response;
|
|
35
|
+
cancelResponseBody(response);
|
|
36
|
+
return notFoundStaticAssetResponse();
|
|
37
|
+
}
|
|
32
38
|
function buildHeaderRecord(response, omitNames = []) {
|
|
33
39
|
const omitted = new Set(omitNames.map((name) => name.toLowerCase()));
|
|
34
40
|
const headers = {};
|
|
@@ -96,4 +102,4 @@ async function resolveStaticAssetSignal(signalResponse, options) {
|
|
|
96
102
|
return mergeHeaders(assetResponse, extraHeaders, assetResponse.ok && signalResponse.status !== 200 ? signalResponse.status : void 0);
|
|
97
103
|
}
|
|
98
104
|
//#endregion
|
|
99
|
-
export { mergeHeaders, resolveStaticAssetSignal };
|
|
105
|
+
export { finalizeMissingStaticAssetResponse, mergeHeaders, resolveStaticAssetSignal };
|