vinext 1.0.0-beta.2 → 1.0.0-beta.4
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 +6 -9
- package/dist/build/client-build-config.js +7 -1
- package/dist/build/precompress.js +1 -1
- package/dist/build/prerender.d.ts +2 -1
- package/dist/build/prerender.js +12 -2
- package/dist/check.js +4 -0
- package/dist/cli-args.d.ts +2 -1
- package/dist/cli-args.js +10 -0
- package/dist/cli.js +14 -8
- package/dist/client/navigation-runtime.d.ts +6 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.js +4 -1
- package/dist/config/dotenv.d.ts +3 -4
- package/dist/config/dotenv.js +30 -22
- package/dist/config/next-config.d.ts +16 -5
- package/dist/config/next-config.js +7 -0
- package/dist/entries/app-browser-entry.d.ts +4 -10
- package/dist/entries/app-browser-entry.js +20 -4
- package/dist/entries/app-rsc-entry.js +21 -3
- package/dist/entries/app-rsc-manifest.js +19 -0
- package/dist/entries/pages-client-entry.js +0 -1
- package/dist/entries/pages-server-entry.js +13 -3
- package/dist/index.js +122 -49
- package/dist/init-cloudflare.d.ts +3 -1
- package/dist/init-cloudflare.js +59 -5
- package/dist/plugins/client-reference-dedup.js +7 -5
- package/dist/plugins/extensionless-dynamic-import.js +23 -18
- package/dist/plugins/ignore-dynamic-requests.js +3 -1
- package/dist/plugins/import-meta-url.js +17 -6
- package/dist/plugins/require-context.js +20 -15
- package/dist/plugins/sass.js +3 -4
- package/dist/plugins/transform-cache.d.ts +19 -0
- package/dist/plugins/transform-cache.js +36 -0
- package/dist/routing/app-route-graph.d.ts +14 -6
- package/dist/routing/app-route-graph.js +106 -16
- package/dist/server/api-handler.d.ts +2 -0
- package/dist/server/api-handler.js +7 -6
- package/dist/server/app-bfcache-identity.js +28 -2
- package/dist/server/app-browser-entry.js +175 -75
- package/dist/server/app-browser-navigation-controller.d.ts +23 -21
- package/dist/server/app-browser-navigation-controller.js +30 -5
- package/dist/server/app-browser-prefetch-response.d.ts +9 -0
- package/dist/server/app-browser-prefetch-response.js +32 -0
- package/dist/server/app-browser-state.d.ts +8 -3
- package/dist/server/app-browser-state.js +9 -3
- package/dist/server/app-page-cache-finalizer.js +1 -1
- package/dist/server/app-page-cache.d.ts +1 -1
- package/dist/server/app-page-cache.js +16 -2
- package/dist/server/app-page-dispatch.d.ts +9 -1
- package/dist/server/app-page-dispatch.js +37 -8
- package/dist/server/app-page-element-builder.d.ts +4 -1
- package/dist/server/app-page-element-builder.js +34 -7
- package/dist/server/app-page-head.d.ts +3 -3
- package/dist/server/app-page-head.js +58 -13
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +2 -2
- package/dist/server/app-page-http-access-fallback-metadata.js +9 -1
- package/dist/server/app-page-probe.d.ts +4 -0
- package/dist/server/app-page-probe.js +6 -2
- package/dist/server/app-page-render.d.ts +1 -1
- package/dist/server/app-page-render.js +13 -3
- package/dist/server/app-page-request.d.ts +3 -1
- package/dist/server/app-page-request.js +4 -13
- package/dist/server/app-page-response.d.ts +2 -0
- package/dist/server/app-page-response.js +7 -2
- package/dist/server/app-page-route-wiring.d.ts +10 -2
- package/dist/server/app-page-route-wiring.js +269 -59
- package/dist/server/app-pages-bridge.d.ts +2 -1
- package/dist/server/app-pages-bridge.js +3 -1
- package/dist/server/app-route-handler-cache.js +4 -0
- package/dist/server/app-route-handler-dispatch.js +9 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-module-loader.d.ts +6 -0
- package/dist/server/app-route-module-loader.js +3 -0
- package/dist/server/app-router-entry.js +6 -3
- package/dist/server/app-rsc-cache-busting.d.ts +7 -0
- package/dist/server/app-rsc-cache-busting.js +6 -0
- package/dist/server/app-rsc-errors.js +10 -0
- package/dist/server/app-rsc-handler.d.ts +2 -0
- package/dist/server/app-rsc-handler.js +30 -13
- package/dist/server/app-rsc-render-mode.d.ts +3 -2
- package/dist/server/app-rsc-render-mode.js +4 -1
- package/dist/server/app-rsc-request-normalization.js +65 -4
- package/dist/server/app-rsc-route-matching.d.ts +9 -0
- package/dist/server/app-rsc-route-matching.js +6 -0
- package/dist/server/app-server-action-execution.d.ts +1 -1
- package/dist/server/app-ssr-entry.js +4 -4
- package/dist/server/app-visited-response-cache.d.ts +6 -1
- package/dist/server/app-visited-response-cache.js +49 -1
- package/dist/server/cache-control.d.ts +2 -2
- package/dist/server/cache-control.js +2 -1
- package/dist/server/dev-server.d.ts +3 -1
- package/dist/server/dev-server.js +204 -348
- package/dist/server/edge-api-runtime.d.ts +10 -1
- package/dist/server/edge-api-runtime.js +29 -1
- package/dist/server/headers.d.ts +4 -2
- package/dist/server/headers.js +6 -3
- package/dist/server/isr-cache.d.ts +10 -33
- package/dist/server/isr-cache.js +33 -43
- package/dist/server/isr-decision.d.ts +2 -2
- package/dist/server/pages-api-route.d.ts +4 -0
- package/dist/server/pages-api-route.js +6 -3
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +6 -4
- package/dist/server/pages-dev-hydration.js +0 -1
- package/dist/server/pages-document-asset-props.d.ts +26 -0
- package/dist/server/pages-document-asset-props.js +69 -0
- package/dist/server/pages-get-initial-props.d.ts +1 -1
- package/dist/server/pages-get-initial-props.js +1 -4
- package/dist/server/pages-i18n.js +64 -16
- package/dist/server/pages-node-compat.d.ts +2 -0
- package/dist/server/pages-node-compat.js +10 -6
- package/dist/server/pages-page-data.d.ts +61 -9
- package/dist/server/pages-page-data.js +334 -74
- package/dist/server/pages-page-handler.d.ts +6 -1
- package/dist/server/pages-page-handler.js +119 -20
- package/dist/server/pages-page-response.d.ts +7 -3
- package/dist/server/pages-page-response.js +41 -33
- package/dist/server/pages-request-pipeline.d.ts +7 -0
- package/dist/server/pages-request-pipeline.js +5 -1
- package/dist/server/pages-revalidate.d.ts +1 -1
- package/dist/server/pages-revalidate.js +54 -8
- package/dist/server/pages-router-entry.d.ts +1 -0
- package/dist/server/pages-router-entry.js +10 -4
- package/dist/server/prerender-manifest.d.ts +1 -0
- package/dist/server/prod-server.d.ts +2 -1
- package/dist/server/prod-server.js +38 -13
- package/dist/server/revalidation-host.d.ts +11 -0
- package/dist/server/revalidation-host.js +19 -0
- package/dist/server/seed-cache.js +1 -1
- package/dist/server/worker-revalidation-context.d.ts +13 -0
- package/dist/server/worker-revalidation-context.js +30 -0
- package/dist/shims/app-router-scroll-state.d.ts +2 -1
- package/dist/shims/app-router-scroll-state.js +7 -2
- package/dist/shims/cache-handler.d.ts +1 -1
- package/dist/shims/cache-handler.js +10 -7
- package/dist/shims/cache-runtime.d.ts +6 -0
- package/dist/shims/cache-runtime.js +4 -1
- package/dist/shims/cache.js +1 -1
- package/dist/shims/document.js +15 -2
- package/dist/shims/error.js +1 -1
- package/dist/shims/fetch-cache.js +1 -1
- package/dist/shims/font-google-base.js +17 -8
- package/dist/shims/font-local.js +41 -10
- package/dist/shims/hash-scroll.d.ts +1 -1
- package/dist/shims/hash-scroll.js +2 -1
- package/dist/shims/headers.d.ts +10 -13
- package/dist/shims/headers.js +85 -36
- package/dist/shims/internal/cookie-serialize.d.ts +10 -9
- package/dist/shims/internal/cookie-serialize.js +9 -8
- package/dist/shims/internal/interpolate-as.d.ts +15 -1
- package/dist/shims/internal/interpolate-as.js +27 -2
- package/dist/shims/link.d.ts +2 -0
- package/dist/shims/link.js +77 -24
- package/dist/shims/metadata.d.ts +18 -34
- package/dist/shims/metadata.js +98 -56
- package/dist/shims/navigation.d.ts +18 -2
- package/dist/shims/navigation.js +70 -21
- package/dist/shims/request-context.d.ts +6 -2
- package/dist/shims/router.js +18 -7
- package/dist/shims/script.js +1 -1
- package/dist/shims/server.d.ts +7 -6
- package/dist/shims/server.js +156 -57
- package/dist/shims/slot.d.ts +2 -1
- package/dist/shims/slot.js +6 -2
- package/dist/shims/streamed-icons.d.ts +9 -0
- package/dist/shims/streamed-icons.js +33 -0
- package/dist/shims/unified-request-context.d.ts +21 -2
- package/dist/shims/unified-request-context.js +82 -1
- package/dist/utils/cache-control-metadata.d.ts +2 -1
- package/dist/utils/cache-control-metadata.js +5 -1
- package/dist/utils/html-limited-bots.js +1 -1
- package/dist/utils/protocol-headers.d.ts +7 -1
- package/dist/utils/protocol-headers.js +7 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
2
2
|
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
3
|
+
import { VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
|
|
3
4
|
import { notFoundStaticAssetResponse } from "./http-error-responses.js";
|
|
4
5
|
import { isOpenRedirectShaped } from "./open-redirect.js";
|
|
5
6
|
import { cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders } from "./request-pipeline.js";
|
|
@@ -7,6 +8,7 @@ import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js"
|
|
|
7
8
|
import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, handleConfiguredImageOptimization, isImageOptimizationPath } from "./image-optimization.js";
|
|
8
9
|
import { finalizeMissingStaticAssetResponse } from "./worker-utils.js";
|
|
9
10
|
import { fetchWorkerFilesystemRoute, runPagesRequest, wrapMiddlewareWithBasePath } from "./pages-request-pipeline.js";
|
|
11
|
+
import { createWorkerRevalidationContext } from "./worker-revalidation-context.js";
|
|
10
12
|
import { registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
|
|
11
13
|
import { registerConfiguredImageOptimizer } from "virtual:vinext-image-adapters";
|
|
12
14
|
import * as pagesEntry from "virtual:vinext-server-entry";
|
|
@@ -25,7 +27,7 @@ import * as pagesEntry from "virtual:vinext-server-entry";
|
|
|
25
27
|
* import handler from "vinext/server/pages-router-entry";
|
|
26
28
|
* return handler.fetch(request, env, ctx);
|
|
27
29
|
*/
|
|
28
|
-
const { handleApiRoute, hasMiddleware, matchPageRoute, normalizeDataRequest, renderPage, runMiddleware, vinextConfig } = pagesEntry;
|
|
30
|
+
const { authorizeOnDemandRevalidate, handleApiRoute, hasMiddleware, matchPageRoute, normalizeDataRequest, renderPage, runMiddleware, vinextConfig } = pagesEntry;
|
|
29
31
|
const basePath = vinextConfig?.basePath ?? "";
|
|
30
32
|
const assetPathPrefix = assetPrefixPathname(vinextConfig?.assetPrefix ?? "");
|
|
31
33
|
const trailingSlash = vinextConfig?.trailingSlash ?? false;
|
|
@@ -47,7 +49,8 @@ const imageConfig = vinextConfig?.images ? {
|
|
|
47
49
|
var pages_router_entry_default = { async fetch(request, env, ctx) {
|
|
48
50
|
return handleRequest(request, env, ctx);
|
|
49
51
|
} };
|
|
50
|
-
async function handleRequest(request, env,
|
|
52
|
+
async function handleRequest(request, env, platformCtx) {
|
|
53
|
+
const ctx = createWorkerRevalidationContext(platformCtx, (internalRequest, internalCtx) => handleRequest(internalRequest, env, internalCtx));
|
|
51
54
|
registerConfiguredCacheAdapters(env);
|
|
52
55
|
registerConfiguredImageOptimizer(env);
|
|
53
56
|
try {
|
|
@@ -59,7 +62,9 @@ async function handleRequest(request, env, ctx) {
|
|
|
59
62
|
return new Response("Bad Request", { status: 400 });
|
|
60
63
|
}
|
|
61
64
|
const missingBuildAsset = isNextStaticPath(pathname, basePath, assetPathPrefix);
|
|
62
|
-
|
|
65
|
+
const filteredHeaders = ctx.isInternalPagesRevalidation ? new Headers(request.headers) : filterInternalHeaders(request.headers);
|
|
66
|
+
filteredHeaders.delete(VINEXT_REVALIDATE_HOST_HEADER);
|
|
67
|
+
request = cloneRequestWithHeaders(request, filteredHeaders);
|
|
63
68
|
const hadBasePath = !basePath || hasBasePath(pathname, basePath);
|
|
64
69
|
{
|
|
65
70
|
const stripped = stripBasePath(pathname, basePath);
|
|
@@ -93,10 +98,11 @@ async function handleRequest(request, env, ctx) {
|
|
|
93
98
|
isDataRequest: isDataReq,
|
|
94
99
|
hasMiddleware,
|
|
95
100
|
ctx,
|
|
101
|
+
authorizeOnDemandRevalidate: typeof authorizeOnDemandRevalidate === "function" ? authorizeOnDemandRevalidate : void 0,
|
|
96
102
|
matchPageRoute: typeof matchPageRoute === "function" ? matchPageRoute : null,
|
|
97
103
|
runMiddleware: typeof runMiddleware === "function" ? wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath) : null,
|
|
98
104
|
renderPage: typeof renderPage === "function" ? (req, resolvedUrl, options, stagedHeaders) => renderPage(req, resolvedUrl, null, ctx, stagedHeaders, options) : null,
|
|
99
|
-
handleApi: typeof handleApiRoute === "function" ? (req, apiUrl) => handleApiRoute(req, apiUrl, ctx) : null,
|
|
105
|
+
handleApi: typeof handleApiRoute === "function" ? (req, apiUrl) => handleApiRoute(req, apiUrl, ctx, new URL(req.url).origin, "worker") : null,
|
|
100
106
|
serveFilesystemRoute: async (requestPathname, _stagedHeaders, phase) => {
|
|
101
107
|
if (!env?.ASSETS) return false;
|
|
102
108
|
return fetchWorkerFilesystemRoute(request, requestPathname, phase, (assetRequest) => Promise.resolve(env.ASSETS.fetch(assetRequest)));
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NextI18nConfig } from "../config/next-config.js";
|
|
1
2
|
import { negotiateEncoding } from "./accept-encoding.js";
|
|
2
3
|
import { StaticFileCache } from "./static-file-cache.js";
|
|
3
4
|
import { resolveRequestHost, trustProxy, trustedHosts } from "./proxy-trust.js";
|
|
@@ -103,7 +104,7 @@ declare function tryServeStatic(req: IncomingMessage, res: ServerResponse, clien
|
|
|
103
104
|
* When `urlOverride` is provided, it is used as the path + query string
|
|
104
105
|
* instead of `req.url`.
|
|
105
106
|
*/
|
|
106
|
-
declare function nodeToWebRequest(req: IncomingMessage, urlOverride?: string, prerenderSecret?: string): Request;
|
|
107
|
+
declare function nodeToWebRequest(req: IncomingMessage, urlOverride?: string, prerenderSecret?: string, i18nConfig?: NextI18nConfig | null, authorizeOnDemandRevalidate?: (headerValue: string | null) => boolean): Request;
|
|
107
108
|
/**
|
|
108
109
|
* Stream a Web Response back to a Node.js ServerResponse.
|
|
109
110
|
* Supports streaming compression for SSR responses.
|
|
@@ -16,6 +16,7 @@ import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath, isS
|
|
|
16
16
|
import { installSocketErrorBackstop } from "./socket-error-backstop.js";
|
|
17
17
|
import { CONTENT_TYPES, StaticFileCache, etagFromFilenameHash } from "./static-file-cache.js";
|
|
18
18
|
import { collectInlineCssManifest } from "../build/inline-css.js";
|
|
19
|
+
import { readTrustedRevalidationHostname } from "./revalidation-host.js";
|
|
19
20
|
import { mergeHeaders } from "./worker-utils.js";
|
|
20
21
|
import { runPagesRequest, wrapMiddlewareWithBasePath } from "./pages-request-pipeline.js";
|
|
21
22
|
import { computeClientRuntimeMetadata } from "../utils/client-runtime-metadata.js";
|
|
@@ -557,13 +558,16 @@ async function statIfFile(filePath) {
|
|
|
557
558
|
* When `urlOverride` is provided, it is used as the path + query string
|
|
558
559
|
* instead of `req.url`.
|
|
559
560
|
*/
|
|
560
|
-
function nodeToWebRequest(req, urlOverride, prerenderSecret) {
|
|
561
|
-
const
|
|
562
|
-
const url = new URL(urlOverride ?? req.url ?? "/", origin);
|
|
561
|
+
function nodeToWebRequest(req, urlOverride, prerenderSecret, i18nConfig, authorizeOnDemandRevalidate) {
|
|
562
|
+
const proto = resolveRequestProtocol(req);
|
|
563
563
|
const rawHeaders = nodeHeadersToWebHeaders(req.headers);
|
|
564
|
+
const revalidationHostname = readTrustedRevalidationHostname(rawHeaders, i18nConfig, authorizeOnDemandRevalidate);
|
|
565
|
+
const origin = `${proto}://${revalidationHostname ?? resolveRequestHost(req, "localhost")}`;
|
|
566
|
+
const url = new URL(urlOverride ?? req.url ?? "/", origin);
|
|
564
567
|
const prerenderRouteParamsPayload = readTrustedPrerenderRouteParamsFromHeaders(rawHeaders, prerenderSecret);
|
|
565
568
|
const isTrustedSpeculativePrerender = process.env.VINEXT_PRERENDER === "1" && prerenderSecret !== void 0 && rawHeaders.get("x-vinext-prerender-secret") === prerenderSecret && rawHeaders.get("x-vinext-prerender-speculative") === "1";
|
|
566
569
|
const headers = filterInternalHeaders(rawHeaders);
|
|
570
|
+
if (revalidationHostname) headers.set("host", revalidationHostname);
|
|
567
571
|
const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParamsPayload);
|
|
568
572
|
if (prerenderRouteParamsHeader !== null) headers.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
|
|
569
573
|
if (isTrustedSpeculativePrerender) headers.set(VINEXT_PRERENDER_SPECULATIVE_HEADER, "1");
|
|
@@ -660,19 +664,33 @@ async function startProdServer(options = {}) {
|
|
|
660
664
|
silent
|
|
661
665
|
});
|
|
662
666
|
}
|
|
663
|
-
function createNodeExecutionContext() {
|
|
667
|
+
function createNodeExecutionContext(trustedRevalidateOrigin) {
|
|
664
668
|
return {
|
|
669
|
+
hostRuntime: "node",
|
|
665
670
|
waitUntil(promise) {
|
|
666
671
|
Promise.resolve(promise).catch(() => {});
|
|
667
672
|
},
|
|
668
|
-
passThroughOnException() {}
|
|
673
|
+
passThroughOnException() {},
|
|
674
|
+
trustedRevalidateOrigin
|
|
669
675
|
};
|
|
670
676
|
}
|
|
677
|
+
function resolveTrustedNodeRevalidateOrigin(req, configuredHost, configuredPort) {
|
|
678
|
+
const port = req.socket.localPort ?? configuredPort;
|
|
679
|
+
return `http://${normalizeInternalFetchHost(configuredHost)}:${port}`;
|
|
680
|
+
}
|
|
681
|
+
function normalizeInternalFetchHost(host) {
|
|
682
|
+
if (!host || host === "0.0.0.0" || host === "::") return "localhost";
|
|
683
|
+
if (host.includes(":") && !host.startsWith("[")) return `[${host}]`;
|
|
684
|
+
return host;
|
|
685
|
+
}
|
|
671
686
|
function resolveAppRouterHandler(entry) {
|
|
672
|
-
if (typeof entry === "function")
|
|
687
|
+
if (typeof entry === "function") {
|
|
688
|
+
const handler = entry;
|
|
689
|
+
return (request, ctx) => Promise.resolve(handler(request, ctx));
|
|
690
|
+
}
|
|
673
691
|
if (entry && typeof entry === "object" && "fetch" in entry) {
|
|
674
692
|
const workerEntry = entry;
|
|
675
|
-
if (typeof workerEntry.fetch === "function") return (request) => Promise.resolve(workerEntry.fetch(request, void 0,
|
|
693
|
+
if (typeof workerEntry.fetch === "function") return (request, ctx) => Promise.resolve(workerEntry.fetch(request, void 0, ctx));
|
|
676
694
|
}
|
|
677
695
|
console.error("[vinext] App Router entry must export either a default handler function or a Worker-style default export with fetch()");
|
|
678
696
|
process.exit(1);
|
|
@@ -793,6 +811,8 @@ async function startAppRouterServer(options) {
|
|
|
793
811
|
const appRouterBasePath = typeof rscModule.__basePath === "string" ? rscModule.__basePath : "";
|
|
794
812
|
const appRouterInlineCss = rscModule.__inlineCss === true;
|
|
795
813
|
const appRouterHasPagesDir = rscModule.__hasPagesDir === true;
|
|
814
|
+
const appRouterI18nConfig = rscModule.__i18nConfig ?? null;
|
|
815
|
+
const appRouterAuthorizeOnDemandRevalidate = typeof rscModule.authorizeOnDemandRevalidate === "function" ? rscModule.authorizeOnDemandRevalidate : void 0;
|
|
796
816
|
const appImageAllowedWidths = Array.isArray(rscModule.__imageAllowedWidths) ? rscModule.__imageAllowedWidths : [...DEFAULT_DEVICE_SIZES, ...DEFAULT_IMAGE_SIZES];
|
|
797
817
|
let imageConfig = typeof rscModule.__imageConfig === "object" && rscModule.__imageConfig !== null ? rscModule.__imageConfig : void 0;
|
|
798
818
|
if (imageConfig === void 0) {
|
|
@@ -870,8 +890,8 @@ async function startAppRouterServer(options) {
|
|
|
870
890
|
return;
|
|
871
891
|
}
|
|
872
892
|
try {
|
|
873
|
-
const request = nodeToWebRequest(req, rawUrl, prerenderSecret);
|
|
874
|
-
const response = await rscHandler(request);
|
|
893
|
+
const request = nodeToWebRequest(req, rawUrl, prerenderSecret, appRouterI18nConfig, appRouterAuthorizeOnDemandRevalidate);
|
|
894
|
+
const response = await rscHandler(request, createNodeExecutionContext(resolveTrustedNodeRevalidateOrigin(req, host, port)));
|
|
875
895
|
if (missingBuildAsset && response.status === 404) {
|
|
876
896
|
cancelResponseBody(response);
|
|
877
897
|
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
|
|
@@ -935,14 +955,16 @@ function readPagesServerEntryPageRoutes(value) {
|
|
|
935
955
|
*
|
|
936
956
|
* Uses the server entry (dist/server/entry.js) which exports:
|
|
937
957
|
* - renderPage(request, url, manifest, ctx?, middlewareHeaders?) — SSR rendering (Web Request → Response)
|
|
938
|
-
* - handleApiRoute(request, url, ctx?) — API route handling
|
|
958
|
+
* - handleApiRoute(request, url, ctx?, trustedRevalidateOrigin?) — API route handling
|
|
959
|
+
* (ctx optional; pass for ctx.waitUntil() on Workers)
|
|
960
|
+
* - authorizeOnDemandRevalidate(header) — validates against the bundled build secret
|
|
939
961
|
* - runMiddleware(request, ctx?) — middleware execution (ctx optional; pass for ctx.waitUntil() on Workers)
|
|
940
962
|
* - vinextConfig — embedded next.config.js settings
|
|
941
963
|
*/
|
|
942
964
|
async function startPagesRouterServer(options) {
|
|
943
965
|
const { port, host, clientDir, serverEntryPath, compress, purpose, silent } = options;
|
|
944
966
|
const serverEntry = await importServerEntryModule(serverEntryPath);
|
|
945
|
-
const { renderPage, handleApiRoute: handleApi, runMiddleware, vinextConfig, buildId: pagesBuildId } = serverEntry;
|
|
967
|
+
const { renderPage, handleApiRoute: handleApi, authorizeOnDemandRevalidate, runMiddleware, vinextConfig, buildId: pagesBuildId } = serverEntry;
|
|
946
968
|
const matchPageRoute = typeof serverEntry.matchPageRoute === "function" ? serverEntry.matchPageRoute : void 0;
|
|
947
969
|
const hasMiddleware = serverEntry.hasMiddleware === true;
|
|
948
970
|
const pageRoutes = readPagesServerEntryPageRoutes(serverEntry.pageRoutes);
|
|
@@ -1095,11 +1117,13 @@ async function startPagesRouterServer(options) {
|
|
|
1095
1117
|
const protocol = resolveRequestProtocol(req);
|
|
1096
1118
|
const hostHeader = resolveRequestHost(req, `${host}:${port}`);
|
|
1097
1119
|
const rawReqHeaders = nodeHeadersToWebHeaders(req.headers);
|
|
1120
|
+
const revalidationHostname = readTrustedRevalidationHostname(rawReqHeaders, i18nConfig, typeof authorizeOnDemandRevalidate === "function" ? authorizeOnDemandRevalidate : void 0);
|
|
1098
1121
|
const isDataRequest = isDataReq;
|
|
1099
1122
|
const reqHeaders = filterInternalHeaders(rawReqHeaders);
|
|
1123
|
+
if (revalidationHostname) reqHeaders.set("host", revalidationHostname);
|
|
1100
1124
|
const method = req.method ?? "GET";
|
|
1101
1125
|
const hasBody = method !== "GET" && method !== "HEAD";
|
|
1102
|
-
const result = await runPagesRequest(new Request(`${protocol}://${hostHeader}${url}`, {
|
|
1126
|
+
const result = await runPagesRequest(new Request(`${protocol}://${revalidationHostname ?? hostHeader}${url}`, {
|
|
1103
1127
|
method,
|
|
1104
1128
|
headers: reqHeaders,
|
|
1105
1129
|
body: hasBody ? readNodeStream(req) : void 0,
|
|
@@ -1117,6 +1141,7 @@ async function startPagesRouterServer(options) {
|
|
|
1117
1141
|
hasMiddleware,
|
|
1118
1142
|
ctx: void 0,
|
|
1119
1143
|
rawSearch: rawQs,
|
|
1144
|
+
authorizeOnDemandRevalidate: typeof authorizeOnDemandRevalidate === "function" ? authorizeOnDemandRevalidate : void 0,
|
|
1120
1145
|
configMatchPathname,
|
|
1121
1146
|
matchPageRoute: matchPageRoute ?? null,
|
|
1122
1147
|
runMiddleware: typeof runMiddleware === "function" ? wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath) : null,
|
|
@@ -1124,7 +1149,7 @@ async function startPagesRouterServer(options) {
|
|
|
1124
1149
|
...options,
|
|
1125
1150
|
originalUrl: originalRenderUrl
|
|
1126
1151
|
}) : null,
|
|
1127
|
-
handleApi: typeof handleApi === "function" ? (request, apiUrl) => handleApi(request, apiUrl, createNodeExecutionContext()) : null,
|
|
1152
|
+
handleApi: typeof handleApi === "function" ? (request, apiUrl) => handleApi(request, apiUrl, createNodeExecutionContext(), resolveTrustedNodeRevalidateOrigin(req, host, port), "node") : null,
|
|
1128
1153
|
serveFilesystemRoute: async (requestPathname, stagedHeaders, phase) => {
|
|
1129
1154
|
if (req.method !== "GET" && req.method !== "HEAD" || requestPathname === "/" || requestPathname === "/api" || requestPathname.startsWith("/api/") || phase === "direct" && requestPathname.startsWith(`/_next/static/`)) return false;
|
|
1130
1155
|
return tryServeStatic(req, res, clientDir, requestPathname, compress, staticCache, stagedHeaders);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NextI18nConfig } from "../config/next-config.js";
|
|
2
|
+
|
|
3
|
+
//#region src/server/revalidation-host.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Read the logical request hostname carried by a server-pinned revalidation
|
|
6
|
+
* loopback. The side channel is accepted only as part of the authenticated
|
|
7
|
+
* revalidation protocol and only for an exact configured i18n domain.
|
|
8
|
+
*/
|
|
9
|
+
declare function readTrustedRevalidationHostname(headers: Headers, i18nConfig: NextI18nConfig | null | undefined, authorizeRevalidation?: (headerValue: string | null) => boolean): string | null;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { readTrustedRevalidationHostname };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
|
|
2
|
+
import { isOnDemandRevalidateRequest } from "./isr-cache.js";
|
|
3
|
+
import { normalizeDomainHostname } from "../utils/domain-locale.js";
|
|
4
|
+
//#region src/server/revalidation-host.ts
|
|
5
|
+
/**
|
|
6
|
+
* Read the logical request hostname carried by a server-pinned revalidation
|
|
7
|
+
* loopback. The side channel is accepted only as part of the authenticated
|
|
8
|
+
* revalidation protocol and only for an exact configured i18n domain.
|
|
9
|
+
*/
|
|
10
|
+
function readTrustedRevalidationHostname(headers, i18nConfig, authorizeRevalidation = isOnDemandRevalidateRequest) {
|
|
11
|
+
if (!i18nConfig?.domains?.length || !authorizeRevalidation(headers.get("x-prerender-revalidate"))) return null;
|
|
12
|
+
const rawHostname = headers.get(VINEXT_REVALIDATE_HOST_HEADER);
|
|
13
|
+
if (!rawHostname) return null;
|
|
14
|
+
const hostname = rawHostname.trim().toLowerCase();
|
|
15
|
+
if (normalizeDomainHostname(hostname) !== hostname) return null;
|
|
16
|
+
return i18nConfig.domains.find((item) => normalizeDomainHostname(item.domain) === hostname)?.domain.toLowerCase() ?? null;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { readTrustedRevalidationHostname };
|
|
@@ -66,7 +66,7 @@ async function seedMemoryCacheFromPrerender(serverDir, options) {
|
|
|
66
66
|
const rscKey = options?.buildAppPageRscKey?.(cachePathname) ?? baseKey + ":rsc";
|
|
67
67
|
const revalidateSeconds = typeof route.revalidate === "number" ? route.revalidate : void 0;
|
|
68
68
|
const expireSeconds = typeof route.expire === "number" ? route.expire : void 0;
|
|
69
|
-
const tags = buildAppPageCacheTags(cachePathname, []);
|
|
69
|
+
const tags = buildAppPageCacheTags(cachePathname, route.tags ?? []);
|
|
70
70
|
if (await seedHtml(writeAppPageEntry, prerenderDir, htmlKey, artifactPathname, trailingSlash, route.headers, revalidateSeconds, expireSeconds, tags)) {
|
|
71
71
|
await seedRsc(writeAppPageEntry, prerenderDir, rscKey, artifactPathname, revalidateSeconds, expireSeconds, tags);
|
|
72
72
|
seeded++;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ExecutionContextLike } from "../shims/request-context.js";
|
|
2
|
+
|
|
3
|
+
//#region src/server/worker-revalidation-context.d.ts
|
|
4
|
+
type PlatformExecutionContext = Partial<ExecutionContextLike>;
|
|
5
|
+
/**
|
|
6
|
+
* Add a request-local, in-process Pages revalidation dispatcher to a Worker
|
|
7
|
+
* execution context. Re-entering with the derived internal context preserves
|
|
8
|
+
* the authenticated protocol headers while keeping ordinary inbound requests
|
|
9
|
+
* on the normal header-scrubbing path.
|
|
10
|
+
*/
|
|
11
|
+
declare function createWorkerRevalidationContext(base: PlatformExecutionContext | undefined, handleInternalRequest: (request: Request, ctx: ExecutionContextLike) => Promise<Response>): ExecutionContextLike;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { createWorkerRevalidationContext };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/server/worker-revalidation-context.ts
|
|
2
|
+
function deriveExecutionContext(base, dispatchPagesRevalidate, isInternalPagesRevalidation) {
|
|
3
|
+
return {
|
|
4
|
+
waitUntil(promise) {
|
|
5
|
+
if (typeof base?.waitUntil === "function") base.waitUntil(promise);
|
|
6
|
+
else Promise.resolve(promise).catch(() => {});
|
|
7
|
+
},
|
|
8
|
+
...typeof base?.passThroughOnException === "function" ? { passThroughOnException() {
|
|
9
|
+
base.passThroughOnException?.();
|
|
10
|
+
} } : {},
|
|
11
|
+
hostRuntime: "worker",
|
|
12
|
+
...base?.cache === void 0 ? {} : { cache: base.cache },
|
|
13
|
+
...base?.trustedRevalidateOrigin === void 0 ? {} : { trustedRevalidateOrigin: base.trustedRevalidateOrigin },
|
|
14
|
+
dispatchPagesRevalidate,
|
|
15
|
+
isInternalPagesRevalidation
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Add a request-local, in-process Pages revalidation dispatcher to a Worker
|
|
20
|
+
* execution context. Re-entering with the derived internal context preserves
|
|
21
|
+
* the authenticated protocol headers while keeping ordinary inbound requests
|
|
22
|
+
* on the normal header-scrubbing path.
|
|
23
|
+
*/
|
|
24
|
+
function createWorkerRevalidationContext(base, handleInternalRequest) {
|
|
25
|
+
if (typeof base?.dispatchPagesRevalidate === "function") return base;
|
|
26
|
+
const dispatchPagesRevalidate = (request) => handleInternalRequest(request, deriveExecutionContext(base, dispatchPagesRevalidate, true));
|
|
27
|
+
return deriveExecutionContext(base, dispatchPagesRevalidate, false);
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { createWorkerRevalidationContext };
|
|
@@ -9,8 +9,9 @@ type AppRouterScrollIntent = Readonly<{
|
|
|
9
9
|
declare function beginAppRouterScrollIntent(hash: string | null): AppRouterScrollIntent;
|
|
10
10
|
declare function clearAppRouterScrollIntent(): void;
|
|
11
11
|
declare function getPendingAppRouterScrollIntent(): AppRouterScrollIntent | null;
|
|
12
|
+
declare function isLatestAppRouterScrollIntent(expected: AppRouterScrollIntent | null | undefined): boolean;
|
|
12
13
|
declare function claimAppRouterScrollIntentForCommit(expected: AppRouterScrollIntent | null | undefined, commitId: number): void;
|
|
13
14
|
declare function markAppRouterScrollIntentHeadHoisted(expected: AppRouterScrollIntent | null | undefined, commitId: number): void;
|
|
14
15
|
declare function consumeAppRouterScrollIntent(expected: AppRouterScrollIntent | null | undefined, commitId?: number): AppRouterScrollIntent | null;
|
|
15
16
|
//#endregion
|
|
16
|
-
export { AppRouterScrollIntent, beginAppRouterScrollIntent, claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, markAppRouterScrollIntentHeadHoisted };
|
|
17
|
+
export { AppRouterScrollIntent, beginAppRouterScrollIntent, claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, isLatestAppRouterScrollIntent, markAppRouterScrollIntentHeadHoisted };
|
|
@@ -22,11 +22,16 @@ function beginAppRouterScrollIntent(hash) {
|
|
|
22
22
|
return intent;
|
|
23
23
|
}
|
|
24
24
|
function clearAppRouterScrollIntent() {
|
|
25
|
-
getScrollIntentStore()
|
|
25
|
+
const store = getScrollIntentStore();
|
|
26
|
+
store.nextId += 1;
|
|
27
|
+
store.pending = null;
|
|
26
28
|
}
|
|
27
29
|
function getPendingAppRouterScrollIntent() {
|
|
28
30
|
return getScrollIntentStore().pending;
|
|
29
31
|
}
|
|
32
|
+
function isLatestAppRouterScrollIntent(expected) {
|
|
33
|
+
return expected !== null && expected !== void 0 && getScrollIntentStore().nextId === expected.id;
|
|
34
|
+
}
|
|
30
35
|
function claimAppRouterScrollIntentForCommit(expected, commitId) {
|
|
31
36
|
const store = getScrollIntentStore();
|
|
32
37
|
const intent = store.pending;
|
|
@@ -59,4 +64,4 @@ function consumeAppRouterScrollIntent(expected, commitId) {
|
|
|
59
64
|
return intent;
|
|
60
65
|
}
|
|
61
66
|
//#endregion
|
|
62
|
-
export { beginAppRouterScrollIntent, claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, markAppRouterScrollIntentHeadHoisted };
|
|
67
|
+
export { beginAppRouterScrollIntent, claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, isLatestAppRouterScrollIntent, markAppRouterScrollIntentHeadHoisted };
|
|
@@ -9,7 +9,7 @@ type CacheHandlerValue = {
|
|
|
9
9
|
value: IncrementalCacheValue | null;
|
|
10
10
|
};
|
|
11
11
|
type CacheControlMetadata = {
|
|
12
|
-
revalidate: number;
|
|
12
|
+
revalidate: number | false;
|
|
13
13
|
expire?: number;
|
|
14
14
|
};
|
|
15
15
|
type IncrementalCacheValue = CachedFetchValue | CachedAppPageValue | CachedPagesValue | CachedRouteValue | CachedRedirectValue | CachedImageValue;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readCacheControlNumberField } from "../utils/cache-control-metadata.js";
|
|
1
|
+
import { readCacheControlNumberField, readCacheControlRevalidateField } from "../utils/cache-control-metadata.js";
|
|
2
2
|
//#region src/shims/cache-handler.ts
|
|
3
3
|
var NoOpCacheHandler = class {
|
|
4
4
|
async get(_key, _ctx) {
|
|
@@ -88,12 +88,14 @@ var MemoryCacheHandler = class {
|
|
|
88
88
|
const revalidatedAt = this.tagRevalidatedAt.get(tag);
|
|
89
89
|
if (revalidatedAt && revalidatedAt >= entry.lastModified) return null;
|
|
90
90
|
}
|
|
91
|
-
if (entry.expireAt !== null && Date.now() > entry.expireAt) {
|
|
92
|
-
this.deleteEntry(key);
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
91
|
this.touchEntry(key, entry);
|
|
96
92
|
const now = Date.now();
|
|
93
|
+
if (entry.expireAt !== null && now > entry.expireAt) return {
|
|
94
|
+
lastModified: entry.lastModified,
|
|
95
|
+
value: entry.value,
|
|
96
|
+
cacheState: "expired",
|
|
97
|
+
cacheControl: entry.cacheControl
|
|
98
|
+
};
|
|
97
99
|
const requestedRevalidate = readPositiveNumberField(ctx, "revalidate");
|
|
98
100
|
const requestedRevalidateAt = requestedRevalidate === void 0 ? null : entry.lastModified + requestedRevalidate * 1e3;
|
|
99
101
|
if (entry.revalidateAt !== null && now > entry.revalidateAt || requestedRevalidateAt !== null && now > requestedRevalidateAt) return {
|
|
@@ -113,14 +115,15 @@ var MemoryCacheHandler = class {
|
|
|
113
115
|
if (data && "tags" in data && Array.isArray(data.tags)) for (const tag of data.tags) tagSet.add(tag);
|
|
114
116
|
for (const tag of readStringArrayField(ctx, "tags")) tagSet.add(tag);
|
|
115
117
|
const tags = [...tagSet];
|
|
116
|
-
let effectiveRevalidate =
|
|
118
|
+
let effectiveRevalidate = readCacheControlRevalidateField(ctx);
|
|
117
119
|
const effectiveExpire = readCacheControlNumberField(ctx, "expire");
|
|
118
120
|
if (data && "revalidate" in data && typeof data.revalidate === "number") effectiveRevalidate = data.revalidate;
|
|
121
|
+
else if (data && "revalidate" in data && data.revalidate === false) effectiveRevalidate ??= false;
|
|
119
122
|
if (effectiveRevalidate === 0) return;
|
|
120
123
|
const now = Date.now();
|
|
121
124
|
const revalidateAt = typeof effectiveRevalidate === "number" && effectiveRevalidate > 0 ? now + effectiveRevalidate * 1e3 : null;
|
|
122
125
|
const expireAt = typeof effectiveExpire === "number" && effectiveExpire > 0 ? now + effectiveExpire * 1e3 : null;
|
|
123
|
-
const cacheControl = typeof effectiveRevalidate === "number" ? effectiveExpire === void 0 ? { revalidate: effectiveRevalidate } : {
|
|
126
|
+
const cacheControl = typeof effectiveRevalidate === "number" || effectiveRevalidate === false ? effectiveExpire === void 0 ? { revalidate: effectiveRevalidate } : {
|
|
124
127
|
revalidate: effectiveRevalidate,
|
|
125
128
|
expire: effectiveExpire
|
|
126
129
|
} : void 0;
|
|
@@ -71,6 +71,12 @@ declare function runWithPrivateCache<T>(fn: () => T | Promise<T>): T | Promise<T
|
|
|
71
71
|
*/
|
|
72
72
|
declare function clearPrivateCache(): void;
|
|
73
73
|
type RegisterCachedFunctionOptions = {
|
|
74
|
+
/**
|
|
75
|
+
* Whether the original function declaration accepts a second argument.
|
|
76
|
+
* Function.length cannot represent default or rest parameters, so the
|
|
77
|
+
* transform records this separately for metadata parent resolution.
|
|
78
|
+
*/
|
|
79
|
+
acceptsSecondArgument?: boolean;
|
|
74
80
|
/**
|
|
75
81
|
* Internal transform metadata for file-level `"use cache"` default exports
|
|
76
82
|
* in App Router `page.*` files. Page components receive framework-owned
|
|
@@ -334,10 +334,13 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
334
334
|
configurable: true
|
|
335
335
|
});
|
|
336
336
|
cachedFn[USE_CACHE_FUNCTION_SYMBOL] = true;
|
|
337
|
+
if (options.acceptsSecondArgument !== void 0) Reflect.set(cachedFn, USE_CACHE_ACCEPTS_SECOND_ARGUMENT_SYMBOL, options.acceptsSecondArgument);
|
|
337
338
|
return cachedFn;
|
|
338
339
|
}
|
|
339
340
|
/** @internal Symbol used to identify "use cache" wrapper functions. */
|
|
340
341
|
const USE_CACHE_FUNCTION_SYMBOL = Symbol.for("vinext.useCacheFunction");
|
|
342
|
+
/** @internal Symbol carrying transform-derived cached function argument metadata. */
|
|
343
|
+
const USE_CACHE_ACCEPTS_SECOND_ARGUMENT_SYMBOL = Symbol.for("vinext.useCacheAcceptsSecondArgument");
|
|
341
344
|
function throwPrivateUseCacheInsidePublicUseCacheError() {
|
|
342
345
|
const error = /* @__PURE__ */ new Error("\"use cache: private\" must not be used within \"use cache\". It can only be nested inside of another \"use cache: private\".");
|
|
343
346
|
const ctx = getRequestContext();
|
|
@@ -347,7 +350,7 @@ function throwPrivateUseCacheInsidePublicUseCacheError() {
|
|
|
347
350
|
function recordRequestScopedCacheControl(cacheControl) {
|
|
348
351
|
if (cacheControl === void 0) return;
|
|
349
352
|
_setRequestScopedCacheLife({
|
|
350
|
-
revalidate: cacheControl.revalidate,
|
|
353
|
+
revalidate: cacheControl.revalidate === false ? void 0 : cacheControl.revalidate,
|
|
351
354
|
expire: cacheControl.expire
|
|
352
355
|
});
|
|
353
356
|
}
|
package/dist/shims/cache.js
CHANGED
|
@@ -4,10 +4,10 @@ import { getRequestExecutionContext, runWithExecutionContext } from "./request-c
|
|
|
4
4
|
import { MemoryCacheHandler, NoOpCacheHandler, configureMemoryCacheHandler, getCacheHandler, getDataCacheHandler, setCacheHandler, setDataCacheHandler } from "./cache-handler.js";
|
|
5
5
|
import { getCdnCacheAdapter } from "./cdn-cache.js";
|
|
6
6
|
import { fnv1a64 } from "../utils/hash.js";
|
|
7
|
+
import { encodeCacheTag, encodeCacheTags } from "../utils/encode-cache-tag.js";
|
|
7
8
|
import { makeHangingPromise } from "./internal/make-hanging-promise.js";
|
|
8
9
|
import { getHeadersAccessPhase, isDraftModeEnabled, markDynamicUsage } from "./headers.js";
|
|
9
10
|
import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, getRegisteredCacheContext, markActionRevalidation, recordUnstableCacheObservation, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
|
|
10
|
-
import { encodeCacheTag, encodeCacheTags } from "../utils/encode-cache-tag.js";
|
|
11
11
|
import { addCollectedRequestTags, getCurrentFetchSoftTags } from "./fetch-cache.js";
|
|
12
12
|
import { workUnitAsyncStorage } from "./internal/work-unit-async-storage.js";
|
|
13
13
|
//#region src/shims/cache.ts
|
package/dist/shims/document.js
CHANGED
|
@@ -8,6 +8,12 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
* custom Pages Router documents. Vinext's renderer replaces the Main and
|
|
9
9
|
* NextScript placeholders with the rendered page and hydration scripts.
|
|
10
10
|
*/
|
|
11
|
+
const documentAssetMarkerAttributes = {
|
|
12
|
+
headNonce: "data-vinext-head-nonce",
|
|
13
|
+
headCrossOrigin: "data-vinext-head-cross-origin",
|
|
14
|
+
scriptNonce: "data-vinext-script-nonce",
|
|
15
|
+
scriptCrossOrigin: "data-vinext-script-cross-origin"
|
|
16
|
+
};
|
|
11
17
|
const HtmlContext = React.createContext(void 0);
|
|
12
18
|
function Html(props) {
|
|
13
19
|
return /* @__PURE__ */ jsx("html", { ...props });
|
|
@@ -39,9 +45,11 @@ var Head = class extends React.Component {
|
|
|
39
45
|
return [];
|
|
40
46
|
}
|
|
41
47
|
render() {
|
|
42
|
-
const { children, ...props } = this.props;
|
|
48
|
+
const { children, nonce, crossOrigin, ...props } = this.props;
|
|
43
49
|
return /* @__PURE__ */ jsx("head", {
|
|
44
50
|
...props,
|
|
51
|
+
...nonce ? { [documentAssetMarkerAttributes.headNonce]: nonce } : {},
|
|
52
|
+
...crossOrigin ? { [documentAssetMarkerAttributes.headCrossOrigin]: crossOrigin } : {},
|
|
45
53
|
children
|
|
46
54
|
});
|
|
47
55
|
}
|
|
@@ -70,7 +78,12 @@ var NextScript = class extends React.Component {
|
|
|
70
78
|
return JSON.stringify(context.__NEXT_DATA__);
|
|
71
79
|
}
|
|
72
80
|
render() {
|
|
73
|
-
|
|
81
|
+
const { nonce, crossOrigin } = this.props;
|
|
82
|
+
return /* @__PURE__ */ jsx("span", {
|
|
83
|
+
...nonce ? { [documentAssetMarkerAttributes.scriptNonce]: nonce } : {},
|
|
84
|
+
...crossOrigin ? { [documentAssetMarkerAttributes.scriptCrossOrigin]: crossOrigin } : {},
|
|
85
|
+
dangerouslySetInnerHTML: { __html: "<!-- __NEXT_SCRIPTS__ -->" }
|
|
86
|
+
});
|
|
74
87
|
}
|
|
75
88
|
};
|
|
76
89
|
var Document = class extends React.Component {
|
package/dist/shims/error.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { AppRouterContext } from "./internal/app-router-context.js";
|
|
2
2
|
import { RouterContext } from "./internal/router-context.js";
|
|
3
|
-
import Head from "./head.js";
|
|
4
3
|
import { isNextRouterError } from "./navigation-errors.js";
|
|
5
4
|
import "./navigation.js";
|
|
5
|
+
import Head from "./head.js";
|
|
6
6
|
import { useUntrackedPathname } from "./internal/navigation-untracked.js";
|
|
7
7
|
import React from "react";
|
|
8
8
|
//#region src/shims/error.tsx
|
|
@@ -2,9 +2,9 @@ import { getOrCreateAls } from "./internal/als-registry.js";
|
|
|
2
2
|
import { getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation } from "./unified-request-context.js";
|
|
3
3
|
import { getRequestExecutionContext } from "./request-context.js";
|
|
4
4
|
import { getDataCacheHandler } from "./cache-handler.js";
|
|
5
|
+
import { encodeCacheTags } from "../utils/encode-cache-tag.js";
|
|
5
6
|
import { markDynamicUsage } from "./headers.js";
|
|
6
7
|
import { _hasPendingRevalidatedTag, _setRequestScopedCacheLife } from "./cache-request-state.js";
|
|
7
|
-
import { encodeCacheTags } from "../utils/encode-cache-tag.js";
|
|
8
8
|
//#region src/shims/fetch-cache.ts
|
|
9
9
|
/**
|
|
10
10
|
* Extended fetch() with Next.js caching semantics.
|
|
@@ -19,7 +19,16 @@ import { buildGoogleFontsUrl as buildGoogleFontsUrl$1 } from "../build/google-fo
|
|
|
19
19
|
* // inter.style -> { fontFamily: "'Inter', 'Inter Fallback'", fontStyle: "normal" }
|
|
20
20
|
* // inter.variable -> CSS class that sets the font CSS variable when requested
|
|
21
21
|
*/
|
|
22
|
-
const
|
|
22
|
+
const _INJECTED_FONTS_KEY = Symbol.for("vinext.font.injectedFonts");
|
|
23
|
+
const _INJECTED_CLASS_RULES_KEY = Symbol.for("vinext.font.injectedClassRules");
|
|
24
|
+
const _INJECTED_VARIABLE_RULES_KEY = Symbol.for("vinext.font.injectedVariableRules");
|
|
25
|
+
const _INJECTED_SELF_HOSTED_KEY = Symbol.for("vinext.font.injectedSelfHosted");
|
|
26
|
+
const _SSR_FONT_STYLES_KEY = Symbol.for("vinext.font.ssrFontStyles");
|
|
27
|
+
const _SSR_FONT_URLS_KEY = Symbol.for("vinext.font.ssrFontUrls");
|
|
28
|
+
const _SSR_FONT_PRELOADS_KEY = Symbol.for("vinext.font.ssrFontPreloads");
|
|
29
|
+
const _SSR_FONT_PRELOAD_HREFS_KEY = Symbol.for("vinext.font.ssrFontPreloadHrefs");
|
|
30
|
+
const _g = globalThis;
|
|
31
|
+
const injectedFonts = _g[_INJECTED_FONTS_KEY] ??= /* @__PURE__ */ new Set();
|
|
23
32
|
/**
|
|
24
33
|
* Convert a font family name to a CSS variable name.
|
|
25
34
|
* e.g., "Inter" -> "--font-inter", "Roboto Mono" -> "--font-roboto-mono"
|
|
@@ -128,7 +137,7 @@ function injectFontStylesheet(url) {
|
|
|
128
137
|
}
|
|
129
138
|
}
|
|
130
139
|
/** Track which className CSS rules have been injected. */
|
|
131
|
-
const injectedClassRules = /* @__PURE__ */ new Set();
|
|
140
|
+
const injectedClassRules = _g[_INJECTED_CLASS_RULES_KEY] ??= /* @__PURE__ */ new Set();
|
|
132
141
|
/**
|
|
133
142
|
* Inject a CSS rule that maps a className to the exported font style.
|
|
134
143
|
*
|
|
@@ -152,7 +161,7 @@ function injectClassNameRule(className, fontStyle) {
|
|
|
152
161
|
document.head.appendChild(styleElement);
|
|
153
162
|
}
|
|
154
163
|
/** Track which variable class CSS rules have been injected. */
|
|
155
|
-
const injectedVariableRules = /* @__PURE__ */ new Set();
|
|
164
|
+
const injectedVariableRules = _g[_INJECTED_VARIABLE_RULES_KEY] ??= /* @__PURE__ */ new Set();
|
|
156
165
|
/**
|
|
157
166
|
* Inject a CSS rule that sets a CSS variable on an element.
|
|
158
167
|
* This is what makes `<html className={inter.variable}>` set the CSS variable
|
|
@@ -177,7 +186,7 @@ function injectVariableClassRule(variableClassName, cssVarName, fontFamily) {
|
|
|
177
186
|
style.setAttribute("data-vinext-font-variable", variableClassName);
|
|
178
187
|
document.head.appendChild(style);
|
|
179
188
|
}
|
|
180
|
-
const ssrFontStyles = [];
|
|
189
|
+
const ssrFontStyles = _g[_SSR_FONT_STYLES_KEY] ??= [];
|
|
181
190
|
/**
|
|
182
191
|
* Get collected SSR font class styles (used by the renderer).
|
|
183
192
|
* Note: We don't clear the arrays because fonts are loaded at module import
|
|
@@ -186,7 +195,7 @@ const ssrFontStyles = [];
|
|
|
186
195
|
function getSSRFontStyles() {
|
|
187
196
|
return [...ssrFontStyles];
|
|
188
197
|
}
|
|
189
|
-
const ssrFontUrls = [];
|
|
198
|
+
const ssrFontUrls = _g[_SSR_FONT_URLS_KEY] ??= [];
|
|
190
199
|
/**
|
|
191
200
|
* Get collected SSR font URLs (used by the renderer).
|
|
192
201
|
* Note: We don't clear the arrays because fonts are loaded at module import
|
|
@@ -195,8 +204,8 @@ const ssrFontUrls = [];
|
|
|
195
204
|
function getSSRFontLinks() {
|
|
196
205
|
return [...ssrFontUrls];
|
|
197
206
|
}
|
|
198
|
-
const ssrFontPreloads = [];
|
|
199
|
-
const ssrFontPreloadHrefs = /* @__PURE__ */ new Set();
|
|
207
|
+
const ssrFontPreloads = _g[_SSR_FONT_PRELOADS_KEY] ??= [];
|
|
208
|
+
const ssrFontPreloadHrefs = _g[_SSR_FONT_PRELOAD_HREFS_KEY] ??= /* @__PURE__ */ new Set();
|
|
200
209
|
/**
|
|
201
210
|
* Get collected SSR font preload data (used by the renderer).
|
|
202
211
|
* Returns an array of { href, type } objects for emitting
|
|
@@ -220,7 +229,7 @@ function collectFontPreloads(urls) {
|
|
|
220
229
|
}
|
|
221
230
|
}
|
|
222
231
|
/** Track injected self-hosted @font-face blocks (deduplicate) */
|
|
223
|
-
const injectedSelfHosted = /* @__PURE__ */ new Set();
|
|
232
|
+
const injectedSelfHosted = _g[_INJECTED_SELF_HOSTED_KEY] ??= /* @__PURE__ */ new Set();
|
|
224
233
|
/**
|
|
225
234
|
* Inject self-hosted @font-face CSS (from the build plugin).
|
|
226
235
|
* This replaces the CDN <link> tag with inline CSS.
|