vinext 1.1.0 → 1.2.1
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 +22 -10
- package/dist/build/client-build-config.d.ts +10 -0
- package/dist/build/client-build-config.js +18 -2
- package/dist/build/output-root-externals.d.ts +21 -0
- package/dist/build/output-root-externals.js +40 -0
- package/dist/build/pages-client-assets-module.d.ts +8 -0
- package/dist/build/pages-client-assets-module.js +21 -1
- package/dist/build/prerender-paths.js +6 -4
- package/dist/build/prerender.js +1 -1
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/ssr-manifest.d.ts +2 -0
- package/dist/build/ssr-manifest.js +6 -2
- package/dist/check.js +12 -12
- package/dist/cli-dev-config.js +3 -3
- package/dist/cli.js +3 -2
- package/dist/client/client-redirect-matcher.d.ts +14 -0
- package/dist/client/client-redirect-matcher.js +37 -0
- package/dist/client/client-redirects.d.ts +27 -0
- package/dist/client/client-redirects.js +28 -0
- package/dist/client/client-rewrites.d.ts +2 -1
- package/dist/client/client-rewrites.js +1 -1
- package/dist/config/config-matchers.d.ts +26 -11
- package/dist/config/config-matchers.js +90 -88
- package/dist/config/destination-params.d.ts +47 -0
- package/dist/config/destination-params.js +116 -0
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +3 -0
- package/dist/entries/app-rsc-entry.d.ts +4 -0
- package/dist/entries/app-rsc-entry.js +20 -6
- package/dist/entries/pages-client-entry.js +3 -1
- package/dist/entries/pages-server-entry.js +13 -37
- package/dist/index.d.ts +3 -1
- package/dist/index.js +246 -136
- package/dist/init-cloudflare.d.ts +9 -0
- package/dist/init-cloudflare.js +107 -31
- package/dist/init-platform.d.ts +4 -0
- package/dist/init-platform.js +27 -2
- package/dist/init.d.ts +2 -1
- package/dist/init.js +153 -9
- package/dist/plugins/ast-scope.d.ts +7 -0
- package/dist/plugins/ast-scope.js +59 -3
- package/dist/plugins/ast-utils.d.ts +53 -2
- package/dist/plugins/ast-utils.js +90 -2
- package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
- package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
- package/dist/plugins/commonjs-esm-facade.js +2 -2
- package/dist/plugins/css-module-imports.js +13 -20
- package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +11 -11
- package/dist/plugins/extensionless-dynamic-import.js +2 -3
- package/dist/plugins/fonts.d.ts +1 -1
- package/dist/plugins/fonts.js +3 -3
- package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +5 -7
- package/dist/plugins/import-meta-url.js +3 -4
- package/dist/plugins/instrumentation-client.js +3 -2
- package/dist/plugins/middleware-export-validation.js +2 -3
- package/dist/plugins/middleware-server-only.d.ts +5 -4
- package/dist/plugins/middleware-server-only.js +8 -5
- package/dist/plugins/og-harfbuzz.js +2 -3
- package/dist/plugins/optimize-imports.js +3 -4
- package/dist/plugins/pages-node-externals.js +3 -4
- package/dist/plugins/remove-console.js +2 -18
- package/dist/plugins/require-condition-resolution.js +3 -3
- package/dist/plugins/require-context.js +2 -3
- package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
- package/dist/plugins/rsc-scan-glob-imports.js +50 -0
- package/dist/plugins/strip-server-exports.js +265 -102
- package/dist/plugins/styled-jsx.js +2 -3
- package/dist/plugins/transform-result.d.ts +9 -5
- package/dist/plugins/transitive-externals.js +1 -1
- package/dist/plugins/typeof-window.d.ts +2 -2
- package/dist/plugins/use-cache-callable.d.ts +21 -2
- package/dist/plugins/use-cache-callable.js +84 -35
- package/dist/plugins/worker-image-imports.js +30 -33
- package/dist/plugins/worker-server-only-imports.d.ts +20 -0
- package/dist/plugins/worker-server-only-imports.js +31 -0
- package/dist/plugins/worker-use-server.d.ts +25 -0
- package/dist/plugins/worker-use-server.js +153 -0
- package/dist/server/api-handler.d.ts +1 -0
- package/dist/server/api-handler.js +3 -2
- package/dist/server/app-action-forwarding.js +2 -2
- package/dist/server/app-browser-action-result.d.ts +1 -1
- package/dist/server/app-browser-action-result.js +9 -2
- package/dist/server/app-browser-entry.js +3 -3
- package/dist/server/app-browser-interception-context.js +1 -1
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-prefetch-response.js +2 -2
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-supplemental-refresh.js +1 -1
- package/dist/server/app-middleware.d.ts +11 -0
- package/dist/server/app-middleware.js +17 -2
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-cache.d.ts +1 -1
- package/dist/server/app-page-cache.js +1 -1
- package/dist/server/app-page-dispatch.d.ts +3 -1
- package/dist/server/app-page-dispatch.js +5 -4
- package/dist/server/app-page-ppr-runtime.js +1 -1
- package/dist/server/app-page-render-observation.js +1 -1
- package/dist/server/app-page-render.js +1 -1
- package/dist/server/app-page-request.js +53 -15
- package/dist/server/app-page-route-wiring.js +2 -2
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +3 -4
- package/dist/server/app-prerender-endpoints.js +9 -6
- package/dist/server/app-render-abort-error.d.ts +19 -0
- package/dist/server/app-render-abort-error.js +31 -1
- package/dist/server/app-request-stage-dispatch.js +6 -2
- package/dist/server/app-request-stage-independent-entry.js +29 -9
- package/dist/server/app-response-stage-entry.js +11 -3
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +1 -0
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +5 -2
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +4 -1
- package/dist/server/app-route-handler-runtime.js +46 -25
- package/dist/server/app-router-entry.js +29 -10
- package/dist/server/app-rsc-cache-busting.d.ts +16 -0
- package/dist/server/app-rsc-cache-busting.js +30 -13
- package/dist/server/app-rsc-errors.js +20 -16
- package/dist/server/app-rsc-handler.d.ts +7 -0
- package/dist/server/app-rsc-handler.js +89 -39
- package/dist/server/app-rsc-request-normalization.js +3 -3
- package/dist/server/app-rsc-response-stage.js +5 -3
- package/dist/server/app-segment-config.d.ts +2 -1
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +62 -23
- package/dist/server/app-ssr-entry.js +7 -5
- package/dist/server/app-visited-response-cache.js +2 -2
- package/dist/server/app-worker-stages.d.ts +5 -0
- package/dist/server/app-worker-stages.js +1 -1
- package/dist/server/cacheability-request.js +2 -2
- package/dist/server/client-build-files.d.ts +16 -0
- package/dist/server/client-build-files.js +36 -0
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/config-headers.js +1 -1
- package/dist/server/defer-until-stream-consumed.d.ts +2 -1
- package/dist/server/defer-until-stream-consumed.js +3 -1
- package/dist/server/dev-server.js +39 -28
- package/dist/server/dev-stack-sourcemap.js +18 -23
- package/dist/server/document-initial-head.d.ts +0 -11
- package/dist/server/document-initial-head.js +1 -1
- package/dist/server/forwarded-middleware-context.d.ts +5 -0
- package/dist/server/forwarded-middleware-context.js +22 -0
- package/dist/server/headers.d.ts +4 -1
- package/dist/server/headers.js +4 -1
- package/dist/server/http-conditional.d.ts +11 -0
- package/dist/server/http-conditional.js +10 -1
- package/dist/server/http-error-responses.d.ts +1 -1
- package/dist/server/image-optimization.d.ts +38 -0
- package/dist/server/image-optimization.js +94 -4
- package/dist/server/isr-cache.d.ts +10 -0
- package/dist/server/isr-cache.js +41 -6
- package/dist/server/metadata-route-response.js +11 -10
- package/dist/server/middleware-matcher.d.ts +2 -0
- package/dist/server/middleware-matcher.js +23 -2
- package/dist/server/middleware-path-to-regexp.js +1 -1
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +38 -25
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +3 -1
- package/dist/server/multi-stage.d.ts +11 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/normalize-path.d.ts +0 -13
- package/dist/server/normalize-path.js +1 -34
- package/dist/server/open-redirect.d.ts +11 -4
- package/dist/server/open-redirect.js +11 -4
- package/dist/server/pages-api-route.d.ts +3 -2
- package/dist/server/pages-api-route.js +6 -5
- package/dist/server/pages-cache-tag.d.ts +12 -0
- package/dist/server/pages-cache-tag.js +19 -0
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-data-route.d.ts +10 -0
- package/dist/server/pages-data-route.js +21 -3
- package/dist/server/pages-document-asset-props.d.ts +5 -1
- package/dist/server/pages-document-asset-props.js +13 -5
- package/dist/server/pages-document-splice.d.ts +19 -0
- package/dist/server/pages-document-splice.js +55 -0
- package/dist/server/pages-i18n.d.ts +12 -1
- package/dist/server/pages-i18n.js +18 -4
- package/dist/server/pages-node-compat.d.ts +16 -5
- package/dist/server/pages-node-compat.js +20 -12
- package/dist/server/pages-page-data.d.ts +32 -24
- package/dist/server/pages-page-data.js +51 -121
- package/dist/server/pages-page-handler.d.ts +0 -6
- package/dist/server/pages-page-handler.js +189 -127
- package/dist/server/pages-page-response.d.ts +12 -6
- package/dist/server/pages-page-response.js +42 -35
- package/dist/server/pages-request-pipeline.d.ts +10 -2
- package/dist/server/pages-request-pipeline.js +41 -22
- package/dist/server/pages-request-stage-entry.d.ts +6 -0
- package/dist/server/pages-request-stage-entry.js +75 -16
- package/dist/server/pages-response-stage-entry.js +4 -0
- package/dist/server/pages-revalidate.js +3 -3
- package/dist/server/pages-router-entry.js +5 -4
- package/dist/server/prerender-manifest.d.ts +3 -3
- package/dist/server/prerender-manifest.js +4 -3
- package/dist/server/prerender-work-unit-setup.js +4 -0
- package/dist/server/prod-server.d.ts +12 -0
- package/dist/server/prod-server.js +204 -74
- package/dist/server/proper-error.d.ts +4 -0
- package/dist/server/proper-error.js +31 -0
- package/dist/server/request-pipeline.d.ts +4 -1
- package/dist/server/request-pipeline.js +3 -2
- package/dist/server/revalidation-request.d.ts +1 -0
- package/dist/server/revalidation-request.js +1 -1
- package/dist/server/rsc-stream-hints.d.ts +1 -1
- package/dist/server/rsc-stream-hints.js +52 -5
- package/dist/server/seed-cache.d.ts +1 -0
- package/dist/server/seed-cache.js +5 -4
- package/dist/server/server-reference-loader.d.ts +4 -0
- package/dist/server/server-reference-loader.js +29 -0
- package/dist/server/socket-error-backstop.d.ts +9 -1
- package/dist/server/socket-error-backstop.js +46 -17
- package/dist/server/static-file-signal.d.ts +15 -4
- package/dist/server/static-file-signal.js +46 -12
- package/dist/server/worker-image-optimization.d.ts +34 -0
- package/dist/server/worker-image-optimization.js +99 -0
- package/dist/server/worker-stages.d.ts +1 -1
- package/dist/server/worker-stages.js +2 -2
- package/dist/server/worker-utils.d.ts +8 -3
- package/dist/server/worker-utils.js +12 -7
- package/dist/shims/app-router-scroll.js +4 -1
- package/dist/shims/app-router-tree-context.d.ts +5 -0
- package/dist/shims/app-router-tree-context.js +27 -0
- package/dist/shims/cache-callable-runtime.d.ts +4 -2
- package/dist/shims/cache-callable-runtime.js +21 -12
- package/dist/shims/cache-handler.js +1 -9
- package/dist/shims/cache-runtime.d.ts +6 -1
- package/dist/shims/cache-runtime.js +2 -1
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +40 -13
- package/dist/shims/cdn-cache.d.ts +8 -0
- package/dist/shims/cdn-cache.js +17 -1
- package/dist/shims/disable-smooth-scroll.d.ts +3 -0
- package/dist/shims/disable-smooth-scroll.js +36 -0
- package/dist/shims/document-placeholders.d.ts +19 -0
- package/dist/shims/document-placeholders.js +45 -0
- package/dist/shims/document.js +21 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
- package/dist/shims/dynamic-preload-chunks.js +13 -9
- package/dist/shims/dynamic.d.ts +1 -1
- package/dist/shims/dynamic.js +60 -8
- package/dist/shims/fetch-cache-state.d.ts +66 -0
- package/dist/shims/fetch-cache-state.js +92 -0
- package/dist/shims/fetch-cache.d.ts +3 -67
- package/dist/shims/fetch-cache.js +160 -125
- package/dist/shims/head.d.ts +10 -6
- package/dist/shims/head.js +16 -14
- package/dist/shims/headers.js +2 -2
- package/dist/shims/image.js +2 -1
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +1 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +1 -0
- package/dist/shims/internal/work-store-scope.d.ts +5 -0
- package/dist/shims/internal/work-store-scope.js +24 -0
- package/dist/shims/link-prefetch.js +5 -4
- package/dist/shims/link.js +2 -2
- package/dist/shims/navigation.js +34 -9
- package/dist/shims/request-context.d.ts +2 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/router.js +21 -32
- package/dist/shims/server.d.ts +27 -4
- package/dist/shims/server.js +65 -9
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/url-utils.d.ts +9 -0
- package/dist/shims/url-utils.js +15 -4
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/domain-locale.js +1 -1
- package/dist/utils/hash.d.ts +7 -0
- package/dist/utils/hash.js +11 -1
- package/dist/utils/package-name.d.ts +6 -0
- package/dist/utils/package-name.js +12 -1
- package/dist/utils/plugin-rsc-version.d.ts +6 -0
- package/dist/utils/plugin-rsc-version.js +41 -0
- package/dist/utils/prerender-output-paths.js +15 -4
- package/dist/utils/public-file-path.d.ts +10 -2
- package/dist/utils/public-file-path.js +13 -9
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.d.ts +10 -0
- package/dist/utils/react-version.js +39 -16
- package/package.json +11 -7
- package/dist/build/nitro-route-rules.d.ts +0 -47
- package/dist/build/nitro-route-rules.js +0 -79
- package/dist/plugins/cache-flight-codec.d.ts +0 -19
- package/dist/plugins/cache-flight-codec.js +0 -68
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getOrCreateAls } from "./als-registry.js";
|
|
2
|
+
//#region src/shims/internal/work-store-scope.ts
|
|
3
|
+
/**
|
|
4
|
+
* Marks the work that Next.js runs with a work store (`workAsyncStorage`):
|
|
5
|
+
* App Router renders, Server Actions, route handlers and metadata routes,
|
|
6
|
+
* `generateStaticParams`, and middleware. Pages Router renders, API routes
|
|
7
|
+
* and `getStaticPaths` run without one.
|
|
8
|
+
*
|
|
9
|
+
* Next.js only applies some rules inside a work store, such as skipping the
|
|
10
|
+
* read for an `unstable_cache` nested in another's callback.
|
|
11
|
+
* Source: https://github.com/vercel/next.js/blob/canary/packages/next/src/server/web/spec-extension/unstable-cache.ts
|
|
12
|
+
*/
|
|
13
|
+
const _workStoreScopeAls = getOrCreateAls("vinext.workStoreScope.als");
|
|
14
|
+
function runInWorkStoreScope(fn) {
|
|
15
|
+
return _workStoreScopeAls.run(true, fn);
|
|
16
|
+
}
|
|
17
|
+
function runOutsideWorkStoreScope(fn) {
|
|
18
|
+
return _workStoreScopeAls.run(false, fn);
|
|
19
|
+
}
|
|
20
|
+
function isInsideWorkStoreScope() {
|
|
21
|
+
return _workStoreScopeAls.getStore() === true;
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { isInsideWorkStoreScope, runInWorkStoreScope, runOutsideWorkStoreScope };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
2
|
-
import { isAbsoluteOrProtocolRelativeUrl } from "./url-utils.js";
|
|
2
|
+
import { collapseLeadingSlashes, isAbsoluteOrProtocolRelativeUrl } from "./url-utils.js";
|
|
3
3
|
//#region src/shims/link-prefetch.ts
|
|
4
4
|
function canLinkPrefetch(input) {
|
|
5
5
|
return input.nodeEnv === "production" && input.prefetch !== false && !input.isDangerous;
|
|
@@ -32,9 +32,10 @@ function getLinkPrefetchHref(input) {
|
|
|
32
32
|
const current = new URL(currentOrigin);
|
|
33
33
|
const parsed = href.startsWith("//") ? new URL(href, current.origin) : new URL(href);
|
|
34
34
|
if (parsed.origin !== current.origin) return null;
|
|
35
|
-
|
|
36
|
-
if (!
|
|
37
|
-
|
|
35
|
+
const pathname = collapseLeadingSlashes(parsed.pathname);
|
|
36
|
+
if (!basePath) return pathname + parsed.search + parsed.hash;
|
|
37
|
+
if (!hasBasePath(pathname, basePath)) return null;
|
|
38
|
+
return collapseLeadingSlashes(stripBasePath(pathname, basePath)) + parsed.search + parsed.hash;
|
|
38
39
|
} catch {
|
|
39
40
|
return null;
|
|
40
41
|
}
|
package/dist/shims/link.js
CHANGED
|
@@ -317,7 +317,7 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale) {
|
|
|
317
317
|
async function promotePrefetchEntriesForNavigation(href) {
|
|
318
318
|
if (typeof window === "undefined") return;
|
|
319
319
|
if (!hasAppNavigationRuntime()) return;
|
|
320
|
-
const [{ getPrefetchCache }, { stripRscCacheBustingSearchParam, stripRscSuffix }] = await Promise.all([loadNavigationModule(), import("../server/app-rsc-cache-busting.js")]);
|
|
320
|
+
const [{ getPrefetchCache }, { parseRscRequestPath, stripRscCacheBustingSearchParam, stripRscSuffix }] = await Promise.all([loadNavigationModule(), import("../server/app-rsc-cache-busting.js")]);
|
|
321
321
|
let target;
|
|
322
322
|
try {
|
|
323
323
|
target = new URL(toCanonicalBrowserNavigationHref(href, window.location.href, __basePath, __trailingSlash), window.location.href);
|
|
@@ -330,7 +330,7 @@ async function promotePrefetchEntriesForNavigation(href) {
|
|
|
330
330
|
const [rscUrl] = cacheKey.split("\0", 1);
|
|
331
331
|
let cached;
|
|
332
332
|
try {
|
|
333
|
-
cached =
|
|
333
|
+
cached = parseRscRequestPath(rscUrl);
|
|
334
334
|
} catch {
|
|
335
335
|
continue;
|
|
336
336
|
}
|
package/dist/shims/navigation.js
CHANGED
|
@@ -9,14 +9,15 @@ import { getPprFallbackShellState, markPprFallbackShellDynamicBoundary } from ".
|
|
|
9
9
|
import { AppRouterContext } from "./internal/app-router-context.js";
|
|
10
10
|
import { resolveDirectHybridClientRouteOwner } from "./internal/hybrid-client-route-owner-direct.js";
|
|
11
11
|
import { isHashOnlyBrowserUrlChange, toCanonicalBrowserNavigationHref, toSameOriginAppPath, withBasePath } from "./url-utils.js";
|
|
12
|
-
import {
|
|
12
|
+
import { disableSmoothScrollDuringRouteTransition } from "./disable-smooth-scroll.js";
|
|
13
|
+
import { retryScrollTo, scrollToHashTarget } from "./hash-scroll.js";
|
|
13
14
|
import { AppElementsWire } from "../server/app-elements-wire.js";
|
|
14
15
|
import "../server/app-elements.js";
|
|
15
16
|
import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessors, clearClientHydrationContext, clearServerInsertedHTML, flushServerInsertedHTML, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getLayoutSegmentContext, getNavigationContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "./navigation-context-state.js";
|
|
16
17
|
import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow } from "./navigation-errors.js";
|
|
17
18
|
import { clearAppNavigationFailureTarget, stageAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
|
|
18
19
|
import { beginAppRouterScrollIntent, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, isLatestAppRouterScrollIntent } from "./app-router-scroll-state.js";
|
|
19
|
-
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam, stripRscSuffix } from "../server/app-rsc-cache-busting.js";
|
|
20
|
+
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, formatRscRequestPath, parseRscRequestPath, stripRscCacheBustingSearchParam, stripRscSuffix } from "../server/app-rsc-cache-busting.js";
|
|
20
21
|
import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
|
|
21
22
|
import { getNavigationRuntime, hasAppNavigationRuntime } from "../client/navigation-runtime.js";
|
|
22
23
|
import { UnrecognizedActionError, unstable_isUnrecognizedActionError } from "./unrecognized-action-error.js";
|
|
@@ -235,7 +236,7 @@ function resolvePrefetchCacheEntryMountedSlotsHeader(entry) {
|
|
|
235
236
|
}
|
|
236
237
|
function normalizeRscCacheLookupUrl(rscUrl) {
|
|
237
238
|
try {
|
|
238
|
-
const url =
|
|
239
|
+
const url = parseRscRequestPath(rscUrl);
|
|
239
240
|
stripRscCacheBustingSearchParam(url);
|
|
240
241
|
return `${url.pathname}${url.search}`;
|
|
241
242
|
} catch {
|
|
@@ -244,7 +245,7 @@ function normalizeRscCacheLookupUrl(rscUrl) {
|
|
|
244
245
|
}
|
|
245
246
|
function normalizeRscCacheLookupPathname(rscUrl) {
|
|
246
247
|
try {
|
|
247
|
-
const url =
|
|
248
|
+
const url = parseRscRequestPath(rscUrl);
|
|
248
249
|
return stripRscSuffix(url.pathname);
|
|
249
250
|
} catch {
|
|
250
251
|
return null;
|
|
@@ -434,8 +435,7 @@ function toAppPrefetchDestination(href) {
|
|
|
434
435
|
}
|
|
435
436
|
const browserHref = toCanonicalBrowserNavigationHref(localHref, window.location.href, __basePath, __trailingSlash);
|
|
436
437
|
try {
|
|
437
|
-
|
|
438
|
-
return `${url.pathname}${url.search}`;
|
|
438
|
+
return formatRscRequestPath(new URL(browserHref, window.location.href));
|
|
439
439
|
} catch {
|
|
440
440
|
return browserHref.split("#", 1)[0];
|
|
441
441
|
}
|
|
@@ -797,6 +797,22 @@ async function fetchRouteTreeGatedPrefetch(options) {
|
|
|
797
797
|
return fetchFullRscPayload();
|
|
798
798
|
}
|
|
799
799
|
/**
|
|
800
|
+
* Whether a prefetch response may be decoded as Flight. A successful response
|
|
801
|
+
* that is not Flight (e.g. a Route Handler's text download) is a miss: decoding
|
|
802
|
+
* its bytes would let text shaped like Flight resource hints insert scripts.
|
|
803
|
+
* Navigation then fetches it and falls back to a document navigation.
|
|
804
|
+
*
|
|
805
|
+
* Ported from Next.js: fetchPrefetchResponse in
|
|
806
|
+
* packages/next/src/client/components/segment-cache/cache.ts, which skips the
|
|
807
|
+
* check in `output: "export"` because a static host, not Next.js, chooses the
|
|
808
|
+
* MIME type of the exported `.txt` payloads.
|
|
809
|
+
*/
|
|
810
|
+
function isFlightPrefetchResponse(response) {
|
|
811
|
+
if (!response.ok) return false;
|
|
812
|
+
if (process.env.NODE_ENV === "production" && process.env.__NEXT_CONFIG_OUTPUT === "export") return true;
|
|
813
|
+
return response.headers.get("content-type")?.toLowerCase().startsWith(VINEXT_RSC_CONTENT_TYPE) === true;
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
800
816
|
* Prefetch an RSC response and snapshot it for later consumption.
|
|
801
817
|
* Stores the in-flight promise so immediate clicks can await it instead
|
|
802
818
|
* of firing a duplicate fetch.
|
|
@@ -824,7 +840,7 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
|
|
|
824
840
|
addPrefetchInvalidationCallback(entry, options?.onInvalidate);
|
|
825
841
|
entry.fetchPromise = fetchPromise;
|
|
826
842
|
entry.pending = fetchPromise.then(async (response) => {
|
|
827
|
-
if (response
|
|
843
|
+
if (isFlightPrefetchResponse(response)) {
|
|
828
844
|
const snapshot = await snapshotRscResponse(response);
|
|
829
845
|
if (cache.get(cacheKey) !== entry) return;
|
|
830
846
|
const previousSize = getPrefetchCacheEntrySize(entry);
|
|
@@ -841,6 +857,7 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
|
|
|
841
857
|
evictPrefetchCacheIfNeeded();
|
|
842
858
|
} else {
|
|
843
859
|
releaseAppPrefetchFetchSlot(response);
|
|
860
|
+
response.body?.cancel().catch(() => {});
|
|
844
861
|
deletePrefetchCacheEntry(cache, prefetched, cacheKey, entry, false);
|
|
845
862
|
}
|
|
846
863
|
}).catch(() => {
|
|
@@ -1333,11 +1350,19 @@ function commitHashOnlyHistoryState(href, mode, scroll) {
|
|
|
1333
1350
|
function applyAppRouterScrollFallback(intent) {
|
|
1334
1351
|
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
1335
1352
|
if (intent.hash !== null) {
|
|
1336
|
-
|
|
1353
|
+
const hash = intent.hash;
|
|
1354
|
+
requestAnimationFrame(() => {
|
|
1355
|
+
if (!isLatestAppRouterScrollIntent(intent)) return;
|
|
1356
|
+
disableSmoothScrollDuringRouteTransition(() => {
|
|
1357
|
+
scrollToHashTarget(hash);
|
|
1358
|
+
});
|
|
1359
|
+
});
|
|
1337
1360
|
return;
|
|
1338
1361
|
}
|
|
1339
1362
|
if (intent.targetHoistedInHead) return;
|
|
1340
|
-
|
|
1363
|
+
disableSmoothScrollDuringRouteTransition(() => {
|
|
1364
|
+
document.documentElement.scrollTop = 0;
|
|
1365
|
+
});
|
|
1341
1366
|
}
|
|
1342
1367
|
function scheduleAppRouterScrollFallback(intent) {
|
|
1343
1368
|
queueMicrotask(() => {
|
|
@@ -44,6 +44,8 @@ export type ExecutionContextLike = {
|
|
|
44
44
|
isInternalPagesRevalidation?: boolean;
|
|
45
45
|
/** Marks a build-secret-authorized Worker request that may run prerender discovery hooks. */
|
|
46
46
|
isPrerenderPathDiscovery?: boolean;
|
|
47
|
+
/** Marks an adapter-invoked regeneration of an entry stored for this build. */
|
|
48
|
+
isStoredEntryRegeneration?: boolean;
|
|
47
49
|
/**
|
|
48
50
|
* Installed only by the prerender server: records the page's special error
|
|
49
51
|
* that escaped the shell, with the headers to store, for the build.
|
|
@@ -3,7 +3,8 @@ import { NavigationContext } from "./navigation-context-state.js";
|
|
|
3
3
|
import "./navigation.js";
|
|
4
4
|
import { CacheLifeConfig, CacheState } from "./cache-request-state.js";
|
|
5
5
|
import { RootParamsState } from "./root-params.js";
|
|
6
|
-
import { FetchCacheState } from "./fetch-cache.js";
|
|
6
|
+
import { FetchCacheState } from "./fetch-cache-state.js";
|
|
7
|
+
import "./fetch-cache.js";
|
|
7
8
|
import { HeadersAccessPhase, VinextHeadersShimState } from "./internal/headers-state.js";
|
|
8
9
|
import { HeadersContext } from "./headers.js";
|
|
9
10
|
import { RouterState, SSRContext } from "./router-state.js";
|
package/dist/shims/router.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { isUnknownRecord } from "../utils/record.js";
|
|
2
2
|
import { parseCookieHeader } from "../utils/parse-cookie.js";
|
|
3
3
|
import { isExternalUrl } from "../utils/external-url.js";
|
|
4
|
-
import { sortRoutes, splitPathSegments } from "../routing/utils.js";
|
|
5
4
|
import { hasBasePath, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
|
|
5
|
+
import { substituteDestinationParams } from "../config/destination-params.js";
|
|
6
|
+
import { sortRoutes, splitPathSegments } from "../routing/utils.js";
|
|
6
7
|
import { assertSafeNavigationUrl } from "./url-safety.js";
|
|
7
8
|
import { addLocalePrefix, getDomainLocaleUrl, getLocalePathPrefix } from "../utils/domain-locale.js";
|
|
8
9
|
import { AppRouterContext } from "./internal/app-router-context.js";
|
|
@@ -19,6 +20,7 @@ import { resolveDirectHybridClientRouteOwner } from "./internal/hybrid-client-ro
|
|
|
19
20
|
import { installWindowNext } from "../client/window-next.js";
|
|
20
21
|
import { getWindowOrigin, isAbsoluteOrProtocolRelativeUrl, isAbsoluteUrl, isHashOnlyBrowserUrlChange, normalizePathTrailingSlash, toBrowserNavigationHref, toSameOriginAppPath, toSameOriginPath, withBasePath } from "./url-utils.js";
|
|
21
22
|
import { addQueryParam, mergeRewriteQuery, mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
|
|
23
|
+
import { disableSmoothScrollDuringRouteTransition } from "./disable-smooth-scroll.js";
|
|
22
24
|
import { scrollToHashTarget } from "./hash-scroll.js";
|
|
23
25
|
import { installPagesRouterRuntime, setPagesRouterPopStateHandler, setStampInitialHistoryState } from "./pages-router-runtime.js";
|
|
24
26
|
import { interpolateDynamicRouteHref, resolveDynamicRouteHref } from "./internal/interpolate-as.js";
|
|
@@ -129,16 +131,9 @@ function scrollToPagesRouterPosition({ x, y }) {
|
|
|
129
131
|
window.scrollTo(x, y);
|
|
130
132
|
return;
|
|
131
133
|
}
|
|
132
|
-
|
|
133
|
-
if (!(htmlElement.dataset.scrollBehavior === "smooth")) {
|
|
134
|
+
disableSmoothScrollDuringRouteTransition(() => {
|
|
134
135
|
window.scrollTo(x, y);
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
const previousScrollBehavior = htmlElement.style.scrollBehavior;
|
|
138
|
-
htmlElement.style.scrollBehavior = "auto";
|
|
139
|
-
htmlElement.getClientRects();
|
|
140
|
-
window.scrollTo(x, y);
|
|
141
|
-
htmlElement.style.scrollBehavior = previousScrollBehavior;
|
|
136
|
+
});
|
|
142
137
|
}
|
|
143
138
|
function isAtScrollPosition({ x, y }) {
|
|
144
139
|
return Math.abs(window.scrollX - x) <= SCROLL_RESTORE_TOLERANCE_PX && Math.abs(window.scrollY - y) <= SCROLL_RESTORE_TOLERANCE_PX;
|
|
@@ -940,7 +935,6 @@ function isAppComponent(value) {
|
|
|
940
935
|
function resolveSameOriginRedirectedUrl(responseUrl) {
|
|
941
936
|
const appPath = toSameOriginAppPath(responseUrl, __basePath);
|
|
942
937
|
if (appPath === null) return null;
|
|
943
|
-
if (appPath.startsWith("//")) return normalizePathTrailingSlash(responseUrl, __trailingSlash);
|
|
944
938
|
return normalizePathTrailingSlash(appPath, __trailingSlash);
|
|
945
939
|
}
|
|
946
940
|
function stripLocalePrefixForApiRedirect(appPath) {
|
|
@@ -962,19 +956,13 @@ function resolveLocalRedirectUrl(location) {
|
|
|
962
956
|
let appPath;
|
|
963
957
|
if (location.startsWith("/") && !location.startsWith("//")) try {
|
|
964
958
|
const parsed = new URL(location, "http://vinext.local");
|
|
965
|
-
|
|
959
|
+
const pathname = stripBasePath(parsed.pathname, __basePath);
|
|
960
|
+
appPath = pathname.startsWith("//") ? toSameOriginAppPath(new URL(location, window.location.href).href, __basePath) : pathname + parsed.search + parsed.hash;
|
|
966
961
|
} catch {
|
|
967
962
|
appPath = location;
|
|
968
963
|
}
|
|
969
964
|
else appPath = toSameOriginAppPath(location, __basePath);
|
|
970
965
|
if (appPath === null) return null;
|
|
971
|
-
if (appPath.startsWith("//")) try {
|
|
972
|
-
const browserUrl = new URL(location, window.location.href);
|
|
973
|
-
if (browserUrl.origin !== getWindowOrigin()) return null;
|
|
974
|
-
return normalizePathTrailingSlash(browserUrl.href, __trailingSlash);
|
|
975
|
-
} catch {
|
|
976
|
-
return null;
|
|
977
|
-
}
|
|
978
966
|
return normalizePathTrailingSlash(stripLocalePrefixForApiRedirect(appPath), __trailingSlash);
|
|
979
967
|
}
|
|
980
968
|
function hasClientRewriteRules() {
|
|
@@ -1020,10 +1008,10 @@ async function resolveClientConfigRedirect(href) {
|
|
|
1020
1008
|
if (!redirects || redirects.length === 0) return null;
|
|
1021
1009
|
const routeContext = getClientConfigRouteContext(href);
|
|
1022
1010
|
if (!routeContext) return null;
|
|
1023
|
-
const {
|
|
1024
|
-
const redirect =
|
|
1011
|
+
const [{ matchClientRedirect }, { preserveRedirectDestinationQuery }] = await Promise.all([import("../client/client-redirect-matcher.js"), import("../config/config-matchers.js")]);
|
|
1012
|
+
const redirect = matchClientRedirect(routeContext.pathname, redirects, routeContext.context, routeContext.basePathState);
|
|
1025
1013
|
if (!redirect) return null;
|
|
1026
|
-
return preserveRedirectDestinationQuery(__basePath && routeContext.basePathState.hadBasePath && !isExternalUrl(redirect.destination) && !hasBasePath(redirect.destination, __basePath) ? __basePath + redirect.destination : redirect.destination, routeContext.search);
|
|
1014
|
+
return preserveRedirectDestinationQuery(__basePath && routeContext.basePathState.hadBasePath && !isExternalUrl(redirect.destination) && !hasBasePath(redirect.destination, __basePath) ? __basePath + redirect.destination : redirect.destination, routeContext.search, redirect.destinationQuery);
|
|
1027
1015
|
}
|
|
1028
1016
|
async function applyClientConfigRewrite(href, rewrite) {
|
|
1029
1017
|
const routeContext = getClientConfigRouteContext(href);
|
|
@@ -1076,12 +1064,6 @@ function simpleClientConfigSourceCouldMatch(pathname, source) {
|
|
|
1076
1064
|
const normalizedPathname = removeTrailingSlash(pathname);
|
|
1077
1065
|
return normalizedPathname === normalizedPrefix || normalizedPathname.startsWith(`${normalizedPrefix}/`);
|
|
1078
1066
|
}
|
|
1079
|
-
function substituteSimpleClientConfigDestination(destination, params) {
|
|
1080
|
-
const keys = Object.keys(params);
|
|
1081
|
-
if (keys.length === 0) return destination;
|
|
1082
|
-
const alternation = keys.sort((a, b) => b.length - a.length).map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
1083
|
-
return destination.replace(new RegExp(`:(${alternation})([+*])?(?![A-Za-z0-9_])`, "g"), (_token, key) => params[key] ?? _token);
|
|
1084
|
-
}
|
|
1085
1067
|
function isExternalClientConfigUrl(url) {
|
|
1086
1068
|
return /^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith("//");
|
|
1087
1069
|
}
|
|
@@ -1111,7 +1093,7 @@ function resolveClientConfigRewriteSync(href) {
|
|
|
1111
1093
|
const params = matchSimpleClientConfigPattern(routeContext.pathname, rewrite.source);
|
|
1112
1094
|
if (params === void 0) return void 0;
|
|
1113
1095
|
if (params === null) continue;
|
|
1114
|
-
const rewritten =
|
|
1096
|
+
const rewritten = substituteDestinationParams(rewrite.destination, params, "rewrite");
|
|
1115
1097
|
if (isExternalClientConfigUrl(rewritten)) return { kind: "document" };
|
|
1116
1098
|
currentHref = mergeRewriteQuery(currentHref, rewritten);
|
|
1117
1099
|
matched = true;
|
|
@@ -1827,6 +1809,10 @@ async function performNavigation(url, as, options, mode, onStateUpdate, redirect
|
|
|
1827
1809
|
const absoluteHistoryUrl = sameOriginPath === null ? void 0 : origin && inputHref.startsWith(origin) ? inputHref.slice(origin.length) : sameOriginPath;
|
|
1828
1810
|
const currentRoute = window.__NEXT_DATA__?.page ?? stripBasePath(window.location.pathname, __basePath);
|
|
1829
1811
|
const currentAs = stripBasePath(window.location.pathname, __basePath) + window.location.search;
|
|
1812
|
+
const resolveRelativeRoutePath = (href) => href === "" || /^[/?#]/.test(href) || isAbsoluteUrl(href) ? href : resolvePagesRouterHref(href, {
|
|
1813
|
+
pathname: currentRoute,
|
|
1814
|
+
asPath: currentAs
|
|
1815
|
+
}, __basePath);
|
|
1830
1816
|
const preparedHistoryHref = (isAbsoluteUrl(inputHref) ? toSameOriginAppPath(inputHref, __basePath) : null) ?? absoluteHistoryUrl ?? resolvePagesRouterHref(inputHref, {
|
|
1831
1817
|
pathname: currentRoute,
|
|
1832
1818
|
asPath: currentAs
|
|
@@ -1836,12 +1822,12 @@ async function performNavigation(url, as, options, mode, onStateUpdate, redirect
|
|
|
1836
1822
|
const replaceInheritedLocale = options?.locale !== void 0 && (!as ? urlInheritsCurrentPath || typeof url !== "string" && inheritsVisiblePath(url) : typeof as !== "string" && inheritsVisiblePath(as));
|
|
1837
1823
|
const credentialedHistoryHref = credentialedSameOriginHref(url);
|
|
1838
1824
|
const credentialedDisplayHref = credentialedSameOriginHref(as) ?? (!as ? credentialedHistoryHref : void 0);
|
|
1839
|
-
as = as ? resolveUrl(as, true) : void 0;
|
|
1825
|
+
as = as ? resolveRelativeRoutePath(resolveUrl(as, true)) : void 0;
|
|
1840
1826
|
assertSafeNavigationUrl(resolveUrl(url));
|
|
1841
1827
|
if (as !== void 0) assertSafeNavigationUrl(as);
|
|
1842
1828
|
const isHydrationQueryUpdate = options?._h === 1;
|
|
1843
1829
|
const navigationLocale = resolveTransitionLocale(options?.locale);
|
|
1844
|
-
const unlocalizedRouteHref = resolveUrl(isQueryOnlyString ? `${stripBasePath(window.location.pathname, __basePath)}${url}` : url);
|
|
1830
|
+
const unlocalizedRouteHref = resolveRelativeRoutePath(resolveUrl(isQueryOnlyString ? `${stripBasePath(window.location.pathname, __basePath)}${url}` : url));
|
|
1845
1831
|
const localRouteHref = isExternalUrl(unlocalizedRouteHref) ? toSameOriginAppPath(unlocalizedRouteHref, __basePath) : unlocalizedRouteHref;
|
|
1846
1832
|
const implicitDynamicRoute = !isHydrationQueryUpdate && as === void 0 && localRouteHref !== null ? resolveDynamicRouteHref(localRouteHref) : null;
|
|
1847
1833
|
const routeForNavigation = implicitDynamicRoute?.as ?? unlocalizedRouteHref;
|
|
@@ -2018,7 +2004,10 @@ See more info: https://nextjs.org/docs/messages/invalid-relative-url-external-as
|
|
|
2018
2004
|
emitBeforeHistoryChange();
|
|
2019
2005
|
if (doScroll) {
|
|
2020
2006
|
if (hash) scrollToHashTarget(hash);
|
|
2021
|
-
else
|
|
2007
|
+
else scrollToPagesRouterPosition({
|
|
2008
|
+
x: 0,
|
|
2009
|
+
y: 0
|
|
2010
|
+
});
|
|
2022
2011
|
}
|
|
2023
2012
|
}
|
|
2024
2013
|
onStateUpdate?.();
|
package/dist/shims/server.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export type RequestInit = globalThis.RequestInit & {
|
|
|
26
26
|
}>;
|
|
27
27
|
} | null;
|
|
28
28
|
trailingSlash?: boolean;
|
|
29
|
+
skipTrailingSlashRedirect?: boolean;
|
|
29
30
|
};
|
|
30
31
|
signal?: AbortSignal;
|
|
31
32
|
duplex?: "half";
|
|
@@ -41,13 +42,20 @@ export declare class NextRequest extends Request {
|
|
|
41
42
|
get page(): void;
|
|
42
43
|
get ua(): void;
|
|
43
44
|
/**
|
|
44
|
-
* Client IP address.
|
|
45
|
-
*
|
|
45
|
+
* Client IP address. Next.js removed `ip` in v15; vinext keeps it as an
|
|
46
|
+
* extension. Returns undefined unless the value comes from a trusted source.
|
|
47
|
+
*
|
|
48
|
+
* On Cloudflare Workers (the request carries `cf` metadata), Cloudflare's
|
|
49
|
+
* edge sets `CF-Connecting-IP`. Elsewhere these headers are client-supplied
|
|
50
|
+
* and are only honored behind a trusted proxy (`VINEXT_TRUST_PROXY` /
|
|
51
|
+
* `VINEXT_TRUSTED_HOSTS`), matching the `X-Forwarded-*` policy.
|
|
46
52
|
*/
|
|
47
53
|
get ip(): string | undefined;
|
|
48
54
|
/**
|
|
49
|
-
* Geolocation data.
|
|
50
|
-
*
|
|
55
|
+
* Geolocation data. Next.js removed `geo` in v15; vinext keeps it as an
|
|
56
|
+
* extension. Read from Cloudflare's `request.cf` metadata on Workers, or
|
|
57
|
+
* from platform geo headers behind a trusted proxy. Returns undefined
|
|
58
|
+
* otherwise, because any client can send these headers.
|
|
51
59
|
*/
|
|
52
60
|
get geo(): {
|
|
53
61
|
city?: string;
|
|
@@ -109,6 +117,14 @@ export type NextURLConfig = {
|
|
|
109
117
|
* honour the user's `trailingSlash` config.
|
|
110
118
|
*/
|
|
111
119
|
trailingSlash?: boolean;
|
|
120
|
+
/**
|
|
121
|
+
* When true, the trailing slash follows the parsed URL instead, and
|
|
122
|
+
* `trailingSlash` only decides the root, like Next.js's
|
|
123
|
+
* getNextPathnameInfo. Without the trailing-slash redirect, requests
|
|
124
|
+
* arrive in either form, so the config can no longer be applied as a
|
|
125
|
+
* policy.
|
|
126
|
+
*/
|
|
127
|
+
skipTrailingSlashRedirect?: boolean;
|
|
112
128
|
};
|
|
113
129
|
};
|
|
114
130
|
export declare class NextURL {
|
|
@@ -121,6 +137,8 @@ export declare class NextURL {
|
|
|
121
137
|
*/
|
|
122
138
|
private _configBasePath;
|
|
123
139
|
private _basePath;
|
|
140
|
+
private _configTrailingSlash;
|
|
141
|
+
private _manualTrailingSlash;
|
|
124
142
|
private _trailingSlash;
|
|
125
143
|
private _locale;
|
|
126
144
|
private _configDefaultLocale;
|
|
@@ -129,6 +147,11 @@ export declare class NextURL {
|
|
|
129
147
|
private _domains;
|
|
130
148
|
private _domainLocale;
|
|
131
149
|
constructor(input: string | URL, base?: string | URL, config?: NextURLConfig);
|
|
150
|
+
/**
|
|
151
|
+
* With `skipTrailingSlashRedirect`, take the slash from the parsed pathname
|
|
152
|
+
* (before basePath and locale are stripped), as getNextPathnameInfo does.
|
|
153
|
+
*/
|
|
154
|
+
private _analyzeTrailingSlash;
|
|
132
155
|
/** Strip basePath prefix from the internal pathname.
|
|
133
156
|
* Mirrors Next.js's getNextPathnameInfo (re-run by NextURL.analyze() on
|
|
134
157
|
* every parse, including `href` reassignment): basePath is only considered
|
package/dist/shims/server.js
CHANGED
|
@@ -3,10 +3,11 @@ import { MIDDLEWARE_SET_COOKIE_HEADER } from "../utils/protocol-headers.js";
|
|
|
3
3
|
import { encodeMiddlewareRequestHeaders } from "../utils/middleware-request-headers.js";
|
|
4
4
|
import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
|
|
5
5
|
import { hasBasePath, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
|
|
6
|
-
import { getRequestExecutionContext } from "./request-context.js";
|
|
7
6
|
import { MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER } from "../server/headers.js";
|
|
7
|
+
import { getRequestExecutionContext } from "./request-context.js";
|
|
8
8
|
import { validateCookieAttributeValue, validateCookieName } from "./internal/cookie-serialize.js";
|
|
9
9
|
import { assertSafeNavigationUrl } from "./url-safety.js";
|
|
10
|
+
import { trustProxy } from "../server/proxy-trust.js";
|
|
10
11
|
import { userAgent, userAgentFromString } from "./user-agent.js";
|
|
11
12
|
//#region src/shims/server.ts
|
|
12
13
|
/**
|
|
@@ -97,6 +98,19 @@ function initWithoutInputBody(input, init) {
|
|
|
97
98
|
body: null
|
|
98
99
|
};
|
|
99
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* workerd's `request.cf` metadata. Only the Workers runtime sets it, so its
|
|
103
|
+
* presence means the request came through Cloudflare's edge rather than
|
|
104
|
+
* straight from a client.
|
|
105
|
+
*/
|
|
106
|
+
function readCloudflareMetadata(request) {
|
|
107
|
+
const cf = Reflect.get(request, "cf");
|
|
108
|
+
return cf !== null && typeof cf === "object" ? cf : void 0;
|
|
109
|
+
}
|
|
110
|
+
function readStringField(source, key) {
|
|
111
|
+
const value = Reflect.get(source, key);
|
|
112
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
113
|
+
}
|
|
100
114
|
var NextRequest = class extends Request {
|
|
101
115
|
_nextUrl;
|
|
102
116
|
_url;
|
|
@@ -131,7 +145,8 @@ var NextRequest = class extends Request {
|
|
|
131
145
|
basePath: _nextConfig.basePath,
|
|
132
146
|
nextConfig: {
|
|
133
147
|
i18n,
|
|
134
|
-
trailingSlash: _nextConfig.trailingSlash
|
|
148
|
+
trailingSlash: _nextConfig.trailingSlash,
|
|
149
|
+
skipTrailingSlashRedirect: _nextConfig.skipTrailingSlashRedirect
|
|
135
150
|
}
|
|
136
151
|
} : void 0;
|
|
137
152
|
this._nextUrl = new NextURL(url, void 0, urlConfig);
|
|
@@ -154,17 +169,39 @@ var NextRequest = class extends Request {
|
|
|
154
169
|
throw new Error("NextRequest.ua has been removed; use userAgent() instead");
|
|
155
170
|
}
|
|
156
171
|
/**
|
|
157
|
-
* Client IP address.
|
|
158
|
-
*
|
|
172
|
+
* Client IP address. Next.js removed `ip` in v15; vinext keeps it as an
|
|
173
|
+
* extension. Returns undefined unless the value comes from a trusted source.
|
|
174
|
+
*
|
|
175
|
+
* On Cloudflare Workers (the request carries `cf` metadata), Cloudflare's
|
|
176
|
+
* edge sets `CF-Connecting-IP`. Elsewhere these headers are client-supplied
|
|
177
|
+
* and are only honored behind a trusted proxy (`VINEXT_TRUST_PROXY` /
|
|
178
|
+
* `VINEXT_TRUSTED_HOSTS`), matching the `X-Forwarded-*` policy.
|
|
159
179
|
*/
|
|
160
180
|
get ip() {
|
|
181
|
+
if (readCloudflareMetadata(this)) return this.headers.get("cf-connecting-ip") ?? void 0;
|
|
182
|
+
if (!trustProxy) return void 0;
|
|
161
183
|
return this.headers.get("cf-connecting-ip") ?? this.headers.get("x-real-ip") ?? this.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ?? void 0;
|
|
162
184
|
}
|
|
163
185
|
/**
|
|
164
|
-
* Geolocation data.
|
|
165
|
-
*
|
|
186
|
+
* Geolocation data. Next.js removed `geo` in v15; vinext keeps it as an
|
|
187
|
+
* extension. Read from Cloudflare's `request.cf` metadata on Workers, or
|
|
188
|
+
* from platform geo headers behind a trusted proxy. Returns undefined
|
|
189
|
+
* otherwise, because any client can send these headers.
|
|
166
190
|
*/
|
|
167
191
|
get geo() {
|
|
192
|
+
const cf = readCloudflareMetadata(this);
|
|
193
|
+
if (cf) {
|
|
194
|
+
const country = readStringField(cf, "country");
|
|
195
|
+
if (!country) return void 0;
|
|
196
|
+
return {
|
|
197
|
+
country,
|
|
198
|
+
city: readStringField(cf, "city"),
|
|
199
|
+
region: readStringField(cf, "region"),
|
|
200
|
+
latitude: readStringField(cf, "latitude"),
|
|
201
|
+
longitude: readStringField(cf, "longitude")
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
if (!trustProxy) return void 0;
|
|
168
205
|
const country = this.headers.get("cf-ipcountry") ?? this.headers.get("x-vercel-ip-country") ?? void 0;
|
|
169
206
|
if (!country) return void 0;
|
|
170
207
|
return {
|
|
@@ -266,6 +303,8 @@ var NextURL = class NextURL {
|
|
|
266
303
|
*/
|
|
267
304
|
_configBasePath;
|
|
268
305
|
_basePath;
|
|
306
|
+
_configTrailingSlash;
|
|
307
|
+
_manualTrailingSlash;
|
|
269
308
|
_trailingSlash;
|
|
270
309
|
_locale;
|
|
271
310
|
_configDefaultLocale;
|
|
@@ -277,7 +316,10 @@ var NextURL = class NextURL {
|
|
|
277
316
|
this._url = new URL(input.toString(), base);
|
|
278
317
|
this._configBasePath = config?.basePath ?? "";
|
|
279
318
|
this._basePath = this._configBasePath;
|
|
280
|
-
this.
|
|
319
|
+
this._configTrailingSlash = config?.nextConfig?.trailingSlash ?? false;
|
|
320
|
+
this._manualTrailingSlash = config?.nextConfig?.skipTrailingSlashRedirect === true;
|
|
321
|
+
this._trailingSlash = this._configTrailingSlash;
|
|
322
|
+
this._analyzeTrailingSlash();
|
|
281
323
|
this._stripBasePath();
|
|
282
324
|
const i18n = config?.nextConfig?.i18n;
|
|
283
325
|
if (i18n) {
|
|
@@ -290,6 +332,15 @@ var NextURL = class NextURL {
|
|
|
290
332
|
this._analyzeI18n();
|
|
291
333
|
}
|
|
292
334
|
}
|
|
335
|
+
/**
|
|
336
|
+
* With `skipTrailingSlashRedirect`, take the slash from the parsed pathname
|
|
337
|
+
* (before basePath and locale are stripped), as getNextPathnameInfo does.
|
|
338
|
+
*/
|
|
339
|
+
_analyzeTrailingSlash() {
|
|
340
|
+
if (!this._manualTrailingSlash) return;
|
|
341
|
+
const { pathname } = this._url;
|
|
342
|
+
this._trailingSlash = pathname !== "/" ? pathname.endsWith("/") : this._configTrailingSlash;
|
|
343
|
+
}
|
|
293
344
|
/** Strip basePath prefix from the internal pathname.
|
|
294
345
|
* Mirrors Next.js's getNextPathnameInfo (re-run by NextURL.analyze() on
|
|
295
346
|
* every parse, including `href` reassignment): basePath is only considered
|
|
@@ -348,7 +399,8 @@ var NextURL = class NextURL {
|
|
|
348
399
|
*/
|
|
349
400
|
_applyTrailingSlash(pathname) {
|
|
350
401
|
if (pathname === "" || pathname === "/") return pathname;
|
|
351
|
-
|
|
402
|
+
const pathnameWithoutBasePath = this._basePath ? stripBasePath(pathname, this._basePath) : pathname;
|
|
403
|
+
if (!this._manualTrailingSlash && pathnameWithoutBasePath.startsWith("/_next/")) return removeTrailingSlash(pathname);
|
|
352
404
|
if (this._trailingSlash) return pathname.endsWith("/") ? pathname : pathname + "/";
|
|
353
405
|
return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
|
354
406
|
}
|
|
@@ -361,6 +413,7 @@ var NextURL = class NextURL {
|
|
|
361
413
|
}
|
|
362
414
|
set href(value) {
|
|
363
415
|
this._url.href = value;
|
|
416
|
+
this._analyzeTrailingSlash();
|
|
364
417
|
this._stripBasePath();
|
|
365
418
|
this._analyzeI18n();
|
|
366
419
|
}
|
|
@@ -467,7 +520,10 @@ var NextURL = class NextURL {
|
|
|
467
520
|
locales: domain.locales ? [...domain.locales] : void 0
|
|
468
521
|
}))
|
|
469
522
|
};
|
|
470
|
-
if (this.
|
|
523
|
+
if (this._manualTrailingSlash) {
|
|
524
|
+
nextConfig.skipTrailingSlashRedirect = true;
|
|
525
|
+
if (this._configTrailingSlash) nextConfig.trailingSlash = true;
|
|
526
|
+
} else if (this._trailingSlash) nextConfig.trailingSlash = true;
|
|
471
527
|
const config = {
|
|
472
528
|
basePath: this._configBasePath,
|
|
473
529
|
nextConfig: Object.keys(nextConfig).length > 0 ? nextConfig : void 0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ExecutionContextLike } from "./request-context.js";
|
|
2
2
|
import { CacheState } from "./cache-request-state.js";
|
|
3
3
|
import { RootParamsState } from "./root-params.js";
|
|
4
|
-
import { FetchCacheState } from "./fetch-cache.js";
|
|
4
|
+
import { FetchCacheState } from "./fetch-cache-state.js";
|
|
5
5
|
import { VinextHeadersShimState } from "./internal/headers-state.js";
|
|
6
6
|
import { RouterState } from "./router-state.js";
|
|
7
7
|
import { markFullyBufferedBody, preserveFullyBufferedBodyMetadata } from "../server/fully-buffered-response.js";
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
export declare function isAbsoluteUrl(url: string): boolean;
|
|
3
3
|
export declare function isAbsoluteOrProtocolRelativeUrl(url: string): boolean;
|
|
4
4
|
export declare function getWindowOrigin(): string | null;
|
|
5
|
+
/**
|
|
6
|
+
* A same-origin pathname can start with "//" (e.g. `https://app.com//evil.com`),
|
|
7
|
+
* and as a local path that is a protocol-relative reference to another host.
|
|
8
|
+
* Collapse the leading slashes: Next.js does the same for these URLs, on the
|
|
9
|
+
* client (`resolveHref`) or with its server's repeated-slash 308.
|
|
10
|
+
*/
|
|
11
|
+
export declare function collapseLeadingSlashes(pathname: string): string;
|
|
5
12
|
/**
|
|
6
13
|
* If `url` is an absolute same-origin URL, return the local path
|
|
7
14
|
* (pathname + search + hash). Returns null for truly external URLs
|
|
@@ -30,6 +37,8 @@ export declare function toSameOriginAppPath(url: string, basePath: string): stri
|
|
|
30
37
|
* `.well-known`-aware redirect rule shipped in `routes-manifest.json`.
|
|
31
38
|
* - Query strings and hash fragments are preserved verbatim.
|
|
32
39
|
* - Idempotent: already-canonical paths round-trip unchanged.
|
|
40
|
+
* - With `skipTrailingSlashRedirect`, every path is returned as written, like
|
|
41
|
+
* Next.js's `__NEXT_MANUAL_TRAILING_SLASH` short-circuit.
|
|
33
42
|
*/
|
|
34
43
|
export declare function normalizePathTrailingSlash(path: string, trailingSlash: boolean): string;
|
|
35
44
|
/**
|
package/dist/shims/url-utils.js
CHANGED
|
@@ -25,6 +25,15 @@ function getWindowOrigin() {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
+
* A same-origin pathname can start with "//" (e.g. `https://app.com//evil.com`),
|
|
29
|
+
* and as a local path that is a protocol-relative reference to another host.
|
|
30
|
+
* Collapse the leading slashes: Next.js does the same for these URLs, on the
|
|
31
|
+
* client (`resolveHref`) or with its server's repeated-slash 308.
|
|
32
|
+
*/
|
|
33
|
+
function collapseLeadingSlashes(pathname) {
|
|
34
|
+
return pathname.replace(/^\/{2,}/, "/");
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
28
37
|
* If `url` is an absolute same-origin URL, return the local path
|
|
29
38
|
* (pathname + search + hash). Returns null for truly external URLs
|
|
30
39
|
* or on the server (where origin is unknown).
|
|
@@ -34,7 +43,7 @@ function toSameOriginPath(url) {
|
|
|
34
43
|
if (!origin) return null;
|
|
35
44
|
try {
|
|
36
45
|
const parsed = url.startsWith("//") ? new URL(url, origin) : new URL(url);
|
|
37
|
-
if (parsed.origin === origin) return parsed.pathname + parsed.search + parsed.hash;
|
|
46
|
+
if (parsed.origin === origin) return collapseLeadingSlashes(parsed.pathname) + parsed.search + parsed.hash;
|
|
38
47
|
} catch {}
|
|
39
48
|
return null;
|
|
40
49
|
}
|
|
@@ -49,7 +58,7 @@ function toSameOriginAppPath(url, basePath) {
|
|
|
49
58
|
try {
|
|
50
59
|
const parsed = new URL(localPath, "http://vinext.local");
|
|
51
60
|
if (!hasBasePath(parsed.pathname, basePath)) return null;
|
|
52
|
-
return stripBasePath(parsed.pathname, basePath) + parsed.search + parsed.hash;
|
|
61
|
+
return collapseLeadingSlashes(stripBasePath(parsed.pathname, basePath)) + parsed.search + parsed.hash;
|
|
53
62
|
} catch {
|
|
54
63
|
return localPath;
|
|
55
64
|
}
|
|
@@ -99,9 +108,11 @@ function removeRouteTrailingSlash(route) {
|
|
|
99
108
|
* `.well-known`-aware redirect rule shipped in `routes-manifest.json`.
|
|
100
109
|
* - Query strings and hash fragments are preserved verbatim.
|
|
101
110
|
* - Idempotent: already-canonical paths round-trip unchanged.
|
|
111
|
+
* - With `skipTrailingSlashRedirect`, every path is returned as written, like
|
|
112
|
+
* Next.js's `__NEXT_MANUAL_TRAILING_SLASH` short-circuit.
|
|
102
113
|
*/
|
|
103
114
|
function normalizePathTrailingSlash(path, trailingSlash) {
|
|
104
|
-
if (!path.startsWith("/") || path.startsWith("//")) return path;
|
|
115
|
+
if (!path.startsWith("/") || path.startsWith("//") || process.env.__VINEXT_MANUAL_TRAILING_SLASH === "true") return path;
|
|
105
116
|
const { pathname, query, hash } = parsePath(path);
|
|
106
117
|
if (trailingSlash) {
|
|
107
118
|
if (/\.[^/]+\/?$/.test(pathname)) return `${removeRouteTrailingSlash(pathname)}${query}${hash}`;
|
|
@@ -162,4 +173,4 @@ function isHashOnlyBrowserUrlChange(href, currentHref, basePath = "") {
|
|
|
162
173
|
}
|
|
163
174
|
}
|
|
164
175
|
//#endregion
|
|
165
|
-
export { getWindowOrigin, isAbsoluteOrProtocolRelativeUrl, isAbsoluteUrl, isHashOnlyBrowserUrlChange, normalizePathTrailingSlash, resolveRelativeHref, toBrowserNavigationHref, toCanonicalBrowserNavigationHref, toSameOriginAppPath, toSameOriginPath, withBasePath };
|
|
176
|
+
export { collapseLeadingSlashes, getWindowOrigin, isAbsoluteOrProtocolRelativeUrl, isAbsoluteUrl, isHashOnlyBrowserUrlChange, normalizePathTrailingSlash, resolveRelativeHref, toBrowserNavigationHref, toCanonicalBrowserNavigationHref, toSameOriginAppPath, toSameOriginPath, withBasePath };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
import { isAbsoluteAssetPrefix, resolveAssetsDir } from "./asset-prefix.js";
|
|
3
3
|
import { manifestFileWithAssetPrefix, manifestFileWithBase } from "./manifest-paths.js";
|
|
4
|
-
import { findClientEntryFile, findPagesClientEntryFile, readClientBuildManifest } from "./client-build-manifest.js";
|
|
5
4
|
import { findClientEntryFileFromVinextManifest, findPagesClientEntryFileFromVinextManifest, readClientEntryManifest } from "./client-entry-manifest.js";
|
|
5
|
+
import { findClientEntryFile, findPagesClientEntryFile, readClientBuildManifest } from "./client-build-manifest.js";
|
|
6
6
|
import { computeDynamicImportPreloads, computeLazyChunks, dynamicImportPreloadsWithBase } from "./lazy-chunks.js";
|
|
7
7
|
//#region src/utils/client-runtime-metadata.ts
|
|
8
8
|
function collectCssGraph(buildManifest, applyBase) {
|