vinext 1.1.0 → 1.2.0
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 -9
- package/dist/build/client-build-config.d.ts +10 -0
- package/dist/build/client-build-config.js +18 -2
- package/dist/build/pages-client-assets-module.d.ts +8 -0
- package/dist/build/pages-client-assets-module.js +21 -1
- package/dist/build/prerender-paths.js +5 -3
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/ssr-manifest.d.ts +2 -0
- package/dist/build/ssr-manifest.js +6 -2
- package/dist/check.js +7 -6
- package/dist/cli.js +2 -1
- package/dist/client/client-redirect-matcher.d.ts +14 -0
- package/dist/client/client-redirect-matcher.js +37 -0
- package/dist/client/client-redirects.d.ts +27 -0
- package/dist/client/client-redirects.js +28 -0
- package/dist/client/client-rewrites.d.ts +2 -1
- package/dist/client/client-rewrites.js +1 -1
- package/dist/config/config-matchers.d.ts +26 -11
- package/dist/config/config-matchers.js +78 -81
- package/dist/config/destination-params.d.ts +47 -0
- package/dist/config/destination-params.js +116 -0
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +3 -0
- package/dist/entries/app-rsc-entry.d.ts +4 -0
- package/dist/entries/app-rsc-entry.js +20 -6
- package/dist/entries/pages-client-entry.js +3 -1
- package/dist/entries/pages-server-entry.js +13 -37
- package/dist/index.d.ts +3 -1
- package/dist/index.js +134 -43
- package/dist/init-cloudflare.d.ts +9 -0
- package/dist/init-cloudflare.js +107 -31
- package/dist/init-platform.d.ts +4 -0
- package/dist/init-platform.js +27 -2
- package/dist/init.d.ts +1 -0
- package/dist/init.js +67 -3
- package/dist/plugins/ast-scope.d.ts +7 -0
- package/dist/plugins/ast-scope.js +59 -3
- package/dist/plugins/cache-flight-codec.d.ts +1 -1
- package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +9 -8
- package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +3 -4
- package/dist/plugins/middleware-server-only.d.ts +5 -4
- package/dist/plugins/middleware-server-only.js +8 -5
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
- package/dist/plugins/rsc-scan-glob-imports.js +50 -0
- package/dist/plugins/strip-server-exports.js +262 -98
- package/dist/plugins/transform-result.d.ts +9 -5
- package/dist/plugins/transitive-externals.js +1 -1
- package/dist/plugins/typeof-window.d.ts +2 -2
- package/dist/plugins/use-cache-callable.js +8 -2
- package/dist/plugins/worker-server-only-imports.d.ts +20 -0
- package/dist/plugins/worker-server-only-imports.js +31 -0
- package/dist/plugins/worker-use-server.d.ts +25 -0
- package/dist/plugins/worker-use-server.js +129 -0
- package/dist/server/api-handler.d.ts +1 -0
- package/dist/server/api-handler.js +2 -1
- package/dist/server/app-browser-action-result.d.ts +1 -1
- package/dist/server/app-browser-action-result.js +9 -2
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-middleware.d.ts +11 -0
- package/dist/server/app-middleware.js +17 -2
- package/dist/server/app-page-cache.d.ts +1 -1
- package/dist/server/app-page-cache.js +1 -1
- package/dist/server/app-page-dispatch.d.ts +3 -1
- package/dist/server/app-page-dispatch.js +4 -3
- package/dist/server/app-page-ppr-runtime.js +1 -1
- package/dist/server/app-page-render-observation.js +1 -1
- package/dist/server/app-page-request.js +53 -15
- package/dist/server/app-page-route-wiring.js +2 -2
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +2 -3
- package/dist/server/app-prerender-endpoints.js +9 -6
- package/dist/server/app-request-stage-dispatch.js +6 -2
- package/dist/server/app-request-stage-independent-entry.js +25 -5
- package/dist/server/app-response-stage-entry.js +10 -2
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +1 -0
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +5 -2
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +4 -1
- package/dist/server/app-route-handler-runtime.js +45 -24
- package/dist/server/app-router-entry.js +24 -5
- package/dist/server/app-rsc-cache-busting.js +1 -1
- package/dist/server/app-rsc-errors.js +20 -16
- package/dist/server/app-rsc-handler.d.ts +7 -0
- package/dist/server/app-rsc-handler.js +85 -35
- package/dist/server/app-rsc-response-stage.js +4 -2
- package/dist/server/app-segment-config.d.ts +2 -1
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +61 -22
- package/dist/server/app-ssr-entry.js +2 -1
- package/dist/server/app-worker-stages.d.ts +5 -0
- package/dist/server/app-worker-stages.js +1 -1
- package/dist/server/cacheability-request.js +2 -2
- package/dist/server/client-build-files.d.ts +16 -0
- package/dist/server/client-build-files.js +36 -0
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/dev-server.js +38 -27
- package/dist/server/dev-stack-sourcemap.js +18 -23
- package/dist/server/document-initial-head.d.ts +0 -11
- package/dist/server/document-initial-head.js +1 -1
- package/dist/server/forwarded-middleware-context.d.ts +5 -0
- package/dist/server/forwarded-middleware-context.js +22 -0
- package/dist/server/headers.d.ts +4 -1
- package/dist/server/headers.js +4 -1
- package/dist/server/http-conditional.d.ts +11 -0
- package/dist/server/http-conditional.js +10 -1
- package/dist/server/http-error-responses.d.ts +1 -1
- package/dist/server/image-optimization.d.ts +38 -0
- package/dist/server/image-optimization.js +93 -4
- package/dist/server/isr-cache.d.ts +10 -0
- package/dist/server/isr-cache.js +41 -6
- package/dist/server/metadata-route-response.js +9 -8
- package/dist/server/middleware-matcher.d.ts +2 -0
- package/dist/server/middleware-matcher.js +23 -2
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +33 -20
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +3 -1
- package/dist/server/multi-stage.d.ts +11 -0
- package/dist/server/normalize-path.d.ts +0 -13
- package/dist/server/normalize-path.js +1 -34
- package/dist/server/pages-api-route.d.ts +3 -2
- package/dist/server/pages-api-route.js +4 -3
- package/dist/server/pages-cache-tag.d.ts +12 -0
- package/dist/server/pages-cache-tag.js +19 -0
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-data-route.d.ts +10 -0
- package/dist/server/pages-data-route.js +19 -2
- package/dist/server/pages-document-asset-props.d.ts +5 -1
- package/dist/server/pages-document-asset-props.js +13 -5
- package/dist/server/pages-document-splice.d.ts +19 -0
- package/dist/server/pages-document-splice.js +55 -0
- package/dist/server/pages-i18n.d.ts +12 -1
- package/dist/server/pages-i18n.js +18 -4
- package/dist/server/pages-node-compat.d.ts +16 -5
- package/dist/server/pages-node-compat.js +20 -12
- package/dist/server/pages-page-data.d.ts +32 -24
- package/dist/server/pages-page-data.js +50 -120
- package/dist/server/pages-page-handler.d.ts +0 -6
- package/dist/server/pages-page-handler.js +188 -126
- package/dist/server/pages-page-response.d.ts +12 -6
- package/dist/server/pages-page-response.js +41 -34
- package/dist/server/pages-request-pipeline.d.ts +10 -2
- package/dist/server/pages-request-pipeline.js +37 -18
- package/dist/server/pages-request-stage-entry.d.ts +6 -0
- package/dist/server/pages-request-stage-entry.js +71 -12
- package/dist/server/pages-response-stage-entry.js +4 -0
- package/dist/server/pages-revalidate.js +1 -1
- package/dist/server/pages-router-entry.js +4 -3
- package/dist/server/prerender-manifest.d.ts +3 -3
- package/dist/server/prerender-manifest.js +4 -3
- package/dist/server/prerender-work-unit-setup.js +4 -0
- package/dist/server/prod-server.d.ts +12 -0
- package/dist/server/prod-server.js +199 -69
- package/dist/server/proper-error.d.ts +4 -0
- package/dist/server/proper-error.js +31 -0
- package/dist/server/request-pipeline.d.ts +4 -1
- package/dist/server/request-pipeline.js +3 -2
- package/dist/server/revalidation-request.d.ts +1 -0
- package/dist/server/revalidation-request.js +1 -1
- package/dist/server/rsc-stream-hints.js +31 -2
- package/dist/server/seed-cache.d.ts +1 -0
- package/dist/server/seed-cache.js +5 -4
- package/dist/server/server-reference-loader.d.ts +4 -0
- package/dist/server/server-reference-loader.js +29 -0
- package/dist/server/socket-error-backstop.d.ts +9 -1
- package/dist/server/socket-error-backstop.js +46 -17
- package/dist/server/static-file-signal.d.ts +15 -4
- package/dist/server/static-file-signal.js +46 -12
- package/dist/server/worker-image-optimization.d.ts +34 -0
- package/dist/server/worker-image-optimization.js +86 -0
- package/dist/server/worker-stages.d.ts +1 -1
- package/dist/server/worker-stages.js +2 -2
- package/dist/server/worker-utils.d.ts +8 -3
- package/dist/server/worker-utils.js +12 -7
- package/dist/shims/app-router-scroll.js +4 -1
- package/dist/shims/app-router-tree-context.d.ts +5 -0
- package/dist/shims/app-router-tree-context.js +27 -0
- package/dist/shims/cache-callable-runtime.d.ts +4 -2
- package/dist/shims/cache-callable-runtime.js +21 -12
- package/dist/shims/cache-handler.js +1 -9
- package/dist/shims/cache-runtime.d.ts +6 -1
- package/dist/shims/cache-runtime.js +2 -1
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +40 -13
- package/dist/shims/cdn-cache.d.ts +8 -0
- package/dist/shims/cdn-cache.js +17 -1
- package/dist/shims/disable-smooth-scroll.d.ts +3 -0
- package/dist/shims/disable-smooth-scroll.js +36 -0
- package/dist/shims/document-placeholders.d.ts +19 -0
- package/dist/shims/document-placeholders.js +45 -0
- package/dist/shims/document.js +21 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
- package/dist/shims/dynamic-preload-chunks.js +13 -9
- package/dist/shims/dynamic.d.ts +1 -1
- package/dist/shims/dynamic.js +60 -8
- package/dist/shims/fetch-cache-state.d.ts +66 -0
- package/dist/shims/fetch-cache-state.js +92 -0
- package/dist/shims/fetch-cache.d.ts +3 -67
- package/dist/shims/fetch-cache.js +160 -125
- package/dist/shims/head.d.ts +10 -6
- package/dist/shims/head.js +15 -13
- package/dist/shims/image.js +2 -1
- package/dist/shims/internal/work-store-scope.d.ts +5 -0
- package/dist/shims/internal/work-store-scope.js +24 -0
- package/dist/shims/navigation.js +31 -5
- package/dist/shims/request-context.d.ts +2 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/router.js +12 -20
- package/dist/shims/server.d.ts +16 -0
- package/dist/shims/server.js +24 -4
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/url-utils.d.ts +2 -0
- package/dist/shims/url-utils.js +3 -1
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/hash.d.ts +7 -0
- package/dist/utils/hash.js +11 -1
- package/dist/utils/package-name.d.ts +6 -0
- package/dist/utils/package-name.js +12 -1
- package/dist/utils/plugin-rsc-version.d.ts +4 -0
- package/dist/utils/plugin-rsc-version.js +15 -0
- package/dist/utils/prerender-output-paths.js +15 -4
- package/dist/utils/public-file-path.d.ts +10 -2
- package/dist/utils/public-file-path.js +13 -9
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.d.ts +3 -0
- package/dist/utils/react-version.js +1 -1
- package/package.json +7 -3
|
@@ -3,6 +3,7 @@ import { buildRequestHeadersFromMiddlewareResponse, getUnconsumedMiddlewareReque
|
|
|
3
3
|
import { analyzeRegexSafety } from "../utils/regex-safety.js";
|
|
4
4
|
import { normalizeHost, parseCookies, requestContextFromRequest } from "./request-context.js";
|
|
5
5
|
import { isExternalUrl } from "../utils/external-url.js";
|
|
6
|
+
import { substituteDestinationParams, substituteRedirectDestinationQuery } from "./destination-params.js";
|
|
6
7
|
//#region src/config/config-matchers.ts
|
|
7
8
|
/**
|
|
8
9
|
* Cache for compiled regex patterns in matchConfigPattern.
|
|
@@ -44,14 +45,6 @@ const _compiledHeaderSourceCache = /* @__PURE__ */ new Map();
|
|
|
44
45
|
*/
|
|
45
46
|
const _compiledConditionCache = /* @__PURE__ */ new Map();
|
|
46
47
|
/**
|
|
47
|
-
* Cache for destination substitution regexes in substituteDestinationParams.
|
|
48
|
-
*
|
|
49
|
-
* The regex depends only on the set of param keys captured from the matched
|
|
50
|
-
* source pattern. Caching by sorted key list avoids recompiling a new RegExp
|
|
51
|
-
* for repeated redirect/rewrite calls that use the same param shape.
|
|
52
|
-
*/
|
|
53
|
-
const _compiledDestinationParamCache = /* @__PURE__ */ new Map();
|
|
54
|
-
/**
|
|
55
48
|
* Generic helper for the regex compilation caches above.
|
|
56
49
|
*
|
|
57
50
|
* Each cache stores the compiled artifact (or `null` when safeRegExp rejected
|
|
@@ -561,13 +554,10 @@ function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAU
|
|
|
561
554
|
onRuleSourceMatch?.(redirect);
|
|
562
555
|
const conditionParams = redirect.has || redirect.missing ? collectConditionParams(redirect.has, redirect.missing, ctx) : _emptyParams();
|
|
563
556
|
if (!conditionParams) continue;
|
|
564
|
-
localeMatch = {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
}),
|
|
569
|
-
permanent: redirect.permanent
|
|
570
|
-
};
|
|
557
|
+
localeMatch = resolveRedirectMatch(redirect, {
|
|
558
|
+
[entry.paramName]: "",
|
|
559
|
+
...conditionParams
|
|
560
|
+
});
|
|
571
561
|
localeMatchIndex = entry.originalIndex;
|
|
572
562
|
break;
|
|
573
563
|
}
|
|
@@ -584,13 +574,10 @@ function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAU
|
|
|
584
574
|
onRuleSourceMatch?.(redirect);
|
|
585
575
|
const conditionParams = redirect.has || redirect.missing ? collectConditionParams(redirect.has, redirect.missing, ctx) : _emptyParams();
|
|
586
576
|
if (!conditionParams) continue;
|
|
587
|
-
localeMatch = {
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
}),
|
|
592
|
-
permanent: redirect.permanent
|
|
593
|
-
};
|
|
577
|
+
localeMatch = resolveRedirectMatch(redirect, {
|
|
578
|
+
[entry.paramName]: localePart,
|
|
579
|
+
...conditionParams
|
|
580
|
+
});
|
|
594
581
|
localeMatchIndex = entry.originalIndex;
|
|
595
582
|
break;
|
|
596
583
|
}
|
|
@@ -604,13 +591,10 @@ function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAU
|
|
|
604
591
|
onRuleSourceMatch?.(redirect);
|
|
605
592
|
const conditionParams = redirect.has || redirect.missing ? collectConditionParams(redirect.has, redirect.missing, ctx) : _emptyParams();
|
|
606
593
|
if (!conditionParams) continue;
|
|
607
|
-
return {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
}),
|
|
612
|
-
permanent: redirect.permanent
|
|
613
|
-
};
|
|
594
|
+
return resolveRedirectMatch(redirect, {
|
|
595
|
+
...params,
|
|
596
|
+
...conditionParams
|
|
597
|
+
});
|
|
614
598
|
}
|
|
615
599
|
}
|
|
616
600
|
return localeMatch;
|
|
@@ -636,12 +620,24 @@ function matchRewrite(pathname, rewrites, ctx, basePathState = _BASEPATH_DEFAULT
|
|
|
636
620
|
...params,
|
|
637
621
|
...conditionParams
|
|
638
622
|
};
|
|
639
|
-
return substituteAndSanitizeRewriteDestination(rewrite.destination, rewriteParams);
|
|
623
|
+
return substituteAndSanitizeRewriteDestination(serializeRewriteDestinationTemplate(rewrite.destination), rewriteParams);
|
|
640
624
|
}
|
|
641
625
|
}
|
|
642
626
|
return null;
|
|
643
627
|
}
|
|
644
628
|
/**
|
|
629
|
+
* Next.js prepareDestination URL-parses the destination template before it
|
|
630
|
+
* substitutes params, so a literal `é` routes as `%C3%A9` while substituted
|
|
631
|
+
* values stay verbatim: a captured `../admin` is never resolved to `/admin`.
|
|
632
|
+
*
|
|
633
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/prepare-destination.ts
|
|
634
|
+
*/
|
|
635
|
+
function serializeRewriteDestinationTemplate(destination) {
|
|
636
|
+
if (!destination.startsWith("/") || destination.startsWith("//")) return destination;
|
|
637
|
+
const parsed = new URL(destination, "http://n");
|
|
638
|
+
return parsed.pathname + parsed.search + parsed.hash;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
645
641
|
* Check whether a rewrite source can match a pathname without evaluating its
|
|
646
642
|
* request-dependent `has` / `missing` conditions.
|
|
647
643
|
*
|
|
@@ -654,47 +650,20 @@ function matchesRewriteSource(pathname, rewrite, basePathState = _BASEPATH_DEFAU
|
|
|
654
650
|
return shouldEvaluateRule(rewrite.basePath, basePathState) && matchConfigPattern(pathname, rewrite.source) !== null;
|
|
655
651
|
}
|
|
656
652
|
/**
|
|
657
|
-
* Substitute all matched route params into a redirect/rewrite destination.
|
|
658
|
-
*
|
|
659
|
-
* Handles repeated params (e.g. `/api/:id/:id`) and catch-all suffix forms
|
|
660
|
-
* (`:path*`, `:path+`) in a single pass. Unknown params are left intact.
|
|
661
|
-
*/
|
|
662
|
-
function substituteDestinationParams(destination, params) {
|
|
663
|
-
const keys = Object.keys(params);
|
|
664
|
-
if (keys.length === 0) return destination;
|
|
665
|
-
const sortedKeys = [...keys].sort((a, b) => b.length - a.length);
|
|
666
|
-
const cacheKey = sortedKeys.join("\0");
|
|
667
|
-
let paramRe = _compiledDestinationParamCache.get(cacheKey);
|
|
668
|
-
if (!paramRe) {
|
|
669
|
-
const paramAlternation = sortedKeys.map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
670
|
-
paramRe = new RegExp(`:(${paramAlternation})([+*])?(?![A-Za-z0-9_])`, "g");
|
|
671
|
-
_compiledDestinationParamCache.set(cacheKey, paramRe);
|
|
672
|
-
}
|
|
673
|
-
const replaceParams = (value, encodeParam) => value.replace(paramRe, (_token, key) => encodeParam(params[key]));
|
|
674
|
-
const hashIndex = destination.indexOf("#");
|
|
675
|
-
const beforeHash = hashIndex === -1 ? destination : destination.slice(0, hashIndex);
|
|
676
|
-
const hash = hashIndex === -1 ? "" : destination.slice(hashIndex);
|
|
677
|
-
const queryIndex = beforeHash.indexOf("?");
|
|
678
|
-
if (queryIndex !== -1) {
|
|
679
|
-
const beforeQuery = beforeHash.slice(0, queryIndex);
|
|
680
|
-
const query = beforeHash.slice(queryIndex + 1);
|
|
681
|
-
return `${replaceParams(beforeQuery, (value) => value)}?${replaceParams(query, encodeDestinationQueryParamValue)}${replaceParams(hash, (value) => value)}`;
|
|
682
|
-
}
|
|
683
|
-
return replaceParams(destination, (value) => value);
|
|
684
|
-
}
|
|
685
|
-
function encodeDestinationQueryParamValue(value) {
|
|
686
|
-
const params = new URLSearchParams();
|
|
687
|
-
params.set("", value);
|
|
688
|
-
return params.toString().slice(1);
|
|
689
|
-
}
|
|
690
|
-
/**
|
|
691
653
|
* Substitute params into a redirect/rewrite destination and sanitize the
|
|
692
654
|
* result. Used by every redirect/rewrite branch — the substitution can
|
|
693
655
|
* introduce protocol-relative URLs (e.g. `//evil.com` from a decoded `%2F`
|
|
694
656
|
* in a catch-all param), which sanitizeDestination collapses.
|
|
695
657
|
*/
|
|
696
|
-
function substituteAndSanitizeDestination(destination, params) {
|
|
697
|
-
return sanitizeDestination(substituteDestinationParams(destination, params));
|
|
658
|
+
function substituteAndSanitizeDestination(destination, params, kind) {
|
|
659
|
+
return sanitizeDestination(substituteDestinationParams(destination, params, kind));
|
|
660
|
+
}
|
|
661
|
+
function resolveRedirectMatch(redirect, params) {
|
|
662
|
+
return {
|
|
663
|
+
destination: substituteAndSanitizeDestination(redirect.destination, params, "redirect"),
|
|
664
|
+
permanent: redirect.permanent,
|
|
665
|
+
destinationQuery: substituteRedirectDestinationQuery(redirect.destination, params)
|
|
666
|
+
};
|
|
698
667
|
}
|
|
699
668
|
/**
|
|
700
669
|
* Match Next.js's rewrite-specific prepareDestination behavior: source params
|
|
@@ -704,7 +673,7 @@ function substituteAndSanitizeDestination(destination, params) {
|
|
|
704
673
|
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/prepare-destination.ts
|
|
705
674
|
*/
|
|
706
675
|
function substituteAndSanitizeRewriteDestination(destination, params) {
|
|
707
|
-
const rewritten = substituteAndSanitizeDestination(destination, params);
|
|
676
|
+
const rewritten = substituteAndSanitizeDestination(destination, params, "rewrite");
|
|
708
677
|
if (!shouldAppendRewriteParamsToQuery(destination, params)) return rewritten;
|
|
709
678
|
const existingQueryKeys = getDestinationQueryKeys(destination);
|
|
710
679
|
const paramsToAppend = [];
|
|
@@ -771,11 +740,12 @@ function appendQueryParams(url, params) {
|
|
|
771
740
|
* users off-site.
|
|
772
741
|
*
|
|
773
742
|
* This function collapses any leading double (or more) slashes to a single
|
|
774
|
-
* slash for non-external (relative) destinations
|
|
743
|
+
* slash for non-external (relative) destinations, including tab/newline and
|
|
744
|
+
* leading C0 control characters that browsers ignore while parsing.
|
|
775
745
|
*/
|
|
776
746
|
function sanitizeDestination(dest) {
|
|
777
747
|
if (dest.startsWith("http://") || dest.startsWith("https://")) return dest;
|
|
778
|
-
dest = dest.replace(/^[\\/]+/, "/");
|
|
748
|
+
dest = dest.replace(/^[\u0000-\u0020]*(?:[\\/][\t\n\r]*)+/, "/");
|
|
779
749
|
return dest;
|
|
780
750
|
}
|
|
781
751
|
/**
|
|
@@ -795,13 +765,20 @@ function sanitizeDestination(dest) {
|
|
|
795
765
|
* still treated as an RSC fetch. Dropping it breaks RSC fetch semantics
|
|
796
766
|
* (issue #1529).
|
|
797
767
|
*
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
*
|
|
801
|
-
*
|
|
802
|
-
*
|
|
768
|
+
* Ported from Next.js's `{ ...requestQuery, ...destinationQuery }` merge and
|
|
769
|
+
* `stringifyQuery`: request keys keep their order (integer-like keys first, as
|
|
770
|
+
* in a JS object), a destination key overrides the request value in place,
|
|
771
|
+
* and destination-only keys follow. Request keys and values are re-encoded;
|
|
772
|
+
* destination query text is emitted verbatim, except that, like Next.js,
|
|
773
|
+
* destination strings equal to a request key or value are re-encoded too.
|
|
774
|
+
* Pass the match's
|
|
775
|
+
* `destinationQuery` so substituted params keep their value boundaries;
|
|
776
|
+
* without it the destination's own query is split. External destinations are returned untouched (a config redirect to another
|
|
777
|
+
* origin should not leak the original request's query).
|
|
778
|
+
*
|
|
779
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/server/server-route-utils.ts
|
|
803
780
|
*/
|
|
804
|
-
function preserveRedirectDestinationQuery(destination, requestSearch) {
|
|
781
|
+
function preserveRedirectDestinationQuery(destination, requestSearch, destinationQuery) {
|
|
805
782
|
if (requestSearch === "" || requestSearch === "?" || isExternalUrl(destination)) return destination;
|
|
806
783
|
const requestParams = new URLSearchParams(requestSearch);
|
|
807
784
|
if ([...requestParams.keys()].length === 0) return destination;
|
|
@@ -810,13 +787,29 @@ function preserveRedirectDestinationQuery(destination, requestSearch) {
|
|
|
810
787
|
const beforeHash = hashIndex === -1 ? destination : destination.slice(0, hashIndex);
|
|
811
788
|
const queryIndex = beforeHash.indexOf("?");
|
|
812
789
|
const pathPart = queryIndex === -1 ? beforeHash : beforeHash.slice(0, queryIndex);
|
|
813
|
-
const
|
|
814
|
-
const
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
-
|
|
790
|
+
const requestStrings = /* @__PURE__ */ new Set();
|
|
791
|
+
const requestParts = Object.create(null);
|
|
792
|
+
for (const [key, value] of requestParams) {
|
|
793
|
+
requestStrings.add(key);
|
|
794
|
+
requestStrings.add(value);
|
|
795
|
+
(requestParts[key] ??= []).push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
|
|
796
|
+
}
|
|
797
|
+
const encode = (text) => requestStrings.has(text) ? encodeURIComponent(text) : text;
|
|
798
|
+
const destinationParts = Object.create(null);
|
|
799
|
+
for (const [key, keyText, valueText] of destinationQuery ?? substituteRedirectDestinationQuery(destination, {})) (destinationParts[key] ??= []).push(valueText === null ? encode(keyText) : `${encode(keyText)}=${encode(valueText)}`);
|
|
800
|
+
const mergedQuery = Object.values({
|
|
801
|
+
...requestParts,
|
|
802
|
+
...destinationParts
|
|
803
|
+
}).flat().join("&");
|
|
818
804
|
return mergedQuery === "" ? `${pathPart}${hash}` : `${pathPart}?${mergedQuery}${hash}`;
|
|
819
805
|
}
|
|
806
|
+
function parseExternalRewriteUrl(externalUrl) {
|
|
807
|
+
try {
|
|
808
|
+
return new URL(externalUrl);
|
|
809
|
+
} catch {
|
|
810
|
+
return null;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
820
813
|
/**
|
|
821
814
|
* Proxy an incoming request to an external URL and return the upstream response.
|
|
822
815
|
*
|
|
@@ -828,7 +821,11 @@ function preserveRedirectDestinationQuery(destination, requestSearch) {
|
|
|
828
821
|
*/
|
|
829
822
|
async function proxyExternalRequest(request, externalUrl) {
|
|
830
823
|
const originalUrl = new URL(request.url);
|
|
831
|
-
const targetUrl =
|
|
824
|
+
const targetUrl = parseExternalRewriteUrl(externalUrl);
|
|
825
|
+
if (!targetUrl) {
|
|
826
|
+
console.error("[vinext] Invalid external rewrite destination:", externalUrl);
|
|
827
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
828
|
+
}
|
|
832
829
|
const destinationKeys = new Set(targetUrl.searchParams.keys());
|
|
833
830
|
for (const [key, value] of originalUrl.searchParams) if (!destinationKeys.has(key)) targetUrl.searchParams.append(key, value);
|
|
834
831
|
const headers = new Headers(request.headers);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region src/config/destination-params.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Destination param substitution for next.config.js redirects and rewrites.
|
|
4
|
+
*
|
|
5
|
+
* Kept free of server-only imports so the Pages Router client can apply simple
|
|
6
|
+
* beforeFiles rewrites with exactly the same substitution as the server.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Substitute all matched route params into a redirect/rewrite destination.
|
|
10
|
+
*
|
|
11
|
+
* Handles repeated params (e.g. `/api/:id/:id`) and catch-all suffix forms
|
|
12
|
+
* (`:path*`, `:path+`) in a single pass. Unknown params are left intact.
|
|
13
|
+
*
|
|
14
|
+
* Query substitution follows how Next.js consumes each destination kind:
|
|
15
|
+
*
|
|
16
|
+
* - A rewrite's query is parsed into an object before substitution, so the
|
|
17
|
+
* target sees each param verbatim as one value. vinext encodes the whole
|
|
18
|
+
* value so it round-trips back to that verbatim string.
|
|
19
|
+
* - A redirect's query is emitted as Location text with params inserted
|
|
20
|
+
* verbatim, so an already percent-encoded capture is decoded once by the
|
|
21
|
+
* client. vinext inserts redirect params verbatim too.
|
|
22
|
+
*
|
|
23
|
+
* A rewrite's absolute destination is proxied server-side, so params in its
|
|
24
|
+
* authority (`https://:tenant.example.com/`) are percent-encoded, keeping the
|
|
25
|
+
* `%XX` escapes a raw path capture already carries. A decoded `has` capture
|
|
26
|
+
* carrying `#`, `/`, `?`, `@` or `:` then makes the host invalid instead of
|
|
27
|
+
* moving the proxy to another host. Next.js substitutes the hostname verbatim
|
|
28
|
+
* and can be retargeted this way; vinext is stricter.
|
|
29
|
+
*
|
|
30
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/prepare-destination.ts
|
|
31
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/server/server-route-utils.ts
|
|
32
|
+
*/
|
|
33
|
+
export declare function substituteDestinationParams(destination: string, params: Record<string, string>, kind: "redirect" | "rewrite"): string;
|
|
34
|
+
/**
|
|
35
|
+
* Split a redirect destination's query into parts before substituting params,
|
|
36
|
+
* as Next.js's prepareDestination parses the template query first. Each part
|
|
37
|
+
* is `[key, keyText, valueText]`: the texts are the part's template text with
|
|
38
|
+
* params substituted verbatim (`valueText` is `null` without an `=`), and
|
|
39
|
+
* `key` is the decoded key, used only to match request params. Keeping these
|
|
40
|
+
* boundaries means a param containing `&` stays one value when the request
|
|
41
|
+
* query is merged in.
|
|
42
|
+
*
|
|
43
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/prepare-destination.ts
|
|
44
|
+
*/
|
|
45
|
+
export declare function substituteRedirectDestinationQuery(destination: string, params: Record<string, string>): RedirectDestinationQueryPart[];
|
|
46
|
+
export type RedirectDestinationQueryPart = [key: string, keyText: string, valueText: string | null];
|
|
47
|
+
//#endregion
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
//#region src/config/destination-params.ts
|
|
2
|
+
/**
|
|
3
|
+
* Destination param substitution for next.config.js redirects and rewrites.
|
|
4
|
+
*
|
|
5
|
+
* Kept free of server-only imports so the Pages Router client can apply simple
|
|
6
|
+
* beforeFiles rewrites with exactly the same substitution as the server.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Cache for destination substitution regexes in substituteDestinationParams.
|
|
10
|
+
*
|
|
11
|
+
* The regex depends only on the set of param keys captured from the matched
|
|
12
|
+
* source pattern. Caching by sorted key list avoids recompiling a new RegExp
|
|
13
|
+
* for repeated redirect/rewrite calls that use the same param shape.
|
|
14
|
+
*/
|
|
15
|
+
const _compiledDestinationParamCache = /* @__PURE__ */ new Map();
|
|
16
|
+
/**
|
|
17
|
+
* Substitute all matched route params into a redirect/rewrite destination.
|
|
18
|
+
*
|
|
19
|
+
* Handles repeated params (e.g. `/api/:id/:id`) and catch-all suffix forms
|
|
20
|
+
* (`:path*`, `:path+`) in a single pass. Unknown params are left intact.
|
|
21
|
+
*
|
|
22
|
+
* Query substitution follows how Next.js consumes each destination kind:
|
|
23
|
+
*
|
|
24
|
+
* - A rewrite's query is parsed into an object before substitution, so the
|
|
25
|
+
* target sees each param verbatim as one value. vinext encodes the whole
|
|
26
|
+
* value so it round-trips back to that verbatim string.
|
|
27
|
+
* - A redirect's query is emitted as Location text with params inserted
|
|
28
|
+
* verbatim, so an already percent-encoded capture is decoded once by the
|
|
29
|
+
* client. vinext inserts redirect params verbatim too.
|
|
30
|
+
*
|
|
31
|
+
* A rewrite's absolute destination is proxied server-side, so params in its
|
|
32
|
+
* authority (`https://:tenant.example.com/`) are percent-encoded, keeping the
|
|
33
|
+
* `%XX` escapes a raw path capture already carries. A decoded `has` capture
|
|
34
|
+
* carrying `#`, `/`, `?`, `@` or `:` then makes the host invalid instead of
|
|
35
|
+
* moving the proxy to another host. Next.js substitutes the hostname verbatim
|
|
36
|
+
* and can be retargeted this way; vinext is stricter.
|
|
37
|
+
*
|
|
38
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/prepare-destination.ts
|
|
39
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/server/server-route-utils.ts
|
|
40
|
+
*/
|
|
41
|
+
function substituteDestinationParams(destination, params, kind) {
|
|
42
|
+
const paramRe = getDestinationParamRegex(params);
|
|
43
|
+
if (!paramRe) return destination;
|
|
44
|
+
const replaceParams = (value, encodeParam) => value.replace(paramRe, (_token, key) => encodeParam(params[key]));
|
|
45
|
+
if (kind === "redirect") return replaceParams(destination, (value) => value);
|
|
46
|
+
const hashIndex = destination.indexOf("#");
|
|
47
|
+
const beforeHash = hashIndex === -1 ? destination : destination.slice(0, hashIndex);
|
|
48
|
+
const hash = hashIndex === -1 ? "" : destination.slice(hashIndex);
|
|
49
|
+
const queryIndex = beforeHash.indexOf("?");
|
|
50
|
+
const beforeQuery = queryIndex === -1 ? beforeHash : beforeHash.slice(0, queryIndex);
|
|
51
|
+
const authorityEnd = getAbsoluteUrlAuthorityEnd(beforeQuery.replace(paramRe, (token) => "x".repeat(token.length)));
|
|
52
|
+
return `${`${replaceParams(beforeQuery.slice(0, authorityEnd), encodeAuthorityParam)}${replaceParams(beforeQuery.slice(authorityEnd), (value) => value)}`}${queryIndex === -1 ? "" : `?${replaceParams(beforeHash.slice(queryIndex + 1), encodeRewriteQueryParamValue)}`}${replaceParams(hash, (value) => value)}`;
|
|
53
|
+
}
|
|
54
|
+
function getAbsoluteUrlAuthorityEnd(value) {
|
|
55
|
+
const scheme = /^[a-z][a-z0-9+.-]*:[/\\\t\n\r]*/i.exec(value);
|
|
56
|
+
if (!scheme && /^[/\\]/.test(value)) return 0;
|
|
57
|
+
const start = scheme ? scheme[0].length : 0;
|
|
58
|
+
const pathStart = value.slice(start).search(/[/\\]/);
|
|
59
|
+
return pathStart === -1 ? value.length : start + pathStart;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Split a redirect destination's query into parts before substituting params,
|
|
63
|
+
* as Next.js's prepareDestination parses the template query first. Each part
|
|
64
|
+
* is `[key, keyText, valueText]`: the texts are the part's template text with
|
|
65
|
+
* params substituted verbatim (`valueText` is `null` without an `=`), and
|
|
66
|
+
* `key` is the decoded key, used only to match request params. Keeping these
|
|
67
|
+
* boundaries means a param containing `&` stays one value when the request
|
|
68
|
+
* query is merged in.
|
|
69
|
+
*
|
|
70
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/prepare-destination.ts
|
|
71
|
+
*/
|
|
72
|
+
function substituteRedirectDestinationQuery(destination, params) {
|
|
73
|
+
const hashIndex = destination.indexOf("#");
|
|
74
|
+
const beforeHash = hashIndex === -1 ? destination : destination.slice(0, hashIndex);
|
|
75
|
+
const queryIndex = beforeHash.indexOf("?");
|
|
76
|
+
if (queryIndex === -1) return [];
|
|
77
|
+
const paramRe = getDestinationParamRegex(params);
|
|
78
|
+
const substitute = (value) => paramRe ? value.replace(paramRe, (_token, key) => params[key]) : value;
|
|
79
|
+
return beforeHash.slice(queryIndex + 1).split("&").filter(Boolean).map((part) => {
|
|
80
|
+
const equalsIndex = part.indexOf("=");
|
|
81
|
+
const keyText = substitute(equalsIndex === -1 ? part : part.slice(0, equalsIndex));
|
|
82
|
+
const valueText = equalsIndex === -1 ? null : substitute(part.slice(equalsIndex + 1));
|
|
83
|
+
return [
|
|
84
|
+
decodeQueryKey(keyText),
|
|
85
|
+
keyText,
|
|
86
|
+
valueText
|
|
87
|
+
];
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function decodeQueryKey(keyText) {
|
|
91
|
+
const [entry] = new URLSearchParams(keyText.replace(/[&=]/g, (char) => encodeURIComponent(char)));
|
|
92
|
+
return entry?.[0] ?? "";
|
|
93
|
+
}
|
|
94
|
+
function getDestinationParamRegex(params) {
|
|
95
|
+
const keys = Object.keys(params);
|
|
96
|
+
if (keys.length === 0) return null;
|
|
97
|
+
const sortedKeys = [...keys].sort((a, b) => b.length - a.length);
|
|
98
|
+
const cacheKey = sortedKeys.join("\0");
|
|
99
|
+
let paramRe = _compiledDestinationParamCache.get(cacheKey);
|
|
100
|
+
if (!paramRe) {
|
|
101
|
+
const paramAlternation = sortedKeys.map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
102
|
+
paramRe = new RegExp(`:(${paramAlternation})([+*])?(?![A-Za-z0-9_])`, "g");
|
|
103
|
+
_compiledDestinationParamCache.set(cacheKey, paramRe);
|
|
104
|
+
}
|
|
105
|
+
return paramRe;
|
|
106
|
+
}
|
|
107
|
+
function encodeAuthorityParam(value) {
|
|
108
|
+
return value.replace(/%(?![0-9a-f]{2})|[^A-Za-z0-9._~%-]/giu, encodeURIComponent);
|
|
109
|
+
}
|
|
110
|
+
function encodeRewriteQueryParamValue(value) {
|
|
111
|
+
const params = new URLSearchParams();
|
|
112
|
+
params.set("", value);
|
|
113
|
+
return params.toString().slice(1);
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
export { substituteDestinationParams, substituteRedirectDestinationQuery };
|
|
@@ -111,6 +111,12 @@ export type NextConfig = {
|
|
|
111
111
|
crossOrigin?: "anonymous" | "use-credentials";
|
|
112
112
|
/** Whether to add trailing slashes */
|
|
113
113
|
trailingSlash?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Skip the automatic trailing-slash redirects and keep `<Link>`/router
|
|
116
|
+
* hrefs exactly as written.
|
|
117
|
+
* @see https://nextjs.org/docs/app/api-reference/config/next-config-js/skipTrailingSlashRedirect
|
|
118
|
+
*/
|
|
119
|
+
skipTrailingSlashRedirect?: boolean;
|
|
114
120
|
/**
|
|
115
121
|
* Compress responses from the Node production server. Defaults to true.
|
|
116
122
|
* @see https://nextjs.org/docs/app/api-reference/config/next-config-js/compress
|
|
@@ -317,6 +323,7 @@ export type ResolvedNextConfig = {
|
|
|
317
323
|
*/
|
|
318
324
|
assetPrefix: string;
|
|
319
325
|
trailingSlash: boolean;
|
|
326
|
+
skipTrailingSlashRedirect: boolean;
|
|
320
327
|
/** Whether the Node production server compresses responses (`compress`, default true). */
|
|
321
328
|
compress: boolean;
|
|
322
329
|
skipProxyUrlNormalize: boolean;
|
|
@@ -373,6 +373,7 @@ function warnDeprecatedConfigOptions(config, root) {
|
|
|
373
373
|
["experimental.instrumentationHook", `\`experimental.instrumentationHook\` is no longer needed, because \`instrumentation.js\` is available by default. You can remove it from ${configFileName}.`]
|
|
374
374
|
];
|
|
375
375
|
for (const [propertyPath, warning] of warnings) if (hasConfigProperty(config, propertyPath)) warnConfigOnce(warning);
|
|
376
|
+
if (readOptionalRecord(config.experimental)?.skipTrailingSlashRedirect != null) warnConfigOnce(`\`experimental.skipTrailingSlashRedirect\` has been moved to \`skipTrailingSlashRedirect\`. Please update your ${configFileName} file accordingly.`);
|
|
376
377
|
}
|
|
377
378
|
async function resolveNextConfigInput(config, phase = PHASE_DEVELOPMENT_SERVER) {
|
|
378
379
|
return await resolveConfigValue(config, phase);
|
|
@@ -761,6 +762,7 @@ async function resolveNextConfig(config, root = toSlash(process.cwd()), options
|
|
|
761
762
|
basePath: "",
|
|
762
763
|
assetPrefix: "",
|
|
763
764
|
trailingSlash: false,
|
|
765
|
+
skipTrailingSlashRedirect: false,
|
|
764
766
|
compress: true,
|
|
765
767
|
skipProxyUrlNormalize: false,
|
|
766
768
|
typescript: {},
|
|
@@ -947,6 +949,7 @@ async function resolveNextConfig(config, root = toSlash(process.cwd()), options
|
|
|
947
949
|
basePath: config.basePath ?? "",
|
|
948
950
|
assetPrefix: normalizeAssetPrefix(config.assetPrefix),
|
|
949
951
|
trailingSlash: config.trailingSlash ?? false,
|
|
952
|
+
skipTrailingSlashRedirect: (experimental?.skipTrailingSlashRedirect ?? config.skipTrailingSlashRedirect) === true,
|
|
950
953
|
compress: config.compress !== false,
|
|
951
954
|
skipProxyUrlNormalize: config.skipProxyUrlNormalize ?? config.skipMiddlewareUrlNormalize ?? false,
|
|
952
955
|
typescript: typeof config.typescript?.tsconfigPath === "string" ? { tsconfigPath: config.typescript.tsconfigPath } : {},
|
|
@@ -93,6 +93,10 @@ type AppRouterConfig = {
|
|
|
93
93
|
draftModeSecret?: string;
|
|
94
94
|
/** Server-only token used to authorize build-time prerender endpoints. */
|
|
95
95
|
prerenderSecret?: string;
|
|
96
|
+
/** next.config `skipTrailingSlashRedirect`. */
|
|
97
|
+
skipTrailingSlashRedirect?: boolean;
|
|
98
|
+
/** Dev-only key authenticating the hybrid Pages handler's forwarded middleware context. */
|
|
99
|
+
devForwardedMiddlewareContextKey?: string;
|
|
96
100
|
};
|
|
97
101
|
/** Generate the module-free App request stage used by multi-stage Worker outputs. */
|
|
98
102
|
export declare function generateAppRequestRscEntry(appDir: string, routes: AppRoute[], middlewarePath?: string | null, metadataRoutes?: MetadataFileRoute[], _globalErrorPath?: string | null, basePath?: string, trailingSlash?: boolean, config?: AppRouterConfig, instrumentationPath?: string | null): string;
|
|
@@ -25,12 +25,12 @@ import { randomUUID } from "node:crypto";
|
|
|
25
25
|
const DEFAULT_EXPIRE_TIME = 31536e3;
|
|
26
26
|
const DEFAULT_REACT_MAX_HEADERS_LENGTH = 6e3;
|
|
27
27
|
const middlewareRequestHeadersPath = resolveEntryPath("../utils/middleware-request-headers.js", import.meta.url);
|
|
28
|
-
const normalizePathModulePath = resolveEntryPath("../server/normalize-path.js", import.meta.url);
|
|
29
28
|
const appRouteHandlerDispatchPath = resolveEntryPath("../server/app-route-handler-dispatch.js", import.meta.url);
|
|
30
29
|
const appRouteRequestBuiltInsPath = resolveEntryPath("../server/app-route-request-built-ins.js", import.meta.url);
|
|
31
30
|
const appRouteHandlerResponsePath = resolveEntryPath("../server/app-route-handler-response.js", import.meta.url);
|
|
32
31
|
const appRouteHandlerMiddlewareContextPath = resolveEntryPath("../server/app-route-handler-middleware-context.js", import.meta.url);
|
|
33
32
|
const appServerActionExecutionPath = resolveEntryPath("../server/app-server-action-execution.js", import.meta.url);
|
|
33
|
+
const serverReferenceLoaderPath = resolveEntryPath("../server/server-reference-loader.js", import.meta.url);
|
|
34
34
|
const appActionForwardingPath = resolveEntryPath("../server/app-action-forwarding.js", import.meta.url);
|
|
35
35
|
const appMiddlewarePath = resolveEntryPath("../server/app-middleware.js", import.meta.url);
|
|
36
36
|
const metadataRouteResponsePath = resolveEntryPath("../server/metadata-route-response.js", import.meta.url);
|
|
@@ -200,6 +200,7 @@ import { dispatchAppRequestStage as __dispatchAppRequestStage } from ${JSON.stri
|
|
|
200
200
|
import { registerConfiguredCacheAdapters as __registerConfiguredCacheAdapters } from "virtual:vinext-cdn-cache-adapter";
|
|
201
201
|
import { clearAppRequestStageContext as __clearRequestContext, setAppRequestStageNavigationContext as setNavigationContext } from ${JSON.stringify(appRequestStageContextPath)};
|
|
202
202
|
import { matchRoutePattern as __matchRoutePattern } from ${JSON.stringify(routePatternPath)};
|
|
203
|
+
import __pagesClientAssets from "virtual:vinext-pages-client-assets";
|
|
203
204
|
${middlewarePath ? `import { applyAppMiddleware as __applyAppMiddleware } from ${JSON.stringify(appMiddlewarePath)};` : ""}
|
|
204
205
|
${instrumentationPath ? `import * as _instrumentation from ${JSON.stringify(toSlash(instrumentationPath))};
|
|
205
206
|
import { ensureInstrumentationRegistered as __ensureInstrumentationRegistered } from ${JSON.stringify(instrumentationRuntimePath)};
|
|
@@ -216,7 +217,6 @@ ${hasPagesDir ? `import { getDraftModeCookieHeader } from "next/headers";
|
|
|
216
217
|
import * as __pagesRequestEntry from "virtual:vinext-pages-request-entry";
|
|
217
218
|
import { renderPagesFallback as __renderPagesFallback } from ${JSON.stringify(appPagesBridgePath)};
|
|
218
219
|
import { buildRequestHeadersFromMiddlewareResponse as __buildRequestHeadersFromMiddlewareResponse } from ${JSON.stringify(middlewareRequestHeadersPath)};
|
|
219
|
-
import { decodePathParams as __decodePathParams } from ${JSON.stringify(normalizePathModulePath)};
|
|
220
220
|
import { applyRouteHandlerMiddlewareContext as __applyRouteHandlerMiddlewareContext } from ${JSON.stringify(appRouteHandlerMiddlewareContextPath)};` : ""}
|
|
221
221
|
|
|
222
222
|
${hasPagesDir ? `export function __ensureHybridPagesApplication() {
|
|
@@ -238,6 +238,7 @@ export const __imageConfig = ${JSON.stringify({
|
|
|
238
238
|
contentDispositionType: config?.imageConfig?.contentDispositionType,
|
|
239
239
|
contentSecurityPolicy: config?.imageConfig?.contentSecurityPolicy
|
|
240
240
|
})};
|
|
241
|
+
export const __clientBuildFiles = __pagesClientAssets.clientBuildFiles ?? [];
|
|
241
242
|
const __routes = ${JSON.stringify(requestRoutes)};
|
|
242
243
|
const __routeMatcher = __createAppRscRouteMatcher(__routes, ${JSON.stringify(buildAppDecodedPathnamePatterns(routes, config))});
|
|
243
244
|
const __metadataRouteMatchers = ${JSON.stringify(metadataRouteMatchers)};
|
|
@@ -291,6 +292,7 @@ const __requestHandler = createAppRscRequestHandler({
|
|
|
291
292
|
fallback: []
|
|
292
293
|
})},
|
|
293
294
|
draftModeSecret: __draftModeSecret,
|
|
295
|
+
devForwardedMiddlewareContextKey: ${JSON.stringify(config?.devForwardedMiddlewareContextKey ?? null)},
|
|
294
296
|
dispatchMatchedPage() { throw new Error("App request stage attempted to render a page inline"); },
|
|
295
297
|
dispatchMatchedRouteHandler() { throw new Error("App request stage attempted to render a route handler inline"); },
|
|
296
298
|
${instrumentationPath ? "ensureInstrumentation() { return __ensureInstrumentation(); }," : ""}
|
|
@@ -333,6 +335,7 @@ const __requestHandler = createAppRscRequestHandler({
|
|
|
333
335
|
middlewareRequest,
|
|
334
336
|
module: middlewareModule,
|
|
335
337
|
request,
|
|
338
|
+
skipTrailingSlashRedirect: ${JSON.stringify(config?.skipTrailingSlashRedirect ?? false)},
|
|
336
339
|
trailingSlash: __trailingSlash,
|
|
337
340
|
validateExternalRewriteRequest,
|
|
338
341
|
});
|
|
@@ -358,7 +361,6 @@ const __requestHandler = createAppRscRequestHandler({
|
|
|
358
361
|
};
|
|
359
362
|
},
|
|
360
363
|
buildRequestHeaders: __buildRequestHeadersFromMiddlewareResponse,
|
|
361
|
-
decodePathParams: __decodePathParams,
|
|
362
364
|
applyRouteHandlerMiddlewareContext: __applyRouteHandlerMiddlewareContext,
|
|
363
365
|
getDraftModeCookieHeader,
|
|
364
366
|
}
|
|
@@ -366,6 +368,7 @@ const __requestHandler = createAppRscRequestHandler({
|
|
|
366
368
|
},` : ""}
|
|
367
369
|
rootParamNamesByPattern: {},
|
|
368
370
|
setNavigationContext,
|
|
371
|
+
skipTrailingSlashRedirect: ${JSON.stringify(config?.skipTrailingSlashRedirect ?? false)},
|
|
369
372
|
staticParamsMap: {},
|
|
370
373
|
trailingSlash: __trailingSlash,
|
|
371
374
|
validateDevRequestOrigin: __validateDevRequestOrigin,
|
|
@@ -520,14 +523,15 @@ import { registerConfiguredCacheAdapters as __registerConfiguredCacheAdapters }
|
|
|
520
523
|
import __pagesClientAssets from "virtual:vinext-pages-client-assets";
|
|
521
524
|
${actionOwners === void 0 ? `import __vinextActionOwners from ${JSON.stringify(ACTION_OWNER_MANIFEST_ID)};` : ""}
|
|
522
525
|
import { setPagesClientAssets as __setPagesClientAssets } from "vinext/server/pages-client-assets";
|
|
523
|
-
import { decodePathParams as __decodePathParams } from ${JSON.stringify(normalizePathModulePath)};
|
|
524
526
|
import { buildRequestHeadersFromMiddlewareResponse as __buildRequestHeadersFromMiddlewareResponse } from ${JSON.stringify(middlewareRequestHeadersPath)};
|
|
525
527
|
${hasPagesDir ? `import {
|
|
526
528
|
applyRouteHandlerMiddlewareContext as __applyRouteHandlerMiddlewareContext,
|
|
527
529
|
} from ${JSON.stringify(appRouteHandlerResponsePath)};` : ""}
|
|
528
530
|
const __loadAppRouteHandlerDispatch = () => import(${JSON.stringify(appRouteHandlerDispatchPath)});
|
|
529
531
|
${hasServerActions ? `const __loadAppServerActionExecution = () => import(${JSON.stringify(appServerActionExecutionPath)});
|
|
530
|
-
const __loadAppActionForwarding = () => import(${JSON.stringify(appActionForwardingPath)})
|
|
532
|
+
const __loadAppActionForwarding = () => import(${JSON.stringify(appActionForwardingPath)});
|
|
533
|
+
import { isolateServerReferenceLoads as __isolateServerReferenceLoads } from ${JSON.stringify(serverReferenceLoaderPath)};
|
|
534
|
+
__isolateServerReferenceLoads();` : ""}
|
|
531
535
|
${(metadataRoutes?.length ?? 0) > 0 ? `const __loadMetadataRouteResponse = () => import(${JSON.stringify(metadataRouteResponsePath)});` : ""}
|
|
532
536
|
${(metadataRoutes?.length ?? 0) > 0 ? `const __loadFileBasedMetadata = () => import(${JSON.stringify(fileBasedMetadataPath)});
|
|
533
537
|
async function __applyFileBasedMetadata(...args) {
|
|
@@ -578,6 +582,8 @@ import {
|
|
|
578
582
|
SIBLING_PAGE_INTERCEPT_SLOT_KEY as __SIBLING_PAGE_INTERCEPT_SLOT_KEY,
|
|
579
583
|
} from ${JSON.stringify(appRscRouteMatchingPath)};
|
|
580
584
|
import {
|
|
585
|
+
appIsrFallbackShellHtmlKey as __isrFallbackShellHtmlKey,
|
|
586
|
+
appIsrFallbackShellKey as __isrFallbackShellKey,
|
|
581
587
|
appIsrHtmlKey as __isrHtmlKey,
|
|
582
588
|
appIsrRscKey as __isrRscKey,
|
|
583
589
|
appIsrRouteKey as __isrRouteKey,
|
|
@@ -949,6 +955,9 @@ export async function seedMemoryCacheFromPrerender(serverDir) {
|
|
|
949
955
|
buildAppPageHtmlKey(pathname) {
|
|
950
956
|
return __isrHtmlKey(pathname);
|
|
951
957
|
},
|
|
958
|
+
buildAppPageFallbackShellKey(pathname, suffix) {
|
|
959
|
+
return __isrFallbackShellKey(pathname, suffix);
|
|
960
|
+
},
|
|
952
961
|
buildAppPageRscKey(pathname) {
|
|
953
962
|
return __isrRscKey(pathname);
|
|
954
963
|
},
|
|
@@ -993,6 +1002,7 @@ ${rootParamNameEntries.join("\n")}
|
|
|
993
1002
|
};
|
|
994
1003
|
|
|
995
1004
|
__setPagesClientAssets(__pagesClientAssets);
|
|
1005
|
+
export const __clientBuildFiles = __pagesClientAssets.clientBuildFiles ?? [];
|
|
996
1006
|
function __VINEXT_ACTION_OWNERS() { return ${actionOwners === void 0 ? "__vinextActionOwners" : safeJsonStringify(actionOwners)}; }
|
|
997
1007
|
${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandler = createAppRscHandler({"}
|
|
998
1008
|
assetPrefix: __assetPrefix,
|
|
@@ -1013,6 +1023,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1013
1023
|
imageConfig: __runtimeImageConfig,
|
|
1014
1024
|
isDev: process.env.NODE_ENV !== "production",
|
|
1015
1025
|
draftModeSecret: __draftModeSecret,
|
|
1026
|
+
devForwardedMiddlewareContextKey: ${JSON.stringify(config?.devForwardedMiddlewareContextKey ?? null)},
|
|
1016
1027
|
dispatchMatchedPage({
|
|
1017
1028
|
bypassInterceptionContextCache,
|
|
1018
1029
|
cachePathname,
|
|
@@ -1136,6 +1147,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1136
1147
|
isRscRequest,
|
|
1137
1148
|
isrDebug: __isrDebug,
|
|
1138
1149
|
isrGet: __isrGet,
|
|
1150
|
+
isrFallbackShellHtmlKey: __isrFallbackShellHtmlKey,
|
|
1139
1151
|
isrHtmlKey(pathname) {
|
|
1140
1152
|
return __isrHtmlKey(pathname === cleanPathname ? cachePathname : pathname);
|
|
1141
1153
|
},
|
|
@@ -1254,6 +1266,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1254
1266
|
draftModeSecret: __draftModeSecret,
|
|
1255
1267
|
i18n: __i18nConfig,
|
|
1256
1268
|
trailingSlash: __trailingSlash,
|
|
1269
|
+
skipTrailingSlashRedirect: ${JSON.stringify(config?.skipTrailingSlashRedirect ?? false)},
|
|
1257
1270
|
isrDebug: __isrDebug,
|
|
1258
1271
|
isrGet: __isrGet,
|
|
1259
1272
|
isrRouteKey(pathname) {
|
|
@@ -1617,6 +1630,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1617
1630
|
middlewareRequest,
|
|
1618
1631
|
module: middlewareModule,
|
|
1619
1632
|
request,
|
|
1633
|
+
skipTrailingSlashRedirect: ${JSON.stringify(config?.skipTrailingSlashRedirect ?? false)},
|
|
1620
1634
|
trailingSlash: __trailingSlash,
|
|
1621
1635
|
validateExternalRewriteRequest,
|
|
1622
1636
|
});
|
|
@@ -1655,7 +1669,6 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1655
1669
|
};
|
|
1656
1670
|
},
|
|
1657
1671
|
buildRequestHeaders: __buildRequestHeadersFromMiddlewareResponse,
|
|
1658
|
-
decodePathParams: __decodePathParams,
|
|
1659
1672
|
applyRouteHandlerMiddlewareContext: __applyRouteHandlerMiddlewareContext,
|
|
1660
1673
|
getDraftModeCookieHeader,
|
|
1661
1674
|
}
|
|
@@ -1663,6 +1676,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1663
1676
|
},` : ""}
|
|
1664
1677
|
rootParamNamesByPattern: rootParamNamesMap,
|
|
1665
1678
|
setNavigationContext,
|
|
1679
|
+
skipTrailingSlashRedirect: ${JSON.stringify(config?.skipTrailingSlashRedirect ?? false)},
|
|
1666
1680
|
staticParamsMap: generateStaticParamsMap,
|
|
1667
1681
|
trailingSlash: __trailingSlash,
|
|
1668
1682
|
validateDevRequestOrigin: __validateDevRequestOrigin,
|