vinext 1.0.0-beta.11 → 1.0.0-beta.13
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 +39 -12
- package/dist/build/action-owner-manifest.js +23 -5
- package/dist/build/lifecycle.d.ts +42 -0
- package/dist/build/lifecycle.js +246 -0
- package/dist/build/nitro-route-rules.js +1 -1
- package/dist/build/pages-client-assets-module.d.ts +0 -3
- package/dist/build/pages-client-assets-module.js +1 -13
- package/dist/build/precompress.js +1 -1
- package/dist/build/prerender-paths.d.ts +1 -1
- package/dist/build/prerender-paths.js +6 -6
- package/dist/build/prerender-server-pool.js +1 -1
- package/dist/build/prerender.d.ts +1 -1
- package/dist/build/prerender.js +5 -5
- package/dist/build/preview-credentials.d.ts +1 -1
- package/dist/build/preview-credentials.js +2 -2
- package/dist/build/report.js +1 -1
- package/dist/build/run-prerender.d.ts +2 -2
- package/dist/build/run-prerender.js +5 -5
- package/dist/build/standalone.js +2 -2
- package/dist/cli-args.d.ts +5 -13
- package/dist/cli-args.js +2 -45
- package/dist/cli-dev-config.d.ts +6 -2
- package/dist/cli-dev-config.js +160 -3
- package/dist/cli.js +104 -439
- package/dist/config/config-matchers.js +1 -1
- package/dist/config/next-config.d.ts +2 -2
- package/dist/config/next-config.js +5 -5
- package/dist/config/prerender.d.ts +3 -0
- package/dist/config/prerender.js +8 -2
- package/dist/entries/app-browser-entry.js +1 -1
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +25 -5
- package/dist/entries/pages-client-entry.d.ts +1 -0
- package/dist/entries/pages-client-entry.js +17 -2
- package/dist/index.d.ts +6 -8
- package/dist/index.js +282 -105
- package/dist/init-cloudflare.d.ts +3 -2
- package/dist/init-cloudflare.js +117 -5
- package/dist/init-platform.d.ts +2 -0
- package/dist/init-platform.js +9 -3
- package/dist/init.d.ts +7 -5
- package/dist/init.js +41 -22
- package/dist/plugins/dynamic-preload-metadata.js +1 -1
- package/dist/plugins/extensionless-dynamic-import.js +2 -2
- package/dist/plugins/fonts.js +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +1 -1
- package/dist/plugins/import-meta-url.js +1 -1
- package/dist/plugins/instrumentation-client.js +1 -1
- package/dist/plugins/og-assets.js +32 -13
- package/dist/plugins/og-harfbuzz.d.ts +24 -0
- package/dist/plugins/og-harfbuzz.js +260 -0
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/require-condition-resolution.js +2 -2
- package/dist/plugins/require-context.js +2 -2
- package/dist/plugins/typeof-window.js +1 -1
- package/dist/plugins/use-cache-callable.d.ts +0 -2
- package/dist/plugins/use-cache-callable.js +40 -22
- package/dist/plugins/worker-image-imports.js +1 -1
- package/dist/routing/app-route-graph.js +1 -1
- package/dist/routing/app-router.js +1 -1
- package/dist/routing/pages-router.js +1 -1
- package/dist/server/app-action-forwarding.js +1 -1
- package/dist/server/app-browser-entry.js +1 -0
- package/dist/server/app-browser-error.js +1 -1
- package/dist/server/app-elements-wire.js +2 -2
- package/dist/server/app-middleware.js +1 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +14 -2
- package/dist/server/app-page-dispatch.js +1 -1
- package/dist/server/app-page-element-builder.js +3 -2
- package/dist/server/app-page-probe.js +3 -3
- package/dist/server/app-page-render.js +1 -0
- package/dist/server/app-page-request.d.ts +2 -0
- package/dist/server/app-page-request.js +16 -12
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +2 -2
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +3 -2
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +2 -2
- package/dist/server/app-route-handler-runtime.js +1 -1
- package/dist/server/app-router-entry.js +2 -2
- package/dist/server/app-rsc-handler.d.ts +9 -2
- package/dist/server/app-rsc-handler.js +30 -10
- package/dist/server/app-rsc-response-stage.js +6 -3
- package/dist/server/app-rsc-route-matching.js +1 -1
- package/dist/server/app-server-action-execution.js +35 -6
- package/dist/server/app-ssr-entry.js +7 -2
- package/dist/server/app-ssr-stream.js +25 -6
- package/dist/server/app-worker-stages.d.ts +4 -1
- package/dist/server/app-worker-stages.js +4 -4
- package/dist/server/artifact-compatibility.js +1 -1
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/dev-lockfile.d.ts +1 -1
- package/dist/server/dev-lockfile.js +4 -1
- package/dist/server/dev-server.d.ts +1 -1
- package/dist/server/dev-server.js +28 -6
- package/dist/server/dev-stack-sourcemap.js +1 -1
- package/dist/server/html.d.ts +0 -20
- package/dist/server/html.js +16 -1
- package/dist/server/instrumentation.d.ts +4 -9
- package/dist/server/instrumentation.js +10 -15
- package/dist/server/isr-cache.js +3 -3
- package/dist/server/metadata-route-response.d.ts +1 -0
- package/dist/server/metadata-route-response.js +65 -0
- package/dist/server/middleware-runtime.js +3 -3
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +37 -2
- package/dist/server/pages-client-assets.d.ts +7 -0
- package/dist/server/pages-data-route.js +1 -1
- package/dist/server/pages-dev-hydration.d.ts +6 -0
- package/dist/server/pages-dev-hydration.js +19 -7
- package/dist/server/pages-document-initial-props.d.ts +1 -0
- package/dist/server/pages-document-initial-props.js +1 -1
- package/dist/server/pages-page-data.js +2 -2
- package/dist/server/pages-page-handler.js +5 -2
- package/dist/server/pages-page-response.d.ts +1 -0
- package/dist/server/pages-page-response.js +3 -2
- package/dist/server/pages-request-pipeline.js +3 -3
- package/dist/server/pages-request-stage-entry.js +3 -3
- package/dist/server/pages-revalidate.js +1 -1
- package/dist/server/prerender-route-params.js +1 -1
- package/dist/server/prod-server.js +19 -13
- package/dist/server/request-pipeline.js +2 -2
- package/dist/server/rsc-stream-hints.d.ts +12 -0
- package/dist/server/rsc-stream-hints.js +70 -35
- package/dist/server/seed-cache.js +3 -4
- package/dist/server/socket-error-backstop.js +1 -1
- package/dist/shims/cache-callable-runtime.d.ts +38 -0
- package/dist/shims/cache-callable-runtime.js +162 -11
- package/dist/shims/cache-runtime.d.ts +6 -8
- package/dist/shims/cache-runtime.js +89 -24
- package/dist/shims/constants.js +1 -1
- package/dist/shims/dynamic-preload-chunks.js +6 -2
- package/dist/shims/font-local.js +1 -1
- package/dist/shims/form.js +1 -1
- package/dist/shims/head.js +1 -1
- package/dist/shims/headers.js +2 -2
- package/dist/shims/image-config.js +2 -0
- package/dist/shims/internal/app-page-props-cache-key.d.ts +29 -0
- package/dist/shims/internal/app-page-props-cache-key.js +53 -1
- package/dist/shims/internal/format-url-object.d.ts +7 -0
- package/dist/shims/internal/format-url-object.js +53 -0
- package/dist/shims/internal/normalize-router-href.d.ts +15 -0
- package/dist/shims/internal/normalize-router-href.js +41 -0
- package/dist/shims/internal/pages-data-target.d.ts +4 -1
- package/dist/shims/internal/pages-data-target.js +28 -35
- package/dist/shims/internal/route-pattern-for-warning.d.ts +2 -2
- package/dist/shims/internal/route-pattern-for-warning.js +3 -3
- package/dist/shims/link.js +31 -92
- package/dist/shims/metadata.js +5 -4
- package/dist/shims/navigation.js +2 -2
- package/dist/shims/router-state.js +1 -1
- package/dist/shims/router.d.ts +8 -7
- package/dist/shims/router.js +312 -148
- package/dist/shims/script-nonce-context.d.ts +4 -1
- package/dist/shims/script-nonce-context.js +15 -6
- package/dist/shims/server.js +3 -3
- package/dist/utils/built-asset-url.js +1 -1
- package/dist/utils/client-runtime-metadata.d.ts +6 -0
- package/dist/utils/client-runtime-metadata.js +16 -0
- package/dist/utils/lazy-chunks.js +1 -1
- package/dist/utils/project.d.ts +1 -11
- package/dist/utils/project.js +20 -29
- package/dist/utils/react-version.d.ts +3 -1
- package/dist/utils/react-version.js +19 -1
- package/dist/utils/vite-cli-invocation.d.ts +21 -0
- package/dist/utils/vite-cli-invocation.js +144 -0
- package/package.json +10 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
|
|
3
|
-
import { useScriptNonce } from "./script-nonce-context.js";
|
|
3
|
+
import { useInitialStylesheetHrefs, useScriptNonce } from "./script-nonce-context.js";
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { getPagesClientAssets } from "vinext/server/pages-client-assets";
|
|
6
6
|
//#region src/shims/dynamic-preload-chunks.tsx
|
|
@@ -47,18 +47,22 @@ function resolveDynamicPreloadFiles(moduleIds) {
|
|
|
47
47
|
}
|
|
48
48
|
function DynamicPreloadChunks(props) {
|
|
49
49
|
const nonce = useScriptNonce();
|
|
50
|
+
const initialStylesheetHrefs = useInitialStylesheetHrefs();
|
|
50
51
|
if (typeof window !== "undefined") return null;
|
|
51
52
|
const files = resolveDynamicPreloadFiles(props.moduleIds);
|
|
52
53
|
if (files.length === 0) return null;
|
|
54
|
+
const crossOrigin = getPagesClientAssets().crossOrigin ?? "";
|
|
53
55
|
const preloadLinks = [];
|
|
54
56
|
for (const file of files) {
|
|
55
57
|
const assetHref = dynamicPreloadHref(file);
|
|
56
58
|
if (assetHref.endsWith(".css")) {
|
|
57
59
|
const href = appendAssetDeploymentIdQuery(assetHref);
|
|
60
|
+
if (initialStylesheetHrefs?.has(href)) continue;
|
|
58
61
|
preloadLinks.push(React.createElement("link", {
|
|
59
62
|
key: href,
|
|
60
63
|
rel: "stylesheet",
|
|
61
64
|
href,
|
|
65
|
+
crossOrigin,
|
|
62
66
|
nonce,
|
|
63
67
|
precedence: "dynamic"
|
|
64
68
|
}));
|
|
@@ -69,7 +73,7 @@ function DynamicPreloadChunks(props) {
|
|
|
69
73
|
rel: "modulepreload",
|
|
70
74
|
href: assetHref,
|
|
71
75
|
as: "script",
|
|
72
|
-
crossOrigin
|
|
76
|
+
crossOrigin,
|
|
73
77
|
fetchPriority: "low",
|
|
74
78
|
nonce
|
|
75
79
|
}));
|
package/dist/shims/font-local.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { fnv1a64 } from "../utils/hash.js";
|
|
2
1
|
import { escapeCSSString, formatFontClassRule, getFontMimeType, resolveSingleFaceStyle, sanitizeCSSVarName, sanitizeFallback, sanitizeFontDescriptorValue } from "./font-utils.js";
|
|
2
|
+
import { fnv1a64 } from "../utils/hash.js";
|
|
3
3
|
//#region src/shims/font-local.ts
|
|
4
4
|
/**
|
|
5
5
|
* next/font/local shim
|
package/dist/shims/form.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
2
3
|
import { VINEXT_MOUNTED_SLOTS_HEADER } from "../server/app-rsc-vary.js";
|
|
3
4
|
import "../server/headers.js";
|
|
4
5
|
import { assertSafeNavigationUrl } from "./url-safety.js";
|
|
@@ -6,7 +7,6 @@ import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "../server/app-rsc-re
|
|
|
6
7
|
import { AppElementsWire } from "../server/app-elements-wire.js";
|
|
7
8
|
import "../server/app-elements.js";
|
|
8
9
|
import { withBasePath } from "./url-utils.js";
|
|
9
|
-
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
10
10
|
import { createRscRequestHeaders, createRscRequestUrl } from "../server/app-rsc-cache-busting.js";
|
|
11
11
|
import { hasAppNavigationRuntime } from "../client/navigation-runtime.js";
|
|
12
12
|
import { getMountedSlotsHeader, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, navigateClientSide, prefetchRscResponse } from "./navigation.js";
|
package/dist/shims/head.js
CHANGED
|
@@ -75,7 +75,7 @@ function getSSRHeadHTML() {
|
|
|
75
75
|
...defaultHead(),
|
|
76
76
|
..._getSSRHeadChildren(),
|
|
77
77
|
..._getDocumentInitialHead()
|
|
78
|
-
]).map((child) => headChildToHTML(child.type, child.props)).filter(Boolean).join("
|
|
78
|
+
]).map((child) => headChildToHTML(child.type, child.props)).filter(Boolean).join("");
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
81
|
* Tags allowed inside <head>. Anything else is silently dropped.
|
package/dist/shims/headers.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { getOrCreateAls } from "./internal/als-registry.js";
|
|
2
2
|
import { getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation } from "./unified-request-context.js";
|
|
3
|
-
import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
|
|
4
3
|
import { MIDDLEWARE_SET_COOKIE_HEADER } from "../utils/protocol-headers.js";
|
|
5
|
-
import { FLIGHT_HEADERS, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER } from "../server/headers.js";
|
|
6
4
|
import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
|
|
5
|
+
import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
|
|
6
|
+
import { FLIGHT_HEADERS, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER } from "../server/headers.js";
|
|
7
7
|
import { serializeSetCookie, validateCookieName } from "./internal/cookie-serialize.js";
|
|
8
8
|
import { createPprFallbackShellSuspensePromise } from "./ppr-fallback-shell.js";
|
|
9
9
|
//#region src/shims/headers.ts
|
|
@@ -59,6 +59,7 @@ function matchRemotePattern(pattern, url) {
|
|
|
59
59
|
function hasRemoteMatch(domains, remotePatterns, url) {
|
|
60
60
|
return domains.some((domain) => url.hostname === domain) || remotePatterns.some((p) => matchRemotePattern(p, url));
|
|
61
61
|
}
|
|
62
|
+
const IPV4_LITERAL_CHARS_RE = /^[0-9a-fA-FxX.]+$/;
|
|
62
63
|
/**
|
|
63
64
|
* Determine whether a string is a private (non-routable) IP address.
|
|
64
65
|
* Works for IPv4 and IPv6, including bracketed and IPv4-mapped forms.
|
|
@@ -73,6 +74,7 @@ function hasRemoteMatch(domains, remotePatterns, url) {
|
|
|
73
74
|
*/
|
|
74
75
|
function isPrivateIp(ip) {
|
|
75
76
|
if (ip.startsWith("[") && ip.endsWith("]")) ip = ip.slice(1, -1);
|
|
77
|
+
if (!ip.includes(":") && !IPV4_LITERAL_CHARS_RE.test(ip)) return false;
|
|
76
78
|
try {
|
|
77
79
|
const parsed = ipaddr.parse(ip);
|
|
78
80
|
if (parsed instanceof ipaddr.IPv6 && parsed.isIPv4MappedAddress()) return parsed.toIPv4Address().range() !== "unicast";
|
|
@@ -1,4 +1,33 @@
|
|
|
1
1
|
//#region src/shims/internal/app-page-props-cache-key.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Enumerable page marker, matching Next.js's `$$isPage` prop. It must be an
|
|
4
|
+
* ordinary string key: React's createElement drops symbol and non-enumerable
|
|
5
|
+
* props before a server component is invoked.
|
|
6
|
+
*/
|
|
7
|
+
export declare const APP_PAGE_USE_CACHE_MARKER = "$$isPage";
|
|
2
8
|
export declare function markAppPagePropsForUseCache<T extends object>(props: T): T;
|
|
3
9
|
export declare function isMarkedAppPagePropsObject(value: object): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Whether `fn` is a transformed `"use cache"` function, including a bound
|
|
12
|
+
* one. Like Next.js's `isUseCacheFunction`, this survives `.bind()`: React's
|
|
13
|
+
* server-reference `bind` copies `$$typeof`/`$$id` to the bound function but
|
|
14
|
+
* not vinext's own marker symbol.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isUseCacheFunctionReference(fn: unknown): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Add Next.js's `$$isPage` marker when `fn` is a `"use cache"` function
|
|
19
|
+
* invoked as a page component or as a page's generateMetadata/generateViewport
|
|
20
|
+
* (create-component-tree.tsx, resolve-metadata.ts `createSegmentProps`). The
|
|
21
|
+
* cache wrapper reads and removes it, so page semantics follow the invocation
|
|
22
|
+
* even when the cached function is defined in (or re-exported from) another
|
|
23
|
+
* module, or bound.
|
|
24
|
+
*/
|
|
25
|
+
export declare function withUseCachePageMarker<T extends Record<string, unknown>>(fn: unknown, props: T): T;
|
|
26
|
+
/**
|
|
27
|
+
* Whether `value` is page props carrying the `$$isPage` marker. Only plain
|
|
28
|
+
* objects qualify: the framework always passes a plain props object, and
|
|
29
|
+
* reading the marker through a thenable params/searchParams proxy would be
|
|
30
|
+
* observed as a param access.
|
|
31
|
+
*/
|
|
32
|
+
export declare function hasUseCachePageMarker(value: unknown): value is Record<string, unknown>;
|
|
4
33
|
//#endregion
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
//#region src/shims/internal/app-page-props-cache-key.ts
|
|
2
2
|
const APP_PAGE_PROPS_CACHE_KEY_MARKER = Symbol.for("vinext.appPagePropsCacheKeyMarker");
|
|
3
|
+
const USE_CACHE_FUNCTION_SYMBOL = Symbol.for("vinext.useCacheFunction");
|
|
4
|
+
const SERVER_REFERENCE_TAG = Symbol.for("react.server.reference");
|
|
5
|
+
/**
|
|
6
|
+
* Server reference ids of transformed cache functions end in the export name
|
|
7
|
+
* the use-cache transform assigns (`secureExportName` in
|
|
8
|
+
* plugins/use-cache-callable.ts): `$$vinext_cache_` plus an HMAC-SHA256 hex
|
|
9
|
+
* digest. `"use server"` actions keep their own export names.
|
|
10
|
+
*/
|
|
11
|
+
const USE_CACHE_SERVER_REFERENCE_ID_RE = /#\$\$vinext_cache_[0-9a-f]{64}$/;
|
|
12
|
+
/**
|
|
13
|
+
* Enumerable page marker, matching Next.js's `$$isPage` prop. It must be an
|
|
14
|
+
* ordinary string key: React's createElement drops symbol and non-enumerable
|
|
15
|
+
* props before a server component is invoked.
|
|
16
|
+
*/
|
|
17
|
+
const APP_PAGE_USE_CACHE_MARKER = "$$isPage";
|
|
3
18
|
function markAppPagePropsForUseCache(props) {
|
|
4
19
|
Object.defineProperty(props, APP_PAGE_PROPS_CACHE_KEY_MARKER, {
|
|
5
20
|
configurable: false,
|
|
@@ -12,5 +27,42 @@ function markAppPagePropsForUseCache(props) {
|
|
|
12
27
|
function isMarkedAppPagePropsObject(value) {
|
|
13
28
|
return Reflect.get(value, APP_PAGE_PROPS_CACHE_KEY_MARKER) === true;
|
|
14
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Whether `fn` is a transformed `"use cache"` function, including a bound
|
|
32
|
+
* one. Like Next.js's `isUseCacheFunction`, this survives `.bind()`: React's
|
|
33
|
+
* server-reference `bind` copies `$$typeof`/`$$id` to the bound function but
|
|
34
|
+
* not vinext's own marker symbol.
|
|
35
|
+
*/
|
|
36
|
+
function isUseCacheFunctionReference(fn) {
|
|
37
|
+
if (typeof fn !== "function") return false;
|
|
38
|
+
if (Reflect.get(fn, USE_CACHE_FUNCTION_SYMBOL) === true) return true;
|
|
39
|
+
const reference = fn;
|
|
40
|
+
return reference.$$typeof === SERVER_REFERENCE_TAG && typeof reference.$$id === "string" && USE_CACHE_SERVER_REFERENCE_ID_RE.test(reference.$$id);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Add Next.js's `$$isPage` marker when `fn` is a `"use cache"` function
|
|
44
|
+
* invoked as a page component or as a page's generateMetadata/generateViewport
|
|
45
|
+
* (create-component-tree.tsx, resolve-metadata.ts `createSegmentProps`). The
|
|
46
|
+
* cache wrapper reads and removes it, so page semantics follow the invocation
|
|
47
|
+
* even when the cached function is defined in (or re-exported from) another
|
|
48
|
+
* module, or bound.
|
|
49
|
+
*/
|
|
50
|
+
function withUseCachePageMarker(fn, props) {
|
|
51
|
+
return isUseCacheFunctionReference(fn) ? {
|
|
52
|
+
...props,
|
|
53
|
+
[APP_PAGE_USE_CACHE_MARKER]: true
|
|
54
|
+
} : props;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Whether `value` is page props carrying the `$$isPage` marker. Only plain
|
|
58
|
+
* objects qualify: the framework always passes a plain props object, and
|
|
59
|
+
* reading the marker through a thenable params/searchParams proxy would be
|
|
60
|
+
* observed as a param access.
|
|
61
|
+
*/
|
|
62
|
+
function hasUseCachePageMarker(value) {
|
|
63
|
+
if (value === null || typeof value !== "object") return false;
|
|
64
|
+
const prototype = Object.getPrototypeOf(value);
|
|
65
|
+
return (prototype === Object.prototype || prototype === null) && value["$$isPage"] === true;
|
|
66
|
+
}
|
|
15
67
|
//#endregion
|
|
16
|
-
export { isMarkedAppPagePropsObject, markAppPagePropsForUseCache };
|
|
68
|
+
export { APP_PAGE_USE_CACHE_MARKER, hasUseCachePageMarker, isMarkedAppPagePropsObject, isUseCacheFunctionReference, markAppPagePropsForUseCache, withUseCachePageMarker };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { UrlObject } from "node:url";
|
|
2
|
+
//#region src/shims/internal/format-url-object.d.ts
|
|
3
|
+
/** Format Node's public UrlObject shape with the semantics used by Next.js. */
|
|
4
|
+
export declare function formatUrlObject(url: UrlObject): string;
|
|
5
|
+
/** Format a Pages Router UrlObject and surface Next.js's development diagnostics. */
|
|
6
|
+
export declare function formatUrlObjectWithValidation(url: UrlObject): string;
|
|
7
|
+
//#endregion
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { urlQueryToSearchParams } from "../../utils/query.js";
|
|
2
|
+
//#region src/shims/internal/format-url-object.ts
|
|
3
|
+
const slashedProtocols = /https?|ftp|gopher|file/;
|
|
4
|
+
const urlObjectKeys = /* @__PURE__ */ new Set([
|
|
5
|
+
"auth",
|
|
6
|
+
"hash",
|
|
7
|
+
"host",
|
|
8
|
+
"hostname",
|
|
9
|
+
"href",
|
|
10
|
+
"path",
|
|
11
|
+
"pathname",
|
|
12
|
+
"port",
|
|
13
|
+
"protocol",
|
|
14
|
+
"query",
|
|
15
|
+
"search",
|
|
16
|
+
"slashes"
|
|
17
|
+
]);
|
|
18
|
+
/** Format Node's public UrlObject shape with the semantics used by Next.js. */
|
|
19
|
+
function formatUrlObject(url) {
|
|
20
|
+
let { auth, hostname } = url;
|
|
21
|
+
let protocol = url.protocol || "";
|
|
22
|
+
let pathname = url.pathname || "";
|
|
23
|
+
let hash = url.hash || "";
|
|
24
|
+
let query = url.query || "";
|
|
25
|
+
let host = false;
|
|
26
|
+
auth = auth ? `${encodeURIComponent(auth).replace(/%3A/i, ":")}@` : "";
|
|
27
|
+
if (url.host) host = auth + url.host;
|
|
28
|
+
else if (hostname) {
|
|
29
|
+
host = auth + (hostname.includes(":") ? `[${hostname}]` : hostname);
|
|
30
|
+
if (url.port) host += `:${url.port}`;
|
|
31
|
+
}
|
|
32
|
+
if (query && typeof query === "object") query = String(urlQueryToSearchParams(query));
|
|
33
|
+
let search = url.search || query && `?${query}` || "";
|
|
34
|
+
if (protocol && !protocol.endsWith(":")) protocol += ":";
|
|
35
|
+
if (url.slashes || (!protocol || slashedProtocols.test(protocol)) && host !== false) {
|
|
36
|
+
host = `//${host || ""}`;
|
|
37
|
+
if (pathname && !pathname.startsWith("/")) pathname = `/${pathname}`;
|
|
38
|
+
} else if (!host) host = "";
|
|
39
|
+
if (hash && !hash.startsWith("#")) hash = `#${hash}`;
|
|
40
|
+
if (search && !search.startsWith("?")) search = `?${search}`;
|
|
41
|
+
pathname = pathname.replace(/[?#]/g, encodeURIComponent);
|
|
42
|
+
search = search.replace("#", "%23");
|
|
43
|
+
return `${protocol}${host}${pathname}${search}${hash}`;
|
|
44
|
+
}
|
|
45
|
+
/** Format a Pages Router UrlObject and surface Next.js's development diagnostics. */
|
|
46
|
+
function formatUrlObjectWithValidation(url) {
|
|
47
|
+
if (process.env.NODE_ENV === "development") {
|
|
48
|
+
for (const key of Object.keys(url)) if (!urlObjectKeys.has(key)) console.warn(`Unknown key passed via urlObject into url.format: ${key}`);
|
|
49
|
+
}
|
|
50
|
+
return formatUrlObject(url);
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { formatUrlObject, formatUrlObjectWithValidation };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/shims/internal/normalize-router-href.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Warn about and normalize repeated path separators like Next.js `resolveHref`.
|
|
4
|
+
* The protocol separator is preserved and query strings are left untouched.
|
|
5
|
+
*
|
|
6
|
+
* Ported from Next.js: packages/next/src/client/resolve-href.ts
|
|
7
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/client/resolve-href.ts
|
|
8
|
+
*/
|
|
9
|
+
export declare function normalizeRouterHref(href: string, routePathname: string): string;
|
|
10
|
+
/** Resolve a Pages Router href against the route state used by Next.js Link. */
|
|
11
|
+
export declare function resolvePagesRouterHref(href: string, router: {
|
|
12
|
+
pathname: string;
|
|
13
|
+
asPath: string;
|
|
14
|
+
}, basePath: string): string;
|
|
15
|
+
//#endregion
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { hasBasePath } from "../../utils/base-path.js";
|
|
2
|
+
import { getWindowOrigin, isAbsoluteUrl } from "../url-utils.js";
|
|
3
|
+
//#region src/shims/internal/normalize-router-href.ts
|
|
4
|
+
/**
|
|
5
|
+
* Warn about and normalize repeated path separators like Next.js `resolveHref`.
|
|
6
|
+
* The protocol separator is preserved and query strings are left untouched.
|
|
7
|
+
*
|
|
8
|
+
* Ported from Next.js: packages/next/src/client/resolve-href.ts
|
|
9
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/client/resolve-href.ts
|
|
10
|
+
*/
|
|
11
|
+
function normalizeRouterHref(href, routePathname) {
|
|
12
|
+
const protocol = href.match(/^[a-z][a-z0-9+.-]*:\/\//i)?.[0] ?? "";
|
|
13
|
+
const withoutProtocol = protocol ? href.slice(protocol.length) : href;
|
|
14
|
+
if (!/(\/\/|\\)/.test(withoutProtocol.split("?", 1)[0] ?? "")) return href;
|
|
15
|
+
console.error(`Invalid href '${href}' passed to next/router in page: '${routePathname}'. Repeated forward-slashes (//) or backslashes \\ are not valid in the href.`);
|
|
16
|
+
const [pathname, ...query] = withoutProtocol.split("?");
|
|
17
|
+
return protocol + pathname.replace(/\\/g, "/").replace(/\/\/+/g, "/") + (query[0] ? `?${query.join("?")}` : "");
|
|
18
|
+
}
|
|
19
|
+
/** Resolve a Pages Router href against the route state used by Next.js Link. */
|
|
20
|
+
function resolvePagesRouterHref(href, router, basePath) {
|
|
21
|
+
const normalized = normalizeRouterHref(href, router.pathname);
|
|
22
|
+
if (isAbsoluteUrl(normalized)) {
|
|
23
|
+
const origin = getWindowOrigin();
|
|
24
|
+
if (!origin) return normalized;
|
|
25
|
+
try {
|
|
26
|
+
const target = new URL(normalized, origin);
|
|
27
|
+
if (target.origin !== origin || basePath !== "" && !hasBasePath(target.pathname, basePath)) return normalized;
|
|
28
|
+
} catch {
|
|
29
|
+
return normalized;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const base = new URL(normalized.startsWith("#") || normalized.startsWith("?") ? router.asPath : router.pathname, "http://n");
|
|
34
|
+
const resolved = new URL(normalized, base);
|
|
35
|
+
return resolved.origin === base.origin ? resolved.href.slice(resolved.origin.length) : resolved.href;
|
|
36
|
+
} catch {
|
|
37
|
+
return normalized;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { normalizeRouterHref, resolvePagesRouterHref };
|
|
@@ -35,8 +35,11 @@ export type PagesDataTarget = {
|
|
|
35
35
|
};
|
|
36
36
|
type PagesDataNavigationTargetOptions = {
|
|
37
37
|
locale?: string | false;
|
|
38
|
+
/** Force page identity while deriving params and data URLs from browserUrl. */
|
|
39
|
+
routePattern?: string;
|
|
38
40
|
};
|
|
39
|
-
export declare function
|
|
41
|
+
export declare function matchesPagesMiddlewarePath(pathname: string): boolean;
|
|
42
|
+
export declare function getPagesMiddlewareDataHref(browserUrl: string, basePath: string, options?: PagesDataNavigationTargetOptions, routeUrl?: string): string | null;
|
|
40
43
|
/**
|
|
41
44
|
* Decide whether the JSON data-endpoint navigation path is usable for this
|
|
42
45
|
* browser URL. We require:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { removeTrailingSlash, stripBasePath } from "../../utils/base-path.js";
|
|
2
|
-
import { getLocalePathPrefix } from "../../utils/domain-locale.js";
|
|
3
1
|
import { isUnknownRecord } from "../../utils/record.js";
|
|
2
|
+
import { stripBasePath } from "../../utils/base-path.js";
|
|
3
|
+
import { getLocalePathPrefix } from "../../utils/domain-locale.js";
|
|
4
4
|
import { buildPagesDataHref, matchPagesPattern } from "./pages-data-url.js";
|
|
5
5
|
import { NEXT_DEPLOYMENT_ID_HEADER, getDeploymentId } from "../../utils/deployment-id.js";
|
|
6
6
|
import { fetchStaticPagesData, fetchUncachedPagesData } from "./pages-data-fetch-dedup.js";
|
|
@@ -22,10 +22,9 @@ function hasVinextMiddleware(nextData) {
|
|
|
22
22
|
}
|
|
23
23
|
function isClientMiddlewareMatcherObject(value) {
|
|
24
24
|
if (!isUnknownRecord(value)) return false;
|
|
25
|
-
if (typeof value.
|
|
25
|
+
if (typeof value.regexp !== "string") return false;
|
|
26
|
+
if (value.flags !== void 0 && typeof value.flags !== "string") return false;
|
|
26
27
|
if (value.locale !== void 0 && value.locale !== false) return false;
|
|
27
|
-
if (value.has !== void 0 && !Array.isArray(value.has)) return false;
|
|
28
|
-
if (value.missing !== void 0 && !Array.isArray(value.missing)) return false;
|
|
29
28
|
return true;
|
|
30
29
|
}
|
|
31
30
|
function stripLocaleForMiddlewareMatcher(pathname) {
|
|
@@ -35,40 +34,28 @@ function stripLocaleForMiddlewareMatcher(pathname) {
|
|
|
35
34
|
if (!firstSegment || !locales.includes(firstSegment)) return pathname;
|
|
36
35
|
return "/" + pathname.split("/").slice(2).join("/");
|
|
37
36
|
}
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
let pathIndex = 0;
|
|
44
|
-
for (const sourcePart of sourceParts) {
|
|
45
|
-
if (sourcePart.startsWith(":")) {
|
|
46
|
-
if (sourcePart.endsWith("*")) return true;
|
|
47
|
-
if (sourcePart.endsWith("+")) return pathIndex < pathParts.length;
|
|
48
|
-
if (pathIndex >= pathParts.length) return false;
|
|
49
|
-
pathIndex++;
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
if (pathParts[pathIndex] !== sourcePart) return false;
|
|
53
|
-
pathIndex++;
|
|
54
|
-
}
|
|
55
|
-
return pathIndex === pathParts.length;
|
|
37
|
+
function localeAwareMiddlewarePathname(pathname) {
|
|
38
|
+
const locales = window.__VINEXT_LOCALES__;
|
|
39
|
+
const defaultLocale = window.__VINEXT_DEFAULT_LOCALE__;
|
|
40
|
+
if (!locales?.includes(defaultLocale ?? "") || getLocalePathPrefix(pathname, locales)) return pathname;
|
|
41
|
+
return `/${defaultLocale}${pathname === "/" ? "" : pathname}`;
|
|
56
42
|
}
|
|
57
|
-
function
|
|
43
|
+
function matchesPagesMiddlewarePath(pathname) {
|
|
44
|
+
const matcher = window.__VINEXT_MIDDLEWARE_MATCHER__;
|
|
58
45
|
if (matcher === void 0) return true;
|
|
59
|
-
if (typeof matcher === "string") return clientMiddlewareSourceMatches(stripLocaleForMiddlewareMatcher(pathname), matcher);
|
|
60
46
|
if (!Array.isArray(matcher)) return true;
|
|
61
47
|
for (const item of matcher) {
|
|
62
|
-
if (typeof item === "string") {
|
|
63
|
-
if (clientMiddlewareSourceMatches(stripLocaleForMiddlewareMatcher(pathname), item)) return true;
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
48
|
if (!isClientMiddlewareMatcherObject(item)) return true;
|
|
67
|
-
|
|
49
|
+
const candidate = item.locale === false ? localeAwareMiddlewarePathname(pathname) : stripLocaleForMiddlewareMatcher(pathname);
|
|
50
|
+
try {
|
|
51
|
+
if (new RegExp(item.regexp, item.flags).test(candidate)) return true;
|
|
52
|
+
} catch {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
68
55
|
}
|
|
69
56
|
return false;
|
|
70
57
|
}
|
|
71
|
-
function getPagesMiddlewareDataHref(browserUrl, basePath, options = {}) {
|
|
58
|
+
function getPagesMiddlewareDataHref(browserUrl, basePath, options = {}, routeUrl = browserUrl) {
|
|
72
59
|
const nextData = window.__NEXT_DATA__;
|
|
73
60
|
if (!nextData || !hasVinextMiddleware(nextData)) return null;
|
|
74
61
|
const buildId = nextData.buildId;
|
|
@@ -80,13 +67,19 @@ function getPagesMiddlewareDataHref(browserUrl, basePath, options = {}) {
|
|
|
80
67
|
return null;
|
|
81
68
|
}
|
|
82
69
|
if (parsed.origin !== window.location.origin) return null;
|
|
70
|
+
let routeSearch = parsed.search;
|
|
71
|
+
if (routeUrl !== browserUrl) try {
|
|
72
|
+
routeSearch = new URL(routeUrl, window.location.href).search;
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
83
76
|
const pathname = stripBasePath(parsed.pathname, basePath);
|
|
84
|
-
if (!
|
|
77
|
+
if (!matchesPagesMiddlewarePath(pathname)) return null;
|
|
85
78
|
const pathnameLocale = getLocalePathPrefix(pathname, window.__VINEXT_LOCALES__);
|
|
86
79
|
const explicitLocale = options.locale === false ? window.__VINEXT_DEFAULT_LOCALE__ : options.locale;
|
|
87
80
|
const currentLocale = pathnameLocale ?? explicitLocale ?? window.__VINEXT_LOCALE__;
|
|
88
81
|
const dataPathname = pathnameLocale || !currentLocale || !window.__VINEXT_LOCALES__?.includes(currentLocale) ? pathname : `/${currentLocale}${pathname === "/" ? "" : pathname}`;
|
|
89
|
-
return buildPagesDataHref(basePath, buildId, dataPathname,
|
|
82
|
+
return buildPagesDataHref(basePath, buildId, dataPathname, routeSearch);
|
|
90
83
|
}
|
|
91
84
|
/**
|
|
92
85
|
* Decide whether the JSON data-endpoint navigation path is usable for this
|
|
@@ -128,7 +121,7 @@ function resolvePagesDataNavigationTarget(browserUrl, basePath, options = {}) {
|
|
|
128
121
|
const pagePath = stripBasePath(parsed.pathname, basePath);
|
|
129
122
|
const locale = getLocalePathPrefix(pagePath, window.__VINEXT_LOCALES__);
|
|
130
123
|
const pathForMatch = locale ? pagePath.slice(locale.length + 1) || "/" : pagePath;
|
|
131
|
-
const match = matchPagesPattern(pathForMatch, patterns);
|
|
124
|
+
const match = matchPagesPattern(pathForMatch, options.routePattern ? [options.routePattern] : patterns);
|
|
132
125
|
if (!match) return null;
|
|
133
126
|
const loader = loaders[match.pattern];
|
|
134
127
|
if (!loader) return null;
|
|
@@ -195,4 +188,4 @@ function prefetchMiddlewareRewriteLoader(response) {
|
|
|
195
188
|
if (target) target.loader().catch(() => {});
|
|
196
189
|
}
|
|
197
190
|
//#endregion
|
|
198
|
-
export { getPagesMiddlewareDataHref, prefetchPagesData, resolvePagesDataNavigationTarget };
|
|
191
|
+
export { getPagesMiddlewareDataHref, matchesPagesMiddlewarePath, prefetchPagesData, resolvePagesDataNavigationTarget };
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* `installWindowNext()` side effect into every consumer of the Link shim
|
|
14
14
|
* (including the App Router client bundle), clobbering `window.next.router`.
|
|
15
15
|
*
|
|
16
|
-
* On the client
|
|
17
|
-
* back to `window.location.pathname`, then to `"/"`.
|
|
16
|
+
* On the client, Pages Router exposes the pattern through `__NEXT_DATA__.page`.
|
|
17
|
+
* App Router falls back to `window.location.pathname`, then to `"/"`.
|
|
18
18
|
*/
|
|
19
19
|
/**
|
|
20
20
|
* Register the server-side route-pattern accessor. Called once by the
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* `installWindowNext()` side effect into every consumer of the Link shim
|
|
14
14
|
* (including the App Router client bundle), clobbering `window.next.router`.
|
|
15
15
|
*
|
|
16
|
-
* On the client
|
|
17
|
-
* back to `window.location.pathname`, then to `"/"`.
|
|
16
|
+
* On the client, Pages Router exposes the pattern through `__NEXT_DATA__.page`.
|
|
17
|
+
* App Router falls back to `window.location.pathname`, then to `"/"`.
|
|
18
18
|
*/
|
|
19
19
|
const ROUTE_PATTERN_FOR_WARNING_ACCESSOR_KEY = Symbol.for("vinext.router.routePatternForWarningAccessor");
|
|
20
20
|
/**
|
|
@@ -34,7 +34,7 @@ function getCurrentRoutePathnameForWarning() {
|
|
|
34
34
|
} catch {}
|
|
35
35
|
return "/";
|
|
36
36
|
}
|
|
37
|
-
return window.location?.pathname ?? "/";
|
|
37
|
+
return window.__NEXT_DATA__?.page ?? window.location?.pathname ?? "/";
|
|
38
38
|
}
|
|
39
39
|
//#endregion
|
|
40
40
|
export { getCurrentRoutePathnameForWarning, registerRoutePatternForWarningAccessor };
|