vinext 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/client-build-config.d.ts +4 -6
- package/dist/build/client-build-config.js +27 -7
- package/dist/build/prerender.js +1 -2
- package/dist/check.d.ts +18 -0
- package/dist/check.js +37 -17
- package/dist/cli.js +2 -2
- package/dist/config/next-config.d.ts +2 -1
- package/dist/config/next-config.js +3 -0
- package/dist/config/server-external-packages.d.ts +4 -0
- package/dist/config/server-external-packages.js +91 -0
- package/dist/deploy.d.ts +7 -0
- package/dist/deploy.js +25 -18
- package/dist/entries/app-rsc-entry.d.ts +2 -1
- package/dist/entries/app-rsc-entry.js +89 -20
- package/dist/entries/app-rsc-manifest.js +8 -0
- package/dist/entries/pages-client-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +1 -0
- package/dist/index.js +87 -34
- package/dist/init.js +2 -1
- package/dist/plugins/middleware-server-only.d.ts +8 -6
- package/dist/plugins/middleware-server-only.js +8 -7
- package/dist/plugins/og-assets.js +6 -6
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/remove-console.js +1 -1
- package/dist/plugins/strip-server-exports.js +2 -1
- package/dist/routing/app-route-graph.d.ts +6 -2
- package/dist/routing/app-route-graph.js +61 -13
- package/dist/routing/app-router.d.ts +5 -0
- package/dist/routing/app-router.js +5 -0
- package/dist/routing/file-matcher.d.ts +5 -0
- package/dist/routing/file-matcher.js +7 -1
- package/dist/server/app-action-request.d.ts +4 -0
- package/dist/server/app-action-request.js +9 -0
- package/dist/server/app-bfcache-identity.d.ts +12 -2
- package/dist/server/app-bfcache-identity.js +52 -23
- package/dist/server/app-browser-entry.js +42 -147
- package/dist/server/app-browser-history-controller.d.ts +2 -1
- package/dist/server/app-browser-history-controller.js +6 -2
- package/dist/server/app-browser-server-action-client.d.ts +32 -0
- package/dist/server/app-browser-server-action-client.js +128 -0
- package/dist/server/app-fallback-renderer.d.ts +3 -1
- package/dist/server/app-fallback-renderer.js +6 -2
- package/dist/server/app-history-state.d.ts +1 -2
- package/dist/server/app-history-state.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +3 -0
- package/dist/server/app-page-boundary-render.js +14 -3
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +8 -2
- package/dist/server/app-page-dispatch.d.ts +33 -4
- package/dist/server/app-page-dispatch.js +62 -90
- package/dist/server/app-page-element-builder.d.ts +7 -1
- package/dist/server/app-page-element-builder.js +56 -19
- package/dist/server/app-page-head.d.ts +16 -1
- package/dist/server/app-page-head.js +44 -22
- package/dist/server/app-page-method.js +1 -1
- package/dist/server/app-page-params.d.ts +2 -1
- package/dist/server/app-page-params.js +8 -1
- package/dist/server/app-page-ppr-runtime.d.ts +7 -0
- package/dist/server/app-page-ppr-runtime.js +70 -0
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +1 -1
- package/dist/server/app-page-render.d.ts +4 -1
- package/dist/server/app-page-render.js +8 -3
- package/dist/server/app-page-request.d.ts +8 -1
- package/dist/server/app-page-request.js +23 -11
- package/dist/server/app-page-route-wiring.d.ts +6 -1
- package/dist/server/app-page-route-wiring.js +30 -8
- package/dist/server/app-page-search-params-observation.d.ts +4 -2
- package/dist/server/app-page-search-params-observation.js +11 -7
- package/dist/server/app-page-stream.js +2 -1
- package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
- package/dist/server/app-route-handler-cache.js +1 -1
- package/dist/server/app-route-handler-dispatch.js +3 -2
- package/dist/server/app-route-handler-execution.js +5 -3
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +1 -6
- package/dist/server/app-route-module-loader.d.ts +2 -0
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-router-entry.js +7 -6
- package/dist/server/app-rsc-errors.d.ts +12 -1
- package/dist/server/app-rsc-errors.js +29 -3
- package/dist/server/app-rsc-handler.d.ts +15 -13
- package/dist/server/app-rsc-handler.js +28 -33
- package/dist/server/app-rsc-response-finalizer.js +5 -1
- package/dist/server/app-rsc-route-matching.d.ts +7 -0
- package/dist/server/app-rsc-route-matching.js +36 -3
- package/dist/server/app-segment-config.d.ts +1 -0
- package/dist/server/app-segment-config.js +32 -2
- package/dist/server/app-server-action-execution.d.ts +4 -0
- package/dist/server/app-server-action-execution.js +42 -11
- package/dist/server/app-ssr-entry.js +11 -6
- package/dist/server/app-static-generation.d.ts +1 -0
- package/dist/server/app-static-generation.js +1 -0
- package/dist/server/headers.d.ts +3 -1
- package/dist/server/headers.js +3 -1
- package/dist/server/metadata-route-response.d.ts +1 -1
- package/dist/server/prod-server.js +15 -6
- package/dist/server/worker-utils.d.ts +2 -1
- package/dist/server/worker-utils.js +7 -1
- package/dist/shims/dynamic.js +1 -1
- package/dist/shims/error-boundary.d.ts +19 -1
- package/dist/shims/error-boundary.js +11 -1
- package/dist/shims/headers.d.ts +3 -1
- package/dist/shims/headers.js +16 -5
- package/dist/shims/link.js +16 -12
- package/dist/shims/metadata.d.ts +3 -2
- package/dist/shims/metadata.js +8 -4
- package/dist/shims/router.js +13 -2
- package/dist/typegen.js +6 -5
- package/dist/utils/path.d.ts +2 -1
- package/dist/utils/path.js +1 -1
- package/dist/utils/project.d.ts +4 -0
- package/dist/utils/project.js +5 -1
- package/package.json +7 -3
|
@@ -2,9 +2,9 @@ import { AppRouteSemanticIds } from "../routing/app-route-graph.js";
|
|
|
2
2
|
import { AppElements, AppElementsInterception } from "./app-elements-wire.js";
|
|
3
3
|
import { AppPageParams } from "./app-page-boundary.js";
|
|
4
4
|
import { ThenableParamsObserver } from "../shims/thenable-params.js";
|
|
5
|
+
import { Metadata, Viewport } from "../shims/metadata.js";
|
|
5
6
|
import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
|
|
6
7
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
7
|
-
import { Metadata, Viewport } from "../shims/metadata.js";
|
|
8
8
|
import { AppPageRenderIdentity } from "./app-page-render-identity.js";
|
|
9
9
|
import { resolveAppPageChildSegments } from "./app-page-segment-state.js";
|
|
10
10
|
import { ComponentType, ReactNode } from "react";
|
|
@@ -31,6 +31,8 @@ type AppPageRouteWiringSlot<TModule extends AppPageModule = AppPageModule, TErro
|
|
|
31
31
|
/** Graph-owned semantic slot identity. */id?: string | null; /** Slot prop name passed to the owning layout (e.g. "modal" from @modal). */
|
|
32
32
|
name: string;
|
|
33
33
|
default?: TModule | null;
|
|
34
|
+
configLayouts?: readonly (TModule | null | undefined)[] | null;
|
|
35
|
+
configLayoutTreePositions?: readonly number[] | null;
|
|
34
36
|
error?: TErrorModule | null;
|
|
35
37
|
layout?: TModule | null;
|
|
36
38
|
layoutIndex: number;
|
|
@@ -83,6 +85,8 @@ type AppPageRouteWiringRoute<TModule extends AppPageModule = AppPageModule, TErr
|
|
|
83
85
|
templates?: readonly (TModule | null | undefined)[] | null;
|
|
84
86
|
};
|
|
85
87
|
type AppPageSlotOverride<TModule extends AppPageModule = AppPageModule> = {
|
|
88
|
+
branchSegments?: readonly string[] | null;
|
|
89
|
+
layoutSegments?: readonly (readonly string[])[] | null;
|
|
86
90
|
layoutModules?: readonly (TModule | null | undefined)[] | null;
|
|
87
91
|
/**
|
|
88
92
|
* The page module to render for this slot. Optional — when omitted, the
|
|
@@ -118,6 +122,7 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
|
|
|
118
122
|
rootNotFoundModule?: TModule | null;
|
|
119
123
|
rootUnauthorizedModule?: TModule | null;
|
|
120
124
|
route: AppPageRouteWiringRoute<TModule, TErrorModule>;
|
|
125
|
+
createPageElement?: (component: AppPageComponent, props: Readonly<Record<string, unknown>>) => ReactNode;
|
|
121
126
|
searchParams?: unknown;
|
|
122
127
|
slotOverrides?: Readonly<Record<string, AppPageSlotOverride<TModule>>> | null;
|
|
123
128
|
};
|
|
@@ -8,7 +8,7 @@ import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
|
|
|
8
8
|
import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
|
|
9
9
|
import { MetadataHead, ViewportHead, renderMetadataToHtml } from "../shims/metadata.js";
|
|
10
10
|
import { Children as Children$1, ParallelSlot, Slot } from "../shims/slot.js";
|
|
11
|
-
import { resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams } from "./app-page-params.js";
|
|
11
|
+
import { resolveAppPageBranchParams, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams } from "./app-page-params.js";
|
|
12
12
|
import { probeReactServerSubtree } from "./app-page-probe.js";
|
|
13
13
|
import { resolveAppPageChildSegments, resolveAppPageRouteStateKey, resolveAppPageSegmentStateKey } from "./app-page-segment-state.js";
|
|
14
14
|
import { Fragment, Suspense } from "react";
|
|
@@ -16,6 +16,9 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
16
16
|
//#region src/server/app-page-route-wiring.tsx
|
|
17
17
|
const APP_PAGE_LAYOUT_PROBE_CHILD = /* @__PURE__ */ jsx(Fragment, {});
|
|
18
18
|
const DEFAULT_GLOBAL_ERROR_COMPONENT = DefaultGlobalError;
|
|
19
|
+
function resolveSlotLayoutParams(routeSegments, treePosition, params) {
|
|
20
|
+
return resolveAppPageBranchParams(routeSegments, treePosition, params);
|
|
21
|
+
}
|
|
19
22
|
function getDefaultExport(module) {
|
|
20
23
|
return module?.default ?? null;
|
|
21
24
|
}
|
|
@@ -293,7 +296,9 @@ function buildAppPageElements(options) {
|
|
|
293
296
|
const slotId = resolveAppPageSlotId(slot, layoutEntries[targetIndex]?.treePath ?? "/");
|
|
294
297
|
const slotOverride = resolveSlotOverride(slotKey, slotName);
|
|
295
298
|
const slotParams = getEffectiveSlotParams(slotKey, slotName);
|
|
296
|
-
const
|
|
299
|
+
const slotRouteSegments = slot.routeSegments ?? [];
|
|
300
|
+
const slotOwnerParams = resolveAppPageSegmentParams(options.route.routeSegments, layoutEntries[targetIndex]?.treePosition ?? 0, options.matchedParams);
|
|
301
|
+
const slotResetKey = resolveAppPageRouteStateKey(slotRouteSegments, slotParams);
|
|
297
302
|
const overrideOrPageComponent = getDefaultExport(slotOverride?.pageModule) ?? getDefaultExport(slot.page);
|
|
298
303
|
const defaultComponent = getDefaultExport(slot.default);
|
|
299
304
|
if (!overrideOrPageComponent && defaultComponent && options.isRscRequest && options.mountedSlotIds?.has(slotId)) continue;
|
|
@@ -302,23 +307,40 @@ function buildAppPageElements(options) {
|
|
|
302
307
|
elements[slotId] = AppElementsWire.unmatchedSlotValue;
|
|
303
308
|
continue;
|
|
304
309
|
}
|
|
305
|
-
const
|
|
306
|
-
const slotProps = { params: slotThenableParams };
|
|
310
|
+
const slotProps = { params: options.makeThenableParams(slotParams) };
|
|
307
311
|
if (options.searchParams !== void 0) slotProps.searchParams = options.searchParams;
|
|
308
312
|
if (slotOverride?.props) Object.assign(slotProps, slotOverride.props);
|
|
309
|
-
let slotElement =
|
|
313
|
+
let slotElement = options.createPageElement ? options.createPageElement(slotComponent, slotProps) : (() => {
|
|
314
|
+
return /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
|
|
315
|
+
})();
|
|
316
|
+
const hasSlotTreeOverride = slotOverride?.pageModule != null || slotOverride?.layoutModules !== void 0;
|
|
310
317
|
const interceptLayouts = slotOverride?.layoutModules ?? [];
|
|
311
318
|
for (let layoutIndex = interceptLayouts.length - 1; layoutIndex >= 0; layoutIndex--) {
|
|
312
319
|
const interceptLayoutComponent = getDefaultExport(interceptLayouts[layoutIndex]);
|
|
313
320
|
if (!interceptLayoutComponent) continue;
|
|
314
|
-
|
|
315
|
-
|
|
321
|
+
const InterceptLayoutComponent = interceptLayoutComponent;
|
|
322
|
+
const interceptLayoutParams = resolveSlotLayoutParams(slotOverride?.branchSegments ?? slotRouteSegments, slotOverride?.layoutSegments?.[layoutIndex]?.length ?? slotRouteSegments.length, slotParams);
|
|
323
|
+
slotElement = /* @__PURE__ */ jsx(InterceptLayoutComponent, {
|
|
324
|
+
params: options.makeThenableParams(interceptLayoutParams),
|
|
325
|
+
children: slotElement
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
if (!hasSlotTreeOverride) for (let layoutIndex = (slot.configLayouts?.length ?? 0) - 1; layoutIndex >= 0; layoutIndex--) {
|
|
329
|
+
const nestedLayoutComponent = getDefaultExport(slot.configLayouts?.[layoutIndex]);
|
|
330
|
+
if (!nestedLayoutComponent) continue;
|
|
331
|
+
const NestedLayoutComponent = nestedLayoutComponent;
|
|
332
|
+
const nestedLayoutParams = resolveSlotLayoutParams(slotRouteSegments, slot.configLayoutTreePositions?.[layoutIndex] ?? 0, slotParams);
|
|
333
|
+
slotElement = /* @__PURE__ */ jsx(NestedLayoutComponent, {
|
|
334
|
+
params: options.makeThenableParams({
|
|
335
|
+
...slotOwnerParams,
|
|
336
|
+
...nestedLayoutParams
|
|
337
|
+
}),
|
|
316
338
|
children: slotElement
|
|
317
339
|
});
|
|
318
340
|
}
|
|
319
341
|
const slotLayoutComponent = getDefaultExport(slot.layout);
|
|
320
342
|
if (slotLayoutComponent) slotElement = /* @__PURE__ */ jsx(slotLayoutComponent, {
|
|
321
|
-
params:
|
|
343
|
+
params: options.makeThenableParams(slotOwnerParams),
|
|
322
344
|
children: slotElement
|
|
323
345
|
});
|
|
324
346
|
const slotLoadingComponent = getDefaultExport(slot.loading);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { ThenableParams } from "../shims/thenable-params.js";
|
|
1
|
+
import { ThenableParams, ThenableParamsObserver } from "../shims/thenable-params.js";
|
|
2
2
|
import { AppPageSearchParams } from "./app-page-head.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 };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
1
2
|
import { VINEXT_RSC_VARY_HEADER } from "./app-rsc-cache-busting.js";
|
|
2
3
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
3
4
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
@@ -131,7 +132,7 @@ function createAppPageRscErrorTracker(baseOnError) {
|
|
|
131
132
|
return capturedSpecialError;
|
|
132
133
|
},
|
|
133
134
|
onRenderError(error, requestInfo, errorContext) {
|
|
134
|
-
if (error
|
|
135
|
+
if (isNavigationSignalError(error)) {
|
|
135
136
|
if (capturedSpecialError === null) capturedSpecialError = error;
|
|
136
137
|
} else capturedError = error;
|
|
137
138
|
return baseOnError(error, requestInfo, errorContext);
|
|
@@ -4,7 +4,7 @@ import { ReactNode } from "react";
|
|
|
4
4
|
//#region src/server/app-ppr-fallback-shell-render.d.ts
|
|
5
5
|
type AppPageBoundaryOnError = (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
|
|
6
6
|
type AppPageRenderableElement = ReactNode | Record<string, ReactNode>;
|
|
7
|
-
|
|
7
|
+
type WarmPprFallbackShellCachesOptions = {
|
|
8
8
|
element: AppPageRenderableElement;
|
|
9
9
|
onError: AppPageBoundaryOnError;
|
|
10
10
|
renderToReadableStream: (element: AppPageRenderableElement, options: {
|
|
@@ -12,6 +12,7 @@ declare function warmPprFallbackShellCaches(options: {
|
|
|
12
12
|
signal?: AbortSignal;
|
|
13
13
|
}) => ReadableStream<Uint8Array>;
|
|
14
14
|
state: PprFallbackShellState;
|
|
15
|
-
}
|
|
15
|
+
};
|
|
16
|
+
declare function warmPprFallbackShellCaches(options: WarmPprFallbackShellCachesOptions): Promise<void>;
|
|
16
17
|
//#endregion
|
|
17
|
-
export { warmPprFallbackShellCaches };
|
|
18
|
+
export { WarmPprFallbackShellCachesOptions, warmPprFallbackShellCaches };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
2
|
-
import { markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
|
|
3
2
|
import { applyRouteHandlerMiddlewareContext, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, buildRouteHandlerCachedResponse } from "./app-route-handler-response.js";
|
|
3
|
+
import { markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
|
|
4
4
|
import { runAppRouteHandler } from "./app-route-handler-execution.js";
|
|
5
5
|
//#region src/server/app-route-handler-cache.ts
|
|
6
6
|
const EMPTY_PARAMS = Object.freeze({});
|
|
@@ -7,10 +7,10 @@ import { setNavigationContext } from "../shims/navigation-context-state.js";
|
|
|
7
7
|
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
8
8
|
import "../shims/navigation.js";
|
|
9
9
|
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
10
|
-
import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
|
|
11
|
-
import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
|
|
12
10
|
import { applyRouteHandlerMiddlewareContext } from "./app-route-handler-response.js";
|
|
11
|
+
import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
|
|
13
12
|
import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
|
|
13
|
+
import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
|
|
14
14
|
import { executeAppRouteHandler } from "./app-route-handler-execution.js";
|
|
15
15
|
import { readAppRouteHandlerCacheResponse } from "./app-route-handler-cache.js";
|
|
16
16
|
import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
|
|
@@ -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,12 +1,14 @@
|
|
|
1
|
-
import { setHeadersContext } from "../shims/headers.js";
|
|
2
|
-
import {
|
|
3
|
-
import { isPossibleAppRouteActionRequest, resolveAppRouteHandlerSpecialError, shouldApplyAppRouteHandlerRevalidateHeader, shouldWriteAppRouteHandlerCache } from "./app-route-handler-policy.js";
|
|
1
|
+
import { isDraftModeRequest, setHeadersContext } from "../shims/headers.js";
|
|
2
|
+
import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
|
|
4
3
|
import { applyRouteHandlerMiddlewareContext, applyRouteHandlerRevalidateHeader, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, finalizeRouteHandlerResponse, markRouteHandlerCacheMiss } from "./app-route-handler-response.js";
|
|
4
|
+
import { createTrackedAppRouteRequest, markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
|
|
5
5
|
import { createStaticGenerationHeadersContext, getAppRouteStaticGenerationErrorMessage } from "./app-static-generation.js";
|
|
6
|
+
import { resolveAppRouteHandlerSpecialError, shouldApplyAppRouteHandlerRevalidateHeader, shouldWriteAppRouteHandlerCache } from "./app-route-handler-policy.js";
|
|
6
7
|
//#region src/server/app-route-handler-execution.ts
|
|
7
8
|
function configureAppRouteStaticGenerationContext(options) {
|
|
8
9
|
if (options.dynamicConfig === "force-static" || options.dynamicConfig === "error") {
|
|
9
10
|
setHeadersContext(createStaticGenerationHeadersContext({
|
|
11
|
+
draftModeEnabled: options.draftModeSecret !== void 0 && isDraftModeRequest(options.request, options.draftModeSecret),
|
|
10
12
|
draftModeSecret: options.draftModeSecret,
|
|
11
13
|
dynamicConfig: options.dynamicConfig,
|
|
12
14
|
routeKind: "route",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
|
|
1
2
|
import { RouteHandlerHttpMethod, RouteHandlerModule } from "./app-route-handler-runtime.js";
|
|
2
3
|
|
|
3
4
|
//#region src/server/app-route-handler-policy.d.ts
|
|
@@ -43,7 +44,6 @@ type AppRouteHandlerSpecialError = {
|
|
|
43
44
|
type AppRouteHandlerSpecialErrorOptions = {
|
|
44
45
|
isAction: boolean;
|
|
45
46
|
};
|
|
46
|
-
declare function isPossibleAppRouteActionRequest(request: Pick<Request, "headers" | "method">): boolean;
|
|
47
47
|
declare function getAppRouteHandlerRevalidateSeconds(handler: Pick<AppRouteHandlerModule, "revalidate">): number | null;
|
|
48
48
|
declare function hasAppRouteHandlerDefaultExport(handler: RouteHandlerModule): boolean;
|
|
49
49
|
declare function resolveAppRouteHandlerMethod(handler: AppRouteHandlerModule, method: string): ResolvedAppRouteHandlerMethod;
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
import "./headers.js";
|
|
2
1
|
import { parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
|
|
2
|
+
import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
|
|
3
3
|
import { buildRouteHandlerAllowHeader, collectRouteHandlerMethods } from "./app-route-handler-runtime.js";
|
|
4
4
|
//#region src/server/app-route-handler-policy.ts
|
|
5
|
-
function isPossibleAppRouteActionRequest(request) {
|
|
6
|
-
if (request.method.toUpperCase() !== "POST") return false;
|
|
7
|
-
const contentType = request.headers.get("content-type");
|
|
8
|
-
return request.headers.has("x-rsc-action") || request.headers.has("next-action") || contentType === "application/x-www-form-urlencoded" || contentType?.startsWith("multipart/form-data") === true;
|
|
9
|
-
}
|
|
10
5
|
function getAppRouteHandlerRevalidateSeconds(handler) {
|
|
11
6
|
const { revalidate } = handler;
|
|
12
7
|
if (revalidate === false) return Infinity;
|
|
@@ -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 { 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
|
const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(request);
|
|
30
30
|
const filteredHeaders = filterInternalHeaders(request.headers);
|
|
@@ -35,14 +35,15 @@ async function handleRequest(request, env, ctx) {
|
|
|
35
35
|
const handleFn = () => rscHandler(request, ctx);
|
|
36
36
|
const result = await (ctx ? runWithExecutionContext(ctx, handleFn) : handleFn());
|
|
37
37
|
if (result instanceof Response) {
|
|
38
|
+
let response = result;
|
|
38
39
|
if (env?.ASSETS) {
|
|
39
40
|
const assetFetcher = env.ASSETS;
|
|
40
|
-
const assetResponse = await resolveStaticAssetSignal(
|
|
41
|
-
if (assetResponse)
|
|
41
|
+
const assetResponse = await resolveStaticAssetSignal(response, { fetchAsset: (path) => Promise.resolve(assetFetcher.fetch(new Request(new URL(path, request.url)))) });
|
|
42
|
+
if (assetResponse) response = assetResponse;
|
|
42
43
|
}
|
|
43
|
-
return
|
|
44
|
+
return finalizeMissingStaticAssetResponse(response, missingBuildAsset);
|
|
44
45
|
}
|
|
45
|
-
if (result === null || result === void 0) return notFoundResponse();
|
|
46
|
+
if (result === null || result === void 0) return missingBuildAsset ? notFoundStaticAssetResponse() : notFoundResponse();
|
|
46
47
|
return new Response(String(result), { status: 200 });
|
|
47
48
|
}
|
|
48
49
|
//#endregion
|
|
@@ -19,6 +19,17 @@ type CreateRscOnErrorHandlerOptions = {
|
|
|
19
19
|
declare function hasDigest(error: unknown): error is {
|
|
20
20
|
digest: unknown;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* vinext's mirror of Next.js's `getDigestForWellKnownError`: returns the digest
|
|
24
|
+
* string only when the error is a genuine control-flow signal — a redirect,
|
|
25
|
+
* notFound/HTTP-access fallback, bail-out-to-client-side-rendering, or
|
|
26
|
+
* dynamic-server-usage throw. Any other digest (e.g. a hashed digest stamped on
|
|
27
|
+
* a real error, or an obfuscated digest transported from a nested boundary)
|
|
28
|
+
* returns undefined so the caller still reports it as a real error. Mere
|
|
29
|
+
* presence of a `digest` field is NOT enough — that conflation swallowed a class
|
|
30
|
+
* of server render errors with no instrumentation/telemetry.
|
|
31
|
+
*/
|
|
32
|
+
declare function getDigestForWellKnownError(error: unknown): string | undefined;
|
|
22
33
|
/**
|
|
23
34
|
* djb2 hash matching Next.js's string-hash package for RSC error digests.
|
|
24
35
|
*/
|
|
@@ -26,4 +37,4 @@ declare function errorDigest(input: string): string;
|
|
|
26
37
|
declare function sanitizeErrorForClient(error: unknown, nodeEnv?: string | undefined): unknown;
|
|
27
38
|
declare function createRscOnErrorHandler(options: CreateRscOnErrorHandlerOptions): (error: unknown) => string | undefined;
|
|
28
39
|
//#endregion
|
|
29
|
-
export { createRscOnErrorHandler, errorDigest, hasDigest, sanitizeErrorForClient };
|
|
40
|
+
export { createRscOnErrorHandler, errorDigest, getDigestForWellKnownError, hasDigest, sanitizeErrorForClient };
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
+
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
1
2
|
import { resolveAppPageSpecialError } from "./app-page-execution.js";
|
|
2
3
|
//#region src/server/app-rsc-errors.ts
|
|
3
4
|
function hasDigest(error) {
|
|
4
5
|
return Boolean(error && typeof error === "object" && "digest" in error);
|
|
5
6
|
}
|
|
7
|
+
const BAILOUT_TO_CSR_DIGEST = "BAILOUT_TO_CLIENT_SIDE_RENDERING";
|
|
8
|
+
const DYNAMIC_SERVER_USAGE_DIGEST = "DYNAMIC_SERVER_USAGE";
|
|
9
|
+
/**
|
|
10
|
+
* vinext's mirror of Next.js's `getDigestForWellKnownError`: returns the digest
|
|
11
|
+
* string only when the error is a genuine control-flow signal — a redirect,
|
|
12
|
+
* notFound/HTTP-access fallback, bail-out-to-client-side-rendering, or
|
|
13
|
+
* dynamic-server-usage throw. Any other digest (e.g. a hashed digest stamped on
|
|
14
|
+
* a real error, or an obfuscated digest transported from a nested boundary)
|
|
15
|
+
* returns undefined so the caller still reports it as a real error. Mere
|
|
16
|
+
* presence of a `digest` field is NOT enough — that conflation swallowed a class
|
|
17
|
+
* of server render errors with no instrumentation/telemetry.
|
|
18
|
+
*/
|
|
19
|
+
function getDigestForWellKnownError(error) {
|
|
20
|
+
if (!hasDigest(error)) return;
|
|
21
|
+
const digest = String(error.digest);
|
|
22
|
+
if (isNavigationSignalError(error) || digest === BAILOUT_TO_CSR_DIGEST || digest === DYNAMIC_SERVER_USAGE_DIGEST) return digest;
|
|
23
|
+
}
|
|
6
24
|
function getThrownValueMessage(error) {
|
|
7
25
|
return error instanceof Error ? error.message : String(error);
|
|
8
26
|
}
|
|
@@ -27,14 +45,22 @@ function sanitizeErrorForClient(error, nodeEnv = process.env.NODE_ENV) {
|
|
|
27
45
|
function createRscOnErrorHandler(options) {
|
|
28
46
|
return (error) => {
|
|
29
47
|
const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV;
|
|
30
|
-
|
|
48
|
+
const wellKnownDigest = getDigestForWellKnownError(error);
|
|
49
|
+
if (wellKnownDigest !== void 0) return wellKnownDigest;
|
|
31
50
|
if (nodeEnv !== "production" && error instanceof Error && error.message.includes("Only plain objects, and a few built-ins, can be passed to Client Components")) {
|
|
32
51
|
console.error("[vinext] RSC serialization error: a non-plain object was passed from a Server Component to a Client Component.\n\nCommon causes:\n * Passing a module namespace (import * as X) directly as a prop.\n Unlike Next.js (webpack), Vite produces real ESM module namespace objects\n which are not serializable. Fix: pass individual values instead,\n e.g. <Comp value={module.value} />\n * Passing a class instance (new Foo()) as a prop.\n Fix: convert to a plain object, e.g. { id: foo.id, name: foo.name }\n * Passing a Date, Map, or Set. Use .toISOString(), [...map.entries()], etc.\n * Passing Object.create(null). Use { ...obj } to restore a prototype.\n\nOriginal error:", error.message);
|
|
33
52
|
return;
|
|
34
53
|
}
|
|
35
54
|
if (options.requestInfo && options.errorContext && error) options.reportRequestError(error instanceof Error ? error : new Error(getThrownValueMessage(error)), options.requestInfo, options.errorContext);
|
|
36
|
-
if (
|
|
55
|
+
if (hasDigest(error)) return String(error.digest);
|
|
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
|
+
}
|
|
37
63
|
};
|
|
38
64
|
}
|
|
39
65
|
//#endregion
|
|
40
|
-
export { createRscOnErrorHandler, errorDigest, hasDigest, sanitizeErrorForClient };
|
|
66
|
+
export { createRscOnErrorHandler, errorDigest, getDigestForWellKnownError, hasDigest, sanitizeErrorForClient };
|
|
@@ -2,21 +2,26 @@ import { NextHeader, NextI18nConfig, NextRedirect, NextRewrite } from "../config
|
|
|
2
2
|
import { ImageConfig } from "./image-optimization.js";
|
|
3
3
|
import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
|
|
4
4
|
import { RootParams } from "../shims/root-params.js";
|
|
5
|
-
import {
|
|
6
|
-
import { AppMiddlewareContext } from "./app-middleware.js";
|
|
5
|
+
import { AppMiddlewareContext, ApplyAppMiddlewareResult } from "./app-middleware.js";
|
|
7
6
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
7
|
+
import { AppPagePprFallbackCacheShell } from "./app-ppr-fallback-shell.js";
|
|
8
8
|
import { AppPrerenderRootParamNamesMap, AppPrerenderStaticParamsMap } from "./app-prerender-endpoints.js";
|
|
9
|
-
import { MetadataRouteMakeThenableParams, MetadataRuntimeRoute } from "./metadata-route-response.js";
|
|
10
9
|
import { ReactFormState } from "react-dom/client";
|
|
11
10
|
|
|
12
11
|
//#region src/server/app-rsc-handler.d.ts
|
|
13
12
|
type AppPageParams = Record<string, string | string[]>;
|
|
14
|
-
type MetadataRoutes = readonly MetadataRuntimeRoute[];
|
|
15
|
-
type MakeThenableParams = MetadataRouteMakeThenableParams;
|
|
16
13
|
type StaticParamsMap = AppPrerenderStaticParamsMap;
|
|
17
14
|
type RootParamNamesMap = AppPrerenderRootParamNamesMap;
|
|
18
15
|
type AppRscMiddlewareContext = AppMiddlewareContext;
|
|
16
|
+
type RunAppMiddlewareOptions = {
|
|
17
|
+
cleanPathname: string;
|
|
18
|
+
context: AppRscMiddlewareContext;
|
|
19
|
+
isDataRequest: boolean;
|
|
20
|
+
request: Request;
|
|
21
|
+
};
|
|
19
22
|
type AppRscHandlerRoute = {
|
|
23
|
+
__loadPage?: unknown;
|
|
24
|
+
__loadRouteHandler?: unknown;
|
|
20
25
|
isDynamic: boolean;
|
|
21
26
|
params?: readonly string[];
|
|
22
27
|
page?: unknown;
|
|
@@ -147,7 +152,6 @@ type NavigationContextValue = {
|
|
|
147
152
|
type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
|
|
148
153
|
basePath: string;
|
|
149
154
|
buildId: string | null;
|
|
150
|
-
cacheComponents?: boolean;
|
|
151
155
|
clearRequestContext: () => void;
|
|
152
156
|
configHeaders: NextHeader[];
|
|
153
157
|
configRedirects: NextRedirect[];
|
|
@@ -173,18 +177,16 @@ type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
|
|
|
173
177
|
* Node server and dev included, not just the Cloudflare worker entry.
|
|
174
178
|
*/
|
|
175
179
|
registerCacheAdapters: (env?: Record<string, unknown>) => void;
|
|
176
|
-
handleProgressiveActionRequest
|
|
177
|
-
|
|
180
|
+
handleProgressiveActionRequest?: (options: HandleProgressiveActionRequestOptions) => Promise<Response | ProgressiveActionFormStateResult | null>;
|
|
181
|
+
handleMetadataRouteRequest?: (cleanPathname: string) => Promise<Response | null>;
|
|
182
|
+
createPprFallbackShells?: (route: Pick<AppRscHandlerRoute, "params" | "pattern" | "rootParamNames">, params: AppPageParams) => AppPagePprFallbackCacheShell[];
|
|
183
|
+
handleServerActionRequest?: (options: HandleServerActionRequestOptions) => Promise<Response | null>;
|
|
178
184
|
i18nConfig: NextI18nConfig | null;
|
|
179
185
|
imageConfig?: ImageConfig;
|
|
180
186
|
isDev: boolean;
|
|
181
|
-
isMiddlewareProxy: boolean;
|
|
182
187
|
loadPrerenderPagesRoutes?: () => Promise<unknown>;
|
|
183
|
-
makeThenableParams: MakeThenableParams;
|
|
184
188
|
matchRoute: (pathname: string) => AppRscRouteMatch<TRoute> | null;
|
|
185
|
-
|
|
186
|
-
middlewareFilePath: string | null;
|
|
187
|
-
middlewareModule: MiddlewareModule | null;
|
|
189
|
+
runMiddleware?: (options: RunAppMiddlewareOptions) => Promise<ApplyAppMiddlewareResult>;
|
|
188
190
|
publicFiles: ReadonlySet<string>;
|
|
189
191
|
renderNotFound: (options: RenderNotFoundOptions<TRoute>) => Promise<Response | null>;
|
|
190
192
|
renderPagesFallback?: (options: RenderPagesFallbackOptions) => Promise<Response | null>;
|
|
@@ -19,6 +19,7 @@ import { matchPrerenderRouteParamsPayload, readTrustedPrerenderRouteParams, seri
|
|
|
19
19
|
import { getRenderedConcreteUrlPathsForRoute } from "./pregenerated-concrete-paths.js";
|
|
20
20
|
import { pickRootParams, setRootParams } from "../shims/root-params.js";
|
|
21
21
|
import { flattenErrorCauses } from "../utils/error-cause.js";
|
|
22
|
+
import { createServerActionNotFoundResponse, getServerActionNotFoundMessage } from "./server-action-not-found.js";
|
|
22
23
|
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
23
24
|
import { buildPostMwRequestContext } from "./app-post-middleware-context.js";
|
|
24
25
|
import { finalizeAppRscResponse } from "./app-rsc-response-finalizer.js";
|
|
@@ -47,6 +48,11 @@ function isExecutionContextLike(value) {
|
|
|
47
48
|
if (!value || typeof value !== "object") return false;
|
|
48
49
|
return hasProperty(value, "waitUntil") && typeof value.waitUntil === "function";
|
|
49
50
|
}
|
|
51
|
+
function createMissingServerActionResponse(options, actionId) {
|
|
52
|
+
console.warn(getServerActionNotFoundMessage(actionId));
|
|
53
|
+
options.clearRequestContext();
|
|
54
|
+
return createServerActionNotFoundResponse();
|
|
55
|
+
}
|
|
50
56
|
function redirectDestinationWithBasePath(destination, basePath) {
|
|
51
57
|
if (!basePath || isExternalUrl(destination) || hasBasePath(destination, basePath)) return destination;
|
|
52
58
|
return basePath + destination;
|
|
@@ -165,19 +171,12 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
165
171
|
status: null
|
|
166
172
|
};
|
|
167
173
|
let didMiddlewareRewrite = false;
|
|
168
|
-
if (options.
|
|
169
|
-
const
|
|
170
|
-
const middlewareResult = await applyAppMiddleware({
|
|
171
|
-
basePath: options.basePath,
|
|
174
|
+
if (options.runMiddleware) {
|
|
175
|
+
const middlewareResult = await options.runMiddleware({
|
|
172
176
|
cleanPathname,
|
|
173
177
|
context: middlewareContext,
|
|
174
|
-
filePath: options.middlewareFilePath ?? void 0,
|
|
175
|
-
i18nConfig: options.i18nConfig,
|
|
176
178
|
isDataRequest,
|
|
177
|
-
|
|
178
|
-
module: options.middlewareModule,
|
|
179
|
-
request: userlandRequest,
|
|
180
|
-
trailingSlash: options.trailingSlash
|
|
179
|
+
request: userlandRequest
|
|
181
180
|
});
|
|
182
181
|
if (middlewareResult.kind === "response") return applyConfigHeadersToMiddlewareRedirect(middlewareResult.response, {
|
|
183
182
|
basePathState,
|
|
@@ -211,13 +210,8 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
211
210
|
if (!imageRedirect) return new Response("Invalid image optimization parameters", { status: 400 });
|
|
212
211
|
return Response.redirect(new URL(imageRedirect, url.origin).href, 302);
|
|
213
212
|
}
|
|
214
|
-
if (options.
|
|
215
|
-
const
|
|
216
|
-
const metadataRouteResponse = await handleMetadataRouteRequest({
|
|
217
|
-
metadataRoutes: options.metadataRoutes,
|
|
218
|
-
cleanPathname,
|
|
219
|
-
makeThenableParams: options.makeThenableParams
|
|
220
|
-
});
|
|
213
|
+
if (options.handleMetadataRouteRequest) {
|
|
214
|
+
const metadataRouteResponse = await options.handleMetadataRouteRequest(cleanPathname);
|
|
221
215
|
if (metadataRouteResponse) {
|
|
222
216
|
applyConfigHeadersToResponse(metadataRouteResponse.headers, {
|
|
223
217
|
basePathState,
|
|
@@ -255,13 +249,16 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
255
249
|
const contentType = request.headers.get("content-type") || "";
|
|
256
250
|
const isPostRequest = request.method.toUpperCase() === "POST";
|
|
257
251
|
let progressiveActionResult = null;
|
|
258
|
-
if (isPostRequest && contentType.startsWith("multipart/form-data") && !actionId)
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
252
|
+
if (isPostRequest && contentType.startsWith("multipart/form-data") && !actionId) {
|
|
253
|
+
if (options.handleProgressiveActionRequest) progressiveActionResult = await options.handleProgressiveActionRequest({
|
|
254
|
+
actionId,
|
|
255
|
+
cleanPathname,
|
|
256
|
+
contentType,
|
|
257
|
+
middlewareContext,
|
|
258
|
+
request
|
|
259
|
+
});
|
|
260
|
+
else if (preActionMatch?.route.__loadPage && !preActionMatch.route.__loadRouteHandler) return createMissingServerActionResponse(options, null);
|
|
261
|
+
}
|
|
265
262
|
if (progressiveActionResult instanceof Response) return progressiveActionResult;
|
|
266
263
|
const progressiveActionFormState = progressiveActionResult?.kind === "form-state" ? progressiveActionResult : null;
|
|
267
264
|
const isProgressiveActionRender = progressiveActionFormState !== null;
|
|
@@ -269,7 +266,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
269
266
|
const failedProgressiveActionResult = progressiveActionFormState && "actionError" in progressiveActionFormState ? progressiveActionFormState : null;
|
|
270
267
|
const actionFailed = failedProgressiveActionResult !== null;
|
|
271
268
|
const actionError = failedProgressiveActionResult?.actionError;
|
|
272
|
-
const serverActionResponse = isPostRequest && actionId ? await options.handleServerActionRequest({
|
|
269
|
+
const serverActionResponse = isPostRequest && actionId && options.handleServerActionRequest ? await options.handleServerActionRequest({
|
|
273
270
|
actionId,
|
|
274
271
|
cleanPathname,
|
|
275
272
|
contentType,
|
|
@@ -281,6 +278,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
281
278
|
searchParams: getResolvedSearchParams()
|
|
282
279
|
}) : null;
|
|
283
280
|
if (serverActionResponse) return serverActionResponse;
|
|
281
|
+
if (isPostRequest && actionId && !options.handleServerActionRequest) return createMissingServerActionResponse(options, actionId);
|
|
284
282
|
let match = preActionMatch;
|
|
285
283
|
const renderPagesForMatchKind = async (matchKind) => {
|
|
286
284
|
const response = match === null || match.route.isDynamic ? await options.renderPagesFallback?.({
|
|
@@ -394,14 +392,11 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
394
392
|
const renderParams = prerenderRouteParams ?? params;
|
|
395
393
|
const resolvedSearchParams = getResolvedSearchParams();
|
|
396
394
|
let runtimeFallbackShells = [];
|
|
397
|
-
if (options.
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
rootParamNames: route.rootParamNames
|
|
403
|
-
}, params);
|
|
404
|
-
}
|
|
395
|
+
if (options.createPprFallbackShells && request.method === "GET" && !isRscRequest && !isPrerenderFallbackShell && route.params) runtimeFallbackShells = options.createPprFallbackShells({
|
|
396
|
+
params: route.params,
|
|
397
|
+
pattern: route.pattern,
|
|
398
|
+
rootParamNames: route.rootParamNames
|
|
399
|
+
}, params);
|
|
405
400
|
options.setNavigationContext({
|
|
406
401
|
pathname: canonicalPathname,
|
|
407
402
|
searchParams: resolvedSearchParams,
|
|
@@ -22,7 +22,11 @@ import { mergeVaryHeader } from "./middleware-response-headers.js";
|
|
|
22
22
|
*/
|
|
23
23
|
function finalizeAppRscResponse(response, request, options) {
|
|
24
24
|
if (response.status >= 300 && response.status < 400) return response;
|
|
25
|
-
if (!response.headers.has("x-vinext-static-file"))
|
|
25
|
+
if (!response.headers.has("x-vinext-static-file")) {
|
|
26
|
+
const varyHeader = response.headers.get("Vary");
|
|
27
|
+
if (varyHeader === null) response.headers.set("Vary", VINEXT_RSC_VARY_HEADER);
|
|
28
|
+
else if (varyHeader !== VINEXT_RSC_VARY_HEADER) mergeVaryHeader(response.headers, VINEXT_RSC_VARY_HEADER);
|
|
29
|
+
}
|
|
26
30
|
if (!response.headers.has("Cache-Control")) applyCdnResponseHeaders(response.headers, { cacheControl: "" });
|
|
27
31
|
if (!options.configHeaders.length) return response;
|
|
28
32
|
const url = new URL(request.url);
|