vinext 1.0.0-beta.0 → 1.0.0-beta.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 +21 -2
- package/dist/build/assets-ignore.js +1 -1
- package/dist/build/clean-output.js +1 -1
- package/dist/build/client-build-config.js +7 -4
- package/dist/build/css-url-assets.js +3 -3
- package/dist/build/google-fonts/fallback-metrics.js +1 -1
- package/dist/build/google-fonts/font-metadata.js +1 -1
- package/dist/build/inject-pregenerated-paths.js +1 -1
- package/dist/build/inline-css.js +2 -5
- package/dist/build/module-dependency-cache.d.ts +4 -0
- package/dist/build/module-dependency-cache.js +13 -0
- package/dist/build/next-client-runtime-manifests.js +1 -1
- package/dist/build/pages-client-assets-module.js +1 -1
- package/dist/build/precompress.js +7 -7
- package/dist/build/prerender-paths.d.ts +2 -2
- package/dist/build/prerender-paths.js +10 -15
- package/dist/build/prerender-server-pool.js +2 -2
- package/dist/build/prerender.js +1 -1
- package/dist/build/preview-credentials.d.ts +11 -0
- package/dist/build/preview-credentials.js +19 -0
- package/dist/build/report.d.ts +8 -4
- package/dist/build/report.js +14 -6
- package/dist/build/run-prerender.d.ts +2 -11
- package/dist/build/run-prerender.js +2 -10
- package/dist/build/server-manifest.js +1 -1
- package/dist/build/ssr-manifest.d.ts +4 -0
- package/dist/build/ssr-manifest.js +10 -6
- package/dist/build/standalone.js +37 -37
- package/dist/cache/cache-adapters-virtual.d.ts +1 -17
- package/dist/cache/cache-adapters-virtual.js +20 -11
- package/dist/check.d.ts +0 -16
- package/dist/check.js +27 -36
- package/dist/cli.js +61 -55
- package/dist/client/instrumentation-client-inject.js +1 -1
- package/dist/client/pages-router-link-navigation.js +1 -1
- package/dist/config/config-matchers.d.ts +13 -37
- package/dist/config/config-matchers.js +33 -123
- package/dist/config/dotenv.js +1 -1
- package/dist/config/next-config.d.ts +7 -3
- package/dist/config/next-config.js +84 -15
- package/dist/config/prerender.d.ts +2 -2
- package/dist/config/prerender.js +7 -15
- package/dist/config/request-context.d.ts +14 -0
- package/dist/config/request-context.js +26 -0
- package/dist/config/server-external-packages.js +1 -1
- package/dist/config/tsconfig-paths.js +2 -2
- package/dist/{node_modules/.pnpm/am-i-vibing@0.5.0/node_modules → deps/.pnpm/am-i-vibing@0.5.0/deps}/am-i-vibing/dist/detector-1yx2Hoe0.js +2 -2
- package/dist/deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js +50 -0
- package/dist/entries/app-rsc-entry.js +39 -14
- package/dist/entries/app-rsc-manifest.js +21 -4
- package/dist/entries/pages-client-entry.js +6 -5
- package/dist/entries/pages-server-entry.js +18 -28
- package/dist/entries/runtime-entry-module.js +2 -2
- package/dist/index.js +314 -230
- package/dist/init-cloudflare.js +1 -1
- package/dist/init-platform.js +1 -1
- package/dist/init.d.ts +6 -4
- package/dist/init.js +25 -27
- package/dist/plugins/ast-utils.js +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +7 -7
- package/dist/plugins/extensionless-dynamic-import.js +1 -1
- package/dist/plugins/fonts.js +3 -3
- package/dist/plugins/ignore-dynamic-requests.js +13 -8
- package/dist/plugins/import-meta-url.js +16 -17
- package/dist/plugins/middleware-export-validation.js +1 -1
- package/dist/plugins/middleware-server-only.js +2 -2
- package/dist/plugins/og-asset-ownership.js +7 -6
- package/dist/plugins/og-assets.js +5 -6
- package/dist/plugins/optimize-imports.js +12 -13
- package/dist/plugins/postcss.js +1 -1
- package/dist/plugins/remove-console.js +1 -1
- package/dist/plugins/require-context.js +1 -1
- package/dist/plugins/sass.js +2 -2
- package/dist/plugins/server-externals-manifest.js +1 -1
- package/dist/plugins/strip-server-exports.js +1 -1
- package/dist/plugins/styled-jsx.js +3 -2
- package/dist/plugins/typeof-window.js +1 -1
- package/dist/routing/app-route-graph.d.ts +16 -15
- package/dist/routing/app-route-graph.js +86 -88
- package/dist/routing/app-router.d.ts +0 -5
- package/dist/routing/app-router.js +12 -11
- package/dist/routing/file-matcher.d.ts +13 -28
- package/dist/routing/file-matcher.js +31 -44
- package/dist/routing/pages-router.js +26 -32
- package/dist/routing/route-matching.d.ts +14 -1
- package/dist/routing/route-matching.js +13 -1
- package/dist/routing/route-pattern.d.ts +2 -1
- package/dist/routing/route-pattern.js +7 -4
- package/dist/routing/route-trie.d.ts +5 -1
- package/dist/routing/route-trie.js +5 -2
- package/dist/server/api-handler.js +41 -33
- package/dist/server/app-browser-entry.js +18 -11
- package/dist/server/app-browser-history-controller.d.ts +1 -1
- package/dist/server/app-browser-history-controller.js +3 -3
- package/dist/server/app-browser-navigation-controller.js +4 -2
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-elements-wire.d.ts +2 -1
- package/dist/server/app-fallback-renderer.d.ts +11 -0
- package/dist/server/app-fallback-renderer.js +16 -2
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-page-boundary-render.d.ts +26 -2
- package/dist/server/app-page-boundary-render.js +190 -55
- package/dist/server/app-page-cache-finalizer.d.ts +1 -1
- package/dist/server/app-page-cache.d.ts +1 -1
- package/dist/server/app-page-dispatch.d.ts +12 -2
- package/dist/server/app-page-dispatch.js +37 -51
- package/dist/server/app-page-element-builder.d.ts +8 -2
- package/dist/server/app-page-element-builder.js +112 -27
- package/dist/server/app-page-execution.d.ts +3 -1
- package/dist/server/app-page-execution.js +31 -39
- package/dist/server/app-page-head.d.ts +54 -2
- package/dist/server/app-page-head.js +164 -78
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +106 -0
- package/dist/server/app-page-render.d.ts +2 -2
- package/dist/server/app-page-render.js +1 -1
- package/dist/server/app-page-request.d.ts +12 -0
- package/dist/server/app-page-request.js +134 -14
- package/dist/server/app-page-route-wiring.d.ts +9 -0
- package/dist/server/app-page-route-wiring.js +44 -4
- package/dist/server/app-post-middleware-context.d.ts +1 -1
- package/dist/server/app-post-middleware-context.js +1 -1
- package/dist/server/app-route-handler-dispatch.js +31 -17
- package/dist/server/app-route-handler-execution.d.ts +6 -1
- package/dist/server/app-route-handler-execution.js +41 -15
- package/dist/server/app-route-handler-policy.d.ts +2 -0
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-module-loader.d.ts +3 -1
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-route-tree-prefetch.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +1 -1
- package/dist/server/app-rsc-cache-busting.js +1 -1
- package/dist/server/app-rsc-errors.d.ts +1 -1
- package/dist/server/app-rsc-errors.js +12 -2
- package/dist/server/app-rsc-handler.d.ts +10 -5
- package/dist/server/app-rsc-handler.js +51 -23
- package/dist/server/app-rsc-redirect-flight.d.ts +66 -0
- package/dist/server/app-rsc-redirect-flight.js +71 -0
- package/dist/server/app-rsc-request-normalization.d.ts +3 -2
- package/dist/server/app-rsc-request-normalization.js +8 -2
- package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
- package/dist/server/app-rsc-response-finalizer.js +5 -11
- package/dist/server/app-rsc-route-matching.d.ts +20 -0
- package/dist/server/app-rsc-route-matching.js +87 -11
- package/dist/server/app-segment-config.js +15 -5
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +8 -6
- package/dist/server/app-ssr-entry.js +4 -1
- package/dist/server/app-ssr-stream.d.ts +2 -7
- package/dist/server/app-ssr-stream.js +5 -10
- package/dist/server/cache-proof.js +1 -1
- package/dist/server/config-headers.d.ts +24 -0
- package/dist/server/config-headers.js +52 -0
- package/dist/server/default-global-error-module.d.ts +3 -1
- package/dist/server/default-not-found-module.d.ts +3 -1
- package/dist/server/dev-initial-server-error.d.ts +1 -1
- package/dist/server/dev-lockfile.js +2 -3
- package/dist/server/dev-route-files.js +1 -1
- package/dist/server/dev-server.js +281 -173
- package/dist/server/dev-stack-sourcemap.js +4 -3
- package/dist/server/headers.d.ts +3 -1
- package/dist/server/headers.js +3 -1
- package/dist/server/image-optimization.js +2 -2
- package/dist/server/implicit-tags.js +2 -1
- package/dist/server/instrumentation.js +2 -2
- package/dist/server/isr-cache.d.ts +1 -1
- package/dist/server/isr-cache.js +1 -1
- package/dist/server/metadata-routes.js +4 -4
- package/dist/server/middleware-matcher-pattern.d.ts +22 -0
- package/dist/server/middleware-matcher-pattern.js +219 -0
- package/dist/server/middleware-matcher.d.ts +2 -7
- package/dist/server/middleware-matcher.js +13 -60
- package/dist/server/middleware-path-to-regexp.d.ts +14 -0
- package/dist/server/middleware-path-to-regexp.js +228 -0
- package/dist/server/middleware-response-headers.js +1 -1
- package/dist/server/middleware-runtime.js +5 -4
- package/dist/server/middleware.d.ts +2 -1
- package/dist/server/middleware.js +3 -2
- package/dist/server/navigation-planner.d.ts +2 -0
- package/dist/server/navigation-planner.js +8 -2
- package/dist/server/next-error-digest.d.ts +9 -24
- package/dist/server/next-error-digest.js +23 -15
- package/dist/server/operation-token.js +1 -1
- package/dist/server/pages-body-parser-config.js +2 -1
- package/dist/server/pages-data-route.d.ts +11 -1
- package/dist/server/pages-data-route.js +16 -1
- package/dist/server/pages-dev-hydration.d.ts +14 -0
- package/dist/server/pages-dev-hydration.js +83 -0
- package/dist/server/pages-dev-module-url.js +2 -2
- package/dist/server/pages-get-initial-props.d.ts +15 -2
- package/dist/server/pages-get-initial-props.js +16 -6
- package/dist/server/pages-node-compat.d.ts +13 -6
- package/dist/server/pages-node-compat.js +44 -45
- package/dist/server/pages-page-data.d.ts +4 -2
- package/dist/server/pages-page-data.js +20 -10
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +74 -43
- package/dist/server/pages-page-response.d.ts +2 -2
- package/dist/server/pages-page-response.js +1 -1
- package/dist/server/pages-preview.d.ts +26 -0
- package/dist/server/pages-preview.js +165 -0
- package/dist/server/pages-readiness.d.ts +5 -4
- package/dist/server/pages-readiness.js +4 -2
- package/dist/server/pages-request-pipeline.d.ts +1 -0
- package/dist/server/pages-request-pipeline.js +25 -11
- package/dist/server/pages-router-entry.js +6 -0
- package/dist/server/prerender-route-params.js +2 -2
- package/dist/server/prod-server.d.ts +1 -4
- package/dist/server/prod-server.js +44 -30
- package/dist/server/request-pipeline.d.ts +15 -29
- package/dist/server/request-pipeline.js +25 -60
- package/dist/server/rsc-stream-hints.js +122 -18
- package/dist/server/seed-cache.js +1 -1
- package/dist/server/socket-error-backstop.js +1 -1
- package/dist/server/static-file-cache.js +7 -8
- package/dist/server/worker-utils.js +1 -1
- package/dist/shims/app.d.ts +1 -1
- package/dist/shims/cache-request-state.d.ts +27 -1
- package/dist/shims/cache-request-state.js +60 -1
- package/dist/shims/cache-runtime.d.ts +12 -1
- package/dist/shims/cache-runtime.js +22 -7
- package/dist/shims/cache.d.ts +5 -5
- package/dist/shims/cache.js +28 -11
- package/dist/shims/constants.js +1 -1
- package/dist/shims/document.d.ts +42 -83
- package/dist/shims/document.js +62 -53
- package/dist/shims/dynamic.d.ts +5 -25
- package/dist/shims/dynamic.js +29 -8
- package/dist/shims/error-boundary.d.ts +4 -4
- package/dist/shims/error.d.ts +22 -6
- package/dist/shims/error.js +53 -15
- package/dist/shims/fetch-cache.js +13 -4
- package/dist/shims/font-google-base.d.ts +11 -4
- package/dist/shims/font-local.d.ts +10 -3
- package/dist/shims/font-utils.js +1 -1
- package/dist/shims/form.d.ts +1 -1
- package/dist/shims/head.d.ts +13 -2
- package/dist/shims/head.js +6 -6
- package/dist/shims/headers.d.ts +28 -31
- package/dist/shims/headers.js +115 -53
- package/dist/shims/image.d.ts +27 -37
- package/dist/shims/image.js +21 -14
- package/dist/shims/internal/cookie-serialize.d.ts +3 -1
- package/dist/shims/internal/cookie-serialize.js +3 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
- package/dist/shims/internal/pages-data-fetch-dedup.js +5 -3
- package/dist/shims/internal/utils.d.ts +3 -3
- package/dist/shims/layout-segment-context.d.ts +1 -1
- package/dist/shims/legacy-image.d.ts +3 -37
- package/dist/shims/legacy-image.js +6 -16
- package/dist/shims/link.d.ts +16 -21
- package/dist/shims/link.js +25 -13
- package/dist/shims/navigation-context-state.d.ts +1 -1
- package/dist/shims/navigation-errors.d.ts +2 -1
- package/dist/shims/navigation-errors.js +9 -13
- package/dist/shims/navigation.d.ts +8 -4
- package/dist/shims/navigation.js +29 -18
- package/dist/shims/next-shims-augmentations.d.ts +1 -0
- package/dist/shims/next-shims-public.d.ts +1 -0
- package/dist/shims/public-shim-map.json.js +103 -0
- package/dist/shims/readonly-url-search-params.d.ts +3 -3
- package/dist/shims/readonly-url-search-params.js +3 -3
- package/dist/shims/request-state-types.d.ts +1 -1
- package/dist/shims/router-state.d.ts +1 -0
- package/dist/shims/router.d.ts +57 -22
- package/dist/shims/router.js +178 -46
- package/dist/shims/script.d.ts +6 -10
- package/dist/shims/script.js +7 -4
- package/dist/shims/server.d.ts +45 -22
- package/dist/shims/server.js +46 -7
- package/dist/shims/slot.d.ts +1 -1
- package/dist/shims/thenable-params.js +1 -1
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +2 -0
- package/dist/shims/url-safety.d.ts +1 -1
- package/dist/shims/url-safety.js +2 -2
- package/dist/typegen.d.ts +8 -2
- package/dist/typegen.js +84 -25
- package/dist/utils/client-build-manifest.js +2 -2
- package/dist/utils/client-entry-manifest.js +1 -1
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/commonjs-loader.js +3 -3
- package/dist/utils/domain-locale.d.ts +2 -2
- package/dist/utils/external-url.d.ts +5 -0
- package/dist/utils/external-url.js +7 -0
- package/dist/utils/mdx-scan.js +1 -1
- package/dist/utils/path.d.ts +1 -13
- package/dist/utils/path.js +1 -15
- package/dist/utils/plugin-options.d.ts +4 -0
- package/dist/utils/plugin-options.js +8 -0
- package/dist/utils/project.d.ts +0 -6
- package/dist/utils/project.js +2 -8
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.js +1 -1
- package/dist/utils/redirect-digest.d.ts +9 -0
- package/dist/utils/redirect-digest.js +25 -0
- package/dist/utils/regex-safety.d.ts +8 -0
- package/dist/utils/regex-safety.js +737 -0
- package/dist/utils/vinext-root.js +1 -1
- package/dist/utils/vite-version.d.ts +5 -2
- package/dist/utils/vite-version.js +43 -17
- package/package.json +16 -4
- /package/dist/build/google-fonts/{fallback-metrics-data.js → fallback-metrics-data.json.js} +0 -0
- /package/dist/build/google-fonts/{font-data.js → font-data.json.js} +0 -0
- /package/dist/{node_modules/.pnpm/process-ancestry@0.1.0/node_modules → deps/.pnpm/process-ancestry@0.1.0/deps}/process-ancestry/dist/index.js +0 -0
|
@@ -39,12 +39,14 @@ type LazyLoadableSlot = {
|
|
|
39
39
|
configLayouts?: readonly unknown[];
|
|
40
40
|
loading?: unknown;
|
|
41
41
|
error?: unknown;
|
|
42
|
+
notFound?: unknown;
|
|
42
43
|
__loadPage?: LazyModuleThunk | null;
|
|
43
44
|
__loadDefault?: LazyModuleThunk | null;
|
|
44
45
|
__loadLayout?: LazyModuleThunk | null;
|
|
45
46
|
__loadConfigLayouts?: LazyModuleLoaderArray | null;
|
|
46
47
|
__loadLoading?: LazyModuleThunk | null;
|
|
47
|
-
__loadError?: LazyModuleThunk | null;
|
|
48
|
+
__loadError?: LazyModuleThunk | null;
|
|
49
|
+
__loadNotFound?: LazyModuleThunk | null; /** Hydrated only after an intercept matches, not with the slot's base modules. */
|
|
48
50
|
intercepts?: LazyLoadableIntercept[];
|
|
49
51
|
};
|
|
50
52
|
type LazyLoadableRoute = {
|
|
@@ -64,6 +64,7 @@ function ensureAppRouteModulesLoaded(route) {
|
|
|
64
64
|
pushArrayLoads(loads, slot.configLayouts, slot.__loadConfigLayouts);
|
|
65
65
|
pushFieldLoad(loads, slot, "loading", slot.__loadLoading);
|
|
66
66
|
pushFieldLoad(loads, slot, "error", slot.__loadError);
|
|
67
|
+
pushFieldLoad(loads, slot, "notFound", slot.__loadNotFound);
|
|
67
68
|
}
|
|
68
69
|
if (loads.length === 0) {
|
|
69
70
|
route.__loaded = true;
|
|
@@ -86,7 +86,7 @@ function modulesByTreePosition(modules, positions) {
|
|
|
86
86
|
async function buildTree(route) {
|
|
87
87
|
const layoutsByPosition = layoutModuleByTreePosition(route);
|
|
88
88
|
const root = createNode("", layoutsByPosition.get(0));
|
|
89
|
-
const nodesByPosition = new Map([[0, root]]);
|
|
89
|
+
const nodesByPosition = /* @__PURE__ */ new Map([[0, root]]);
|
|
90
90
|
let current = root;
|
|
91
91
|
for (const [index, segment] of route.routeSegments.entries()) {
|
|
92
92
|
const position = index + 1;
|
|
@@ -189,7 +189,7 @@ async function resolveInvalidRscCacheBustingRequest(options) {
|
|
|
189
189
|
const actualHash = url.searchParams.get(VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM);
|
|
190
190
|
const expectedHash = await computeRscCacheBustingSearchParam(options.request.headers);
|
|
191
191
|
if (actualHash === null && expectedHash === "" && url.pathname.endsWith(".rsc")) return null;
|
|
192
|
-
const acceptedHashes = new Set([expectedHash]);
|
|
192
|
+
const acceptedHashes = /* @__PURE__ */ new Set([expectedHash]);
|
|
193
193
|
if (actualHash !== null && actualHash !== expectedHash) {
|
|
194
194
|
acceptedHashes.add(computeLegacyRscCacheBustingSearchParam(options.request.headers));
|
|
195
195
|
if (normalizeRenderModeHeaderValue(options.request.headers.get("X-Vinext-Rsc-Render-Mode")) === null) {
|
|
@@ -34,7 +34,7 @@ declare function getDigestForWellKnownError(error: unknown): string | undefined;
|
|
|
34
34
|
* djb2 hash matching Next.js's string-hash package for RSC error digests.
|
|
35
35
|
*/
|
|
36
36
|
declare function errorDigest(input: string): string;
|
|
37
|
-
declare function sanitizeErrorForClient(error: unknown, nodeEnv?:
|
|
37
|
+
declare function sanitizeErrorForClient(error: unknown, nodeEnv?: "development" | "production" | "test"): unknown;
|
|
38
38
|
declare function createRscOnErrorHandler(options: CreateRscOnErrorHandlerOptions): (error: unknown) => string | undefined;
|
|
39
39
|
//#endregion
|
|
40
40
|
export { createRscOnErrorHandler, errorDigest, getDigestForWellKnownError, hasDigest, sanitizeErrorForClient };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
2
2
|
import { resolveAppPageSpecialError } from "./app-page-execution.js";
|
|
3
3
|
//#region src/server/app-rsc-errors.ts
|
|
4
|
+
const ORIGINAL_SERVER_ERROR = Symbol.for("vinext.originalServerError");
|
|
4
5
|
function hasDigest(error) {
|
|
5
6
|
return Boolean(error && typeof error === "object" && "digest" in error);
|
|
6
7
|
}
|
|
@@ -39,7 +40,13 @@ function sanitizeErrorForClient(error, nodeEnv = process.env.NODE_ENV) {
|
|
|
39
40
|
if (resolveAppPageSpecialError(error)) return error;
|
|
40
41
|
if (nodeEnv !== "production") return error;
|
|
41
42
|
const sanitized = /* @__PURE__ */ new Error("An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.");
|
|
42
|
-
sanitized.digest = errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
|
|
43
|
+
sanitized.digest = hasDigest(error) ? String(error.digest) : errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
|
|
44
|
+
Object.defineProperty(sanitized, ORIGINAL_SERVER_ERROR, {
|
|
45
|
+
configurable: false,
|
|
46
|
+
enumerable: false,
|
|
47
|
+
value: error,
|
|
48
|
+
writable: false
|
|
49
|
+
});
|
|
43
50
|
return sanitized;
|
|
44
51
|
}
|
|
45
52
|
function createRscOnErrorHandler(options) {
|
|
@@ -51,7 +58,10 @@ function createRscOnErrorHandler(options) {
|
|
|
51
58
|
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);
|
|
52
59
|
return;
|
|
53
60
|
}
|
|
54
|
-
if (options.requestInfo && options.errorContext && error)
|
|
61
|
+
if (options.requestInfo && options.errorContext && error) {
|
|
62
|
+
const reportableError = typeof error === "object" && ORIGINAL_SERVER_ERROR in error ? Reflect.get(error, ORIGINAL_SERVER_ERROR) : error;
|
|
63
|
+
options.reportRequestError(reportableError instanceof Error ? reportableError : new Error(getThrownValueMessage(reportableError)), options.requestInfo, options.errorContext);
|
|
64
|
+
}
|
|
55
65
|
if (hasDigest(error)) return String(error.digest);
|
|
56
66
|
if (error) {
|
|
57
67
|
const digest = errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { NextHeader, NextI18nConfig, NextRedirect, NextRewrite } from "../config/next-config.js";
|
|
2
2
|
import { ImageConfig } from "./image-optimization.js";
|
|
3
3
|
import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
|
|
4
|
+
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
4
5
|
import { RootParams } from "../shims/root-params.js";
|
|
5
6
|
import { AppMiddlewareContext, ApplyAppMiddlewareResult } from "./app-middleware.js";
|
|
6
|
-
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
7
7
|
import { AppPagePprFallbackCacheShell } from "./app-ppr-fallback-shell.js";
|
|
8
8
|
import { AppPrerenderRootParamNamesMap, AppPrerenderStaticParamsMap } from "./app-prerender-endpoints.js";
|
|
9
9
|
import { AppRouteTreePrefetchRoute, PrefetchInliningConfig } from "./app-route-tree-prefetch.js";
|
|
@@ -48,6 +48,7 @@ type DispatchMatchedPageOptions<TRoute> = {
|
|
|
48
48
|
actionFailed?: boolean;
|
|
49
49
|
handlerStart: number;
|
|
50
50
|
interceptionContext: string | null;
|
|
51
|
+
interceptionPathname: string;
|
|
51
52
|
isProgressiveActionRender: boolean;
|
|
52
53
|
isRscRequest: boolean;
|
|
53
54
|
middlewareContext: AppRscMiddlewareContext;
|
|
@@ -87,12 +88,13 @@ type DispatchMatchedRouteHandlerOptions<TRoute> = {
|
|
|
87
88
|
route: TRoute;
|
|
88
89
|
searchParams: URLSearchParams;
|
|
89
90
|
};
|
|
90
|
-
type HandleProgressiveActionRequestOptions = {
|
|
91
|
+
type HandleProgressiveActionRequestOptions<TRoute> = {
|
|
91
92
|
actionId: string | null;
|
|
92
93
|
cleanPathname: string;
|
|
93
94
|
contentType: string;
|
|
94
95
|
middlewareContext: AppRscMiddlewareContext;
|
|
95
96
|
request: Request;
|
|
97
|
+
routeMatch: AppRscRouteMatch<TRoute> | null;
|
|
96
98
|
};
|
|
97
99
|
/**
|
|
98
100
|
* Side-effect headers captured during a progressive (no-JS) server action's
|
|
@@ -114,7 +116,7 @@ type ProgressiveActionFormStateResult = ({
|
|
|
114
116
|
formState: null;
|
|
115
117
|
kind: "form-state";
|
|
116
118
|
} & ProgressiveActionSideEffects);
|
|
117
|
-
type HandleServerActionRequestOptions = {
|
|
119
|
+
type HandleServerActionRequestOptions<TRoute> = {
|
|
118
120
|
actionId: string | null;
|
|
119
121
|
cleanPathname: string;
|
|
120
122
|
contentType: string;
|
|
@@ -123,6 +125,8 @@ type HandleServerActionRequestOptions = {
|
|
|
123
125
|
middlewareContext: AppRscMiddlewareContext;
|
|
124
126
|
mountedSlotsHeader: string | null;
|
|
125
127
|
request: Request;
|
|
128
|
+
routeMatch: AppRscRouteMatch<TRoute> | null;
|
|
129
|
+
routePathname: string;
|
|
126
130
|
searchParams: URLSearchParams;
|
|
127
131
|
};
|
|
128
132
|
type RenderNotFoundOptions<TRoute> = {
|
|
@@ -183,15 +187,16 @@ type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
|
|
|
183
187
|
* Node server and dev included, not just the Cloudflare worker entry.
|
|
184
188
|
*/
|
|
185
189
|
registerCacheAdapters: (env?: Record<string, unknown>) => void;
|
|
186
|
-
handleProgressiveActionRequest?: (options: HandleProgressiveActionRequestOptions) => Promise<Response | ProgressiveActionFormStateResult | null>;
|
|
190
|
+
handleProgressiveActionRequest?: (options: HandleProgressiveActionRequestOptions<TRoute>) => Promise<Response | ProgressiveActionFormStateResult | null>;
|
|
187
191
|
handleMetadataRouteRequest?: (cleanPathname: string) => Promise<Response | null>;
|
|
188
192
|
createPprFallbackShells?: (route: Pick<AppRscHandlerRoute, "params" | "pattern" | "rootParamNames">, params: AppPageParams) => AppPagePprFallbackCacheShell[];
|
|
189
|
-
handleServerActionRequest?: (options: HandleServerActionRequestOptions) => Promise<Response | null>;
|
|
193
|
+
handleServerActionRequest?: (options: HandleServerActionRequestOptions<TRoute>) => Promise<Response | null>;
|
|
190
194
|
i18nConfig: NextI18nConfig | null;
|
|
191
195
|
imageConfig?: ImageConfig;
|
|
192
196
|
isDev: boolean;
|
|
193
197
|
loadPrerenderPagesRoutes?: () => Promise<unknown>;
|
|
194
198
|
matchRoute: (pathname: string) => AppRscRouteMatch<TRoute> | null;
|
|
199
|
+
matchRequestRoute?: (pathname: string) => AppRscRouteMatch<TRoute> | null;
|
|
195
200
|
runMiddleware?: (options: RunAppMiddlewareOptions) => Promise<ApplyAppMiddlewareResult>;
|
|
196
201
|
publicFiles: ReadonlySet<string>;
|
|
197
202
|
prefetchInlining?: PrefetchInliningConfig;
|
|
@@ -3,9 +3,10 @@ import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base
|
|
|
3
3
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
4
|
import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
|
|
5
5
|
import { ACTION_REVALIDATED_HEADER } from "./headers.js";
|
|
6
|
-
import {
|
|
6
|
+
import { requestContextFromRequest } from "../config/request-context.js";
|
|
7
|
+
import { isExternalUrl } from "../utils/external-url.js";
|
|
7
8
|
import { notFoundResponse } from "./http-error-responses.js";
|
|
8
|
-
import {
|
|
9
|
+
import { cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, normalizeTrailingSlash, resolvePublicFileRoute } from "./request-pipeline.js";
|
|
9
10
|
import { headersContextFromRequest } from "../shims/headers.js";
|
|
10
11
|
import { ensureFetchPatch, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
|
|
11
12
|
import { mergeRewriteQuery } from "../utils/query.js";
|
|
@@ -29,7 +30,10 @@ import { finalizeAppRscResponse } from "./app-rsc-response-finalizer.js";
|
|
|
29
30
|
import { normalizeRscRequest } from "./app-rsc-request-normalization.js";
|
|
30
31
|
import { runWithPrerenderWorkUnit } from "./prerender-work-unit-setup.js";
|
|
31
32
|
//#region src/server/app-rsc-handler.ts
|
|
32
|
-
const STATIC_METADATA_CONFIG_HEADER_OVERRIDES = new Set(["cache-control"]);
|
|
33
|
+
const STATIC_METADATA_CONFIG_HEADER_OVERRIDES = /* @__PURE__ */ new Set(["cache-control"]);
|
|
34
|
+
const HAS_CONFIG_HEADERS = process.env.__VINEXT_HAS_CONFIG_HEADERS !== "false";
|
|
35
|
+
const HAS_CONFIG_REDIRECTS = process.env.__VINEXT_HAS_CONFIG_REDIRECTS !== "false";
|
|
36
|
+
const HAS_CONFIG_REWRITES = process.env.__VINEXT_HAS_CONFIG_REWRITES !== "false";
|
|
33
37
|
function applyMiddlewareContextToResponse(response, middlewareContext) {
|
|
34
38
|
if (!middlewareContext.headers && middlewareContext.status == null) return response;
|
|
35
39
|
const headers = new Headers(response.headers);
|
|
@@ -61,12 +65,14 @@ function redirectDestinationWithBasePath(destination, basePath, hadBasePath) {
|
|
|
61
65
|
return basePath + destination;
|
|
62
66
|
}
|
|
63
67
|
async function applyRewrite(options, cleanPathname) {
|
|
64
|
-
if (!options.rewrites.length) return null;
|
|
65
|
-
const
|
|
68
|
+
if (!HAS_CONFIG_REWRITES || !options.rewrites.length) return null;
|
|
69
|
+
const sourcePathname = options.paramsPathname ?? cleanPathname;
|
|
70
|
+
const configMatchers = await import("../config/config-matchers.js");
|
|
71
|
+
const rewritten = configMatchers.matchRewrite(sourcePathname, options.rewrites, options.requestContext, options.basePathState, options.paramsPathname);
|
|
66
72
|
if (!rewritten) return null;
|
|
67
73
|
if (isExternalUrl(rewritten)) {
|
|
68
74
|
options.clearRequestContext();
|
|
69
|
-
return proxyExternalRequest(options.request, rewritten);
|
|
75
|
+
return configMatchers.proxyExternalRequest(options.request, rewritten);
|
|
70
76
|
}
|
|
71
77
|
return rewritten;
|
|
72
78
|
}
|
|
@@ -81,9 +87,10 @@ function requestContextForResolvedUrl(requestContext, resolvedUrl, baseUrl) {
|
|
|
81
87
|
function pathnameForResolvedUrl(resolvedUrl) {
|
|
82
88
|
return resolvedUrl.split("#", 1)[0].split("?", 1)[0];
|
|
83
89
|
}
|
|
84
|
-
function applyConfigHeadersToMiddlewareRedirect(response, options) {
|
|
90
|
+
async function applyConfigHeadersToMiddlewareRedirect(response, options) {
|
|
85
91
|
if (response.status < 300 || response.status >= 400) return response;
|
|
86
|
-
if (!options.configHeaders.length) return response;
|
|
92
|
+
if (!HAS_CONFIG_HEADERS || !options.configHeaders.length) return response;
|
|
93
|
+
const { applyConfigHeadersToResponse } = await import("./config-headers.js");
|
|
87
94
|
const headers = new Headers();
|
|
88
95
|
applyConfigHeadersToResponse(headers, {
|
|
89
96
|
configHeaders: options.configHeaders,
|
|
@@ -130,6 +137,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
130
137
|
const normalized = normalizeRscRequest(request, options.basePath, canHandleOutsideBasePath);
|
|
131
138
|
if (normalized instanceof Response) return normalized;
|
|
132
139
|
const { url, isRscRequest, interceptionContextHeader, mountedSlotsHeader, renderMode, clientReuseManifest, hadBasePath } = normalized;
|
|
140
|
+
const { requestCleanPathname } = normalized;
|
|
133
141
|
let { pathname, cleanPathname } = normalized;
|
|
134
142
|
let resolvedUrl = cleanPathname + url.search;
|
|
135
143
|
const originalResolvedUrl = resolvedUrl;
|
|
@@ -139,6 +147,8 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
139
147
|
basePath: options.basePath,
|
|
140
148
|
hadBasePath
|
|
141
149
|
};
|
|
150
|
+
let cleanPathnameIsRequestPathname = true;
|
|
151
|
+
const matchCleanPathname = () => cleanPathnameIsRequestPathname && options.matchRequestRoute ? options.matchRequestRoute(requestCleanPathname) : options.matchRoute(cleanPathname);
|
|
142
152
|
if (pathname === "/__vinext/prerender/static-params" || pathname === "/__vinext/prerender/pages-static-paths") {
|
|
143
153
|
const { handleAppPrerenderEndpoint } = await import("./app-prerender-endpoints.js");
|
|
144
154
|
const prerenderEndpointResponse = await handleAppPrerenderEndpoint(request, {
|
|
@@ -152,13 +162,15 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
152
162
|
});
|
|
153
163
|
if (prerenderEndpointResponse) return prerenderEndpointResponse;
|
|
154
164
|
}
|
|
155
|
-
const trailingSlashRedirect = normalizeTrailingSlash(
|
|
165
|
+
const trailingSlashRedirect = normalizeTrailingSlash(requestCleanPathname, hadBasePath ? options.basePath : "", options.trailingSlash, url.search);
|
|
156
166
|
if (trailingSlashRedirect) return trailingSlashRedirect;
|
|
157
167
|
const matchPathname = (p) => normalizeDefaultLocalePathname(p, options.i18nConfig, { hostname: url.hostname });
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
168
|
+
const redirectPathname = matchPathname(requestCleanPathname);
|
|
169
|
+
const configMatchers = HAS_CONFIG_REDIRECTS && options.configRedirects.length ? await import("../config/config-matchers.js") : null;
|
|
170
|
+
const redirect = configMatchers ? configMatchers.matchRedirect(redirectPathname, options.configRedirects, preMiddlewareRequestContext, basePathState) : null;
|
|
171
|
+
if (configMatchers && redirect) {
|
|
172
|
+
const destination = configMatchers.sanitizeDestination(redirectDestinationWithBasePath(redirect.destination, options.basePath, hadBasePath));
|
|
173
|
+
const location = isRscRequest && request.headers.get("RSC") === "1" ? await createRscRedirectLocation(destination, request) : configMatchers.preserveRedirectDestinationQuery(destination, url.search);
|
|
162
174
|
return new Response(null, {
|
|
163
175
|
status: redirect.permanent ? 308 : 307,
|
|
164
176
|
headers: { Location: location }
|
|
@@ -189,11 +201,12 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
189
201
|
if (middlewareResult.kind === "response") return applyConfigHeadersToMiddlewareRedirect(middlewareResult.response, {
|
|
190
202
|
basePathState,
|
|
191
203
|
configHeaders: options.configHeaders,
|
|
192
|
-
pathname: matchPathname(
|
|
204
|
+
pathname: matchPathname(requestCleanPathname),
|
|
193
205
|
requestContext: preMiddlewareRequestContext
|
|
194
206
|
});
|
|
195
207
|
cleanPathname = middlewareResult.cleanPathname;
|
|
196
208
|
didMiddlewareRewrite = middlewareResult.rewritten;
|
|
209
|
+
if (didMiddlewareRewrite || cleanPathname !== normalized.cleanPathname) cleanPathnameIsRequestPathname = false;
|
|
197
210
|
didMiddlewareRewritePathname = cleanPathname !== normalized.cleanPathname;
|
|
198
211
|
if (middlewareResult.search !== null) url.search = middlewareResult.search;
|
|
199
212
|
resolvedUrl = cleanPathname + url.search;
|
|
@@ -214,12 +227,14 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
214
227
|
clearRequestContext: options.clearRequestContext,
|
|
215
228
|
request: normalizedUserlandRequest,
|
|
216
229
|
requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
|
|
230
|
+
paramsPathname: matchPathname(cleanPathnameIsRequestPathname ? requestCleanPathname : cleanPathname),
|
|
217
231
|
rewrites: [rewrite]
|
|
218
232
|
}, matchPathname(cleanPathname));
|
|
219
233
|
if (beforeFilesRewrite instanceof Response) return beforeFilesRewrite;
|
|
220
234
|
if (beforeFilesRewrite) {
|
|
221
235
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, beforeFilesRewrite);
|
|
222
236
|
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
237
|
+
cleanPathnameIsRequestPathname = false;
|
|
223
238
|
filesystemRouteEligible = true;
|
|
224
239
|
}
|
|
225
240
|
}
|
|
@@ -238,14 +253,16 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
238
253
|
clearRequestContext: options.clearRequestContext,
|
|
239
254
|
request: normalizedUserlandRequest,
|
|
240
255
|
requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
|
|
256
|
+
paramsPathname: matchPathname(cleanPathnameIsRequestPathname ? requestCleanPathname : cleanPathname),
|
|
241
257
|
rewrites: [rewrite]
|
|
242
258
|
}, matchPathname(cleanPathname));
|
|
243
259
|
if (rewritten instanceof Response) return rewritten;
|
|
244
260
|
if (!rewritten) continue;
|
|
245
261
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
246
262
|
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
263
|
+
cleanPathnameIsRequestPathname = false;
|
|
247
264
|
filesystemRouteEligible = true;
|
|
248
|
-
actionMatch =
|
|
265
|
+
actionMatch = matchCleanPathname();
|
|
249
266
|
if (actionMatch) break;
|
|
250
267
|
}
|
|
251
268
|
if (!actionMatch) for (const rewrite of options.configRewrites.fallback) {
|
|
@@ -254,14 +271,16 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
254
271
|
clearRequestContext: options.clearRequestContext,
|
|
255
272
|
request: normalizedUserlandRequest,
|
|
256
273
|
requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
|
|
274
|
+
paramsPathname: matchPathname(cleanPathnameIsRequestPathname ? requestCleanPathname : cleanPathname),
|
|
257
275
|
rewrites: [rewrite]
|
|
258
276
|
}, matchPathname(cleanPathname));
|
|
259
277
|
if (rewritten instanceof Response) return rewritten;
|
|
260
278
|
if (!rewritten) continue;
|
|
261
279
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
262
280
|
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
281
|
+
cleanPathnameIsRequestPathname = false;
|
|
263
282
|
filesystemRouteEligible = true;
|
|
264
|
-
actionMatch =
|
|
283
|
+
actionMatch = matchCleanPathname();
|
|
265
284
|
if (actionMatch) break;
|
|
266
285
|
}
|
|
267
286
|
resolvedLateRewritesForAction = filesystemRouteEligible;
|
|
@@ -275,16 +294,17 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
275
294
|
}
|
|
276
295
|
if (filesystemRouteEligible && options.handleMetadataRouteRequest) {
|
|
277
296
|
const metadataRouteResponse = await options.handleMetadataRouteRequest(cleanPathname);
|
|
278
|
-
if (metadataRouteResponse) {
|
|
297
|
+
if (metadataRouteResponse && HAS_CONFIG_HEADERS && options.configHeaders.length) {
|
|
298
|
+
const { applyConfigHeadersToResponse } = await import("./config-headers.js");
|
|
279
299
|
applyConfigHeadersToResponse(metadataRouteResponse.headers, {
|
|
280
300
|
basePathState,
|
|
281
301
|
configHeaders: options.configHeaders,
|
|
282
302
|
overwriteExisting: STATIC_METADATA_CONFIG_HEADER_OVERRIDES,
|
|
283
|
-
pathname: matchPathname(cleanPathname),
|
|
303
|
+
pathname: matchPathname(cleanPathnameIsRequestPathname ? requestCleanPathname : cleanPathname),
|
|
284
304
|
requestContext: preMiddlewareRequestContext
|
|
285
305
|
});
|
|
286
|
-
return applyMiddlewareContextToResponse(metadataRouteResponse, middlewareContext);
|
|
287
306
|
}
|
|
307
|
+
if (metadataRouteResponse) return applyMiddlewareContextToResponse(metadataRouteResponse, middlewareContext);
|
|
288
308
|
}
|
|
289
309
|
const publicFileResponse = filesystemRouteEligible ? resolvePublicFileRoute({
|
|
290
310
|
cleanPathname,
|
|
@@ -306,7 +326,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
306
326
|
searchParams: getResolvedSearchParams(),
|
|
307
327
|
params: {}
|
|
308
328
|
});
|
|
309
|
-
const preActionMatch = filesystemRouteEligible ?
|
|
329
|
+
const preActionMatch = filesystemRouteEligible ? matchCleanPathname() : null;
|
|
310
330
|
if (preActionMatch) setRootParams(pickRootParams(preActionMatch.params, preActionMatch.route.rootParamNames));
|
|
311
331
|
if (pagesDataRequest && didMiddlewareRewritePathname && preActionMatch) {
|
|
312
332
|
const headers = new Headers();
|
|
@@ -327,7 +347,8 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
327
347
|
cleanPathname,
|
|
328
348
|
contentType,
|
|
329
349
|
middlewareContext,
|
|
330
|
-
request
|
|
350
|
+
request,
|
|
351
|
+
routeMatch: preActionMatch
|
|
331
352
|
});
|
|
332
353
|
else if (preActionMatch?.route.__loadPage && !preActionMatch.route.__loadRouteHandler) return createMissingServerActionResponse(options, null);
|
|
333
354
|
}
|
|
@@ -351,6 +372,8 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
351
372
|
middlewareContext,
|
|
352
373
|
mountedSlotsHeader,
|
|
353
374
|
request,
|
|
375
|
+
routeMatch: preActionMatch,
|
|
376
|
+
routePathname: cleanPathnameIsRequestPathname ? requestCleanPathname : cleanPathname,
|
|
354
377
|
searchParams: getResolvedSearchParams()
|
|
355
378
|
}) : null;
|
|
356
379
|
if (serverActionResponse) return serverActionResponse;
|
|
@@ -390,16 +413,18 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
390
413
|
clearRequestContext: options.clearRequestContext,
|
|
391
414
|
request: normalizedUserlandRequest,
|
|
392
415
|
requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
|
|
416
|
+
paramsPathname: matchPathname(cleanPathnameIsRequestPathname ? requestCleanPathname : cleanPathname),
|
|
393
417
|
rewrites: [rewrite]
|
|
394
418
|
}, matchPathname(cleanPathname));
|
|
395
419
|
if (afterFilesRewrite instanceof Response) return afterFilesRewrite;
|
|
396
420
|
if (!afterFilesRewrite) continue;
|
|
397
421
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, afterFilesRewrite);
|
|
398
422
|
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
423
|
+
cleanPathnameIsRequestPathname = false;
|
|
399
424
|
filesystemRouteEligible = true;
|
|
400
425
|
const claimedRscCacheBustingRedirect = await validateClaimedOutsideBasePathRsc();
|
|
401
426
|
if (claimedRscCacheBustingRedirect) return claimedRscCacheBustingRedirect;
|
|
402
|
-
match =
|
|
427
|
+
match = matchCleanPathname();
|
|
403
428
|
const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
|
|
404
429
|
if (rewrittenStaticPagesResponse) {
|
|
405
430
|
options.clearRequestContext();
|
|
@@ -423,16 +448,18 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
423
448
|
clearRequestContext: options.clearRequestContext,
|
|
424
449
|
request: normalizedUserlandRequest,
|
|
425
450
|
requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
|
|
451
|
+
paramsPathname: matchPathname(cleanPathnameIsRequestPathname ? requestCleanPathname : cleanPathname),
|
|
426
452
|
rewrites: [rewrite]
|
|
427
453
|
}, matchPathname(cleanPathname));
|
|
428
454
|
if (fallbackRewrite instanceof Response) return fallbackRewrite;
|
|
429
455
|
if (!fallbackRewrite) continue;
|
|
430
456
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
|
|
431
457
|
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
458
|
+
cleanPathnameIsRequestPathname = false;
|
|
432
459
|
filesystemRouteEligible = true;
|
|
433
460
|
const claimedRscCacheBustingRedirect = await validateClaimedOutsideBasePathRsc();
|
|
434
461
|
if (claimedRscCacheBustingRedirect) return claimedRscCacheBustingRedirect;
|
|
435
|
-
match =
|
|
462
|
+
match = matchCleanPathname();
|
|
436
463
|
const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
|
|
437
464
|
if (rewrittenStaticPagesResponse) {
|
|
438
465
|
options.clearRequestContext();
|
|
@@ -536,6 +563,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
536
563
|
actionFailed,
|
|
537
564
|
handlerStart,
|
|
538
565
|
interceptionContext: interceptionContextHeader,
|
|
566
|
+
interceptionPathname: cleanPathnameIsRequestPathname ? requestCleanPathname : cleanPathname,
|
|
539
567
|
isProgressiveActionRender,
|
|
540
568
|
isRscRequest,
|
|
541
569
|
middlewareContext,
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/server/app-rsc-redirect-flight.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Encoding of a `redirect()` for RSC transport: the canonical
|
|
6
|
+
* `NEXT_REDIRECT;<type>;<url>;<status>;` digest and the flight payload that
|
|
7
|
+
* carries it. Kept in one module so the digest format and the stream that
|
|
8
|
+
* serializes it have a single owner; `buildAppPageSpecialErrorResponse` and the
|
|
9
|
+
* boundary/dispatch special-error paths all depend on this contract.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Builds the canonical `NEXT_REDIRECT;<type>;<url>;<status>;` digest that
|
|
13
|
+
* Next.js encodes on `redirect()` / `permanentRedirect()` throws. Used when we
|
|
14
|
+
* synthesize a flight payload for an RSC navigation: the digest must round-trip
|
|
15
|
+
* through the client's `RedirectErrorBoundary` so the same
|
|
16
|
+
* `getURLFromRedirectError` / `getRedirectTypeFromError` helpers decode it.
|
|
17
|
+
*
|
|
18
|
+
* The URL is included verbatim, not encoded — Next.js's `getRedirectError`
|
|
19
|
+
* sets `digest = ${CODE};${type};${url};${status};` with the raw URL, and the
|
|
20
|
+
* client decodes via `error.digest.split(';').slice(2, -2).join(';')`. We
|
|
21
|
+
* default `type=replace` because `redirect()` is replace-style outside of
|
|
22
|
+
* server actions, matching Next.js's `getRedirectError` default.
|
|
23
|
+
*
|
|
24
|
+
* Reference:
|
|
25
|
+
* `.nextjs-ref/packages/next/src/client/components/redirect.ts:20-23`
|
|
26
|
+
* `.nextjs-ref/packages/next/src/client/components/redirect-error.ts`
|
|
27
|
+
*/
|
|
28
|
+
declare function formatNextRedirectDigest(options: {
|
|
29
|
+
type: "push" | "replace";
|
|
30
|
+
url: string;
|
|
31
|
+
statusCode: number;
|
|
32
|
+
}): string;
|
|
33
|
+
/**
|
|
34
|
+
* The subset of `renderToReadableStream` the redirect-flight encoding needs.
|
|
35
|
+
* Both the boundary and dispatch special-error paths hand in their own
|
|
36
|
+
* environment-specific renderer, which accepts a wider element type; a plain
|
|
37
|
+
* throwing React element satisfies all of them.
|
|
38
|
+
*/
|
|
39
|
+
type RedirectFlightStreamRenderer = (element: ReactNode, options: {
|
|
40
|
+
onError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
|
|
41
|
+
}) => ReadableStream<Uint8Array>;
|
|
42
|
+
/**
|
|
43
|
+
* Builds an RSC flight payload that encodes a `redirect()` as a React error
|
|
44
|
+
* carrying the canonical `NEXT_REDIRECT;<type>;<url>;<status>;` digest. We
|
|
45
|
+
* render a tiny element that throws immediately; `renderToReadableStream`'s
|
|
46
|
+
* `onError` returns the digest, react-server-dom-webpack serializes the error
|
|
47
|
+
* into the stream, and the client's `RedirectErrorBoundary` decodes it via
|
|
48
|
+
* `getURLFromRedirectError` / `getRedirectTypeFromError`. The HTTP response
|
|
49
|
+
* stays 200 because the redirect rides in the flight body, not the status line.
|
|
50
|
+
*
|
|
51
|
+
* Mirrors Next.js's `generateDynamicFlightRenderResult` in `app-render.tsx`,
|
|
52
|
+
* where a redirect thrown during RSC rendering propagates through
|
|
53
|
+
* `renderToFlightStream`'s `onError` into the flight payload.
|
|
54
|
+
*
|
|
55
|
+
* This is the single owner of the redirect-flight encoding: the matched
|
|
56
|
+
* dispatch paths (`renderLayoutSpecialError` / `renderPageSpecialError`) and the
|
|
57
|
+
* route-miss boundary path (`renderBoundarySpecialErrorResponse`) both call it
|
|
58
|
+
* through the `buildRscRedirectFlightStream` option of
|
|
59
|
+
* `buildAppPageSpecialErrorResponse`.
|
|
60
|
+
*/
|
|
61
|
+
declare function buildRscRedirectFlightStream(options: {
|
|
62
|
+
renderToReadableStream: RedirectFlightStreamRenderer;
|
|
63
|
+
digest: string;
|
|
64
|
+
}): ReadableStream<Uint8Array>;
|
|
65
|
+
//#endregion
|
|
66
|
+
export { RedirectFlightStreamRenderer, buildRscRedirectFlightStream, formatNextRedirectDigest };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createElement } from "react";
|
|
2
|
+
//#region src/server/app-rsc-redirect-flight.ts
|
|
3
|
+
/**
|
|
4
|
+
* Encoding of a `redirect()` for RSC transport: the canonical
|
|
5
|
+
* `NEXT_REDIRECT;<type>;<url>;<status>;` digest and the flight payload that
|
|
6
|
+
* carries it. Kept in one module so the digest format and the stream that
|
|
7
|
+
* serializes it have a single owner; `buildAppPageSpecialErrorResponse` and the
|
|
8
|
+
* boundary/dispatch special-error paths all depend on this contract.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Builds the canonical `NEXT_REDIRECT;<type>;<url>;<status>;` digest that
|
|
12
|
+
* Next.js encodes on `redirect()` / `permanentRedirect()` throws. Used when we
|
|
13
|
+
* synthesize a flight payload for an RSC navigation: the digest must round-trip
|
|
14
|
+
* through the client's `RedirectErrorBoundary` so the same
|
|
15
|
+
* `getURLFromRedirectError` / `getRedirectTypeFromError` helpers decode it.
|
|
16
|
+
*
|
|
17
|
+
* The URL is included verbatim, not encoded — Next.js's `getRedirectError`
|
|
18
|
+
* sets `digest = ${CODE};${type};${url};${status};` with the raw URL, and the
|
|
19
|
+
* client decodes via `error.digest.split(';').slice(2, -2).join(';')`. We
|
|
20
|
+
* default `type=replace` because `redirect()` is replace-style outside of
|
|
21
|
+
* server actions, matching Next.js's `getRedirectError` default.
|
|
22
|
+
*
|
|
23
|
+
* Reference:
|
|
24
|
+
* `.nextjs-ref/packages/next/src/client/components/redirect.ts:20-23`
|
|
25
|
+
* `.nextjs-ref/packages/next/src/client/components/redirect-error.ts`
|
|
26
|
+
*/
|
|
27
|
+
function formatNextRedirectDigest(options) {
|
|
28
|
+
return `NEXT_REDIRECT;${options.type};${options.url};${options.statusCode};`;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Error thrown by the redirect-flight renderer below. Its `digest` is the
|
|
32
|
+
* canonical `NEXT_REDIRECT;...` string that react-server-dom's `onError`
|
|
33
|
+
* reports so the client's `RedirectErrorBoundary` can decode it. A named
|
|
34
|
+
* subclass keeps `digest` a real field rather than an `as`-cast on a plain
|
|
35
|
+
* `Error`.
|
|
36
|
+
*/
|
|
37
|
+
var RscRedirectFlightError = class extends Error {
|
|
38
|
+
digest;
|
|
39
|
+
constructor(digest) {
|
|
40
|
+
super("NEXT_REDIRECT");
|
|
41
|
+
this.digest = digest;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Builds an RSC flight payload that encodes a `redirect()` as a React error
|
|
46
|
+
* carrying the canonical `NEXT_REDIRECT;<type>;<url>;<status>;` digest. We
|
|
47
|
+
* render a tiny element that throws immediately; `renderToReadableStream`'s
|
|
48
|
+
* `onError` returns the digest, react-server-dom-webpack serializes the error
|
|
49
|
+
* into the stream, and the client's `RedirectErrorBoundary` decodes it via
|
|
50
|
+
* `getURLFromRedirectError` / `getRedirectTypeFromError`. The HTTP response
|
|
51
|
+
* stays 200 because the redirect rides in the flight body, not the status line.
|
|
52
|
+
*
|
|
53
|
+
* Mirrors Next.js's `generateDynamicFlightRenderResult` in `app-render.tsx`,
|
|
54
|
+
* where a redirect thrown during RSC rendering propagates through
|
|
55
|
+
* `renderToFlightStream`'s `onError` into the flight payload.
|
|
56
|
+
*
|
|
57
|
+
* This is the single owner of the redirect-flight encoding: the matched
|
|
58
|
+
* dispatch paths (`renderLayoutSpecialError` / `renderPageSpecialError`) and the
|
|
59
|
+
* route-miss boundary path (`renderBoundarySpecialErrorResponse`) both call it
|
|
60
|
+
* through the `buildRscRedirectFlightStream` option of
|
|
61
|
+
* `buildAppPageSpecialErrorResponse`.
|
|
62
|
+
*/
|
|
63
|
+
function buildRscRedirectFlightStream(options) {
|
|
64
|
+
const { digest } = options;
|
|
65
|
+
const throwingElement = createElement(function NextRedirectFlightThrower() {
|
|
66
|
+
throw new RscRedirectFlightError(digest);
|
|
67
|
+
});
|
|
68
|
+
return options.renderToReadableStream(throwingElement, { onError: () => digest });
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { buildRscRedirectFlightStream, formatNextRedirectDigest };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
|
|
2
|
-
import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
3
2
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
3
|
+
import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
4
4
|
|
|
5
5
|
//#region src/server/app-rsc-request-normalization.d.ts
|
|
6
6
|
type NormalizedRscRequest = {
|
|
7
7
|
/** Parsed URL. Callers may mutate `url.search` after middleware runs. */url: URL; /** Normalized pathname with basePath stripped. Used for all internal routing. */
|
|
8
8
|
pathname: string; /** Pathname with `.rsc` suffix removed. Used for route matching and navigation context. */
|
|
9
|
-
cleanPathname: string; /**
|
|
9
|
+
cleanPathname: string; /** Original encoded request pathname with basePath and `.rsc` removed. */
|
|
10
|
+
requestCleanPathname: string; /** True when the request targets a canonical `.rsc` payload URL. */
|
|
10
11
|
isRscRequest: boolean; /** Sanitized X-Vinext-Interception-Context header (null bytes stripped). null when absent. */
|
|
11
12
|
interceptionContextHeader: string | null; /** Normalized x-vinext-mounted-slots header (deduplicated, sorted). null when absent or blank. */
|
|
12
13
|
mountedSlotsHeader: string | null; /** Semantic RSC payload mode. HTML requests always normalize to "navigation". */
|
|
@@ -50,14 +50,19 @@ function normalizeRscRequest(request, basePath, allowOutsideBasePath = false) {
|
|
|
50
50
|
return badRequestResponse();
|
|
51
51
|
}
|
|
52
52
|
let pathname = normalizePath(decoded);
|
|
53
|
+
let requestPathname = url.pathname;
|
|
53
54
|
let hadBasePath = true;
|
|
54
55
|
if (basePath) {
|
|
55
|
-
hadBasePath = hasBasePath(
|
|
56
|
+
hadBasePath = hasBasePath(requestPathname, basePath);
|
|
56
57
|
if (!hadBasePath && !pathname.startsWith("/__vinext/") && !allowOutsideBasePath) return notFoundResponse();
|
|
57
|
-
if (hadBasePath)
|
|
58
|
+
if (hadBasePath) {
|
|
59
|
+
pathname = stripBasePath(pathname, basePath);
|
|
60
|
+
requestPathname = stripBasePath(requestPathname, basePath);
|
|
61
|
+
}
|
|
58
62
|
}
|
|
59
63
|
const isRscRequest = pathname.endsWith(".rsc") || request.headers.get("RSC") === "1";
|
|
60
64
|
const cleanPathname = stripRscSuffix(pathname);
|
|
65
|
+
const requestCleanPathname = stripRscSuffix(requestPathname);
|
|
61
66
|
const interceptionContextHeader = normalizeInterceptionContextHeader(request.headers.get(VINEXT_INTERCEPTION_CONTEXT_HEADER));
|
|
62
67
|
const mountedSlotsHeader = normalizeMountedSlotsHeader(request.headers.get(VINEXT_MOUNTED_SLOTS_HEADER));
|
|
63
68
|
const renderMode = isRscRequest ? parseAppRscRenderMode(request.headers.get(VINEXT_RSC_RENDER_MODE_HEADER)) : APP_RSC_RENDER_MODE_NAVIGATION;
|
|
@@ -67,6 +72,7 @@ function normalizeRscRequest(request, basePath, allowOutsideBasePath = false) {
|
|
|
67
72
|
url,
|
|
68
73
|
pathname,
|
|
69
74
|
cleanPathname,
|
|
75
|
+
requestCleanPathname,
|
|
70
76
|
isRscRequest,
|
|
71
77
|
interceptionContextHeader,
|
|
72
78
|
mountedSlotsHeader,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextHeader, NextI18nConfig } from "../config/next-config.js";
|
|
2
|
-
import { RequestContext } from "../config/
|
|
2
|
+
import { RequestContext } from "../config/request-context.js";
|
|
3
3
|
|
|
4
4
|
//#region src/server/app-rsc-response-finalizer.d.ts
|
|
5
5
|
type FinalizeAppRscResponseOptions = {
|
|
@@ -32,6 +32,6 @@ type FinalizeAppRscResponseOptions = {
|
|
|
32
32
|
* headers that throw on mutation, and Next.js does not apply config headers
|
|
33
33
|
* to redirects regardless.
|
|
34
34
|
*/
|
|
35
|
-
declare function finalizeAppRscResponse(response: Response, request: Request, options: FinalizeAppRscResponseOptions): Response
|
|
35
|
+
declare function finalizeAppRscResponse(response: Response, request: Request, options: FinalizeAppRscResponseOptions): Promise<Response>;
|
|
36
36
|
//#endregion
|
|
37
37
|
export { finalizeAppRscResponse };
|