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
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
2
1
|
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
3
2
|
import "./headers.js";
|
|
4
|
-
import { normalizePath } from "./normalize-path.js";
|
|
5
|
-
import { applyConfigHeadersToResponse } from "./request-pipeline.js";
|
|
6
3
|
import { applyCdnResponseHeaders } from "./cache-control.js";
|
|
7
4
|
import { normalizeDefaultLocalePathname } from "./pages-i18n.js";
|
|
8
5
|
import { VINEXT_RSC_VARY_HEADER } from "./app-rsc-cache-busting.js";
|
|
9
6
|
import { mergeVaryHeader } from "./middleware-response-headers.js";
|
|
10
7
|
//#region src/server/app-rsc-response-finalizer.ts
|
|
8
|
+
const HAS_CONFIG_HEADERS = process.env.__VINEXT_HAS_CONFIG_HEADERS !== "false";
|
|
11
9
|
/**
|
|
12
10
|
* Apply App Router response finalization that must happen outside individual
|
|
13
11
|
* route dispatchers.
|
|
@@ -20,7 +18,7 @@ import { mergeVaryHeader } from "./middleware-response-headers.js";
|
|
|
20
18
|
* headers that throw on mutation, and Next.js does not apply config headers
|
|
21
19
|
* to redirects regardless.
|
|
22
20
|
*/
|
|
23
|
-
function finalizeAppRscResponse(response, request, options) {
|
|
21
|
+
async function finalizeAppRscResponse(response, request, options) {
|
|
24
22
|
if (response.status >= 300 && response.status < 400) return response;
|
|
25
23
|
if (!response.headers.has("x-vinext-static-file")) {
|
|
26
24
|
const varyHeader = response.headers.get("Vary");
|
|
@@ -28,17 +26,13 @@ function finalizeAppRscResponse(response, request, options) {
|
|
|
28
26
|
else if (varyHeader !== VINEXT_RSC_VARY_HEADER) mergeVaryHeader(response.headers, VINEXT_RSC_VARY_HEADER);
|
|
29
27
|
}
|
|
30
28
|
if (!response.headers.has("Cache-Control")) applyCdnResponseHeaders(response.headers, { cacheControl: "" });
|
|
31
|
-
if (!options.configHeaders.length) return response;
|
|
29
|
+
if (!HAS_CONFIG_HEADERS || !options.configHeaders.length) return response;
|
|
32
30
|
const url = new URL(request.url);
|
|
33
|
-
let pathname;
|
|
34
|
-
try {
|
|
35
|
-
pathname = normalizePath(normalizePathnameForRouteMatch(url.pathname));
|
|
36
|
-
} catch {
|
|
37
|
-
pathname = url.pathname;
|
|
38
|
-
}
|
|
31
|
+
let pathname = url.pathname;
|
|
39
32
|
const hadBasePath = !options.basePath || hasBasePath(pathname, options.basePath);
|
|
40
33
|
pathname = stripBasePath(pathname, options.basePath);
|
|
41
34
|
const matchPathname = options.i18nConfig ? normalizeDefaultLocalePathname(pathname, options.i18nConfig, { hostname: url.hostname }) : pathname;
|
|
35
|
+
const { applyConfigHeadersToResponse } = await import("./config-headers.js");
|
|
42
36
|
applyConfigHeadersToResponse(response.headers, {
|
|
43
37
|
configHeaders: options.configHeaders,
|
|
44
38
|
pathname: matchPathname,
|
|
@@ -33,9 +33,13 @@ type AppRscInterceptForMatching = {
|
|
|
33
33
|
interceptLayouts: readonly unknown[];
|
|
34
34
|
interceptLayoutSegments?: readonly (readonly string[])[];
|
|
35
35
|
interceptBranchSegments?: readonly string[];
|
|
36
|
+
interceptNotFoundBranchSegments?: readonly string[];
|
|
36
37
|
__loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
|
|
37
38
|
page: unknown;
|
|
38
39
|
__pageLoader?: (() => Promise<unknown>) | null;
|
|
40
|
+
notFound?: unknown;
|
|
41
|
+
__loadNotFound?: (() => Promise<unknown>) | null;
|
|
42
|
+
notFoundTreePosition?: number | null;
|
|
39
43
|
params: readonly string[];
|
|
40
44
|
};
|
|
41
45
|
type AppRscSlotForMatching = {
|
|
@@ -50,14 +54,20 @@ type AppRscSiblingInterceptForMatching = {
|
|
|
50
54
|
interceptLayouts: readonly unknown[];
|
|
51
55
|
interceptLayoutSegments?: readonly (readonly string[])[];
|
|
52
56
|
interceptBranchSegments?: readonly string[];
|
|
57
|
+
interceptNotFoundBranchSegments?: readonly string[];
|
|
53
58
|
__loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
|
|
54
59
|
page: unknown;
|
|
55
60
|
__pageLoader?: (() => Promise<unknown>) | null;
|
|
61
|
+
notFound?: unknown;
|
|
62
|
+
__loadNotFound?: (() => Promise<unknown>) | null;
|
|
63
|
+
notFoundTreePosition?: number | null;
|
|
56
64
|
params: readonly string[];
|
|
57
65
|
};
|
|
58
66
|
type AppRscRouteForMatching = {
|
|
67
|
+
__loadRouteHandler?: unknown;
|
|
59
68
|
pattern: string;
|
|
60
69
|
patternParts: string[];
|
|
70
|
+
routeHandler?: unknown;
|
|
61
71
|
slots?: Record<string, AppRscSlotForMatching>;
|
|
62
72
|
siblingIntercepts?: AppRscSiblingInterceptForMatching[];
|
|
63
73
|
};
|
|
@@ -68,6 +78,8 @@ type AppRscInterceptMatch = AppRscInterceptLookupEntry & {
|
|
|
68
78
|
type AppRscInterceptLoadState = {
|
|
69
79
|
page: unknown;
|
|
70
80
|
pageLoading: Promise<unknown> | null;
|
|
81
|
+
notFound: unknown;
|
|
82
|
+
notFoundLoading: Promise<unknown> | null;
|
|
71
83
|
interceptLayoutsLoading: Promise<readonly unknown[]> | null;
|
|
72
84
|
};
|
|
73
85
|
type AppRscInterceptLookupEntry = {
|
|
@@ -81,9 +93,13 @@ type AppRscInterceptLookupEntry = {
|
|
|
81
93
|
interceptLayouts: readonly unknown[];
|
|
82
94
|
interceptLayoutSegments?: readonly (readonly string[])[];
|
|
83
95
|
interceptBranchSegments?: readonly string[];
|
|
96
|
+
interceptNotFoundBranchSegments?: readonly string[];
|
|
84
97
|
__loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
|
|
85
98
|
page: unknown;
|
|
86
99
|
__pageLoader?: (() => Promise<unknown>) | null;
|
|
100
|
+
notFound: unknown;
|
|
101
|
+
__loadNotFound?: (() => Promise<unknown>) | null;
|
|
102
|
+
notFoundTreePosition?: number | null;
|
|
87
103
|
__loadState: AppRscInterceptLoadState;
|
|
88
104
|
params: readonly string[];
|
|
89
105
|
slotId: string | null;
|
|
@@ -93,6 +109,10 @@ declare function createAppRscRouteMatcher<Route extends AppRscRouteForMatching>(
|
|
|
93
109
|
route: Route;
|
|
94
110
|
params: AppRscRouteParams;
|
|
95
111
|
} | null;
|
|
112
|
+
matchRequestRoute(url: string): {
|
|
113
|
+
route: Route;
|
|
114
|
+
params: AppRscRouteParams;
|
|
115
|
+
} | null;
|
|
96
116
|
findIntercept(pathname: string, sourcePathname?: string | null): AppRscInterceptMatch | null;
|
|
97
117
|
};
|
|
98
118
|
declare function matchAppRscRoutePattern(urlParts: string[], patternParts: string[]): AppRscRouteParams | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { splitPathnameForRouteMatch } from "../routing/utils.js";
|
|
2
|
-
import { buildRouteTrie,
|
|
3
|
-
import { matchRoutePattern, matchRoutePatternPrefix } from "../routing/route-pattern.js";
|
|
1
|
+
import { decodeMatchedParams, splitPathSegments, splitPathnameForRouteMatch } from "../routing/utils.js";
|
|
2
|
+
import { buildRouteTrie, trieMatchRaw } from "../routing/route-trie.js";
|
|
3
|
+
import { matchRoutePattern, matchRoutePatternPrefix, matchRoutePatternRaw } from "../routing/route-pattern.js";
|
|
4
4
|
//#region src/server/app-rsc-route-matching.ts
|
|
5
5
|
/**
|
|
6
6
|
* Sentinel slot key used for sibling-style interception entries.
|
|
@@ -11,9 +11,61 @@ const SIBLING_PAGE_INTERCEPT_SLOT_KEY = "__vinext_page_intercept";
|
|
|
11
11
|
function createRouteParams() {
|
|
12
12
|
return Object.create(null);
|
|
13
13
|
}
|
|
14
|
-
function appRscPathnameParts(pathname) {
|
|
14
|
+
function appRscPathnameParts(pathname, isNormalized = false) {
|
|
15
15
|
const pathOnly = pathname.split("?")[0];
|
|
16
|
-
|
|
16
|
+
const normalizedPathname = pathOnly === "/" ? "/" : pathOnly.replace(/\/$/, "");
|
|
17
|
+
return isNormalized ? splitPathSegments(normalizedPathname) : splitPathnameForRouteMatch(normalizedPathname);
|
|
18
|
+
}
|
|
19
|
+
function appRscInterceptionSourcePathnameParts(pathname) {
|
|
20
|
+
const pathOnly = pathname.split("?")[0];
|
|
21
|
+
return splitPathSegments(pathOnly === "/" ? "/" : pathOnly.replace(/\/$/, "")).map((segment) => {
|
|
22
|
+
try {
|
|
23
|
+
return decodeURIComponent(segment);
|
|
24
|
+
} catch {
|
|
25
|
+
return segment;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function canonicalizeAppPageParam(value) {
|
|
30
|
+
try {
|
|
31
|
+
return encodeURIComponent(decodeURIComponent(value));
|
|
32
|
+
} catch {
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function canonicalizeAppPageParams(params) {
|
|
37
|
+
for (const key of Object.keys(params)) {
|
|
38
|
+
const value = params[key];
|
|
39
|
+
params[key] = Array.isArray(value) ? value.map(canonicalizeAppPageParam) : canonicalizeAppPageParam(value);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function isAppRouteHandlerRoute(route) {
|
|
43
|
+
return route.routeHandler != null || typeof route.__loadRouteHandler === "function";
|
|
44
|
+
}
|
|
45
|
+
function normalizeMatchedParamsForRoute(result) {
|
|
46
|
+
if (isAppRouteHandlerRoute(result.route)) decodeMatchedParams(result.params);
|
|
47
|
+
else canonicalizeAppPageParams(result.params);
|
|
48
|
+
}
|
|
49
|
+
function extractRawParamsForMatchedRoute(patternParts, pathnameParts) {
|
|
50
|
+
const params = createRouteParams();
|
|
51
|
+
let pathnameIndex = 0;
|
|
52
|
+
for (const part of patternParts) {
|
|
53
|
+
if (!part.startsWith(":")) {
|
|
54
|
+
pathnameIndex += 1;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const isCatchAll = part.endsWith("+") || part.endsWith("*");
|
|
58
|
+
const paramName = part.slice(1, isCatchAll ? -1 : void 0);
|
|
59
|
+
if (isCatchAll) {
|
|
60
|
+
const remaining = pathnameParts.slice(pathnameIndex);
|
|
61
|
+
if (remaining.length > 0) params[paramName] = [...remaining];
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
const value = pathnameParts[pathnameIndex];
|
|
65
|
+
if (value !== void 0) params[paramName] = value;
|
|
66
|
+
pathnameIndex += 1;
|
|
67
|
+
}
|
|
68
|
+
return params;
|
|
17
69
|
}
|
|
18
70
|
function createAppRscRouteMatcher(routes) {
|
|
19
71
|
const routeTrie = buildRouteTrie(routes);
|
|
@@ -21,20 +73,32 @@ function createAppRscRouteMatcher(routes) {
|
|
|
21
73
|
const routeIndexes = new Map(routes.map((route, index) => [route, index]));
|
|
22
74
|
return {
|
|
23
75
|
matchRoute(url) {
|
|
24
|
-
|
|
76
|
+
const rawParts = appRscPathnameParts(url, true);
|
|
77
|
+
const result = trieMatchRaw(routeTrie, appRscPathnameParts(url, false));
|
|
78
|
+
if (!result) return null;
|
|
79
|
+
result.params = extractRawParamsForMatchedRoute(result.route.patternParts, rawParts);
|
|
80
|
+
normalizeMatchedParamsForRoute(result);
|
|
81
|
+
return result;
|
|
82
|
+
},
|
|
83
|
+
matchRequestRoute(url) {
|
|
84
|
+
const result = trieMatchRaw(routeTrie, appRscPathnameParts(url, true));
|
|
85
|
+
if (!result) return null;
|
|
86
|
+
normalizeMatchedParamsForRoute(result);
|
|
87
|
+
return result;
|
|
25
88
|
},
|
|
26
89
|
findIntercept(pathname, sourcePathname = null) {
|
|
27
90
|
if (sourcePathname === null) return null;
|
|
28
|
-
const urlParts = appRscPathnameParts(pathname);
|
|
29
|
-
const sourceParts =
|
|
30
|
-
const matchedSourceRoute =
|
|
91
|
+
const urlParts = appRscPathnameParts(pathname, true);
|
|
92
|
+
const sourceParts = appRscInterceptionSourcePathnameParts(sourcePathname);
|
|
93
|
+
const matchedSourceRoute = trieMatchRaw(routeTrie, sourceParts);
|
|
31
94
|
for (const entry of interceptLookup) {
|
|
32
95
|
if (!matchInterceptSource(sourceParts, entry)) continue;
|
|
33
|
-
const params =
|
|
96
|
+
const params = matchRoutePatternRaw(urlParts, entry.targetPatternParts);
|
|
34
97
|
if (params === null) continue;
|
|
98
|
+
canonicalizeAppPageParams(params);
|
|
35
99
|
const concreteSourceRouteIndex = matchedSourceRoute && entry.sourceMatchPatternParts !== null ? routeIndexes.get(matchedSourceRoute.route) ?? entry.sourceRouteIndex : entry.sourceRouteIndex;
|
|
36
100
|
const sourceRoute = routes[concreteSourceRouteIndex];
|
|
37
|
-
const matchedSourceParams = matchedSourceRoute && entry.sourceMatchPatternParts !== null ? matchedSourceRoute.params : sourceRoute ?
|
|
101
|
+
const matchedSourceParams = matchedSourceRoute && entry.sourceMatchPatternParts !== null ? matchedSourceRoute.params : sourceRoute ? matchRoutePatternRaw(sourceParts, sourceRoute.patternParts) : null;
|
|
38
102
|
if (matchedSourceParams === null && entry.sourceMatchPatternParts === null) continue;
|
|
39
103
|
const sourceParams = matchedSourceParams && entry.sourceMatchPatternParts !== null ? pickPatternParams(matchedSourceParams, entry.sourceMatchPatternParts) : matchedSourceParams ?? createRouteParams();
|
|
40
104
|
return {
|
|
@@ -106,12 +170,18 @@ function createInterceptLookup(routes) {
|
|
|
106
170
|
interceptLayouts: intercept.interceptLayouts,
|
|
107
171
|
interceptLayoutSegments: intercept.interceptLayoutSegments,
|
|
108
172
|
interceptBranchSegments: intercept.interceptBranchSegments,
|
|
173
|
+
interceptNotFoundBranchSegments: intercept.interceptNotFoundBranchSegments,
|
|
109
174
|
__loadInterceptLayouts: intercept.__loadInterceptLayouts,
|
|
110
175
|
page: intercept.page,
|
|
111
176
|
__pageLoader: intercept.__pageLoader,
|
|
177
|
+
notFound: intercept.notFound,
|
|
178
|
+
__loadNotFound: intercept.__loadNotFound,
|
|
179
|
+
notFoundTreePosition: intercept.notFoundTreePosition,
|
|
112
180
|
__loadState: {
|
|
113
181
|
page: intercept.page,
|
|
114
182
|
pageLoading: null,
|
|
183
|
+
notFound: intercept.notFound,
|
|
184
|
+
notFoundLoading: null,
|
|
115
185
|
interceptLayoutsLoading: null
|
|
116
186
|
},
|
|
117
187
|
params: intercept.params
|
|
@@ -133,12 +203,18 @@ function createInterceptLookup(routes) {
|
|
|
133
203
|
interceptLayouts: intercept.interceptLayouts,
|
|
134
204
|
interceptLayoutSegments: intercept.interceptLayoutSegments,
|
|
135
205
|
interceptBranchSegments: intercept.interceptBranchSegments,
|
|
206
|
+
interceptNotFoundBranchSegments: intercept.interceptNotFoundBranchSegments,
|
|
136
207
|
__loadInterceptLayouts: intercept.__loadInterceptLayouts,
|
|
137
208
|
page: intercept.page,
|
|
138
209
|
__pageLoader: intercept.__pageLoader,
|
|
210
|
+
notFound: intercept.notFound,
|
|
211
|
+
__loadNotFound: intercept.__loadNotFound,
|
|
212
|
+
notFoundTreePosition: intercept.notFoundTreePosition,
|
|
139
213
|
__loadState: {
|
|
140
214
|
page: intercept.page,
|
|
141
215
|
pageLoading: null,
|
|
216
|
+
notFound: intercept.notFound,
|
|
217
|
+
notFoundLoading: null,
|
|
142
218
|
interceptLayoutsLoading: null
|
|
143
219
|
},
|
|
144
220
|
params: intercept.params
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { isEdgeApiRuntime } from "./edge-api-runtime.js";
|
|
2
2
|
//#region src/server/app-segment-config.ts
|
|
3
|
-
const DYNAMIC_VALUES = new Set([
|
|
3
|
+
const DYNAMIC_VALUES = /* @__PURE__ */ new Set([
|
|
4
4
|
"auto",
|
|
5
5
|
"error",
|
|
6
6
|
"force-dynamic",
|
|
7
7
|
"force-static"
|
|
8
8
|
]);
|
|
9
|
-
const FETCH_CACHE_VALUES = new Set([
|
|
9
|
+
const FETCH_CACHE_VALUES = /* @__PURE__ */ new Set([
|
|
10
10
|
"auto",
|
|
11
11
|
"default-cache",
|
|
12
12
|
"default-no-store",
|
|
@@ -40,6 +40,15 @@ function resolveDynamicStaleTimeSeconds(current, value) {
|
|
|
40
40
|
function isDynamicSegment(segment) {
|
|
41
41
|
return segment.startsWith("[") && segment.endsWith("]");
|
|
42
42
|
}
|
|
43
|
+
function resolveSegmentConfigOwnerPosition(routeSegments, treePosition) {
|
|
44
|
+
let ownerPosition = Math.min(treePosition - 1, routeSegments.length - 1);
|
|
45
|
+
while (ownerPosition >= 0) {
|
|
46
|
+
const segment = routeSegments[ownerPosition];
|
|
47
|
+
if (!segment.startsWith("@") && !(segment.startsWith("(") && segment.endsWith(")"))) break;
|
|
48
|
+
ownerPosition -= 1;
|
|
49
|
+
}
|
|
50
|
+
return ownerPosition;
|
|
51
|
+
}
|
|
43
52
|
function getParallelSegments(options) {
|
|
44
53
|
if (!options.parallelBranches) return options.parallelSegments ?? [];
|
|
45
54
|
return options.parallelBranches.flatMap((branch) => branch ? [
|
|
@@ -59,8 +68,9 @@ function resolveDynamicParamsConfig(options) {
|
|
|
59
68
|
for (const segment of segments) if (segment?.dynamicParams === false) dynamicParamsConfig = false;
|
|
60
69
|
else if (segment?.dynamicParams === true && dynamicParamsConfig !== false) dynamicParamsConfig = true;
|
|
61
70
|
if (dynamicParamsConfig !== false || !options.routeSegments) return dynamicParamsConfig;
|
|
71
|
+
const routeSegments = options.routeSegments;
|
|
62
72
|
let lastDynamicPosition = -1;
|
|
63
|
-
for (let index =
|
|
73
|
+
for (let index = routeSegments.length - 1; index >= 0; index--) if (isDynamicSegment(routeSegments[index])) {
|
|
64
74
|
lastDynamicPosition = index;
|
|
65
75
|
break;
|
|
66
76
|
}
|
|
@@ -70,7 +80,7 @@ function resolveDynamicParamsConfig(options) {
|
|
|
70
80
|
let lastDynamicSegmentIsStaticOnly = false;
|
|
71
81
|
let lastDynamicSegmentHasStaticParams = false;
|
|
72
82
|
layouts.forEach((layout, index) => {
|
|
73
|
-
if ((layoutPositions[index] ?? 0)
|
|
83
|
+
if (resolveSegmentConfigOwnerPosition(routeSegments, layoutPositions[index] ?? 0) !== lastDynamicPosition) return;
|
|
74
84
|
if (layout?.dynamicParams === false) lastDynamicSegmentIsStaticOnly = true;
|
|
75
85
|
if (typeof layout?.generateStaticParams === "function") lastDynamicSegmentHasStaticParams = true;
|
|
76
86
|
});
|
|
@@ -78,7 +88,7 @@ function resolveDynamicParamsConfig(options) {
|
|
|
78
88
|
if (typeof options.page?.generateStaticParams === "function") lastDynamicSegmentHasStaticParams = true;
|
|
79
89
|
for (const branch of options.parallelBranches ?? []) {
|
|
80
90
|
if (!branch) continue;
|
|
81
|
-
const branchStartPosition =
|
|
91
|
+
const branchStartPosition = routeSegments.length - (branch.routeSegments?.length ?? 0);
|
|
82
92
|
const checkSegment = (segment, ownerPosition) => {
|
|
83
93
|
if (ownerPosition !== lastDynamicPosition) return;
|
|
84
94
|
if (segment?.dynamicParams === false) lastDynamicSegmentIsStaticOnly = true;
|
|
@@ -146,7 +146,9 @@ type HandleServerActionRscRequestOptions<TElement, TRoute extends AppServerActio
|
|
|
146
146
|
buildPageElement: (options: BuildServerActionPageElementOptions<TRoute, TInterceptOpts>) => TElement;
|
|
147
147
|
cleanPathname: string;
|
|
148
148
|
clearRequestContext: () => void;
|
|
149
|
-
contentType: string;
|
|
149
|
+
contentType: string; /** Route selected at the request boundary before action execution. */
|
|
150
|
+
currentRouteMatch: AppServerActionMatch<TRoute> | null; /** Request-aware pathname identity used for current-route interception lookup. */
|
|
151
|
+
currentRoutePathname: string;
|
|
150
152
|
createNotFoundElement: (routeId: string) => TElement;
|
|
151
153
|
createPayloadRouteId: (pathname: string, interceptionContext: string | null) => string;
|
|
152
154
|
createRscOnErrorHandler: (request: Request, pathname: string, pattern: string) => (error: unknown) => unknown;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { splitPathSegments } from "../routing/utils.js";
|
|
2
2
|
import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
3
3
|
import { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER } from "./headers.js";
|
|
4
|
-
import { isExternalUrl } from "../
|
|
4
|
+
import { isExternalUrl } from "../utils/external-url.js";
|
|
5
5
|
import { internalServerErrorResponse, payloadTooLargeResponse } from "./http-error-responses.js";
|
|
6
6
|
import { validateCsrfOrigin, validateServerActionPayload } from "./request-pipeline.js";
|
|
7
7
|
import { APP_RSC_RENDER_MODE_NAVIGATION } from "./app-rsc-render-mode.js";
|
|
8
8
|
import { headersContextFromRequest, isDraftModeRequest, setHeadersContext } from "../shims/headers.js";
|
|
9
|
-
import { getAndClearActionRevalidationKind } from "../shims/cache-request-state.js";
|
|
9
|
+
import { _drainPendingRevalidations, getAndClearActionRevalidationKind } from "../shims/cache-request-state.js";
|
|
10
10
|
import { setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
|
|
11
11
|
import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
|
|
12
12
|
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
@@ -14,10 +14,10 @@ import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js
|
|
|
14
14
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
15
15
|
import { getNextErrorDigest, parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
|
|
16
16
|
import { createServerActionNotFoundResponse, getServerActionNotFoundMessage, isServerActionNotFoundError } from "./server-action-not-found.js";
|
|
17
|
+
import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
|
|
17
18
|
import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
|
|
18
19
|
import "./app-page-stream.js";
|
|
19
20
|
import { buildAppPageTags } from "./implicit-tags.js";
|
|
20
|
-
import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
|
|
21
21
|
import { resolveAppPageActionRerenderTarget } from "./app-page-request.js";
|
|
22
22
|
import { createRootParamsUsageController, pickRootParams, runWithRootParamsScope, runWithRootParamsUsage } from "../shims/root-params.js";
|
|
23
23
|
import { getSetCookieName } from "./cookie-utils.js";
|
|
@@ -403,6 +403,7 @@ async function handleProgressiveServerActionRequest(options) {
|
|
|
403
403
|
options.setHeadersAccessPhase(previousHeadersPhase);
|
|
404
404
|
if (actionThrew) rootParamsUsage.transitionToRender();
|
|
405
405
|
}
|
|
406
|
+
await _drainPendingRevalidations();
|
|
406
407
|
if (!actionRedirect) {
|
|
407
408
|
if (!actionThrew) rootParamsUsage.transitionToRender();
|
|
408
409
|
const actionPendingCookies = dedupePendingCookies(options.getAndClearPendingCookies());
|
|
@@ -612,6 +613,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
612
613
|
options.setHeadersAccessPhase(previousHeadersPhase);
|
|
613
614
|
if (actionThrew && !actionWasForwarded) rootParamsUsage.transitionToRender();
|
|
614
615
|
}
|
|
616
|
+
await _drainPendingRevalidations();
|
|
615
617
|
if (actionRedirect) {
|
|
616
618
|
const actionPendingCookies = dedupePendingCookies(options.getAndClearPendingCookies());
|
|
617
619
|
const actionDraftCookie = options.getDraftModeCookieHeader();
|
|
@@ -648,7 +650,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
648
650
|
headers: withoutRscBodyHeaders(redirectHeaders)
|
|
649
651
|
});
|
|
650
652
|
}
|
|
651
|
-
const currentMatch = options.
|
|
653
|
+
const currentMatch = options.currentRouteMatch;
|
|
652
654
|
if (currentMatch) await options.ensureRouteLoaded?.(currentMatch.route);
|
|
653
655
|
const redirectRenderRequest = createActionRedirectRenderRequest({
|
|
654
656
|
pendingCookies: [...actionPendingCookies, ...actionDraftCookie ? [actionDraftCookie] : []],
|
|
@@ -734,14 +736,14 @@ async function handleServerActionRscRequest(options) {
|
|
|
734
736
|
}, options.clearRequestContext);
|
|
735
737
|
}
|
|
736
738
|
if (!actionThrew) rootParamsUsage.transitionToRender();
|
|
737
|
-
const match = options.
|
|
739
|
+
const match = options.currentRouteMatch;
|
|
738
740
|
let element;
|
|
739
741
|
let errorPattern = match ? match.route.pattern : options.cleanPathname;
|
|
740
742
|
const actionRerenderIsRscRequest = true;
|
|
741
743
|
if (match) {
|
|
742
744
|
const { route: actionRoute, params: actionParams } = match;
|
|
743
745
|
const actionRerenderTarget = await resolveAppPageActionRerenderTarget({
|
|
744
|
-
cleanPathname: options.
|
|
746
|
+
cleanPathname: options.currentRoutePathname,
|
|
745
747
|
currentParams: actionParams,
|
|
746
748
|
currentRoute: actionRoute,
|
|
747
749
|
findIntercept: options.findIntercept,
|
|
@@ -16,7 +16,7 @@ import { setPagesClientAssets } from "./pages-client-assets.js";
|
|
|
16
16
|
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
17
17
|
import { BfcacheStateKeyMapContext, ElementsContext, Slot } from "../shims/slot.js";
|
|
18
18
|
import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
|
|
19
|
-
import { createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform } from "./app-ssr-stream.js";
|
|
19
|
+
import { createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform, waitAtLeastOneReactRenderTask } from "./app-ssr-stream.js";
|
|
20
20
|
import { createInitialBfcacheMaps } from "./app-bfcache-identity.js";
|
|
21
21
|
import { RSC_FORM_STATE_GLOBAL } from "./app-browser-hydration.js";
|
|
22
22
|
import { createClientReferencePreloader } from "./app-client-reference-preloader.js";
|
|
@@ -238,6 +238,7 @@ async function handleSsr(rscStream, navContext, fontData, options) {
|
|
|
238
238
|
};
|
|
239
239
|
let htmlStream;
|
|
240
240
|
let shellErrorRecovered = false;
|
|
241
|
+
let shouldDelayInitialHtmlPull = false;
|
|
241
242
|
if (pprFallbackShellSignal) {
|
|
242
243
|
const prerender = await loadStaticPrerender();
|
|
243
244
|
const htmlAbortController = new AbortController();
|
|
@@ -252,6 +253,7 @@ async function handleSsr(rscStream, navContext, fontData, options) {
|
|
|
252
253
|
try {
|
|
253
254
|
streamingHtmlStream = await renderToReadableStream(ssrRoot, { ...renderOptions });
|
|
254
255
|
if (options?.waitForAllReady === true) await streamingHtmlStream.allReady;
|
|
256
|
+
else shouldDelayInitialHtmlPull = true;
|
|
255
257
|
htmlStream = streamingHtmlStream;
|
|
256
258
|
} catch (error) {
|
|
257
259
|
streamingHtmlStream?.cancel().catch(() => {});
|
|
@@ -281,6 +283,7 @@ async function handleSsr(rscStream, navContext, fontData, options) {
|
|
|
281
283
|
return buildHeadInjectionHtml(ssrNavigationContext, bootstrapModuleUrl, options?.formState ?? null, insertedHTML + errorMetaHTML + getTraceMetaHTML() + initialDevServerErrorHTML, fontHTML, options?.dynamicStaleTimeSeconds, options?.scriptNonce);
|
|
282
284
|
};
|
|
283
285
|
const getBeforeInteractiveHeadHTML = () => renderBeforeInteractiveInlineScripts(beforeInteractiveInlineScripts);
|
|
286
|
+
if (shouldDelayInitialHtmlPull) await waitAtLeastOneReactRenderTask();
|
|
284
287
|
return {
|
|
285
288
|
htmlStream: deferUntilStreamConsumed(htmlStream.pipeThrough(createTickBufferedTransform(rscEmbed, getInsertedHTML, getBeforeInteractiveHeadHTML, inlineCssManifest, inlineCssFontStyles, inlineCssFontStyleFallbackHTML, options?.scriptNonce)), cleanup),
|
|
286
289
|
metadataReady: Promise.resolve(),
|
|
@@ -10,17 +10,12 @@ type InitialNavigationCacheMetadata = {
|
|
|
10
10
|
kind: "dynamic" | "static";
|
|
11
11
|
dynamicStaleTimeSeconds?: number;
|
|
12
12
|
};
|
|
13
|
+
declare function waitAtLeastOneReactRenderTask(): Promise<void>;
|
|
13
14
|
declare function navigationRuntimeRscBootstrapExpression(): string;
|
|
14
15
|
declare function createNavigationRuntimeRscMetadataScript(params: Record<string, string | string[]>, nav: {
|
|
15
16
|
pathname: string;
|
|
16
17
|
searchParams: [string, string][];
|
|
17
18
|
}, dynamicStaleTimeSeconds?: number): string;
|
|
18
|
-
/**
|
|
19
|
-
* Fix invalid preload "as" values in RSC Flight hint lines before they reach
|
|
20
|
-
* the client. React Flight emits HL hints with as="stylesheet" for CSS, but
|
|
21
|
-
* the HTML spec requires as="style" for <link rel="preload">.
|
|
22
|
-
*/
|
|
23
|
-
declare function fixFlightHints(text: string): string;
|
|
24
19
|
/**
|
|
25
20
|
* Create a helper that progressively embeds RSC chunks as inline <script> tags.
|
|
26
21
|
* The browser entry turns the embedded chunks back into Uint8Array data.
|
|
@@ -61,4 +56,4 @@ declare function fixPreloadAs(html: string): string;
|
|
|
61
56
|
*/
|
|
62
57
|
declare function createTickBufferedTransform(rscEmbed: RscEmbedTransform, injectHTML?: HtmlInsertion, injectAfterHeadOpenHTML?: HtmlInsertion, inlineCssManifest?: InlineCssManifest, inlineCssPrependCss?: string, inlineCssPrependFallbackHTML?: string, inlineCssScriptNonce?: string): TransformStream<Uint8Array, Uint8Array>;
|
|
63
58
|
//#endregion
|
|
64
|
-
export { InitialNavigationCacheMetadata, createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform,
|
|
59
|
+
export { InitialNavigationCacheMetadata, createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform, fixPreloadAs, navigationRuntimeRscBootstrapExpression, waitAtLeastOneReactRenderTask };
|
|
@@ -2,6 +2,9 @@ import { createInlineScriptTag, escapeHtmlAttr, htmlTokenListContains, safeJsonS
|
|
|
2
2
|
import { bytesToBase64, concatUint8Arrays } from "./app-rsc-embedded-chunks.js";
|
|
3
3
|
import { NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION } from "../client/navigation-runtime.js";
|
|
4
4
|
//#region src/server/app-ssr-stream.ts
|
|
5
|
+
function waitAtLeastOneReactRenderTask() {
|
|
6
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
7
|
+
}
|
|
5
8
|
const NAVIGATION_RUNTIME_REFERENCE = `self[Symbol.for(${safeJsonStringify(NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION)})]`;
|
|
6
9
|
function navigationRuntimeRscBootstrapExpression() {
|
|
7
10
|
return `((${NAVIGATION_RUNTIME_REFERENCE}??={bootstrap:{routeManifest:null},functions:{}}).bootstrap.rsc??={rsc:[]})`;
|
|
@@ -20,14 +23,6 @@ function createNavigationRuntimeRscDoneScript(metadata) {
|
|
|
20
23
|
}) + ");") + bootstrap + ".done=true";
|
|
21
24
|
}
|
|
22
25
|
/**
|
|
23
|
-
* Fix invalid preload "as" values in RSC Flight hint lines before they reach
|
|
24
|
-
* the client. React Flight emits HL hints with as="stylesheet" for CSS, but
|
|
25
|
-
* the HTML spec requires as="style" for <link rel="preload">.
|
|
26
|
-
*/
|
|
27
|
-
function fixFlightHints(text) {
|
|
28
|
-
return text.replace(/(\d*:HL\[.*?),"stylesheet"(\]|,)/g, "$1,\"style\"$2");
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
26
|
* Create a helper that progressively embeds RSC chunks as inline <script> tags.
|
|
32
27
|
* The browser entry turns the embedded chunks back into Uint8Array data.
|
|
33
28
|
*/
|
|
@@ -46,7 +41,7 @@ function createRscEmbedTransform(embedStream, scriptNonce, getInitialNavigationC
|
|
|
46
41
|
rawChunks.push(result.value);
|
|
47
42
|
try {
|
|
48
43
|
const text = new TextDecoder("utf-8", { fatal: true }).decode(result.value);
|
|
49
|
-
pendingChunks.push(
|
|
44
|
+
pendingChunks.push(text);
|
|
50
45
|
} catch {
|
|
51
46
|
pendingChunks.push([3, bytesToBase64(result.value)]);
|
|
52
47
|
}
|
|
@@ -409,4 +404,4 @@ function createTickBufferedTransform(rscEmbed, injectHTML = "", injectAfterHeadO
|
|
|
409
404
|
});
|
|
410
405
|
}
|
|
411
406
|
//#endregion
|
|
412
|
-
export { createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform,
|
|
407
|
+
export { createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform, fixPreloadAs, navigationRuntimeRscBootstrapExpression, waitAtLeastOneReactRenderTask };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { NextHeader } from "../config/next-config.js";
|
|
2
|
+
import { RequestContext } from "../config/request-context.js";
|
|
3
|
+
import { BasePathMatchState } from "../config/config-matchers.js";
|
|
4
|
+
import { HeaderRecord } from "./request-pipeline.js";
|
|
5
|
+
|
|
6
|
+
//#region src/server/config-headers.d.ts
|
|
7
|
+
type ApplyConfigHeadersOptions = {
|
|
8
|
+
configHeaders: NextHeader[];
|
|
9
|
+
pathname: string;
|
|
10
|
+
requestContext: RequestContext;
|
|
11
|
+
/**
|
|
12
|
+
* basePath gating state. When omitted, every rule is treated as a default
|
|
13
|
+
* (basePath: true) rule for backward compatibility — callers that need to
|
|
14
|
+
* support `basePath: false` headers must pass this in.
|
|
15
|
+
*/
|
|
16
|
+
basePathState?: BasePathMatchState; /** Existing framework-generated headers that matching config rules may replace. */
|
|
17
|
+
overwriteExisting?: ReadonlySet<string>;
|
|
18
|
+
};
|
|
19
|
+
/** Apply matched next.config.js headers to a Web Headers object. */
|
|
20
|
+
declare function applyConfigHeadersToResponse(responseHeaders: Headers, options: ApplyConfigHeadersOptions): void;
|
|
21
|
+
/** Apply matched next.config.js headers to an early response header record. */
|
|
22
|
+
declare function applyConfigHeadersToHeaderRecord(headers: HeaderRecord, options: ApplyConfigHeadersOptions): void;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { applyConfigHeadersToHeaderRecord, applyConfigHeadersToResponse };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { matchHeaders } from "../config/config-matchers.js";
|
|
2
|
+
//#region src/server/config-headers.ts
|
|
3
|
+
function findHeaderRecordKey(headers, lowerName) {
|
|
4
|
+
for (const key of Object.keys(headers)) if (key.toLowerCase() === lowerName) return key;
|
|
5
|
+
}
|
|
6
|
+
function appendHeaderRecord(headers, lowerName, value) {
|
|
7
|
+
const key = findHeaderRecordKey(headers, lowerName) ?? lowerName;
|
|
8
|
+
const existing = headers[key];
|
|
9
|
+
if (existing === void 0) {
|
|
10
|
+
headers[key] = value;
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (Array.isArray(existing)) {
|
|
14
|
+
existing.push(value);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
headers[key] = [existing, value];
|
|
18
|
+
}
|
|
19
|
+
function appendVaryHeaderRecord(headers, value) {
|
|
20
|
+
const key = findHeaderRecordKey(headers, "vary") ?? "vary";
|
|
21
|
+
const existing = headers[key];
|
|
22
|
+
if (existing === void 0) {
|
|
23
|
+
headers[key] = value;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(existing)) {
|
|
27
|
+
existing.push(value);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
headers[key] = existing + ", " + value;
|
|
31
|
+
}
|
|
32
|
+
/** Apply matched next.config.js headers to a Web Headers object. */
|
|
33
|
+
function applyConfigHeadersToResponse(responseHeaders, options) {
|
|
34
|
+
const matched = matchHeaders(options.pathname, options.configHeaders, options.requestContext, options.basePathState);
|
|
35
|
+
for (const header of matched) {
|
|
36
|
+
const lowerName = header.key.toLowerCase();
|
|
37
|
+
if (lowerName === "vary" || lowerName === "set-cookie") responseHeaders.append(header.key, header.value);
|
|
38
|
+
else if (options.overwriteExisting?.has(lowerName) || !responseHeaders.has(lowerName)) responseHeaders.set(header.key, header.value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Apply matched next.config.js headers to an early response header record. */
|
|
42
|
+
function applyConfigHeadersToHeaderRecord(headers, options) {
|
|
43
|
+
const matched = matchHeaders(options.pathname, options.configHeaders, options.requestContext, options.basePathState);
|
|
44
|
+
for (const header of matched) {
|
|
45
|
+
const lowerName = header.key.toLowerCase();
|
|
46
|
+
if (lowerName === "set-cookie") appendHeaderRecord(headers, lowerName, header.value);
|
|
47
|
+
else if (lowerName === "vary") appendVaryHeaderRecord(headers, header.value);
|
|
48
|
+
else if (findHeaderRecordKey(headers, lowerName) === void 0) headers[lowerName] = header.value;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { applyConfigHeadersToHeaderRecord, applyConfigHeadersToResponse };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
2
|
+
|
|
1
3
|
//#region src/server/default-global-error-module.d.ts
|
|
2
4
|
/**
|
|
3
5
|
* Module-shaped wrapper around vinext's built-in default global error
|
|
@@ -13,7 +15,7 @@
|
|
|
13
15
|
* https://github.com/vercel/next.js/blob/canary/packages/next/src/build/webpack/loaders/next-app-loader/index.ts
|
|
14
16
|
*/
|
|
15
17
|
declare const DEFAULT_GLOBAL_ERROR_MODULE: {
|
|
16
|
-
readonly default:
|
|
18
|
+
readonly default: typeof DefaultGlobalError;
|
|
17
19
|
};
|
|
18
20
|
//#endregion
|
|
19
21
|
export { DEFAULT_GLOBAL_ERROR_MODULE };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import DefaultNotFound from "../shims/default-not-found.js";
|
|
2
|
+
|
|
1
3
|
//#region src/server/default-not-found-module.d.ts
|
|
2
4
|
/**
|
|
3
5
|
* Module-shaped wrapper around vinext's built-in default not-found component.
|
|
@@ -13,7 +15,7 @@
|
|
|
13
15
|
* https://github.com/vercel/next.js/blob/canary/packages/next/src/build/webpack/loaders/next-app-loader/index.ts
|
|
14
16
|
*/
|
|
15
17
|
declare const DEFAULT_NOT_FOUND_MODULE: {
|
|
16
|
-
readonly default:
|
|
18
|
+
readonly default: typeof DefaultNotFound;
|
|
17
19
|
};
|
|
18
20
|
//#endregion
|
|
19
21
|
export { DEFAULT_NOT_FOUND_MODULE };
|
|
@@ -4,6 +4,6 @@ type InitialDevServerErrorPayload = {
|
|
|
4
4
|
name?: string;
|
|
5
5
|
stack?: string;
|
|
6
6
|
};
|
|
7
|
-
declare function createInitialDevServerErrorScript(error: unknown, scriptNonce?: string, nodeEnv?:
|
|
7
|
+
declare function createInitialDevServerErrorScript(error: unknown, scriptNonce?: string, nodeEnv?: "development" | "production" | "test"): string;
|
|
8
8
|
//#endregion
|
|
9
9
|
export { InitialDevServerErrorPayload, createInitialDevServerErrorScript };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
import fs from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
4
3
|
//#region src/server/dev-lockfile.ts
|
|
5
4
|
/**
|
|
6
5
|
* Dev server lock file.
|
|
@@ -99,7 +98,7 @@ function formatAlreadyRunningError(opts) {
|
|
|
99
98
|
if (!existing) return [
|
|
100
99
|
"Another vinext dev server appears to be running in this directory.",
|
|
101
100
|
"",
|
|
102
|
-
`Stale lock file: ${
|
|
101
|
+
`Stale lock file: ${path.relative(cwd, lockfilePath)}`,
|
|
103
102
|
"Remove it manually if no server is running, then re-run `vinext dev`."
|
|
104
103
|
].join("\n");
|
|
105
104
|
const killCommand = process.platform === "win32" ? `taskkill /PID ${existing.pid} /F` : `kill ${existing.pid}`;
|