vinext 1.0.0-beta.0 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -2
- package/dist/build/assets-ignore.js +1 -1
- package/dist/build/clean-output.js +1 -1
- package/dist/build/client-build-config.js +7 -4
- package/dist/build/css-url-assets.js +3 -3
- package/dist/build/google-fonts/fallback-metrics.js +1 -1
- package/dist/build/google-fonts/font-metadata.js +1 -1
- package/dist/build/inject-pregenerated-paths.js +1 -1
- package/dist/build/inline-css.js +2 -5
- package/dist/build/module-dependency-cache.d.ts +4 -0
- package/dist/build/module-dependency-cache.js +13 -0
- package/dist/build/next-client-runtime-manifests.js +1 -1
- package/dist/build/pages-client-assets-module.js +1 -1
- package/dist/build/precompress.js +7 -7
- package/dist/build/prerender-paths.d.ts +2 -2
- package/dist/build/prerender-paths.js +10 -15
- package/dist/build/prerender-server-pool.js +2 -2
- package/dist/build/prerender.js +1 -1
- package/dist/build/preview-credentials.d.ts +11 -0
- package/dist/build/preview-credentials.js +19 -0
- package/dist/build/report.d.ts +8 -4
- package/dist/build/report.js +14 -6
- package/dist/build/run-prerender.d.ts +2 -11
- package/dist/build/run-prerender.js +2 -10
- package/dist/build/server-manifest.js +1 -1
- package/dist/build/ssr-manifest.d.ts +4 -0
- package/dist/build/ssr-manifest.js +10 -6
- package/dist/build/standalone.js +37 -37
- package/dist/cache/cache-adapters-virtual.d.ts +1 -17
- package/dist/cache/cache-adapters-virtual.js +20 -11
- package/dist/check.d.ts +0 -16
- package/dist/check.js +27 -36
- package/dist/cli.js +61 -55
- package/dist/client/instrumentation-client-inject.js +1 -1
- package/dist/client/pages-router-link-navigation.js +1 -1
- package/dist/config/config-matchers.d.ts +13 -37
- package/dist/config/config-matchers.js +33 -123
- package/dist/config/dotenv.js +1 -1
- package/dist/config/next-config.d.ts +7 -3
- package/dist/config/next-config.js +84 -15
- package/dist/config/prerender.d.ts +2 -2
- package/dist/config/prerender.js +7 -15
- package/dist/config/request-context.d.ts +14 -0
- package/dist/config/request-context.js +26 -0
- package/dist/config/server-external-packages.js +1 -1
- package/dist/config/tsconfig-paths.js +2 -2
- package/dist/{node_modules/.pnpm/am-i-vibing@0.5.0/node_modules → deps/.pnpm/am-i-vibing@0.5.0/deps}/am-i-vibing/dist/detector-1yx2Hoe0.js +2 -2
- package/dist/deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js +50 -0
- package/dist/entries/app-rsc-entry.js +39 -14
- package/dist/entries/app-rsc-manifest.js +21 -4
- package/dist/entries/pages-client-entry.js +6 -5
- package/dist/entries/pages-server-entry.js +18 -28
- package/dist/entries/runtime-entry-module.js +2 -2
- package/dist/index.js +314 -230
- package/dist/init-cloudflare.js +1 -1
- package/dist/init-platform.js +1 -1
- package/dist/init.d.ts +6 -4
- package/dist/init.js +25 -27
- package/dist/plugins/ast-utils.js +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +7 -7
- package/dist/plugins/extensionless-dynamic-import.js +1 -1
- package/dist/plugins/fonts.js +3 -3
- package/dist/plugins/ignore-dynamic-requests.js +13 -8
- package/dist/plugins/import-meta-url.js +16 -17
- package/dist/plugins/middleware-export-validation.js +1 -1
- package/dist/plugins/middleware-server-only.js +2 -2
- package/dist/plugins/og-asset-ownership.js +7 -6
- package/dist/plugins/og-assets.js +5 -6
- package/dist/plugins/optimize-imports.js +12 -13
- package/dist/plugins/postcss.js +1 -1
- package/dist/plugins/remove-console.js +1 -1
- package/dist/plugins/require-context.js +1 -1
- package/dist/plugins/sass.js +2 -2
- package/dist/plugins/server-externals-manifest.js +1 -1
- package/dist/plugins/strip-server-exports.js +1 -1
- package/dist/plugins/styled-jsx.js +3 -2
- package/dist/plugins/typeof-window.js +1 -1
- package/dist/routing/app-route-graph.d.ts +16 -15
- package/dist/routing/app-route-graph.js +86 -88
- package/dist/routing/app-router.d.ts +0 -5
- package/dist/routing/app-router.js +12 -11
- package/dist/routing/file-matcher.d.ts +13 -28
- package/dist/routing/file-matcher.js +31 -44
- package/dist/routing/pages-router.js +26 -32
- package/dist/routing/route-matching.d.ts +14 -1
- package/dist/routing/route-matching.js +13 -1
- package/dist/routing/route-pattern.d.ts +2 -1
- package/dist/routing/route-pattern.js +7 -4
- package/dist/routing/route-trie.d.ts +5 -1
- package/dist/routing/route-trie.js +5 -2
- package/dist/server/api-handler.js +41 -33
- package/dist/server/app-browser-entry.js +18 -11
- package/dist/server/app-browser-history-controller.d.ts +1 -1
- package/dist/server/app-browser-history-controller.js +3 -3
- package/dist/server/app-browser-navigation-controller.js +4 -2
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-elements-wire.d.ts +2 -1
- package/dist/server/app-fallback-renderer.d.ts +11 -0
- package/dist/server/app-fallback-renderer.js +16 -2
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-page-boundary-render.d.ts +26 -2
- package/dist/server/app-page-boundary-render.js +190 -55
- package/dist/server/app-page-cache-finalizer.d.ts +1 -1
- package/dist/server/app-page-cache.d.ts +1 -1
- package/dist/server/app-page-dispatch.d.ts +12 -2
- package/dist/server/app-page-dispatch.js +37 -51
- package/dist/server/app-page-element-builder.d.ts +8 -2
- package/dist/server/app-page-element-builder.js +112 -27
- package/dist/server/app-page-execution.d.ts +3 -1
- package/dist/server/app-page-execution.js +31 -39
- package/dist/server/app-page-head.d.ts +54 -2
- package/dist/server/app-page-head.js +164 -78
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +106 -0
- package/dist/server/app-page-render.d.ts +2 -2
- package/dist/server/app-page-render.js +1 -1
- package/dist/server/app-page-request.d.ts +12 -0
- package/dist/server/app-page-request.js +134 -14
- package/dist/server/app-page-route-wiring.d.ts +9 -0
- package/dist/server/app-page-route-wiring.js +44 -4
- package/dist/server/app-post-middleware-context.d.ts +1 -1
- package/dist/server/app-post-middleware-context.js +1 -1
- package/dist/server/app-route-handler-dispatch.js +31 -17
- package/dist/server/app-route-handler-execution.d.ts +6 -1
- package/dist/server/app-route-handler-execution.js +41 -15
- package/dist/server/app-route-handler-policy.d.ts +2 -0
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-module-loader.d.ts +3 -1
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-route-tree-prefetch.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +1 -1
- package/dist/server/app-rsc-cache-busting.js +1 -1
- package/dist/server/app-rsc-errors.d.ts +1 -1
- package/dist/server/app-rsc-errors.js +12 -2
- package/dist/server/app-rsc-handler.d.ts +10 -5
- package/dist/server/app-rsc-handler.js +51 -23
- package/dist/server/app-rsc-redirect-flight.d.ts +66 -0
- package/dist/server/app-rsc-redirect-flight.js +71 -0
- package/dist/server/app-rsc-request-normalization.d.ts +3 -2
- package/dist/server/app-rsc-request-normalization.js +8 -2
- package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
- package/dist/server/app-rsc-response-finalizer.js +5 -11
- package/dist/server/app-rsc-route-matching.d.ts +20 -0
- package/dist/server/app-rsc-route-matching.js +87 -11
- package/dist/server/app-segment-config.js +15 -5
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +8 -6
- package/dist/server/app-ssr-entry.js +4 -1
- package/dist/server/app-ssr-stream.d.ts +2 -7
- package/dist/server/app-ssr-stream.js +5 -10
- package/dist/server/cache-proof.js +1 -1
- package/dist/server/config-headers.d.ts +24 -0
- package/dist/server/config-headers.js +52 -0
- package/dist/server/default-global-error-module.d.ts +3 -1
- package/dist/server/default-not-found-module.d.ts +3 -1
- package/dist/server/dev-initial-server-error.d.ts +1 -1
- package/dist/server/dev-lockfile.js +2 -3
- package/dist/server/dev-route-files.js +1 -1
- package/dist/server/dev-server.js +281 -173
- package/dist/server/dev-stack-sourcemap.js +4 -3
- package/dist/server/headers.d.ts +3 -1
- package/dist/server/headers.js +3 -1
- package/dist/server/image-optimization.js +2 -2
- package/dist/server/implicit-tags.js +2 -1
- package/dist/server/instrumentation.js +2 -2
- package/dist/server/isr-cache.d.ts +1 -1
- package/dist/server/isr-cache.js +1 -1
- package/dist/server/metadata-routes.js +4 -4
- package/dist/server/middleware-matcher-pattern.d.ts +22 -0
- package/dist/server/middleware-matcher-pattern.js +219 -0
- package/dist/server/middleware-matcher.d.ts +2 -7
- package/dist/server/middleware-matcher.js +13 -60
- package/dist/server/middleware-path-to-regexp.d.ts +14 -0
- package/dist/server/middleware-path-to-regexp.js +228 -0
- package/dist/server/middleware-response-headers.js +1 -1
- package/dist/server/middleware-runtime.js +5 -4
- package/dist/server/middleware.d.ts +2 -1
- package/dist/server/middleware.js +3 -2
- package/dist/server/navigation-planner.d.ts +2 -0
- package/dist/server/navigation-planner.js +8 -2
- package/dist/server/next-error-digest.d.ts +9 -24
- package/dist/server/next-error-digest.js +23 -15
- package/dist/server/operation-token.js +1 -1
- package/dist/server/pages-body-parser-config.js +2 -1
- package/dist/server/pages-data-route.d.ts +11 -1
- package/dist/server/pages-data-route.js +16 -1
- package/dist/server/pages-dev-hydration.d.ts +14 -0
- package/dist/server/pages-dev-hydration.js +83 -0
- package/dist/server/pages-dev-module-url.js +2 -2
- package/dist/server/pages-get-initial-props.d.ts +15 -2
- package/dist/server/pages-get-initial-props.js +16 -6
- package/dist/server/pages-node-compat.d.ts +13 -6
- package/dist/server/pages-node-compat.js +44 -45
- package/dist/server/pages-page-data.d.ts +4 -2
- package/dist/server/pages-page-data.js +20 -10
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +74 -43
- package/dist/server/pages-page-response.d.ts +2 -2
- package/dist/server/pages-page-response.js +1 -1
- package/dist/server/pages-preview.d.ts +26 -0
- package/dist/server/pages-preview.js +165 -0
- package/dist/server/pages-readiness.d.ts +5 -4
- package/dist/server/pages-readiness.js +4 -2
- package/dist/server/pages-request-pipeline.d.ts +1 -0
- package/dist/server/pages-request-pipeline.js +25 -11
- package/dist/server/pages-router-entry.js +6 -0
- package/dist/server/prerender-route-params.js +2 -2
- package/dist/server/prod-server.d.ts +1 -4
- package/dist/server/prod-server.js +44 -30
- package/dist/server/request-pipeline.d.ts +15 -29
- package/dist/server/request-pipeline.js +25 -60
- package/dist/server/rsc-stream-hints.js +122 -18
- package/dist/server/seed-cache.js +1 -1
- package/dist/server/socket-error-backstop.js +1 -1
- package/dist/server/static-file-cache.js +7 -8
- package/dist/server/worker-utils.js +1 -1
- package/dist/shims/app.d.ts +1 -1
- package/dist/shims/cache-request-state.d.ts +27 -1
- package/dist/shims/cache-request-state.js +60 -1
- package/dist/shims/cache-runtime.d.ts +12 -1
- package/dist/shims/cache-runtime.js +22 -7
- package/dist/shims/cache.d.ts +5 -5
- package/dist/shims/cache.js +28 -11
- package/dist/shims/constants.js +1 -1
- package/dist/shims/document.d.ts +42 -83
- package/dist/shims/document.js +62 -53
- package/dist/shims/dynamic.d.ts +5 -25
- package/dist/shims/dynamic.js +29 -8
- package/dist/shims/error-boundary.d.ts +4 -4
- package/dist/shims/error.d.ts +22 -6
- package/dist/shims/error.js +53 -15
- package/dist/shims/fetch-cache.js +13 -4
- package/dist/shims/font-google-base.d.ts +11 -4
- package/dist/shims/font-local.d.ts +10 -3
- package/dist/shims/font-utils.js +1 -1
- package/dist/shims/form.d.ts +1 -1
- package/dist/shims/head.d.ts +13 -2
- package/dist/shims/head.js +6 -6
- package/dist/shims/headers.d.ts +28 -31
- package/dist/shims/headers.js +115 -53
- package/dist/shims/image.d.ts +27 -37
- package/dist/shims/image.js +21 -14
- package/dist/shims/internal/cookie-serialize.d.ts +3 -1
- package/dist/shims/internal/cookie-serialize.js +3 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
- package/dist/shims/internal/pages-data-fetch-dedup.js +5 -3
- package/dist/shims/internal/utils.d.ts +3 -3
- package/dist/shims/layout-segment-context.d.ts +1 -1
- package/dist/shims/legacy-image.d.ts +3 -37
- package/dist/shims/legacy-image.js +6 -16
- package/dist/shims/link.d.ts +16 -21
- package/dist/shims/link.js +25 -13
- package/dist/shims/navigation-context-state.d.ts +1 -1
- package/dist/shims/navigation-errors.d.ts +2 -1
- package/dist/shims/navigation-errors.js +9 -13
- package/dist/shims/navigation.d.ts +8 -4
- package/dist/shims/navigation.js +29 -18
- package/dist/shims/next-shims-augmentations.d.ts +1 -0
- package/dist/shims/next-shims-public.d.ts +1 -0
- package/dist/shims/public-shim-map.json.js +103 -0
- package/dist/shims/readonly-url-search-params.d.ts +3 -3
- package/dist/shims/readonly-url-search-params.js +3 -3
- package/dist/shims/request-state-types.d.ts +1 -1
- package/dist/shims/router-state.d.ts +1 -0
- package/dist/shims/router.d.ts +57 -22
- package/dist/shims/router.js +178 -46
- package/dist/shims/script.d.ts +6 -10
- package/dist/shims/script.js +7 -4
- package/dist/shims/server.d.ts +45 -22
- package/dist/shims/server.js +46 -7
- package/dist/shims/slot.d.ts +1 -1
- package/dist/shims/thenable-params.js +1 -1
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +2 -0
- package/dist/shims/url-safety.d.ts +1 -1
- package/dist/shims/url-safety.js +2 -2
- package/dist/typegen.d.ts +8 -2
- package/dist/typegen.js +84 -25
- package/dist/utils/client-build-manifest.js +2 -2
- package/dist/utils/client-entry-manifest.js +1 -1
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/commonjs-loader.js +3 -3
- package/dist/utils/domain-locale.d.ts +2 -2
- package/dist/utils/external-url.d.ts +5 -0
- package/dist/utils/external-url.js +7 -0
- package/dist/utils/mdx-scan.js +1 -1
- package/dist/utils/path.d.ts +1 -13
- package/dist/utils/path.js +1 -15
- package/dist/utils/plugin-options.d.ts +4 -0
- package/dist/utils/plugin-options.js +8 -0
- package/dist/utils/project.d.ts +0 -6
- package/dist/utils/project.js +2 -8
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.js +1 -1
- package/dist/utils/redirect-digest.d.ts +9 -0
- package/dist/utils/redirect-digest.js +25 -0
- package/dist/utils/regex-safety.d.ts +8 -0
- package/dist/utils/regex-safety.js +737 -0
- package/dist/utils/vinext-root.js +1 -1
- package/dist/utils/vite-version.d.ts +5 -2
- package/dist/utils/vite-version.js +43 -17
- package/package.json +16 -4
- /package/dist/build/google-fonts/{fallback-metrics-data.js → fallback-metrics-data.json.js} +0 -0
- /package/dist/build/google-fonts/{font-data.js → font-data.json.js} +0 -0
- /package/dist/{node_modules/.pnpm/process-ancestry@0.1.0/node_modules → deps/.pnpm/process-ancestry@0.1.0/deps}/process-ancestry/dist/index.js +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
1
2
|
import { VINEXT_ORIGINAL_STACK_TRACE_ENDPOINT } from "../utils/dev-stack-sourcemap-endpoint.js";
|
|
2
3
|
import { readFile } from "node:fs/promises";
|
|
3
4
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
@@ -184,7 +185,7 @@ function extractV8ParenMethodName(prefix) {
|
|
|
184
185
|
}
|
|
185
186
|
function normalizeProjectRoot(root) {
|
|
186
187
|
if (!root) return void 0;
|
|
187
|
-
return root
|
|
188
|
+
return toSlash(root).replace(/\/+$/, "") || (root.startsWith("/") ? "/" : void 0);
|
|
188
189
|
}
|
|
189
190
|
function stripTrailingSlash(value) {
|
|
190
191
|
return value?.replace(/[\\/]+$/, "");
|
|
@@ -240,7 +241,7 @@ function isWindowsAbsolutePath(value) {
|
|
|
240
241
|
return /^[A-Za-z]:[\\/]/.test(value);
|
|
241
242
|
}
|
|
242
243
|
function normalizeLocalPathForCompare(value) {
|
|
243
|
-
const normalized = (stripTrailingSlash(value
|
|
244
|
+
const normalized = (stripTrailingSlash(toSlash(value)) ?? "").replace(/\/+/g, "/");
|
|
244
245
|
return /^[A-Za-z]:\//.test(normalized) ? normalized.toLowerCase() : normalized;
|
|
245
246
|
}
|
|
246
247
|
function normalizeIgnoreListPath(value) {
|
|
@@ -255,7 +256,7 @@ function normalizeIgnoreListPath(value) {
|
|
|
255
256
|
try {
|
|
256
257
|
path = decodeURIComponent(path);
|
|
257
258
|
} catch {}
|
|
258
|
-
return path
|
|
259
|
+
return toSlash(path).toLowerCase();
|
|
259
260
|
}
|
|
260
261
|
function isExternalHttpFrame(file, requestHost) {
|
|
261
262
|
if (!/^https?:\/\//i.test(file) || !requestHost) return false;
|
package/dist/server/headers.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ declare const VINEXT_CLIENT_REUSE_MANIFEST_HEADER = "X-Vinext-Client-Reuse-Manif
|
|
|
56
56
|
* cheap way to detect the redirect ahead of stream decode.
|
|
57
57
|
*/
|
|
58
58
|
declare const VINEXT_RSC_REDIRECT_HEADER = "X-Vinext-Rsc-Redirect";
|
|
59
|
+
/** History update mode encoded by a streamed RSC redirect. */
|
|
60
|
+
declare const VINEXT_RSC_REDIRECT_TYPE_HEADER = "X-Vinext-Rsc-Redirect-Type";
|
|
59
61
|
/** Standard RSC header — value "1" indicates an RSC payload request. */
|
|
60
62
|
declare const RSC_HEADER = "RSC";
|
|
61
63
|
/** Server Action invocation header (vinext/vite-rsc protocol). */
|
|
@@ -105,4 +107,4 @@ declare const INTERNAL_HEADERS: string[];
|
|
|
105
107
|
/** Vinext-only internal headers stripped alongside Next.js protocol internals. */
|
|
106
108
|
declare const VINEXT_INTERNAL_HEADERS: string[];
|
|
107
109
|
//#endregion
|
|
108
|
-
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
|
110
|
+
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
package/dist/server/headers.js
CHANGED
|
@@ -55,6 +55,8 @@ const VINEXT_CLIENT_REUSE_MANIFEST_HEADER = "X-Vinext-Client-Reuse-Manifest";
|
|
|
55
55
|
* cheap way to detect the redirect ahead of stream decode.
|
|
56
56
|
*/
|
|
57
57
|
const VINEXT_RSC_REDIRECT_HEADER = "X-Vinext-Rsc-Redirect";
|
|
58
|
+
/** History update mode encoded by a streamed RSC redirect. */
|
|
59
|
+
const VINEXT_RSC_REDIRECT_TYPE_HEADER = "X-Vinext-Rsc-Redirect-Type";
|
|
58
60
|
/** Standard RSC header — value "1" indicates an RSC payload request. */
|
|
59
61
|
const RSC_HEADER = "RSC";
|
|
60
62
|
/** Server Action invocation header (vinext/vite-rsc protocol). */
|
|
@@ -128,4 +130,4 @@ const VINEXT_INTERNAL_HEADERS = [
|
|
|
128
130
|
VINEXT_PRERENDER_CACHE_LIFE_HEADER
|
|
129
131
|
];
|
|
130
132
|
//#endregion
|
|
131
|
-
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
|
133
|
+
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
|
@@ -87,7 +87,7 @@ function resolveDevImageRedirect(requestUrl, allowedWidths = [...DEFAULT_DEVICE_
|
|
|
87
87
|
* https://github.com/vercel/next.js/blob/canary/test/integration/image-optimizer/test/index.test.ts
|
|
88
88
|
*/
|
|
89
89
|
function parseImageParams(url, allowedWidths = [...DEFAULT_DEVICE_SIZES, ...DEFAULT_IMAGE_SIZES], allowedQualities, options = {}) {
|
|
90
|
-
const allowedParamNames = new Set([
|
|
90
|
+
const allowedParamNames = /* @__PURE__ */ new Set([
|
|
91
91
|
"url",
|
|
92
92
|
"w",
|
|
93
93
|
"q",
|
|
@@ -150,7 +150,7 @@ const IMAGE_CONTENT_SECURITY_POLICY = "script-src 'none'; frame-src 'none'; sand
|
|
|
150
150
|
* SVG is intentionally excluded — it can contain embedded JavaScript and is
|
|
151
151
|
* essentially an XML document, not a safe raster image format.
|
|
152
152
|
*/
|
|
153
|
-
const SAFE_IMAGE_CONTENT_TYPES = new Set([
|
|
153
|
+
const SAFE_IMAGE_CONTENT_TYPES = /* @__PURE__ */ new Set([
|
|
154
154
|
"image/jpeg",
|
|
155
155
|
"image/png",
|
|
156
156
|
"image/gif",
|
|
@@ -33,7 +33,8 @@ function buildAppPageTags(cleanPathname, extraTags, routeSegments) {
|
|
|
33
33
|
return buildPageCacheTags(cleanPathname, extraTags, [...routeSegments], "page");
|
|
34
34
|
}
|
|
35
35
|
function buildPageCacheTags(pathname, extraTags, routeSegments, leafKind) {
|
|
36
|
-
const
|
|
36
|
+
const normalizedPathname = pathname.length > 1 && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
|
37
|
+
const tags = [pathname, `${NEXT_CACHE_IMPLICIT_TAG_ID}${normalizedPathname}`];
|
|
37
38
|
if (pathname === "/") appendUnique(tags, `${NEXT_CACHE_IMPLICIT_TAG_ID}/index`);
|
|
38
39
|
if (pathname === "/index") appendUnique(tags, `${NEXT_CACHE_IMPLICIT_TAG_ID}/`);
|
|
39
40
|
appendDerivedTags(tags, buildRouteCachePath(routeSegments, leafKind));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
1
2
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
2
3
|
import fs from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
4
4
|
//#region src/server/instrumentation.ts
|
|
5
5
|
/**
|
|
6
6
|
* instrumentation.ts support
|
|
@@ -51,7 +51,7 @@ async function importModule(runner, id) {
|
|
|
51
51
|
const INSTRUMENTATION_LOCATIONS = ["", "src/"];
|
|
52
52
|
function findInstrumentationHookFile(root, basename, fileMatcher) {
|
|
53
53
|
for (const dir of INSTRUMENTATION_LOCATIONS) for (const ext of fileMatcher.dottedExtensions) {
|
|
54
|
-
const fullPath = path.
|
|
54
|
+
const fullPath = path.join(root, dir, `${basename}${ext}`);
|
|
55
55
|
if (fs.existsSync(fullPath)) return fullPath;
|
|
56
56
|
}
|
|
57
57
|
return null;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { OnRequestErrorContext } from "./instrumentation.js";
|
|
2
2
|
import { RenderObservation } from "./cache-proof.js";
|
|
3
|
+
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
3
4
|
import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
4
5
|
import { CacheHandlerValue, CachedAppPageValue, CachedPagesValue, IncrementalCacheValue } from "../shims/cache-handler.js";
|
|
5
|
-
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
6
6
|
|
|
7
7
|
//#region src/server/isr-cache.d.ts
|
|
8
8
|
/**
|
package/dist/server/isr-cache.js
CHANGED
|
@@ -62,7 +62,7 @@ function getRevalidateSecret() {
|
|
|
62
62
|
const baked = process.env.__VINEXT_REVALIDATE_SECRET;
|
|
63
63
|
if (baked) return baked;
|
|
64
64
|
if (devRevalidateSecret === void 0) {
|
|
65
|
-
const bytes = new Uint8Array(32);
|
|
65
|
+
const bytes = /* @__PURE__ */ new Uint8Array(32);
|
|
66
66
|
crypto.getRandomValues(bytes);
|
|
67
67
|
devRevalidateSecret = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
68
68
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
1
2
|
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
2
3
|
import fs from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
4
4
|
//#region src/server/metadata-routes.ts
|
|
5
5
|
/**
|
|
6
6
|
* File-based metadata route handling.
|
|
@@ -292,7 +292,7 @@ function computeMetadataRouteSuffix(appDirPath, leafName) {
|
|
|
292
292
|
};
|
|
293
293
|
}
|
|
294
294
|
function getMetadataRouteFilename(appDirPath, lastSegment) {
|
|
295
|
-
const ext = path.
|
|
295
|
+
const ext = path.extname(lastSegment);
|
|
296
296
|
const name = lastSegment.slice(0, -ext.length || void 0);
|
|
297
297
|
const { suffix } = computeMetadataRouteSuffix(appDirPath, name);
|
|
298
298
|
return `${name}${suffix ? `-${suffix}` : ""}${ext}`;
|
|
@@ -339,8 +339,8 @@ function metadataRouteSuffix(parentSegments, metaType) {
|
|
|
339
339
|
}
|
|
340
340
|
function withMetadataSuffix(urlPath, suffix) {
|
|
341
341
|
if (!suffix) return urlPath;
|
|
342
|
-
const parsed = path.
|
|
343
|
-
return path.
|
|
342
|
+
const parsed = path.parse(urlPath);
|
|
343
|
+
return path.join(parsed.dir || "/", `${parsed.name}-${suffix}${parsed.ext}`);
|
|
344
344
|
}
|
|
345
345
|
function getMetadataServedUrl(metaType, config, ext, isDynamic, suffix, routeBaseName) {
|
|
346
346
|
if (isDynamic && (metaType === "icon" || metaType === "apple-icon" || metaType === "opengraph-image" || metaType === "twitter-image")) return withMetadataSuffix(`/${routeBaseName}`, suffix);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { HasCondition } from "../config/next-config.js";
|
|
2
|
+
|
|
3
|
+
//#region src/server/middleware-matcher-pattern.d.ts
|
|
4
|
+
type CompiledMiddlewareMatcherPattern = {
|
|
5
|
+
regexp: RegExp;
|
|
6
|
+
error?: never;
|
|
7
|
+
} | {
|
|
8
|
+
regexp?: never;
|
|
9
|
+
error: string;
|
|
10
|
+
kind: "invalid" | "unsafe";
|
|
11
|
+
};
|
|
12
|
+
type MiddlewareMatcherObject = {
|
|
13
|
+
source: string;
|
|
14
|
+
locale?: false;
|
|
15
|
+
has?: HasCondition[];
|
|
16
|
+
missing?: HasCondition[];
|
|
17
|
+
};
|
|
18
|
+
declare function isValidMiddlewareMatcherObjectConfig(value: unknown): value is MiddlewareMatcherObject;
|
|
19
|
+
declare function compileMiddlewareMatcherPattern(source: string): CompiledMiddlewareMatcherPattern;
|
|
20
|
+
declare function validateMiddlewareMatcherPatterns(value: unknown): void;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { CompiledMiddlewareMatcherPattern, MiddlewareMatcherObject, compileMiddlewareMatcherPattern, isValidMiddlewareMatcherObjectConfig, validateMiddlewareMatcherPatterns };
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { analyzeRegexSafety, regexAtomsMayOverlap } from "../utils/regex-safety.js";
|
|
2
|
+
import { middlewarePathTokensToRegExp, normalizeMiddlewarePathTokens, parseMiddlewarePath } from "./middleware-path-to-regexp.js";
|
|
3
|
+
//#region src/server/middleware-matcher-pattern.ts
|
|
4
|
+
const MATCHER_OBJECT_KEYS = /* @__PURE__ */ new Set([
|
|
5
|
+
"source",
|
|
6
|
+
"locale",
|
|
7
|
+
"has",
|
|
8
|
+
"missing"
|
|
9
|
+
]);
|
|
10
|
+
const CONDITION_TYPES_WITH_KEY = /* @__PURE__ */ new Set([
|
|
11
|
+
"header",
|
|
12
|
+
"query",
|
|
13
|
+
"cookie"
|
|
14
|
+
]);
|
|
15
|
+
function invalidConditionReason(value) {
|
|
16
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return "has and missing entries must be objects";
|
|
17
|
+
const condition = value;
|
|
18
|
+
const type = condition.type;
|
|
19
|
+
if (typeof type === "string" && CONDITION_TYPES_WITH_KEY.has(type)) {
|
|
20
|
+
for (const key of Object.keys(condition)) if (key !== "type" && key !== "key" && key !== "value") return `condition contains unsupported field "${key}"`;
|
|
21
|
+
if (typeof condition.key !== "string") return `condition type "${type}" requires a string key`;
|
|
22
|
+
if (condition.value !== void 0 && typeof condition.value !== "string") return `condition type "${type}" requires value to be a string`;
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
if (type === "host") {
|
|
26
|
+
for (const key of Object.keys(condition)) if (key !== "type" && key !== "value") return `host condition contains unsupported field "${key}"`;
|
|
27
|
+
return typeof condition.value === "string" ? null : "host condition requires a string value";
|
|
28
|
+
}
|
|
29
|
+
return "condition type must be header, query, cookie, or host";
|
|
30
|
+
}
|
|
31
|
+
function invalidConditionsReason(value, field) {
|
|
32
|
+
if (value === void 0) return null;
|
|
33
|
+
if (!Array.isArray(value)) return `${field} must be an array`;
|
|
34
|
+
for (const condition of value) {
|
|
35
|
+
const reason = invalidConditionReason(condition);
|
|
36
|
+
if (reason) return `${field} ${reason}`;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
function matcherObjectSource(value) {
|
|
41
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return { error: "matcher entries must be strings or objects" };
|
|
42
|
+
const matcher = value;
|
|
43
|
+
for (const key of Object.keys(matcher)) if (!MATCHER_OBJECT_KEYS.has(key)) return { error: `matcher object contains unsupported field "${key}"` };
|
|
44
|
+
if (typeof matcher.source !== "string") return { error: "matcher object requires a string source" };
|
|
45
|
+
if (matcher.locale !== void 0 && matcher.locale !== false) return { error: "matcher object locale must be false when provided" };
|
|
46
|
+
const invalidHas = invalidConditionsReason(matcher.has, "has");
|
|
47
|
+
if (invalidHas) return { error: invalidHas };
|
|
48
|
+
const invalidMissing = invalidConditionsReason(matcher.missing, "missing");
|
|
49
|
+
if (invalidMissing) return { error: invalidMissing };
|
|
50
|
+
return { source: matcher.source };
|
|
51
|
+
}
|
|
52
|
+
function isValidMiddlewareMatcherObjectConfig(value) {
|
|
53
|
+
return matcherObjectSource(value).error === void 0;
|
|
54
|
+
}
|
|
55
|
+
function patternMatches(pattern, value) {
|
|
56
|
+
try {
|
|
57
|
+
return new RegExp(`^(?:${pattern})$`).test(value);
|
|
58
|
+
} catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function atomsOverlap(left, right) {
|
|
63
|
+
return regexAtomsMayOverlap(left, right, true);
|
|
64
|
+
}
|
|
65
|
+
function groupCanMatchEmpty(group) {
|
|
66
|
+
if (/^\?(?:[=!]|<[=!])/.test(group)) return true;
|
|
67
|
+
return patternMatches(group.startsWith("?:") ? group.slice(2) : group, "");
|
|
68
|
+
}
|
|
69
|
+
function hasOverlappingSequentialRepetition(pattern) {
|
|
70
|
+
const repeatedAtDepth = [[]];
|
|
71
|
+
const groupStarts = [];
|
|
72
|
+
let depth = 0;
|
|
73
|
+
for (let index = 0; index < pattern.length; index++) {
|
|
74
|
+
const character = pattern[index];
|
|
75
|
+
if (character === "(") {
|
|
76
|
+
groupStarts.push(index);
|
|
77
|
+
depth++;
|
|
78
|
+
repeatedAtDepth[depth] = [];
|
|
79
|
+
if (pattern[index + 1] === "?") {
|
|
80
|
+
index++;
|
|
81
|
+
if (pattern[index + 1] === "<" && /[=!]/.test(pattern[index + 2] ?? "")) index += 2;
|
|
82
|
+
else if (/[=:!]/.test(pattern[index + 1] ?? "")) index++;
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (character === ")") {
|
|
87
|
+
const groupStart = groupStarts.pop();
|
|
88
|
+
repeatedAtDepth[depth] = [];
|
|
89
|
+
depth = Math.max(0, depth - 1);
|
|
90
|
+
if (groupStart !== void 0) {
|
|
91
|
+
const modifier = pattern[index + 1];
|
|
92
|
+
if (!(modifier === "*" || modifier === "?" || modifier === "{" && /^\{0(?:,\d*)?\}/.test(pattern.slice(index + 1))) && !groupCanMatchEmpty(pattern.slice(groupStart + 1, index))) repeatedAtDepth[depth] = [];
|
|
93
|
+
}
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (character === "|") {
|
|
97
|
+
repeatedAtDepth[depth] = [];
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (character === "^" || character === "$") continue;
|
|
101
|
+
if (character === "*" || character === "+" || character === "?" || character === "{") continue;
|
|
102
|
+
let atom = character;
|
|
103
|
+
if (character === "\\") {
|
|
104
|
+
if (index + 1 >= pattern.length) return true;
|
|
105
|
+
atom += pattern[++index];
|
|
106
|
+
} else if (character === "[") {
|
|
107
|
+
let classEnd = index + 1;
|
|
108
|
+
if (pattern[classEnd] === "^") classEnd++;
|
|
109
|
+
while (classEnd < pattern.length && pattern[classEnd] !== "]") {
|
|
110
|
+
if (pattern[classEnd] === "\\") classEnd++;
|
|
111
|
+
classEnd++;
|
|
112
|
+
}
|
|
113
|
+
if (classEnd >= pattern.length) return true;
|
|
114
|
+
atom = pattern.slice(index, classEnd + 1);
|
|
115
|
+
index = classEnd;
|
|
116
|
+
} else if (character === ".") atom = ".";
|
|
117
|
+
const quantifierStart = index + 1;
|
|
118
|
+
const quantifier = pattern[quantifierStart];
|
|
119
|
+
let unbounded = quantifier === "*" || quantifier === "+";
|
|
120
|
+
let canBeEmpty = quantifier === "*";
|
|
121
|
+
let quantifierEnd = quantifierStart;
|
|
122
|
+
if (quantifier === "{") {
|
|
123
|
+
const match = /^\{(\d+),\}/.exec(pattern.slice(quantifierStart));
|
|
124
|
+
if (match) {
|
|
125
|
+
unbounded = true;
|
|
126
|
+
canBeEmpty = Number(match[1]) === 0;
|
|
127
|
+
quantifierEnd += match[0].length - 1;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!unbounded) {
|
|
131
|
+
if (quantifier !== "?") repeatedAtDepth[depth] = [];
|
|
132
|
+
if (quantifier === "?") index = quantifierStart;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (repeatedAtDepth[depth].some((previous) => atomsOverlap(previous, atom))) return true;
|
|
136
|
+
repeatedAtDepth[depth] = canBeEmpty ? [...repeatedAtDepth[depth], atom] : [atom];
|
|
137
|
+
index = quantifierEnd;
|
|
138
|
+
}
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
function unsafeTokenReason(token) {
|
|
142
|
+
const regexSafetyIssue = analyzeRegexSafety(token.pattern, { ignoreCase: true });
|
|
143
|
+
if (regexSafetyIssue) {
|
|
144
|
+
if (regexSafetyIssue === "analysis budget exceeded") return `parameter "${token.name}" exceeds the regex analysis budget`;
|
|
145
|
+
return `parameter "${token.name}" contains ${regexSafetyIssue}`;
|
|
146
|
+
}
|
|
147
|
+
if (hasOverlappingSequentialRepetition(token.pattern)) return `parameter "${token.name}" contains overlapping sequential repetition`;
|
|
148
|
+
if (token.modifier !== "*" && token.modifier !== "+") return null;
|
|
149
|
+
if (patternMatches(token.pattern, "") || patternMatches(token.pattern, "/")) return `repeated parameter "${token.name}" may match an empty value or path delimiter`;
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
function validateTokens(tokens) {
|
|
153
|
+
for (const token of tokens) {
|
|
154
|
+
if (typeof token === "string") continue;
|
|
155
|
+
const reason = unsafeTokenReason(token);
|
|
156
|
+
if (reason) return reason;
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
function compileMiddlewareMatcherPattern(source) {
|
|
161
|
+
if (!source.startsWith("/")) return {
|
|
162
|
+
kind: "invalid",
|
|
163
|
+
error: "source must start with /"
|
|
164
|
+
};
|
|
165
|
+
if (source.length > 4096) return {
|
|
166
|
+
kind: "invalid",
|
|
167
|
+
error: "source exceeds max built length of 4096"
|
|
168
|
+
};
|
|
169
|
+
let tokens;
|
|
170
|
+
try {
|
|
171
|
+
tokens = parseMiddlewarePath(source);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
return {
|
|
174
|
+
kind: "invalid",
|
|
175
|
+
error: error instanceof Error ? error.message : "matcher could not be parsed"
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const unsafeReason = validateTokens(tokens);
|
|
179
|
+
if (unsafeReason) return {
|
|
180
|
+
kind: "unsafe",
|
|
181
|
+
error: unsafeReason
|
|
182
|
+
};
|
|
183
|
+
try {
|
|
184
|
+
return { regexp: middlewarePathTokensToRegExp(tokens) };
|
|
185
|
+
} catch {
|
|
186
|
+
const normalizedTokens = normalizeMiddlewarePathTokens(tokens);
|
|
187
|
+
const normalizedUnsafeReason = validateTokens(normalizedTokens);
|
|
188
|
+
if (normalizedUnsafeReason) return {
|
|
189
|
+
kind: "unsafe",
|
|
190
|
+
error: normalizedUnsafeReason
|
|
191
|
+
};
|
|
192
|
+
try {
|
|
193
|
+
return { regexp: middlewarePathTokensToRegExp(normalizedTokens) };
|
|
194
|
+
} catch (error) {
|
|
195
|
+
return {
|
|
196
|
+
kind: "invalid",
|
|
197
|
+
error: error instanceof Error ? error.message : "matcher could not be compiled"
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function validateMiddlewareMatcherPatterns(value) {
|
|
203
|
+
const sources = [];
|
|
204
|
+
if (typeof value === "string") sources.push(value);
|
|
205
|
+
else if (Array.isArray(value)) for (const matcher of value) if (typeof matcher === "string") sources.push(matcher);
|
|
206
|
+
else {
|
|
207
|
+
const result = matcherObjectSource(matcher);
|
|
208
|
+
if (result.error) throw new Error(`Invalid middleware matcher config: ${result.error}.`);
|
|
209
|
+
sources.push(result.source);
|
|
210
|
+
}
|
|
211
|
+
else throw new Error("Invalid middleware matcher config: matcher must be a string or an array of strings or objects.");
|
|
212
|
+
for (const source of sources) {
|
|
213
|
+
const result = compileMiddlewareMatcherPattern(source);
|
|
214
|
+
if (result.regexp) continue;
|
|
215
|
+
throw new Error(`Invalid middleware matcher "${source}": ${result.error}.`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
//#endregion
|
|
219
|
+
export { compileMiddlewareMatcherPattern, isValidMiddlewareMatcherObjectConfig, validateMiddlewareMatcherPatterns };
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NextI18nConfig } from "../config/next-config.js";
|
|
2
|
+
import { MiddlewareMatcherObject } from "./middleware-matcher-pattern.js";
|
|
2
3
|
|
|
3
4
|
//#region src/server/middleware-matcher.d.ts
|
|
4
|
-
type MiddlewareMatcherObject = {
|
|
5
|
-
source: string;
|
|
6
|
-
locale?: false;
|
|
7
|
-
has?: HasCondition[];
|
|
8
|
-
missing?: HasCondition[];
|
|
9
|
-
};
|
|
10
5
|
type MatcherConfig = string | Array<string | MiddlewareMatcherObject>;
|
|
11
6
|
declare function matchesMiddleware(pathname: string, matcher: MatcherConfig | undefined, request?: Request, i18nConfig?: NextI18nConfig | null): boolean;
|
|
12
7
|
declare function matchPattern(pathname: string, pattern: string): boolean;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { removeTrailingSlash } from "../utils/base-path.js";
|
|
2
|
-
import {
|
|
2
|
+
import { requestContextFromRequest } from "../config/request-context.js";
|
|
3
|
+
import { checkHasConditions } from "../config/config-matchers.js";
|
|
4
|
+
import { compileMiddlewareMatcherPattern, isValidMiddlewareMatcherObjectConfig } from "./middleware-matcher-pattern.js";
|
|
3
5
|
//#region src/server/middleware-matcher.ts
|
|
4
6
|
const EMPTY_MIDDLEWARE_REQUEST_CONTEXT = {
|
|
5
7
|
headers: new Headers(),
|
|
@@ -12,30 +14,20 @@ const _mwPatternCache = /* @__PURE__ */ new Map();
|
|
|
12
14
|
function matchesMiddleware(pathname, matcher, request, i18nConfig) {
|
|
13
15
|
if (!matcher) return true;
|
|
14
16
|
if (typeof matcher === "string") return matchMatcherPattern(pathname, matcher, i18nConfig);
|
|
15
|
-
if (!Array.isArray(matcher)) return
|
|
17
|
+
if (!Array.isArray(matcher)) return true;
|
|
16
18
|
const requestContext = request ? requestContextFromRequest(request) : EMPTY_MIDDLEWARE_REQUEST_CONTEXT;
|
|
17
19
|
for (const m of matcher) {
|
|
18
20
|
if (typeof m === "string") {
|
|
19
21
|
if (matchMatcherPattern(pathname, m, i18nConfig)) return true;
|
|
20
22
|
continue;
|
|
21
23
|
}
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
24
|
+
if (!isValidMiddlewareMatcherObjectConfig(m)) return true;
|
|
25
|
+
if (!matchObjectMatcher(pathname, m, i18nConfig)) continue;
|
|
26
|
+
if (!checkHasConditions(m.has, m.missing, requestContext)) continue;
|
|
27
|
+
return true;
|
|
27
28
|
}
|
|
28
29
|
return false;
|
|
29
30
|
}
|
|
30
|
-
function isValidMiddlewareMatcherObject(value) {
|
|
31
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
32
|
-
if (!("source" in value) || typeof value.source !== "string") return false;
|
|
33
|
-
for (const key of Object.keys(value)) if (key !== "source" && key !== "locale" && key !== "has" && key !== "missing") return false;
|
|
34
|
-
if ("locale" in value && value.locale !== void 0 && value.locale !== false) return false;
|
|
35
|
-
if ("has" in value && value.has !== void 0 && !Array.isArray(value.has)) return false;
|
|
36
|
-
if ("missing" in value && value.missing !== void 0 && !Array.isArray(value.missing)) return false;
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
31
|
function matchMatcherPattern(pathname, pattern, i18nConfig) {
|
|
40
32
|
if (!i18nConfig) return matchPattern(pathname, pattern);
|
|
41
33
|
return matchPattern(stripLocalePrefix(pathname, i18nConfig) ?? pathname, pattern);
|
|
@@ -58,54 +50,15 @@ function matchPattern(pathname, pattern) {
|
|
|
58
50
|
_mwPatternCache.set(normalizedPattern, cached);
|
|
59
51
|
}
|
|
60
52
|
if (cached === UNSAFE_MATCHER_PATTERN) return true;
|
|
61
|
-
if (cached === null) return removeTrailingSlash(pathname) === normalizedPattern;
|
|
62
53
|
if (cached.test(pathname)) return true;
|
|
63
54
|
return pathname.endsWith("/") && cached.test(removeTrailingSlash(pathname));
|
|
64
55
|
}
|
|
65
|
-
function extractConstraint(str, re) {
|
|
66
|
-
if (str[re.lastIndex] !== "(") return null;
|
|
67
|
-
const start = re.lastIndex + 1;
|
|
68
|
-
let depth = 1;
|
|
69
|
-
let i = start;
|
|
70
|
-
while (i < str.length && depth > 0) {
|
|
71
|
-
if (str[i] === "(") depth++;
|
|
72
|
-
else if (str[i] === ")") depth--;
|
|
73
|
-
i++;
|
|
74
|
-
}
|
|
75
|
-
if (depth !== 0) return null;
|
|
76
|
-
re.lastIndex = i;
|
|
77
|
-
return str.slice(start, i - 1);
|
|
78
|
-
}
|
|
79
56
|
function compileMatcherPattern(pattern) {
|
|
80
|
-
const
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
while ((tok = tokenRe.exec(pattern)) !== null) if (tok[1] !== void 0) {
|
|
86
|
-
const constraint = hasConstraints ? extractConstraint(pattern, tokenRe) : null;
|
|
87
|
-
regexStr += constraint !== null ? `(?:/(${constraint}))?` : "(?:/.*)?";
|
|
88
|
-
} else if (tok[2] !== void 0) {
|
|
89
|
-
const constraint = hasConstraints ? extractConstraint(pattern, tokenRe) : null;
|
|
90
|
-
regexStr += constraint !== null ? `(?:/(${constraint}))` : "(?:/.+)";
|
|
91
|
-
} else if (tok[3] !== void 0) {
|
|
92
|
-
const constraint = hasConstraints ? extractConstraint(pattern, tokenRe) : null;
|
|
93
|
-
const isOptional = pattern[tokenRe.lastIndex] === "?";
|
|
94
|
-
if (isOptional) tokenRe.lastIndex += 1;
|
|
95
|
-
const group = constraint !== null ? `(${constraint})` : "([^/]+)";
|
|
96
|
-
if (isOptional && regexStr.endsWith("/")) regexStr = regexStr.slice(0, -1) + `(?:/${group})?`;
|
|
97
|
-
else if (isOptional) regexStr += `${group}?`;
|
|
98
|
-
else regexStr += group;
|
|
99
|
-
} else if (tok[0] === ".") regexStr += "\\.";
|
|
100
|
-
else regexStr += tok[0];
|
|
101
|
-
return compileMatcherRegExp("^" + regexStr + "$", pattern);
|
|
102
|
-
}
|
|
103
|
-
function compileMatcherRegExp(regexPattern, sourcePattern) {
|
|
104
|
-
if (!isSafeRegex(regexPattern)) {
|
|
105
|
-
console.warn(`[vinext] Rejecting potentially unsafe middleware matcher (ReDoS risk): ${sourcePattern}\n Middleware will run for all paths to avoid bypassing request guards.\n Simplify the matcher to avoid nested repetition.`);
|
|
106
|
-
return UNSAFE_MATCHER_PATTERN;
|
|
107
|
-
}
|
|
108
|
-
return safeRegExp(regexPattern);
|
|
57
|
+
const result = compileMiddlewareMatcherPattern(pattern);
|
|
58
|
+
if (result.regexp) return result.regexp;
|
|
59
|
+
const problem = result.kind === "unsafe" ? "potentially unsafe" : "invalid";
|
|
60
|
+
console.warn(`[vinext] Rejecting ${problem} middleware matcher: ${pattern}\n ${result.error}.\n Middleware will run for all paths to avoid bypassing request guards.`);
|
|
61
|
+
return UNSAFE_MATCHER_PATTERN;
|
|
109
62
|
}
|
|
110
63
|
//#endregion
|
|
111
64
|
export { matchPattern, matchesMiddleware };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/server/middleware-path-to-regexp.d.ts
|
|
2
|
+
type MiddlewarePathToken = string | MiddlewarePathKey;
|
|
3
|
+
type MiddlewarePathKey = {
|
|
4
|
+
name: string | number;
|
|
5
|
+
prefix: string;
|
|
6
|
+
suffix: string;
|
|
7
|
+
pattern: string;
|
|
8
|
+
modifier: string;
|
|
9
|
+
};
|
|
10
|
+
declare function parseMiddlewarePath(value: string): MiddlewarePathToken[];
|
|
11
|
+
declare function normalizeMiddlewarePathTokens(tokens: MiddlewarePathToken[]): MiddlewarePathToken[];
|
|
12
|
+
declare function middlewarePathTokensToRegExp(tokens: MiddlewarePathToken[]): RegExp;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { MiddlewarePathKey, MiddlewarePathToken, middlewarePathTokensToRegExp, normalizeMiddlewarePathTokens, parseMiddlewarePath };
|