vinext 0.1.2 → 0.1.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/dist/build/client-build-config.d.ts +11 -2
- package/dist/build/client-build-config.js +17 -6
- package/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +42 -12
- package/dist/build/run-prerender.d.ts +10 -2
- package/dist/build/run-prerender.js +15 -1
- package/dist/client/app-nav-failure-handler.d.ts +8 -0
- package/dist/client/app-nav-failure-handler.js +44 -0
- package/dist/client/pages-router-link-navigation.d.ts +33 -7
- package/dist/client/pages-router-link-navigation.js +32 -2
- package/dist/client/vinext-next-data.d.ts +18 -1
- package/dist/client/vinext-next-data.js +2 -0
- package/dist/client/window-next.d.ts +2 -1
- package/dist/client/window-next.js +12 -1
- package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
- package/dist/config/config-matchers.d.ts +11 -1
- package/dist/config/config-matchers.js +87 -16
- package/dist/config/next-config.d.ts +46 -4
- package/dist/config/next-config.js +147 -48
- package/dist/config/tsconfig-paths.js +14 -1
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +200 -112
- package/dist/entries/app-browser-entry.d.ts +9 -3
- package/dist/entries/app-browser-entry.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +65 -5
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/app-ssr-entry.js +1 -1
- package/dist/entries/pages-client-entry.js +66 -20
- package/dist/entries/pages-server-entry.js +47 -31
- package/dist/index.js +417 -102
- package/dist/plugins/dynamic-preload-metadata.js +2 -4
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- package/dist/plugins/fonts.js +5 -4
- package/dist/plugins/optimize-imports.d.ts +2 -1
- package/dist/plugins/optimize-imports.js +11 -9
- package/dist/plugins/postcss.js +7 -7
- package/dist/plugins/strip-server-exports.d.ts +9 -7
- package/dist/plugins/strip-server-exports.js +493 -46
- package/dist/plugins/typeof-window.d.ts +14 -0
- package/dist/plugins/typeof-window.js +150 -0
- package/dist/routing/app-route-graph.d.ts +2 -1
- package/dist/routing/app-route-graph.js +46 -16
- package/dist/routing/file-matcher.d.ts +10 -1
- package/dist/routing/file-matcher.js +22 -1
- package/dist/routing/pages-router.js +3 -3
- package/dist/routing/utils.d.ts +35 -6
- package/dist/routing/utils.js +59 -7
- package/dist/server/api-handler.d.ts +6 -1
- package/dist/server/api-handler.js +21 -15
- package/dist/server/app-browser-action-result.d.ts +19 -6
- package/dist/server/app-browser-action-result.js +20 -11
- package/dist/server/app-browser-entry.js +175 -91
- package/dist/server/app-browser-error.d.ts +10 -6
- package/dist/server/app-browser-error.js +43 -8
- package/dist/server/app-browser-hydration.d.ts +2 -0
- package/dist/server/app-browser-hydration.js +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +5 -3
- package/dist/server/app-browser-navigation-controller.js +23 -2
- package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
- package/dist/server/app-browser-server-action-navigation.js +9 -0
- package/dist/server/app-browser-state.d.ts +1 -1
- package/dist/server/app-browser-state.js +19 -11
- package/dist/server/app-browser-stream.js +86 -43
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-elements-wire.d.ts +6 -1
- package/dist/server/app-elements-wire.js +14 -4
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-fallback-renderer.d.ts +1 -0
- package/dist/server/app-fallback-renderer.js +3 -1
- package/dist/server/app-optimistic-routing.js +2 -2
- package/dist/server/app-page-boundary-render.d.ts +1 -0
- package/dist/server/app-page-boundary-render.js +27 -14
- package/dist/server/app-page-cache-render.d.ts +53 -0
- package/dist/server/app-page-cache-render.js +91 -0
- package/dist/server/app-page-cache.d.ts +16 -2
- package/dist/server/app-page-cache.js +62 -1
- package/dist/server/app-page-dispatch.d.ts +26 -0
- package/dist/server/app-page-dispatch.js +149 -92
- package/dist/server/app-page-element-builder.d.ts +1 -0
- package/dist/server/app-page-element-builder.js +5 -2
- package/dist/server/app-page-execution.d.ts +6 -1
- package/dist/server/app-page-execution.js +21 -1
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +4 -0
- package/dist/server/app-page-render-observation.d.ts +3 -1
- package/dist/server/app-page-render-observation.js +17 -1
- package/dist/server/app-page-render.d.ts +12 -1
- package/dist/server/app-page-render.js +42 -4
- package/dist/server/app-page-request.d.ts +2 -0
- package/dist/server/app-page-request.js +2 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +14 -5
- package/dist/server/app-page-stream.d.ts +15 -3
- package/dist/server/app-page-stream.js +11 -5
- package/dist/server/app-pages-bridge.d.ts +23 -1
- package/dist/server/app-pages-bridge.js +26 -17
- package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
- package/dist/server/app-ppr-fallback-shell-render.js +26 -0
- package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
- package/dist/server/app-ppr-fallback-shell.js +8 -1
- package/dist/server/app-route-handler-dispatch.js +9 -2
- package/dist/server/app-route-handler-policy.d.ts +1 -0
- package/dist/server/app-router-entry.js +5 -0
- package/dist/server/app-rsc-cache-busting.js +2 -0
- package/dist/server/app-rsc-handler.d.ts +28 -0
- package/dist/server/app-rsc-handler.js +195 -59
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +8 -2
- package/dist/server/app-segment-config.d.ts +9 -1
- package/dist/server/app-segment-config.js +12 -3
- package/dist/server/app-server-action-execution.d.ts +1 -0
- package/dist/server/app-server-action-execution.js +47 -15
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +84 -39
- package/dist/server/before-interactive-head.d.ts +17 -0
- package/dist/server/before-interactive-head.js +35 -0
- package/dist/server/cache-control.js +4 -0
- package/dist/server/csp.js +1 -4
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +321 -83
- package/dist/server/hybrid-route-priority.d.ts +22 -0
- package/dist/server/hybrid-route-priority.js +33 -0
- package/dist/server/image-optimization.d.ts +18 -9
- package/dist/server/image-optimization.js +37 -23
- package/dist/server/implicit-tags.d.ts +2 -1
- package/dist/server/implicit-tags.js +4 -1
- package/dist/server/middleware-matcher.js +12 -3
- package/dist/server/middleware-runtime.d.ts +3 -4
- package/dist/server/middleware-runtime.js +2 -0
- package/dist/server/navigation-planner.d.ts +135 -41
- package/dist/server/navigation-planner.js +138 -0
- package/dist/server/navigation-trace.d.ts +9 -1
- package/dist/server/navigation-trace.js +9 -1
- package/dist/server/operation-token.d.ts +40 -0
- package/dist/server/operation-token.js +85 -0
- package/dist/server/pages-api-route.d.ts +6 -0
- package/dist/server/pages-api-route.js +13 -2
- package/dist/server/pages-asset-tags.d.ts +2 -1
- package/dist/server/pages-asset-tags.js +6 -2
- package/dist/server/pages-data-route.d.ts +9 -2
- package/dist/server/pages-data-route.js +18 -6
- package/dist/server/pages-dev-module-url.d.ts +4 -0
- package/dist/server/pages-dev-module-url.js +15 -0
- package/dist/server/pages-document-initial-props.d.ts +4 -15
- package/dist/server/pages-document-initial-props.js +27 -56
- package/dist/server/pages-get-initial-props.d.ts +54 -4
- package/dist/server/pages-get-initial-props.js +43 -1
- package/dist/server/pages-i18n.js +2 -2
- package/dist/server/pages-node-compat.js +2 -2
- package/dist/server/pages-page-data.d.ts +11 -2
- package/dist/server/pages-page-data.js +207 -34
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +62 -23
- package/dist/server/pages-page-response.d.ts +4 -1
- package/dist/server/pages-page-response.js +11 -8
- package/dist/server/pages-readiness.js +1 -1
- package/dist/server/pages-request-pipeline.d.ts +8 -7
- package/dist/server/pages-request-pipeline.js +126 -47
- package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
- package/dist/server/pregenerated-concrete-paths.js +2 -19
- package/dist/server/prerender-manifest.d.ts +33 -0
- package/dist/server/prerender-manifest.js +54 -0
- package/dist/server/prerender-route-params.d.ts +1 -2
- package/dist/server/prod-server.d.ts +3 -1
- package/dist/server/prod-server.js +50 -13
- package/dist/server/request-pipeline.d.ts +3 -15
- package/dist/server/request-pipeline.js +58 -47
- package/dist/server/rsc-stream-hints.d.ts +5 -1
- package/dist/server/rsc-stream-hints.js +6 -1
- package/dist/server/seed-cache.js +10 -18
- package/dist/server/static-file-cache.js +16 -4
- package/dist/shims/app-router-scroll-state.d.ts +3 -1
- package/dist/shims/app-router-scroll-state.js +14 -2
- package/dist/shims/app-router-scroll.d.ts +3 -0
- package/dist/shims/app-router-scroll.js +28 -18
- package/dist/shims/before-interactive-context.d.ts +14 -3
- package/dist/shims/cache-runtime.js +3 -2
- package/dist/shims/cache.d.ts +1 -0
- package/dist/shims/cache.js +1 -1
- package/dist/shims/cdn-cache.d.ts +5 -5
- package/dist/shims/document.d.ts +15 -20
- package/dist/shims/document.js +5 -8
- package/dist/shims/dynamic-preload-chunks.js +6 -4
- package/dist/shims/error-boundary.d.ts +2 -0
- package/dist/shims/error-boundary.js +7 -0
- package/dist/shims/error.js +3 -2
- package/dist/shims/error.react-server.d.ts +9 -0
- package/dist/shims/error.react-server.js +6 -0
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +45 -20
- package/dist/shims/hash-scroll.js +6 -1
- package/dist/shims/headers.js +29 -4
- package/dist/shims/image.js +9 -2
- package/dist/shims/internal/als-registry.js +28 -1
- package/dist/shims/internal/app-route-detection.js +8 -17
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
- package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
- package/dist/shims/internal/navigation-untracked.d.ts +35 -0
- package/dist/shims/internal/navigation-untracked.js +55 -0
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +6 -7
- package/dist/shims/internal/pages-data-fetch-dedup.js +67 -14
- package/dist/shims/internal/pages-data-target.d.ts +7 -2
- package/dist/shims/internal/pages-data-target.js +17 -8
- package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
- package/dist/shims/internal/pages-router-accessor.js +13 -0
- package/dist/shims/internal/router-context.d.ts +2 -1
- package/dist/shims/internal/router-context.js +3 -1
- package/dist/shims/link.js +47 -19
- package/dist/shims/metadata.js +4 -4
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +63 -31
- package/dist/shims/ppr-fallback-shell.d.ts +5 -1
- package/dist/shims/ppr-fallback-shell.js +28 -7
- package/dist/shims/router.d.ts +18 -3
- package/dist/shims/router.js +512 -142
- package/dist/shims/script.js +8 -4
- package/dist/shims/server.d.ts +16 -1
- package/dist/shims/server.js +44 -12
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/built-asset-url.d.ts +4 -0
- package/dist/utils/built-asset-url.js +11 -0
- package/dist/utils/commonjs-loader.d.ts +16 -0
- package/dist/utils/commonjs-loader.js +100 -0
- package/dist/utils/deployment-id.d.ts +8 -0
- package/dist/utils/deployment-id.js +22 -0
- package/dist/utils/has-trailing-comma.d.ts +24 -0
- package/dist/utils/has-trailing-comma.js +62 -0
- package/dist/utils/html-limited-bots.d.ts +18 -1
- package/dist/utils/html-limited-bots.js +23 -1
- package/dist/utils/parse-cookie.d.ts +13 -0
- package/dist/utils/parse-cookie.js +52 -0
- package/dist/utils/path.d.ts +7 -1
- package/dist/utils/path.js +9 -1
- package/dist/utils/text-stream.d.ts +1 -1
- package/dist/utils/text-stream.js +2 -2
- package/dist/utils/vite-version.d.ts +12 -1
- package/dist/utils/vite-version.js +9 -1
- package/package.json +2 -2
- package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
- package/dist/shims/internal/parse-cookie-header.js +0 -30
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { removeTrailingSlash, stripBasePath } from "../../utils/base-path.js";
|
|
2
|
-
import {
|
|
2
|
+
import { getLocalePathPrefix } from "../../utils/domain-locale.js";
|
|
3
|
+
import { resolveHybridClientRouteOwner } from "./hybrid-client-route-owner.js";
|
|
3
4
|
//#region src/shims/internal/app-route-detection.ts
|
|
4
|
-
const appRouteTrieCache = createRouteTrieCache();
|
|
5
5
|
const _COMPONENTS_KEY = Symbol.for("vinext.pagesRouter.components");
|
|
6
6
|
/**
|
|
7
7
|
* Get-or-create the Pages Router `components` map. Returns the same object
|
|
@@ -32,20 +32,11 @@ function resolveSameOriginPathname(href, basePath) {
|
|
|
32
32
|
return null;
|
|
33
33
|
}
|
|
34
34
|
if (url.origin !== window.location.origin) return null;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
* absent (Pages-Router-only build), the URL is external, or no route matches.
|
|
41
|
-
*/
|
|
42
|
-
function matchesAppRoute(href, basePath) {
|
|
43
|
-
if (typeof window === "undefined") return false;
|
|
44
|
-
const routes = window.__VINEXT_LINK_PREFETCH_ROUTES__;
|
|
45
|
-
if (!routes || routes.length === 0) return false;
|
|
46
|
-
const pathname = resolveSameOriginPathname(href, basePath);
|
|
47
|
-
if (pathname === null) return false;
|
|
48
|
-
return matchRouteWithTrie(pathname, routes, appRouteTrieCache) !== null;
|
|
35
|
+
const pathname = stripBasePath(url.pathname, basePath);
|
|
36
|
+
const locale = getLocalePathPrefix(pathname, window.__VINEXT_LOCALES__);
|
|
37
|
+
if (!locale) return pathname;
|
|
38
|
+
const localePrefixLength = locale.length + 1;
|
|
39
|
+
return pathname.length === localePrefixLength ? "/" : pathname.slice(localePrefixLength);
|
|
49
40
|
}
|
|
50
41
|
/**
|
|
51
42
|
* Record `components[pathname] = { __appRouter: true }` on the shared
|
|
@@ -61,7 +52,7 @@ function matchesAppRoute(href, basePath) {
|
|
|
61
52
|
*/
|
|
62
53
|
function markAppRouteDetectedOnPrefetch(href, basePath) {
|
|
63
54
|
if (typeof window === "undefined") return;
|
|
64
|
-
if (
|
|
55
|
+
if (resolveHybridClientRouteOwner(href, basePath) !== "app") return;
|
|
65
56
|
const rawPathname = resolveSameOriginPathname(href, basePath);
|
|
66
57
|
if (rawPathname === null) return;
|
|
67
58
|
const pathname = removeTrailingSlash(rawPathname);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { NextRewrite } from "../../config/next-config.js";
|
|
2
|
+
import { VinextLinkPrefetchRoute, VinextPagesLinkPrefetchRoute } from "../../client/vinext-next-data.js";
|
|
3
|
+
|
|
4
|
+
//#region src/shims/internal/hybrid-client-route-owner.d.ts
|
|
5
|
+
type HybridClientOwner = "app" | "document" | "pages";
|
|
6
|
+
declare global {
|
|
7
|
+
interface Window {
|
|
8
|
+
__VINEXT_LINK_PREFETCH_ROUTES__?: VinextLinkPrefetchRoute[];
|
|
9
|
+
__VINEXT_PAGES_LINK_PREFETCH_ROUTES__?: VinextPagesLinkPrefetchRoute[];
|
|
10
|
+
__VINEXT_CLIENT_REWRITES__?: {
|
|
11
|
+
afterFiles: NextRewrite[];
|
|
12
|
+
beforeFiles: NextRewrite[];
|
|
13
|
+
fallback: NextRewrite[];
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Decide which router should own a soft-navigated URL. Returns:
|
|
19
|
+
* - "app" → the App Router runtime handles the navigation (RSC fetch).
|
|
20
|
+
* - "pages" → Pages owns the URL; the caller must hard-navigate instead.
|
|
21
|
+
* - null → no router matched (preserves the existing 404 path).
|
|
22
|
+
*
|
|
23
|
+
* `basePath` must match what the page uses (typically `process.env.__NEXT_ROUTER_BASEPATH`).
|
|
24
|
+
*
|
|
25
|
+
* The lookup uses the App and Pages manifests on `window` so the same
|
|
26
|
+
* matcher trie produces the same result the server will see when the
|
|
27
|
+
* request lands.
|
|
28
|
+
*/
|
|
29
|
+
declare function resolveHybridClientRouteOwner(href: string, basePath: string): HybridClientOwner | null;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { HybridClientOwner, resolveHybridClientRouteOwner };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { compareHybridRoutePatterns } from "../../routing/utils.js";
|
|
2
|
+
import { stripBasePath } from "../../utils/base-path.js";
|
|
3
|
+
import { createRouteTrieCache, matchRouteWithTrie } from "../../routing/route-matching.js";
|
|
4
|
+
import { isExternalUrl, matchRewrite, parseCookies } from "../../config/config-matchers.js";
|
|
5
|
+
import { getLocalePathPrefix } from "../../utils/domain-locale.js";
|
|
6
|
+
import { mergeRewriteQuery } from "../../utils/query.js";
|
|
7
|
+
//#region src/shims/internal/hybrid-client-route-owner.ts
|
|
8
|
+
/**
|
|
9
|
+
* Client-side resolver that decides whether a URL should be soft-navigated
|
|
10
|
+
* (App Router / RSC) or hard-navigated (Pages Router / document). Delegates
|
|
11
|
+
* the owner decision to `compareHybridRoutePatterns` in `routing/utils.ts`
|
|
12
|
+
* so the server and the client reach the same answer for the same
|
|
13
|
+
* (pages pattern, app pattern) pair.
|
|
14
|
+
*
|
|
15
|
+
* Lives in `shims/internal/` because both `link.tsx` and the App Router
|
|
16
|
+
* browser entry import it without pulling in the server route graph.
|
|
17
|
+
*
|
|
18
|
+
* The App + Pages route manifests are emitted once per page load by the
|
|
19
|
+
* Vite plugin onto the matching `__VINEXT_*_PREFETCH_ROUTES__` window
|
|
20
|
+
* globals (see `entries/app-browser-entry.ts` and
|
|
21
|
+
* `entries/pages-client-entry.ts`). Hybrid builds expose both globals; a
|
|
22
|
+
* single-router build only sets its own.
|
|
23
|
+
*/
|
|
24
|
+
function resolveClientRewrite(href, basePath, rewrites, continueAfterMatch = false) {
|
|
25
|
+
const initialUrl = new URL(href, window.location.href);
|
|
26
|
+
const basePathState = {
|
|
27
|
+
basePath,
|
|
28
|
+
hadBasePath: basePath ? initialUrl.pathname === basePath || initialUrl.pathname.startsWith(`${basePath}/`) : true
|
|
29
|
+
};
|
|
30
|
+
let currentHref = href;
|
|
31
|
+
let matched = false;
|
|
32
|
+
for (const rewrite of rewrites) {
|
|
33
|
+
const pathname = resolveSameOriginPathname(currentHref, basePath);
|
|
34
|
+
if (pathname === null) return null;
|
|
35
|
+
const url = new URL(currentHref, window.location.href);
|
|
36
|
+
const headers = new Headers({ "user-agent": globalThis.navigator?.userAgent ?? "" });
|
|
37
|
+
const context = {
|
|
38
|
+
cookies: parseCookies(globalThis.document?.cookie ?? ""),
|
|
39
|
+
headers,
|
|
40
|
+
host: url.hostname,
|
|
41
|
+
query: url.searchParams
|
|
42
|
+
};
|
|
43
|
+
const rewritten = matchRewrite(pathname, [rewrite], context, basePathState);
|
|
44
|
+
if (rewritten === null) continue;
|
|
45
|
+
if (isExternalUrl(rewritten)) return { kind: "document" };
|
|
46
|
+
currentHref = mergeRewriteQuery(currentHref, rewritten);
|
|
47
|
+
matched = true;
|
|
48
|
+
if (!continueAfterMatch) break;
|
|
49
|
+
}
|
|
50
|
+
return matched ? {
|
|
51
|
+
href: currentHref,
|
|
52
|
+
kind: "rewrite"
|
|
53
|
+
} : null;
|
|
54
|
+
}
|
|
55
|
+
const appRouteTrieCache = createRouteTrieCache();
|
|
56
|
+
const pagesRouteTrieCache = createRouteTrieCache();
|
|
57
|
+
/**
|
|
58
|
+
* Build a `/`-joined pattern from a manifest's `patternParts`. Mirrors the
|
|
59
|
+
* server-side route-graph shape (`{ pattern: string }`) so the
|
|
60
|
+
* `compareHybridRoutePatterns` segment-rank comparator can score both Pages
|
|
61
|
+
* and App patterns. The
|
|
62
|
+
* `patternParts` array never includes an empty string for the static `/`
|
|
63
|
+
* route (the App catch-all handles the bare path), so the simple join is
|
|
64
|
+
* safe for everything the route trie actually matches.
|
|
65
|
+
*/
|
|
66
|
+
function patternFromParts(parts) {
|
|
67
|
+
return "/" + parts.join("/");
|
|
68
|
+
}
|
|
69
|
+
function resolveSameOriginPathname(href, basePath) {
|
|
70
|
+
if (typeof window === "undefined") return null;
|
|
71
|
+
let url;
|
|
72
|
+
try {
|
|
73
|
+
url = new URL(href, window.location.href);
|
|
74
|
+
} catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
if (url.origin !== window.location.origin) return null;
|
|
78
|
+
const pathname = stripBasePath(url.pathname, basePath);
|
|
79
|
+
const locale = getLocalePathPrefix(pathname, window.__VINEXT_LOCALES__);
|
|
80
|
+
if (!locale) return pathname;
|
|
81
|
+
const localePrefixLength = locale.length + 1;
|
|
82
|
+
return pathname.length === localePrefixLength ? "/" : pathname.slice(localePrefixLength);
|
|
83
|
+
}
|
|
84
|
+
function matchAppRoute(href, basePath, routes) {
|
|
85
|
+
const pathname = resolveSameOriginPathname(href, basePath);
|
|
86
|
+
if (pathname === null) return null;
|
|
87
|
+
return matchRouteWithTrie(pathname, routes, appRouteTrieCache)?.route ?? null;
|
|
88
|
+
}
|
|
89
|
+
function matchPagesRoute(href, basePath, routes) {
|
|
90
|
+
const pathname = resolveSameOriginPathname(href, basePath);
|
|
91
|
+
if (pathname === null) return null;
|
|
92
|
+
return matchRouteWithTrie(pathname, routes, pagesRouteTrieCache)?.route ?? null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Decide which router should own a soft-navigated URL. Returns:
|
|
96
|
+
* - "app" → the App Router runtime handles the navigation (RSC fetch).
|
|
97
|
+
* - "pages" → Pages owns the URL; the caller must hard-navigate instead.
|
|
98
|
+
* - null → no router matched (preserves the existing 404 path).
|
|
99
|
+
*
|
|
100
|
+
* `basePath` must match what the page uses (typically `process.env.__NEXT_ROUTER_BASEPATH`).
|
|
101
|
+
*
|
|
102
|
+
* The lookup uses the App and Pages manifests on `window` so the same
|
|
103
|
+
* matcher trie produces the same result the server will see when the
|
|
104
|
+
* request lands.
|
|
105
|
+
*/
|
|
106
|
+
function resolveHybridClientRouteOwner(href, basePath) {
|
|
107
|
+
if (typeof window === "undefined") return null;
|
|
108
|
+
const appRoutes = window.__VINEXT_LINK_PREFETCH_ROUTES__;
|
|
109
|
+
const pagesRoutes = window.__VINEXT_PAGES_LINK_PREFETCH_ROUTES__;
|
|
110
|
+
const rewrites = window.__VINEXT_CLIENT_REWRITES__;
|
|
111
|
+
if (rewrites) {
|
|
112
|
+
const beforeFilesRewrite = resolveClientRewrite(href, basePath, rewrites.beforeFiles, true);
|
|
113
|
+
if (beforeFilesRewrite?.kind === "document") return "document";
|
|
114
|
+
if (beforeFilesRewrite?.kind === "rewrite") href = beforeFilesRewrite.href;
|
|
115
|
+
}
|
|
116
|
+
let appMatch = appRoutes ? matchAppRoute(href, basePath, appRoutes) : null;
|
|
117
|
+
let pagesMatch = pagesRoutes ? matchPagesRoute(href, basePath, pagesRoutes) : null;
|
|
118
|
+
if (rewrites && (appMatch === null || appMatch.isDynamic) && (pagesMatch === null || pagesMatch.isDynamic)) for (const rewrite of rewrites.afterFiles) {
|
|
119
|
+
const afterFilesRewrite = resolveClientRewrite(href, basePath, [rewrite]);
|
|
120
|
+
if (afterFilesRewrite?.kind === "document") return "document";
|
|
121
|
+
if (afterFilesRewrite?.kind !== "rewrite") continue;
|
|
122
|
+
href = afterFilesRewrite.href;
|
|
123
|
+
appMatch = appRoutes ? matchAppRoute(href, basePath, appRoutes) : null;
|
|
124
|
+
pagesMatch = pagesRoutes ? matchPagesRoute(href, basePath, pagesRoutes) : null;
|
|
125
|
+
if (appMatch || pagesMatch) break;
|
|
126
|
+
}
|
|
127
|
+
if (rewrites && appMatch === null && pagesMatch === null) for (const rewrite of rewrites.fallback) {
|
|
128
|
+
const fallbackRewrite = resolveClientRewrite(href, basePath, [rewrite]);
|
|
129
|
+
if (fallbackRewrite?.kind === "document") return "document";
|
|
130
|
+
if (fallbackRewrite?.kind !== "rewrite") continue;
|
|
131
|
+
href = fallbackRewrite.href;
|
|
132
|
+
appMatch = appRoutes ? matchAppRoute(href, basePath, appRoutes) : null;
|
|
133
|
+
pagesMatch = pagesRoutes ? matchPagesRoute(href, basePath, pagesRoutes) : null;
|
|
134
|
+
if (appMatch || pagesMatch) break;
|
|
135
|
+
}
|
|
136
|
+
if (appMatch === null && pagesMatch === null) return null;
|
|
137
|
+
if (pagesMatch === null) return appMatch.documentOnly ? "document" : "app";
|
|
138
|
+
if (appMatch === null) return pagesMatch.documentOnly ? "document" : "pages";
|
|
139
|
+
const owner = compareHybridRoutePatterns(patternFromParts(pagesMatch.patternParts), pagesMatch.isDynamic, patternFromParts(appMatch.patternParts), appMatch.isDynamic);
|
|
140
|
+
return (owner === "app" ? appMatch : pagesMatch).documentOnly ? "document" : owner;
|
|
141
|
+
}
|
|
142
|
+
//#endregion
|
|
143
|
+
export { resolveHybridClientRouteOwner };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//#region src/shims/internal/navigation-untracked.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Internal navigation-untracked pathname hook.
|
|
4
|
+
*
|
|
5
|
+
* Used by `unstable_catchError` error boundaries to avoid subscribing to
|
|
6
|
+
* pathname changes. This is NOT part of the public `next/navigation` API.
|
|
7
|
+
*
|
|
8
|
+
* Ported from Next.js:
|
|
9
|
+
* https://github.com/vercel/next.js/blob/v16.2.6/packages/next/src/client/components/navigation-untracked.ts
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Returns the current pathname without registering it as a tracked render
|
|
13
|
+
* dependency. Unlike `usePathname()`, this does not use `useSyncExternalStore`
|
|
14
|
+
* and therefore does not cause the component to re-render on navigation.
|
|
15
|
+
*
|
|
16
|
+
* Server: returns the pathname from context, or `"/"` when no navigation context
|
|
17
|
+
* is available (the client will hydrate with the real value). The `"/"` fallback
|
|
18
|
+
* deliberately matches vinext's `usePathname()` behavior rather than Next.js's
|
|
19
|
+
* null context default. Returns `null` only when the render is a missing-params
|
|
20
|
+
* shell — vinext does not yet implement fallback-route-param detection, so this
|
|
21
|
+
* path is not currently reachable.
|
|
22
|
+
*
|
|
23
|
+
* Client: prefers the render snapshot **only during an active navigation**
|
|
24
|
+
* transition (`navigationSnapshotActiveCount > 0`) so the hook returns the
|
|
25
|
+
* pending URL, not the stale committed one. After commit, falls back to the
|
|
26
|
+
* cached pathname so user `pushState`/`replaceState` calls are immediately
|
|
27
|
+
* reflected.
|
|
28
|
+
*
|
|
29
|
+
* Used by `unstable_catchError` error boundaries to avoid unnecessary re-renders.
|
|
30
|
+
*
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
declare function useUntrackedPathname(): string | null;
|
|
34
|
+
//#endregion
|
|
35
|
+
export { useUntrackedPathname };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { getPagesNavigationContext } from "./pages-router-accessor.js";
|
|
2
|
+
import { getClientNavigationState, getNavigationContext, useClientNavigationRenderSnapshot } from "../navigation.js";
|
|
3
|
+
//#region src/shims/internal/navigation-untracked.ts
|
|
4
|
+
/**
|
|
5
|
+
* Internal navigation-untracked pathname hook.
|
|
6
|
+
*
|
|
7
|
+
* Used by `unstable_catchError` error boundaries to avoid subscribing to
|
|
8
|
+
* pathname changes. This is NOT part of the public `next/navigation` API.
|
|
9
|
+
*
|
|
10
|
+
* Ported from Next.js:
|
|
11
|
+
* https://github.com/vercel/next.js/blob/v16.2.6/packages/next/src/client/components/navigation-untracked.ts
|
|
12
|
+
*/
|
|
13
|
+
const isServer = typeof window === "undefined";
|
|
14
|
+
function getPathnameSnapshot() {
|
|
15
|
+
const pagesCtx = getPagesNavigationContext();
|
|
16
|
+
if (pagesCtx) return pagesCtx.pathname;
|
|
17
|
+
return getClientNavigationState()?.cachedPathname ?? "/";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns the current pathname without registering it as a tracked render
|
|
21
|
+
* dependency. Unlike `usePathname()`, this does not use `useSyncExternalStore`
|
|
22
|
+
* and therefore does not cause the component to re-render on navigation.
|
|
23
|
+
*
|
|
24
|
+
* Server: returns the pathname from context, or `"/"` when no navigation context
|
|
25
|
+
* is available (the client will hydrate with the real value). The `"/"` fallback
|
|
26
|
+
* deliberately matches vinext's `usePathname()` behavior rather than Next.js's
|
|
27
|
+
* null context default. Returns `null` only when the render is a missing-params
|
|
28
|
+
* shell — vinext does not yet implement fallback-route-param detection, so this
|
|
29
|
+
* path is not currently reachable.
|
|
30
|
+
*
|
|
31
|
+
* Client: prefers the render snapshot **only during an active navigation**
|
|
32
|
+
* transition (`navigationSnapshotActiveCount > 0`) so the hook returns the
|
|
33
|
+
* pending URL, not the stale committed one. After commit, falls back to the
|
|
34
|
+
* cached pathname so user `pushState`/`replaceState` calls are immediately
|
|
35
|
+
* reflected.
|
|
36
|
+
*
|
|
37
|
+
* Used by `unstable_catchError` error boundaries to avoid unnecessary re-renders.
|
|
38
|
+
*
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
function useUntrackedPathname() {
|
|
42
|
+
if (isServer) {
|
|
43
|
+
const ctx = getNavigationContext();
|
|
44
|
+
if (ctx) return ctx.pathname;
|
|
45
|
+
const pagesCtx = getPagesNavigationContext();
|
|
46
|
+
return pagesCtx ? pagesCtx.pathname : "/";
|
|
47
|
+
}
|
|
48
|
+
const renderSnapshot = useClientNavigationRenderSnapshot();
|
|
49
|
+
if (renderSnapshot && (getClientNavigationState()?.navigationSnapshotActiveCount ?? 0) > 0) return renderSnapshot.pathname;
|
|
50
|
+
const pagesCtx = getPagesNavigationContext();
|
|
51
|
+
if (pagesCtx) return pagesCtx.pathname;
|
|
52
|
+
return getPathnameSnapshot();
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { useUntrackedPathname };
|
|
@@ -24,19 +24,18 @@
|
|
|
24
24
|
* directly by anyone, which keeps subsequent clones legal even after one
|
|
25
25
|
* caller has consumed its copy.
|
|
26
26
|
*
|
|
27
|
-
* -
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* handled by the caller's `assertStillCurrent()` checkpoints after `await`,
|
|
32
|
-
* not by abort propagation.
|
|
27
|
+
* - Each caller owns one waiter. Cancelling a waiter leaves the shared request
|
|
28
|
+
* alive while another waiter remains; cancelling the final waiter aborts the
|
|
29
|
+
* underlying fetch and evicts the entry immediately so a replacement caller
|
|
30
|
+
* can retry without joining a doomed request.
|
|
33
31
|
*
|
|
34
32
|
* - The map is module-scoped (one per realm). The Pages Router runs in the
|
|
35
33
|
* browser only, so a single `Map` is sufficient.
|
|
36
34
|
*/
|
|
37
35
|
/**
|
|
38
36
|
* Dedupe a `fetch()` against the `_next/data` endpoint. Multiple concurrent
|
|
39
|
-
* callers for the same
|
|
37
|
+
* callers for the same resolved URL and deployment ID share one underlying
|
|
38
|
+
* network request.
|
|
40
39
|
*
|
|
41
40
|
* Each call returns a freshly-cloned `Response` so consumers can read the
|
|
42
41
|
* body independently. Once the in-flight Promise settles (resolve or reject)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "../../utils/deployment-id.js";
|
|
1
2
|
//#region src/shims/internal/pages-data-fetch-dedup.ts
|
|
2
3
|
/**
|
|
3
4
|
* In-flight request dedup for the Pages Router `/_next/data/<id>/<page>.json`
|
|
@@ -24,21 +25,57 @@
|
|
|
24
25
|
* directly by anyone, which keeps subsequent clones legal even after one
|
|
25
26
|
* caller has consumed its copy.
|
|
26
27
|
*
|
|
27
|
-
* -
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* handled by the caller's `assertStillCurrent()` checkpoints after `await`,
|
|
32
|
-
* not by abort propagation.
|
|
28
|
+
* - Each caller owns one waiter. Cancelling a waiter leaves the shared request
|
|
29
|
+
* alive while another waiter remains; cancelling the final waiter aborts the
|
|
30
|
+
* underlying fetch and evicts the entry immediately so a replacement caller
|
|
31
|
+
* can retry without joining a doomed request.
|
|
33
32
|
*
|
|
34
33
|
* - The map is module-scoped (one per realm). The Pages Router runs in the
|
|
35
34
|
* browser only, so a single `Map` is sufficient.
|
|
36
35
|
*/
|
|
37
|
-
/** Inflight fetch
|
|
36
|
+
/** Inflight fetch entries keyed by the resolved data request identity. */
|
|
38
37
|
const inflight = /* @__PURE__ */ new Map();
|
|
38
|
+
function getInflightKey(dataHref, init) {
|
|
39
|
+
let resolvedHref = dataHref;
|
|
40
|
+
if (typeof window !== "undefined") try {
|
|
41
|
+
resolvedHref = new URL(dataHref, window.location.href).href;
|
|
42
|
+
} catch {}
|
|
43
|
+
const deploymentId = new Headers(init?.headers).get("x-deployment-id") ?? "";
|
|
44
|
+
return `${resolvedHref}\n${deploymentId}`;
|
|
45
|
+
}
|
|
46
|
+
function cloneSharedResponse(key, entry, signal) {
|
|
47
|
+
entry.waiters += 1;
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
let released = false;
|
|
50
|
+
const release = (cancelled) => {
|
|
51
|
+
if (released) return;
|
|
52
|
+
released = true;
|
|
53
|
+
entry.waiters -= 1;
|
|
54
|
+
if (cancelled && entry.waiters === 0 && !entry.settled) {
|
|
55
|
+
if (inflight.get(key) === entry) inflight.delete(key);
|
|
56
|
+
entry.controller.abort();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const abort = () => {
|
|
60
|
+
release(true);
|
|
61
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
62
|
+
};
|
|
63
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
64
|
+
entry.promise.then((response) => {
|
|
65
|
+
signal?.removeEventListener("abort", abort);
|
|
66
|
+
release(false);
|
|
67
|
+
resolve(response.clone());
|
|
68
|
+
}, (error) => {
|
|
69
|
+
signal?.removeEventListener("abort", abort);
|
|
70
|
+
release(false);
|
|
71
|
+
reject(error);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
39
75
|
/**
|
|
40
76
|
* Dedupe a `fetch()` against the `_next/data` endpoint. Multiple concurrent
|
|
41
|
-
* callers for the same
|
|
77
|
+
* callers for the same resolved URL and deployment ID share one underlying
|
|
78
|
+
* network request.
|
|
42
79
|
*
|
|
43
80
|
* Each call returns a freshly-cloned `Response` so consumers can read the
|
|
44
81
|
* body independently. Once the in-flight Promise settles (resolve or reject)
|
|
@@ -48,20 +85,36 @@ const inflight = /* @__PURE__ */ new Map();
|
|
|
48
85
|
* dropped on failure so the next navigation can retry.
|
|
49
86
|
*/
|
|
50
87
|
function dedupedPagesDataFetch(dataHref, init) {
|
|
51
|
-
|
|
88
|
+
const key = getInflightKey(dataHref, init);
|
|
89
|
+
const signal = init?.signal ?? void 0;
|
|
90
|
+
if (signal?.aborted) return Promise.reject(new DOMException("Aborted", "AbortError"));
|
|
91
|
+
let entry = inflight.get(key);
|
|
52
92
|
if (!entry) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
93
|
+
const controller = new AbortController();
|
|
94
|
+
let currentEntry;
|
|
95
|
+
currentEntry = {
|
|
96
|
+
controller,
|
|
97
|
+
promise: fetch(dataHref, {
|
|
98
|
+
...init,
|
|
99
|
+
signal: controller.signal
|
|
100
|
+
}).finally(() => {
|
|
101
|
+
currentEntry.settled = true;
|
|
102
|
+
if (inflight.get(key) === currentEntry) inflight.delete(key);
|
|
103
|
+
}),
|
|
104
|
+
settled: false,
|
|
105
|
+
waiters: 0
|
|
106
|
+
};
|
|
107
|
+
inflight.set(key, currentEntry);
|
|
108
|
+
entry = currentEntry;
|
|
57
109
|
}
|
|
58
|
-
return
|
|
110
|
+
return cloneSharedResponse(key, entry, signal);
|
|
59
111
|
}
|
|
60
112
|
/**
|
|
61
113
|
* Drop every cached in-flight entry. Intended for tests; production code
|
|
62
114
|
* does not need to call this because entries self-evict on settle.
|
|
63
115
|
*/
|
|
64
116
|
function clearPagesDataInflight() {
|
|
117
|
+
for (const entry of inflight.values()) entry.controller.abort();
|
|
65
118
|
inflight.clear();
|
|
66
119
|
}
|
|
67
120
|
//#endregion
|
|
@@ -43,10 +43,15 @@ type PagesDataTarget = {
|
|
|
43
43
|
*/
|
|
44
44
|
declare function resolvePagesDataNavigationTarget(browserUrl: string, basePath: string): PagesDataTarget | null;
|
|
45
45
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
46
|
+
* Prefetch the data JSON and kick off the code-split loader so the chunk is
|
|
47
|
+
* warm by the time the user clicks.
|
|
48
48
|
*
|
|
49
49
|
* Used by both `Router.prefetch()` and `<Link>` hover/viewport prefetch. The
|
|
50
|
+
* JSON request uses `fetch()` rather than `<link rel="prefetch">` so it can
|
|
51
|
+
* carry Next.js's `x-deployment-id` skew-protection header. The in-flight
|
|
52
|
+
* request is shared with a racing navigation; after it settles, the browser's
|
|
53
|
+
* normal HTTP cache remains responsible for reuse.
|
|
54
|
+
*
|
|
50
55
|
* loader's returned Promise is intentionally discarded — `import()` caches the
|
|
51
56
|
* result, so a subsequent navigation re-invocation hits the cache without
|
|
52
57
|
* paying for a second round trip. Errors are swallowed: prefetch is
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { stripBasePath } from "../../utils/base-path.js";
|
|
2
2
|
import { getLocalePathPrefix } from "../../utils/domain-locale.js";
|
|
3
3
|
import { buildPagesDataHref, matchPagesPattern } from "./pages-data-url.js";
|
|
4
|
+
import { NEXT_DEPLOYMENT_ID_HEADER, getDeploymentId } from "../../utils/deployment-id.js";
|
|
5
|
+
import { dedupedPagesDataFetch } from "./pages-data-fetch-dedup.js";
|
|
4
6
|
//#region src/shims/internal/pages-data-target.ts
|
|
5
7
|
/**
|
|
6
8
|
* Shared decision helper for the Pages Router `/_next/data/<id>/<page>.json`
|
|
@@ -66,10 +68,15 @@ function resolvePagesDataNavigationTarget(browserUrl, basePath) {
|
|
|
66
68
|
};
|
|
67
69
|
}
|
|
68
70
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
+
* Prefetch the data JSON and kick off the code-split loader so the chunk is
|
|
72
|
+
* warm by the time the user clicks.
|
|
71
73
|
*
|
|
72
74
|
* Used by both `Router.prefetch()` and `<Link>` hover/viewport prefetch. The
|
|
75
|
+
* JSON request uses `fetch()` rather than `<link rel="prefetch">` so it can
|
|
76
|
+
* carry Next.js's `x-deployment-id` skew-protection header. The in-flight
|
|
77
|
+
* request is shared with a racing navigation; after it settles, the browser's
|
|
78
|
+
* normal HTTP cache remains responsible for reuse.
|
|
79
|
+
*
|
|
73
80
|
* loader's returned Promise is intentionally discarded — `import()` caches the
|
|
74
81
|
* result, so a subsequent navigation re-invocation hits the cache without
|
|
75
82
|
* paying for a second round trip. Errors are swallowed: prefetch is
|
|
@@ -77,12 +84,14 @@ function resolvePagesDataNavigationTarget(browserUrl, basePath) {
|
|
|
77
84
|
*/
|
|
78
85
|
function prefetchPagesData(target) {
|
|
79
86
|
if (typeof document === "undefined") return;
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
const headers = {
|
|
88
|
+
Accept: "application/json",
|
|
89
|
+
purpose: "prefetch",
|
|
90
|
+
"x-nextjs-data": "1"
|
|
91
|
+
};
|
|
92
|
+
const deploymentId = getDeploymentId();
|
|
93
|
+
if (deploymentId) headers[NEXT_DEPLOYMENT_ID_HEADER] = deploymentId;
|
|
94
|
+
dedupedPagesDataFetch(target.dataHref, { headers }).catch(() => {});
|
|
86
95
|
target.loader().catch(() => {});
|
|
87
96
|
}
|
|
88
97
|
//#endregion
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/shims/internal/pages-router-accessor.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shared Pages Router navigation accessor.
|
|
4
|
+
*
|
|
5
|
+
* Both `next/navigation` (usePathname/useParams/useSearchParams) and the
|
|
6
|
+
* internal `useUntrackedPathname` read from the same global Symbol. Keeping
|
|
7
|
+
* the lookup in one place avoids the Symbol string and the error-handling
|
|
8
|
+
* shape from drifting across modules.
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
type PagesNavigationContext = {
|
|
13
|
+
pathname: string | null;
|
|
14
|
+
searchParams: URLSearchParams;
|
|
15
|
+
params: Record<string, string | string[]> | null;
|
|
16
|
+
};
|
|
17
|
+
declare function getPagesNavigationContext(): PagesNavigationContext | null;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { PagesNavigationContext, getPagesNavigationContext };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/shims/internal/pages-router-accessor.ts
|
|
2
|
+
const PAGES_NAVIGATION_ACCESSOR_KEY = Symbol.for("vinext.navigation.pagesNavigationContextAccessor");
|
|
3
|
+
function getPagesNavigationContext() {
|
|
4
|
+
const accessor = globalThis[PAGES_NAVIGATION_ACCESSOR_KEY];
|
|
5
|
+
if (!accessor) return null;
|
|
6
|
+
try {
|
|
7
|
+
return accessor();
|
|
8
|
+
} catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { getPagesNavigationContext };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NextRouter } from "../router.js";
|
|
2
|
+
import { Context } from "react";
|
|
2
3
|
|
|
3
4
|
//#region src/shims/internal/router-context.d.ts
|
|
4
|
-
declare const RouterContext:
|
|
5
|
+
declare const RouterContext: Context<NextRouter | null>;
|
|
5
6
|
//#endregion
|
|
6
7
|
export { RouterContext };
|
|
@@ -6,6 +6,8 @@ import { createContext } from "react";
|
|
|
6
6
|
* Used by: some testing utilities and older libraries.
|
|
7
7
|
* Provides the Pages Router context.
|
|
8
8
|
*/
|
|
9
|
-
const
|
|
9
|
+
const ROUTER_CONTEXT_KEY = Symbol.for("vinext.routerContext");
|
|
10
|
+
const globalState = globalThis;
|
|
11
|
+
const RouterContext = globalState[ROUTER_CONTEXT_KEY] ?? (globalState[ROUTER_CONTEXT_KEY] = createContext(null));
|
|
10
12
|
//#endregion
|
|
11
13
|
export { RouterContext };
|