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
|
@@ -2,7 +2,7 @@ import { stripBasePath } from "../utils/base-path.js";
|
|
|
2
2
|
import { getLocalePathPrefix } from "../utils/domain-locale.js";
|
|
3
3
|
//#region src/client/pages-router-link-navigation.ts
|
|
4
4
|
function resolvePagesRouterQueryOnlyHref(href, { asPath, basePath, fallbackHref, locales }) {
|
|
5
|
-
if (!href.startsWith("?")) return href;
|
|
5
|
+
if (!href.startsWith("?") && !href.startsWith("#")) return href;
|
|
6
6
|
try {
|
|
7
7
|
const fallbackUrl = new URL(fallbackHref);
|
|
8
8
|
const base = new URL(asPath ?? `${stripBasePath(fallbackUrl.pathname, basePath)}${fallbackUrl.search}${fallbackUrl.hash}`, "http://vinext.local");
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { HasCondition, NextHeader, NextI18nConfig, NextRedirect, NextRewrite } from "./next-config.js";
|
|
2
|
+
import { RequestContext, normalizeHost, parseCookies, requestContextFromRequest } from "./request-context.js";
|
|
3
|
+
import { isExternalUrl } from "../utils/external-url.js";
|
|
2
4
|
|
|
3
5
|
//#region src/config/config-matchers.d.ts
|
|
4
6
|
/**
|
|
5
7
|
* Detect regex patterns vulnerable to catastrophic backtracking (ReDoS).
|
|
6
8
|
*
|
|
7
|
-
* Uses
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Uses the same deterministic structural analysis as middleware matcher
|
|
10
|
+
* validation. Nested bounded repetition is accepted only when its repeated
|
|
11
|
+
* language has fixed width and unambiguous branches; a fixed outer count can
|
|
12
|
+
* otherwise still cause polynomially catastrophic backtracking on long near
|
|
13
|
+
* misses.
|
|
11
14
|
*
|
|
12
15
|
* Returns true if the pattern appears safe, false if it's potentially dangerous.
|
|
13
16
|
*/
|
|
14
|
-
declare function isSafeRegex(pattern: string): boolean;
|
|
17
|
+
declare function isSafeRegex(pattern: string, flags?: string): boolean;
|
|
15
18
|
/**
|
|
16
19
|
* Compile a regex pattern safely. Returns the compiled RegExp or null if the
|
|
17
20
|
* pattern is invalid or vulnerable to ReDoS.
|
|
@@ -27,16 +30,6 @@ declare function safeRegExp(pattern: string, flags?: string): RegExp | null;
|
|
|
27
30
|
* which CodeQL flags as incomplete sanitization), then groups are restored.
|
|
28
31
|
*/
|
|
29
32
|
declare function escapeHeaderSource(source: string): string;
|
|
30
|
-
/**
|
|
31
|
-
* Request context needed for evaluating has/missing conditions.
|
|
32
|
-
* Callers extract the relevant parts from the incoming Request.
|
|
33
|
-
*/
|
|
34
|
-
type RequestContext = {
|
|
35
|
-
readonly headers: Headers;
|
|
36
|
-
readonly cookies: Record<string, string>;
|
|
37
|
-
readonly query: URLSearchParams;
|
|
38
|
-
readonly host: string;
|
|
39
|
-
};
|
|
40
33
|
/**
|
|
41
34
|
* basePath gating state passed alongside the pathname to every matcher.
|
|
42
35
|
*
|
|
@@ -59,22 +52,6 @@ type BasePathMatchState = {
|
|
|
59
52
|
*/
|
|
60
53
|
hadBasePath: boolean;
|
|
61
54
|
};
|
|
62
|
-
/**
|
|
63
|
-
* Parse a Cookie header string into a key-value record.
|
|
64
|
-
*/
|
|
65
|
-
declare function parseCookies(cookieHeader: string | null): Record<string, string>;
|
|
66
|
-
/**
|
|
67
|
-
* Build a RequestContext from a Web Request object.
|
|
68
|
-
*
|
|
69
|
-
* `cookies` and `query` are lazy memoized getters: they are consumed only by
|
|
70
|
-
* `has`/`missing` condition evaluation (`checkHasConditions` /
|
|
71
|
-
* `matchesRuleConditions`), and most apps configure no such conditions. The
|
|
72
|
-
* cookie split and `searchParams` access are therefore deferred until first
|
|
73
|
-
* read and computed at most once. Mirrors `headersContextFromRequest` in
|
|
74
|
-
* `shims/headers.ts`.
|
|
75
|
-
*/
|
|
76
|
-
declare function requestContextFromRequest(request: Request): RequestContext;
|
|
77
|
-
declare function normalizeHost(hostHeader: string | null, fallbackHostname: string): string;
|
|
78
55
|
/**
|
|
79
56
|
* Unpack `x-middleware-request-*` headers from the collected middleware
|
|
80
57
|
* response headers into the actual request, and strip all `x-middleware-*`
|
|
@@ -147,7 +124,7 @@ declare function matchRedirect(pathname: string, redirects: NextRedirect[], ctx:
|
|
|
147
124
|
* to evaluate has/missing conditions. Next.js always has request context
|
|
148
125
|
* when evaluating rewrites, so this parameter is required.
|
|
149
126
|
*/
|
|
150
|
-
declare function matchRewrite(pathname: string, rewrites: NextRewrite[], ctx: RequestContext, basePathState?: BasePathMatchState): string | null;
|
|
127
|
+
declare function matchRewrite(pathname: string, rewrites: NextRewrite[], ctx: RequestContext, basePathState?: BasePathMatchState, paramsPathname?: string): string | null;
|
|
151
128
|
/**
|
|
152
129
|
* Check whether a rewrite source can match a pathname without evaluating its
|
|
153
130
|
* request-dependent `has` / `missing` conditions.
|
|
@@ -175,7 +152,6 @@ declare function sanitizeDestination(dest: string): string;
|
|
|
175
152
|
* Detects any URL scheme (http:, https:, data:, javascript:, blob:, etc.)
|
|
176
153
|
* per RFC 3986, plus protocol-relative URLs (//).
|
|
177
154
|
*/
|
|
178
|
-
declare function isExternalUrl(url: string): boolean;
|
|
179
155
|
/**
|
|
180
156
|
* Merge the original request's query params into a config-redirect
|
|
181
157
|
* destination, preserving them on the resulting `Location`.
|
|
@@ -218,8 +194,8 @@ declare function matchHeaders(pathname: string, headers: NextHeader[], ctx: Requ
|
|
|
218
194
|
value: string;
|
|
219
195
|
}>;
|
|
220
196
|
/**
|
|
221
|
-
* Apply Next.js i18n locale-prefix transformation to a set of redirect
|
|
222
|
-
* rewrite rules. Mirrors the relevant slice of Next.js's `processRoutes`
|
|
197
|
+
* Apply Next.js i18n locale-prefix transformation to a set of redirect,
|
|
198
|
+
* rewrite, or header rules. Mirrors the relevant slice of Next.js's `processRoutes`
|
|
223
199
|
* (load-custom-routes.ts) with one deliberate divergence noted below.
|
|
224
200
|
*
|
|
225
201
|
* For each rule:
|
|
@@ -250,8 +226,8 @@ declare function matchHeaders(pathname: string, headers: NextHeader[], ctx: Requ
|
|
|
250
226
|
* Mirrors the Next.js reference in
|
|
251
227
|
* packages/next/src/lib/load-custom-routes.ts — see `processRoutes`.
|
|
252
228
|
*/
|
|
253
|
-
declare function applyLocaleToRoutes<T extends NextRedirect | NextRewrite>(routes: T[], i18n: NextI18nConfig | null | undefined, type: "redirect" | "rewrite", options?: {
|
|
229
|
+
declare function applyLocaleToRoutes<T extends NextRedirect | NextRewrite | NextHeader>(routes: T[], i18n: NextI18nConfig | null | undefined, type: "redirect" | "rewrite" | "header", options?: {
|
|
254
230
|
trailingSlash?: boolean;
|
|
255
231
|
}): T[];
|
|
256
232
|
//#endregion
|
|
257
|
-
export { BasePathMatchState, RequestContext, applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions, escapeHeaderSource, isExternalUrl, isSafeRegex, matchConfigPattern, matchHeaders, matchRedirect, matchRewrite, matchesRewriteSource, normalizeHost, parseCookies, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, safeRegExp, sanitizeDestination };
|
|
233
|
+
export { BasePathMatchState, type RequestContext, applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions, escapeHeaderSource, isExternalUrl, isSafeRegex, matchConfigPattern, matchHeaders, matchRedirect, matchRewrite, matchesRewriteSource, normalizeHost, parseCookies, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, safeRegExp, sanitizeDestination };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "../utils/protocol-headers.js";
|
|
2
2
|
import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
|
|
3
|
-
import {
|
|
3
|
+
import { analyzeRegexSafety } from "../utils/regex-safety.js";
|
|
4
|
+
import { normalizeHost, parseCookies, requestContextFromRequest } from "./request-context.js";
|
|
5
|
+
import { isExternalUrl } from "../utils/external-url.js";
|
|
4
6
|
//#region src/config/config-matchers.ts
|
|
5
7
|
/**
|
|
6
8
|
* Cache for compiled regex patterns in matchConfigPattern.
|
|
@@ -159,7 +161,7 @@ function _getRedirectIndex(redirects) {
|
|
|
159
161
|
return index;
|
|
160
162
|
}
|
|
161
163
|
/** Hop-by-hop headers that should not be forwarded through a proxy. */
|
|
162
|
-
const HOP_BY_HOP_HEADERS = new Set([
|
|
164
|
+
const HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
163
165
|
"connection",
|
|
164
166
|
"keep-alive",
|
|
165
167
|
"proxy-authenticate",
|
|
@@ -175,7 +177,7 @@ const HOP_BY_HOP_HEADERS = new Set([
|
|
|
175
177
|
* still forwards proxy auth credentials, while response sanitization strips
|
|
176
178
|
* them before returning data to the client.
|
|
177
179
|
*/
|
|
178
|
-
const REQUEST_HOP_BY_HOP_HEADERS = new Set([
|
|
180
|
+
const REQUEST_HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
179
181
|
"connection",
|
|
180
182
|
"keep-alive",
|
|
181
183
|
"te",
|
|
@@ -191,75 +193,16 @@ function stripHopByHopRequestHeaders(headers) {
|
|
|
191
193
|
/**
|
|
192
194
|
* Detect regex patterns vulnerable to catastrophic backtracking (ReDoS).
|
|
193
195
|
*
|
|
194
|
-
* Uses
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
196
|
+
* Uses the same deterministic structural analysis as middleware matcher
|
|
197
|
+
* validation. Nested bounded repetition is accepted only when its repeated
|
|
198
|
+
* language has fixed width and unambiguous branches; a fixed outer count can
|
|
199
|
+
* otherwise still cause polynomially catastrophic backtracking on long near
|
|
200
|
+
* misses.
|
|
198
201
|
*
|
|
199
202
|
* Returns true if the pattern appears safe, false if it's potentially dangerous.
|
|
200
203
|
*/
|
|
201
|
-
function isSafeRegex(pattern) {
|
|
202
|
-
|
|
203
|
-
let depth = 0;
|
|
204
|
-
let i = 0;
|
|
205
|
-
while (i < pattern.length) {
|
|
206
|
-
const ch = pattern[i];
|
|
207
|
-
if (ch === "\\") {
|
|
208
|
-
i += 2;
|
|
209
|
-
continue;
|
|
210
|
-
}
|
|
211
|
-
if (ch === "[") {
|
|
212
|
-
i++;
|
|
213
|
-
while (i < pattern.length && pattern[i] !== "]") {
|
|
214
|
-
if (pattern[i] === "\\") i++;
|
|
215
|
-
i++;
|
|
216
|
-
}
|
|
217
|
-
i++;
|
|
218
|
-
continue;
|
|
219
|
-
}
|
|
220
|
-
if (ch === "(") {
|
|
221
|
-
depth++;
|
|
222
|
-
if (quantifierAtDepth.length <= depth) quantifierAtDepth.push(false);
|
|
223
|
-
else quantifierAtDepth[depth] = false;
|
|
224
|
-
i++;
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
if (ch === ")") {
|
|
228
|
-
const hadQuantifier = depth > 0 && quantifierAtDepth[depth];
|
|
229
|
-
if (depth > 0) depth--;
|
|
230
|
-
const next = pattern[i + 1];
|
|
231
|
-
if (next === "+" || next === "*" || next === "{") {
|
|
232
|
-
if (hadQuantifier) return false;
|
|
233
|
-
if (depth >= 0 && depth < quantifierAtDepth.length) quantifierAtDepth[depth] = true;
|
|
234
|
-
}
|
|
235
|
-
i++;
|
|
236
|
-
continue;
|
|
237
|
-
}
|
|
238
|
-
if (ch === "+" || ch === "*") {
|
|
239
|
-
if (depth > 0) quantifierAtDepth[depth] = true;
|
|
240
|
-
i++;
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
if (ch === "?") {
|
|
244
|
-
const prev = i > 0 ? pattern[i - 1] : "";
|
|
245
|
-
if (prev !== "+" && prev !== "*" && prev !== "?" && prev !== "}") {
|
|
246
|
-
if (depth > 0) quantifierAtDepth[depth] = true;
|
|
247
|
-
}
|
|
248
|
-
i++;
|
|
249
|
-
continue;
|
|
250
|
-
}
|
|
251
|
-
if (ch === "{") {
|
|
252
|
-
let j = i + 1;
|
|
253
|
-
while (j < pattern.length && /[\d,]/.test(pattern[j])) j++;
|
|
254
|
-
if (j < pattern.length && pattern[j] === "}" && j > i + 1) {
|
|
255
|
-
if (depth > 0) quantifierAtDepth[depth] = true;
|
|
256
|
-
i = j + 1;
|
|
257
|
-
continue;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
i++;
|
|
261
|
-
}
|
|
262
|
-
return true;
|
|
204
|
+
function isSafeRegex(pattern, flags) {
|
|
205
|
+
return analyzeRegexSafety(pattern, { ignoreCase: flags?.includes("i") }) === null;
|
|
263
206
|
}
|
|
264
207
|
/**
|
|
265
208
|
* Compile a regex pattern safely. Returns the compiled RegExp or null if the
|
|
@@ -268,8 +211,8 @@ function isSafeRegex(pattern) {
|
|
|
268
211
|
* Logs a warning when a pattern is rejected so developers can fix their config.
|
|
269
212
|
*/
|
|
270
213
|
function safeRegExp(pattern, flags) {
|
|
271
|
-
if (!isSafeRegex(pattern)) {
|
|
272
|
-
console.warn(`[vinext] Rejecting potentially unsafe regex pattern (ReDoS risk): ${pattern}\n
|
|
214
|
+
if (!isSafeRegex(pattern, flags)) {
|
|
215
|
+
console.warn(`[vinext] Rejecting potentially unsafe regex pattern (ReDoS risk): ${pattern}\n Nested or ambiguous repetition can cause catastrophic backtracking.\n Simplify the pattern to make repeated matches fixed and unambiguous.`);
|
|
273
216
|
return null;
|
|
274
217
|
}
|
|
275
218
|
try {
|
|
@@ -342,40 +285,6 @@ function shouldEvaluateRule(ruleBasePath, state) {
|
|
|
342
285
|
return ruleBasePath === false ? !state.hadBasePath : state.hadBasePath;
|
|
343
286
|
}
|
|
344
287
|
/**
|
|
345
|
-
* Parse a Cookie header string into a key-value record.
|
|
346
|
-
*/
|
|
347
|
-
function parseCookies(cookieHeader) {
|
|
348
|
-
return parseCookieHeader(cookieHeader);
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Build a RequestContext from a Web Request object.
|
|
352
|
-
*
|
|
353
|
-
* `cookies` and `query` are lazy memoized getters: they are consumed only by
|
|
354
|
-
* `has`/`missing` condition evaluation (`checkHasConditions` /
|
|
355
|
-
* `matchesRuleConditions`), and most apps configure no such conditions. The
|
|
356
|
-
* cookie split and `searchParams` access are therefore deferred until first
|
|
357
|
-
* read and computed at most once. Mirrors `headersContextFromRequest` in
|
|
358
|
-
* `shims/headers.ts`.
|
|
359
|
-
*/
|
|
360
|
-
function requestContextFromRequest(request) {
|
|
361
|
-
const url = new URL(request.url);
|
|
362
|
-
let cookies;
|
|
363
|
-
let query;
|
|
364
|
-
return {
|
|
365
|
-
headers: request.headers,
|
|
366
|
-
get cookies() {
|
|
367
|
-
return cookies ??= parseCookies(request.headers.get("cookie"));
|
|
368
|
-
},
|
|
369
|
-
get query() {
|
|
370
|
-
return query ??= url.searchParams;
|
|
371
|
-
},
|
|
372
|
-
host: normalizeHost(request.headers.get("host"), url.hostname)
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
function normalizeHost(hostHeader, fallbackHostname) {
|
|
376
|
-
return (hostHeader ?? fallbackHostname).split(":", 1)[0].toLowerCase();
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
288
|
* Unpack `x-middleware-request-*` headers from the collected middleware
|
|
380
289
|
* response headers into the actual request, and strip all `x-middleware-*`
|
|
381
290
|
* internal signals so they never reach clients.
|
|
@@ -410,7 +319,7 @@ function _emptyParams() {
|
|
|
410
319
|
return Object.create(null);
|
|
411
320
|
}
|
|
412
321
|
function _matchConditionValue(actualValue, expectedValue) {
|
|
413
|
-
if (expectedValue
|
|
322
|
+
if (!expectedValue) return actualValue ? _emptyParams() : null;
|
|
414
323
|
const re = _cachedConditionRegex(expectedValue);
|
|
415
324
|
if (re) {
|
|
416
325
|
const match = re.exec(actualValue);
|
|
@@ -440,9 +349,10 @@ function matchSingleCondition(condition, ctx) {
|
|
|
440
349
|
return _matchConditionValue(cookieValue, condition.value);
|
|
441
350
|
}
|
|
442
351
|
case "query": {
|
|
443
|
-
const
|
|
444
|
-
if (
|
|
445
|
-
|
|
352
|
+
const queryValues = ctx.query.getAll(condition.key);
|
|
353
|
+
if (queryValues.length === 0) return null;
|
|
354
|
+
if (!condition.value && queryValues.length > 1) return _emptyParams();
|
|
355
|
+
return _matchConditionValue(queryValues[queryValues.length - 1], condition.value);
|
|
446
356
|
}
|
|
447
357
|
case "host":
|
|
448
358
|
if (condition.value !== void 0) return _matchConditionValue(ctx.host, condition.value);
|
|
@@ -710,11 +620,12 @@ function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAU
|
|
|
710
620
|
* to evaluate has/missing conditions. Next.js always has request context
|
|
711
621
|
* when evaluating rewrites, so this parameter is required.
|
|
712
622
|
*/
|
|
713
|
-
function matchRewrite(pathname, rewrites, ctx, basePathState = _BASEPATH_DEFAULT) {
|
|
623
|
+
function matchRewrite(pathname, rewrites, ctx, basePathState = _BASEPATH_DEFAULT, paramsPathname = pathname) {
|
|
714
624
|
for (const rewrite of rewrites) {
|
|
715
625
|
if (!shouldEvaluateRule(rewrite.basePath, basePathState)) continue;
|
|
716
|
-
const
|
|
717
|
-
if (
|
|
626
|
+
const matchedParams = matchConfigPattern(pathname, rewrite.source);
|
|
627
|
+
if (matchedParams) {
|
|
628
|
+
const params = paramsPathname === pathname ? matchedParams : matchConfigPattern(paramsPathname, rewrite.source) ?? matchedParams;
|
|
718
629
|
const conditionParams = rewrite.has || rewrite.missing ? collectConditionParams(rewrite.has, rewrite.missing, ctx) : _emptyParams();
|
|
719
630
|
if (!conditionParams) continue;
|
|
720
631
|
const rewriteParams = {
|
|
@@ -868,9 +779,6 @@ function sanitizeDestination(dest) {
|
|
|
868
779
|
* Detects any URL scheme (http:, https:, data:, javascript:, blob:, etc.)
|
|
869
780
|
* per RFC 3986, plus protocol-relative URLs (//).
|
|
870
781
|
*/
|
|
871
|
-
function isExternalUrl(url) {
|
|
872
|
-
return /^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith("//");
|
|
873
|
-
}
|
|
874
782
|
/**
|
|
875
783
|
* Merge the original request's query params into a config-redirect
|
|
876
784
|
* destination, preserving them on the resulting `Location`.
|
|
@@ -1004,8 +912,8 @@ function _escapeRegexString(value) {
|
|
|
1004
912
|
return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
|
|
1005
913
|
}
|
|
1006
914
|
/**
|
|
1007
|
-
* Apply Next.js i18n locale-prefix transformation to a set of redirect
|
|
1008
|
-
* rewrite rules. Mirrors the relevant slice of Next.js's `processRoutes`
|
|
915
|
+
* Apply Next.js i18n locale-prefix transformation to a set of redirect,
|
|
916
|
+
* rewrite, or header rules. Mirrors the relevant slice of Next.js's `processRoutes`
|
|
1009
917
|
* (load-custom-routes.ts) with one deliberate divergence noted below.
|
|
1010
918
|
*
|
|
1011
919
|
* For each rule:
|
|
@@ -1048,7 +956,8 @@ function applyLocaleToRoutes(routes, i18n, type, options = {}) {
|
|
|
1048
956
|
out.push(r);
|
|
1049
957
|
continue;
|
|
1050
958
|
}
|
|
1051
|
-
const
|
|
959
|
+
const destination = "destination" in r ? r.destination : void 0;
|
|
960
|
+
const isExternal = !!destination && !destination.startsWith("/");
|
|
1052
961
|
if (!isExternal) for (const locale of defaultLocales) {
|
|
1053
962
|
const localizedSource = `/${locale}${suffixFor(r.source)}`;
|
|
1054
963
|
out.push({
|
|
@@ -1057,13 +966,14 @@ function applyLocaleToRoutes(routes, i18n, type, options = {}) {
|
|
|
1057
966
|
});
|
|
1058
967
|
}
|
|
1059
968
|
const internalSource = `${internalLocale}${suffixFor(r.source)}`;
|
|
1060
|
-
let internalDestination =
|
|
969
|
+
let internalDestination = destination;
|
|
1061
970
|
if (internalDestination && internalDestination.startsWith("/") && !isExternal) internalDestination = `/:nextInternalLocale${internalDestination === "/" && !trailingSlash ? "" : internalDestination}`;
|
|
1062
|
-
|
|
971
|
+
const internalRoute = {
|
|
1063
972
|
...r,
|
|
1064
|
-
source: internalSource
|
|
1065
|
-
|
|
1066
|
-
|
|
973
|
+
source: internalSource
|
|
974
|
+
};
|
|
975
|
+
if ("destination" in internalRoute && internalDestination !== void 0) internalRoute.destination = internalDestination;
|
|
976
|
+
out.push(internalRoute);
|
|
1067
977
|
out.push(r);
|
|
1068
978
|
}
|
|
1069
979
|
return out;
|
package/dist/config/dotenv.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { PHASE_PRODUCTION_BUILD } from "../shims/constants.js";
|
|
2
|
+
import { PluginOption } from "vite";
|
|
2
3
|
|
|
3
4
|
//#region src/config/next-config.d.ts
|
|
5
|
+
declare const VINEXT_NEXT_CONFIG_PLUGIN_PROPERTY = "__vinextNextConfig";
|
|
4
6
|
/**
|
|
5
7
|
* Parse a body size limit value (string or number) into bytes.
|
|
6
8
|
* Accepts Next.js-style strings like "1mb", "500kb", "10mb", bare number strings like "1048576" (bytes),
|
|
@@ -52,7 +54,8 @@ type NextHeader = {
|
|
|
52
54
|
key: string;
|
|
53
55
|
value: string;
|
|
54
56
|
}>; /** See {@link NextRedirect.basePath}. */
|
|
55
|
-
basePath?: false;
|
|
57
|
+
basePath?: false; /** See {@link NextRedirect.locale}. */
|
|
58
|
+
locale?: false;
|
|
56
59
|
};
|
|
57
60
|
type NextI18nConfig = {
|
|
58
61
|
/** List of supported locales */locales: string[]; /** The default locale (used when no locale prefix is in the URL) */
|
|
@@ -69,7 +72,7 @@ type NextI18nConfig = {
|
|
|
69
72
|
domain: string;
|
|
70
73
|
defaultLocale: string;
|
|
71
74
|
locales?: string[];
|
|
72
|
-
http?:
|
|
75
|
+
http?: true;
|
|
73
76
|
}>;
|
|
74
77
|
};
|
|
75
78
|
/**
|
|
@@ -241,6 +244,7 @@ type NextConfigFactory = (phase: string, opts: {
|
|
|
241
244
|
defaultConfig: NextConfig;
|
|
242
245
|
}) => NextConfig | Promise<NextConfig>;
|
|
243
246
|
type NextConfigInput = NextConfig | NextConfigFactory;
|
|
247
|
+
declare function findVinextNextConfigInPlugins(plugins: PluginOption[] | undefined): Promise<NextConfigInput | null>;
|
|
244
248
|
/**
|
|
245
249
|
* Resolved configuration with all async values awaited.
|
|
246
250
|
*/
|
|
@@ -564,4 +568,4 @@ declare function extractMdxOptions(config: NextConfig, root?: string): Promise<M
|
|
|
564
568
|
*/
|
|
565
569
|
declare function detectNextIntlConfig(root: string, resolved: ResolvedNextConfig): void;
|
|
566
570
|
//#endregion
|
|
567
|
-
export { HasCondition, MdxOptions, NextConfig, NextConfigInput, NextHeader, NextI18nConfig, NextRedirect, NextRewrite, PHASE_PRODUCTION_BUILD, PrefetchInliningConfig, ResolvedNextConfig, createRscCompatibilityId, detectNextIntlConfig, extractMdxOptions, findNextConfigPath, lightningCssFeatureNamesToMask, loadNextConfig, normalizeAssetPrefix, parseBodySizeLimit, reassignsModuleExports, referencesCjsGlobals, resolveNextConfig, resolveNextConfigInput };
|
|
571
|
+
export { HasCondition, MdxOptions, NextConfig, NextConfigInput, NextHeader, NextI18nConfig, NextRedirect, NextRewrite, PHASE_PRODUCTION_BUILD, PrefetchInliningConfig, ResolvedNextConfig, VINEXT_NEXT_CONFIG_PLUGIN_PROPERTY, createRscCompatibilityId, detectNextIntlConfig, extractMdxOptions, findNextConfigPath, findVinextNextConfigInPlugins, lightningCssFeatureNamesToMask, loadNextConfig, normalizeAssetPrefix, parseBodySizeLimit, reassignsModuleExports, referencesCjsGlobals, resolveNextConfig, resolveNextConfigInput };
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
import path, { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
1
2
|
import { normalizePageExtensions } from "../routing/file-matcher.js";
|
|
2
|
-
import {
|
|
3
|
+
import { isExternalUrl } from "../utils/external-url.js";
|
|
4
|
+
import { applyLocaleToRoutes } from "./config-matchers.js";
|
|
3
5
|
import { isUnknownRecord } from "../utils/record.js";
|
|
4
6
|
import { getHtmlLimitedBotRegex } from "../utils/html-limited-bots.js";
|
|
7
|
+
import { flattenPluginOptions } from "../utils/plugin-options.js";
|
|
5
8
|
import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from "../shims/constants.js";
|
|
6
9
|
import { loadTsconfigResolutionForRoot } from "./tsconfig-paths.js";
|
|
7
10
|
import { loadCommonJsModule, shouldRetryAsCommonJs } from "../utils/commonjs-loader.js";
|
|
8
11
|
import { createRequire } from "node:module";
|
|
9
12
|
import fs from "node:fs";
|
|
10
|
-
import path from "node:path";
|
|
11
13
|
import { fileURLToPath } from "node:url";
|
|
12
14
|
import { randomUUID } from "node:crypto";
|
|
13
15
|
import commonjs from "vite-plugin-commonjs";
|
|
@@ -18,6 +20,7 @@ import commonjs from "vite-plugin-commonjs";
|
|
|
18
20
|
* Loads the Next.js config file (if present) and extracts supported options.
|
|
19
21
|
* Unsupported options are logged as warnings.
|
|
20
22
|
*/
|
|
23
|
+
const VINEXT_NEXT_CONFIG_PLUGIN_PROPERTY = "__vinextNextConfig";
|
|
21
24
|
/**
|
|
22
25
|
* Parse a body size limit value (string or number) into bytes.
|
|
23
26
|
* Accepts Next.js-style strings like "1mb", "500kb", "10mb", bare number strings like "1048576" (bytes),
|
|
@@ -63,6 +66,15 @@ function parseBodySizeLimit(value) {
|
|
|
63
66
|
if (bytes < 1) throw new Error(`Body size limit must be a positive number, got ${bytes}`);
|
|
64
67
|
return bytes;
|
|
65
68
|
}
|
|
69
|
+
async function findVinextNextConfigInPlugins(plugins) {
|
|
70
|
+
const flattened = await flattenPluginOptions(plugins);
|
|
71
|
+
for (const plugin of flattened) {
|
|
72
|
+
if (!isUnknownRecord(plugin)) continue;
|
|
73
|
+
const nextConfig = plugin[VINEXT_NEXT_CONFIG_PLUGIN_PROPERTY];
|
|
74
|
+
if (nextConfig) return nextConfig;
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
66
78
|
const CONFIG_FILES = [
|
|
67
79
|
"next.config.ts",
|
|
68
80
|
"next.config.mts",
|
|
@@ -150,10 +162,12 @@ async function unwrapConfig(mod, phase = PHASE_DEVELOPMENT_SERVER) {
|
|
|
150
162
|
/**
|
|
151
163
|
* Resolve a path through filesystem symlinks, falling back to the original
|
|
152
164
|
* path when the file does not exist (e.g. virtual ids, query-suffixed ids).
|
|
165
|
+
* Output is forward-slashed so it compares consistently with pathslash
|
|
166
|
+
* results (fs.realpathSync returns backslashes on Windows).
|
|
153
167
|
*/
|
|
154
168
|
function safeRealpath(p) {
|
|
155
169
|
try {
|
|
156
|
-
return fs.realpathSync(p);
|
|
170
|
+
return toSlash(fs.realpathSync(p));
|
|
157
171
|
} catch {
|
|
158
172
|
return p;
|
|
159
173
|
}
|
|
@@ -439,8 +453,8 @@ function createRscCompatibilityId(nextConfig) {
|
|
|
439
453
|
* @returns A filesystem path suitable for path operations
|
|
440
454
|
*/
|
|
441
455
|
function resolveCacheHandlerPathToFilesystem(filePath) {
|
|
442
|
-
if (filePath.startsWith("file://")) return fileURLToPath(filePath);
|
|
443
|
-
return filePath;
|
|
456
|
+
if (filePath.startsWith("file://")) return toSlash(fileURLToPath(filePath));
|
|
457
|
+
return toSlash(filePath);
|
|
444
458
|
}
|
|
445
459
|
function resolveHtmlLimitedBots(value) {
|
|
446
460
|
const source = value instanceof RegExp ? value.source : typeof value === "string" ? value : void 0;
|
|
@@ -571,11 +585,71 @@ function normalizePrefetchInliningConfig(value) {
|
|
|
571
585
|
maxSize: Number.isFinite(normalizedMaxSize) ? normalizedMaxSize : Number.MAX_SAFE_INTEGER
|
|
572
586
|
};
|
|
573
587
|
}
|
|
588
|
+
function normalizeI18nConfig(value) {
|
|
589
|
+
if (!value) return null;
|
|
590
|
+
const i18nType = typeof value;
|
|
591
|
+
if (i18nType !== "object") throw new Error(`Specified i18n should be an object received ${i18nType}.\nSee more info here: https://nextjs.org/docs/messages/invalid-i18n-config`);
|
|
592
|
+
const i18n = value;
|
|
593
|
+
if (!Array.isArray(i18n.locales)) throw new Error(`Specified i18n.locales should be an Array received ${typeof i18n.locales}.\nSee more info here: https://nextjs.org/docs/messages/invalid-i18n-config`);
|
|
594
|
+
if (i18n.locales.length > 100) console.warn(`Received ${i18n.locales.length} i18n.locales items which exceeds the recommended max of 100.\nSee more info here: https://nextjs.org/docs/advanced-features/i18n-routing#how-does-this-work-with-static-generation`);
|
|
595
|
+
if (!i18n.defaultLocale || typeof i18n.defaultLocale !== "string") throw new Error("Specified i18n.defaultLocale should be a string.\nSee more info here: https://nextjs.org/docs/messages/invalid-i18n-config");
|
|
596
|
+
if (i18n.domains !== void 0 && !Array.isArray(i18n.domains)) throw new Error(`Specified i18n.domains must be an array of domain objects e.g. [ { domain: 'example.fr', defaultLocale: 'fr', locales: ['fr'] } ] received ${typeof i18n.domains}.\nSee more info here: https://nextjs.org/docs/messages/invalid-i18n-config`);
|
|
597
|
+
if (i18n.domains) {
|
|
598
|
+
const invalidDomainItems = i18n.domains.filter((item) => {
|
|
599
|
+
if (!isUnknownRecord(item) || !item.defaultLocale) return true;
|
|
600
|
+
if (!item.domain || typeof item.domain !== "string") return true;
|
|
601
|
+
if (item.domain.includes(":")) {
|
|
602
|
+
console.warn(`i18n domain: "${item.domain}" is invalid it should be a valid domain without protocol (https://) or port (:3000) e.g. example.vercel.sh`);
|
|
603
|
+
return true;
|
|
604
|
+
}
|
|
605
|
+
const defaultLocaleDuplicate = i18n.domains.find((other) => isUnknownRecord(other) && other.defaultLocale === item.defaultLocale && other.domain !== item.domain);
|
|
606
|
+
if (defaultLocaleDuplicate && isUnknownRecord(defaultLocaleDuplicate)) {
|
|
607
|
+
console.warn(`Both ${item.domain} and ${String(defaultLocaleDuplicate.domain)} configured the defaultLocale ${item.defaultLocale} but only one can. Change one item's default locale to continue`);
|
|
608
|
+
return true;
|
|
609
|
+
}
|
|
610
|
+
let hasInvalidLocale = false;
|
|
611
|
+
if (Array.isArray(item.locales)) for (const locale of item.locales) {
|
|
612
|
+
if (typeof locale !== "string") hasInvalidLocale = true;
|
|
613
|
+
for (const domainItem of i18n.domains) {
|
|
614
|
+
if (domainItem === item || !isUnknownRecord(domainItem)) continue;
|
|
615
|
+
const domainLocales = domainItem.locales;
|
|
616
|
+
if (domainLocales && domainLocales.includes(locale)) {
|
|
617
|
+
console.warn(`Both ${item.domain} and ${String(domainItem.domain)} configured the locale (${String(locale)}) but only one can. Remove it from one i18n.domains config to continue`);
|
|
618
|
+
hasInvalidLocale = true;
|
|
619
|
+
break;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
return hasInvalidLocale;
|
|
624
|
+
});
|
|
625
|
+
if (invalidDomainItems.length > 0) throw new Error(`Invalid i18n.domains values:\n${invalidDomainItems.map((item) => JSON.stringify(item)).join("\n")}\n\ndomains value must follow format { domain: 'example.fr', defaultLocale: 'fr', locales: ['fr'] }.\nSee more info here: https://nextjs.org/docs/messages/invalid-i18n-config`);
|
|
626
|
+
}
|
|
627
|
+
const invalidLocales = i18n.locales.filter((locale) => typeof locale !== "string");
|
|
628
|
+
if (invalidLocales.length > 0) throw new Error(`Specified i18n.locales contains invalid values (${invalidLocales.map(String).join(", ")}), locales must be valid locale tags provided as strings e.g. "en-US".\nSee here for list of valid language sub-tags: http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry`);
|
|
629
|
+
const locales = i18n.locales;
|
|
630
|
+
if (!locales.includes(i18n.defaultLocale)) throw new Error("Specified i18n.defaultLocale should be included in i18n.locales.\nSee more info here: https://nextjs.org/docs/messages/invalid-i18n-config");
|
|
631
|
+
const normalizedLocales = /* @__PURE__ */ new Set();
|
|
632
|
+
const duplicateLocales = /* @__PURE__ */ new Set();
|
|
633
|
+
for (const locale of locales) {
|
|
634
|
+
const localeLower = locale.toLowerCase();
|
|
635
|
+
if (normalizedLocales.has(localeLower)) duplicateLocales.add(locale);
|
|
636
|
+
normalizedLocales.add(localeLower);
|
|
637
|
+
}
|
|
638
|
+
if (duplicateLocales.size > 0) throw new Error(`Specified i18n.locales contains the following duplicate locales:\n${[...duplicateLocales].join(", ")}\nEach locale should be listed only once.\nSee more info here: https://nextjs.org/docs/messages/invalid-i18n-config`);
|
|
639
|
+
const localeDetectionType = typeof i18n.localeDetection;
|
|
640
|
+
if (localeDetectionType !== "boolean" && localeDetectionType !== "undefined") throw new Error(`Specified i18n.localeDetection should be undefined or a boolean received ${localeDetectionType}.\nSee more info here: https://nextjs.org/docs/messages/invalid-i18n-config`);
|
|
641
|
+
return {
|
|
642
|
+
locales: [i18n.defaultLocale, ...locales.filter((locale) => locale !== i18n.defaultLocale)],
|
|
643
|
+
defaultLocale: i18n.defaultLocale,
|
|
644
|
+
localeDetection: i18n.localeDetection ?? true,
|
|
645
|
+
domains: i18n.domains
|
|
646
|
+
};
|
|
647
|
+
}
|
|
574
648
|
/**
|
|
575
649
|
* Resolve a NextConfig into a fully-resolved ResolvedNextConfig.
|
|
576
650
|
* Awaits async functions for redirects/rewrites/headers.
|
|
577
651
|
*/
|
|
578
|
-
async function resolveNextConfig(config, root = process.cwd(), options = {}) {
|
|
652
|
+
async function resolveNextConfig(config, root = toSlash(process.cwd()), options = {}) {
|
|
579
653
|
if (!config) {
|
|
580
654
|
const buildId = await resolveBuildId(void 0);
|
|
581
655
|
const deploymentId = resolveDeploymentId(void 0);
|
|
@@ -643,6 +717,7 @@ async function resolveNextConfig(config, root = process.cwd(), options = {}) {
|
|
|
643
717
|
return resolved;
|
|
644
718
|
}
|
|
645
719
|
warnDeprecatedConfigOptions(config, root);
|
|
720
|
+
const i18n = normalizeI18nConfig(config.i18n);
|
|
646
721
|
let redirects = [];
|
|
647
722
|
if (config.redirects) {
|
|
648
723
|
const result = await config.redirects();
|
|
@@ -729,13 +804,6 @@ async function resolveNextConfig(config, root = process.cwd(), options = {}) {
|
|
|
729
804
|
const experimentalTurbo = readOptionalRecord(experimental?.turbo);
|
|
730
805
|
const turbopack = readOptionalRecord(config.turbopack);
|
|
731
806
|
const resolveExtensions = Array.isArray(turbopack?.resolveExtensions) ? readStringArray(turbopack.resolveExtensions) : Array.isArray(experimentalTurbo?.resolveExtensions) ? readStringArray(experimentalTurbo.resolveExtensions) : null;
|
|
732
|
-
let i18n = null;
|
|
733
|
-
if (config.i18n) i18n = {
|
|
734
|
-
locales: config.i18n.locales,
|
|
735
|
-
defaultLocale: config.i18n.defaultLocale,
|
|
736
|
-
localeDetection: config.i18n.localeDetection ?? true,
|
|
737
|
-
domains: config.i18n.domains
|
|
738
|
-
};
|
|
739
807
|
const buildId = await resolveBuildId(config.generateBuildId);
|
|
740
808
|
const deploymentId = resolveDeploymentId(config.deploymentId);
|
|
741
809
|
const cacheHandler = typeof config.cacheHandler === "string" ? resolveCacheHandlerPathToFilesystem(config.cacheHandler) : void 0;
|
|
@@ -748,6 +816,7 @@ async function resolveNextConfig(config, root = process.cwd(), options = {}) {
|
|
|
748
816
|
afterFiles: applyLocaleToRoutes(rewrites.afterFiles, i18n, "rewrite", opts),
|
|
749
817
|
fallback: applyLocaleToRoutes(rewrites.fallback, i18n, "rewrite", opts)
|
|
750
818
|
};
|
|
819
|
+
headers = applyLocaleToRoutes(headers, i18n, "header", opts);
|
|
751
820
|
}
|
|
752
821
|
const images = config.images ? {
|
|
753
822
|
...config.images,
|
|
@@ -996,7 +1065,7 @@ function invokeLoaderSideEffects(rules, root) {
|
|
|
996
1065
|
* loader rule. The remark/rehype plugins are captured in that closure.
|
|
997
1066
|
* We probe the webpack function with a mock config to extract them.
|
|
998
1067
|
*/
|
|
999
|
-
async function extractMdxOptions(config, root = process.cwd()) {
|
|
1068
|
+
async function extractMdxOptions(config, root = toSlash(process.cwd())) {
|
|
1000
1069
|
return (await probeWebpackConfig(config, root, false)).mdx;
|
|
1001
1070
|
}
|
|
1002
1071
|
/**
|
|
@@ -1090,4 +1159,4 @@ function extractPluginsFromOptions(opts) {
|
|
|
1090
1159
|
return null;
|
|
1091
1160
|
}
|
|
1092
1161
|
//#endregion
|
|
1093
|
-
export { PHASE_PRODUCTION_BUILD, createRscCompatibilityId, detectNextIntlConfig, extractMdxOptions, findNextConfigPath, lightningCssFeatureNamesToMask, loadNextConfig, normalizeAssetPrefix, parseBodySizeLimit, reassignsModuleExports, referencesCjsGlobals, resolveNextConfig, resolveNextConfigInput };
|
|
1162
|
+
export { PHASE_PRODUCTION_BUILD, VINEXT_NEXT_CONFIG_PLUGIN_PROPERTY, createRscCompatibilityId, detectNextIntlConfig, extractMdxOptions, findNextConfigPath, findVinextNextConfigInPlugins, lightningCssFeatureNamesToMask, loadNextConfig, normalizeAssetPrefix, parseBodySizeLimit, reassignsModuleExports, referencesCjsGlobals, resolveNextConfig, resolveNextConfigInput };
|
|
@@ -30,8 +30,8 @@ type ViteConfigLoader = {
|
|
|
30
30
|
loadConfigFromFile: typeof import("vite").loadConfigFromFile;
|
|
31
31
|
};
|
|
32
32
|
declare function normalizeVinextPrerenderConfig(config: VinextPrerenderConfig | undefined): ResolvedVinextPrerenderConfig | null;
|
|
33
|
-
declare function findVinextPrerenderConfigInPlugins(plugins: PluginOption[] | undefined): ResolvedVinextPrerenderConfig | null
|
|
34
|
-
declare function findVinextRouteRootConfigInPlugins(plugins: PluginOption[] | undefined): VinextRouteRootConfig | null
|
|
33
|
+
declare function findVinextPrerenderConfigInPlugins(plugins: PluginOption[] | undefined): Promise<ResolvedVinextPrerenderConfig | null>;
|
|
34
|
+
declare function findVinextRouteRootConfigInPlugins(plugins: PluginOption[] | undefined): Promise<VinextRouteRootConfig | null>;
|
|
35
35
|
declare function loadVinextPrerenderConfigFromViteConfig(vite: ViteConfigLoader, root: string): Promise<ResolvedVinextPrerenderConfig | null>;
|
|
36
36
|
declare function loadVinextRouteRootConfigFromViteConfig(vite: ViteConfigLoader, root: string): Promise<VinextRouteRootConfig | null>;
|
|
37
37
|
declare function resolveVinextPrerenderDecision(options: {
|