vinext 0.1.1 → 0.1.3

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.
Files changed (266) hide show
  1. package/README.md +2 -5
  2. package/dist/build/client-build-config.d.ts +7 -1
  3. package/dist/build/client-build-config.js +9 -1
  4. package/dist/build/prerender.d.ts +9 -1
  5. package/dist/build/prerender.js +41 -12
  6. package/dist/build/run-prerender.d.ts +10 -2
  7. package/dist/build/run-prerender.js +15 -1
  8. package/dist/check.js +4 -3
  9. package/dist/client/app-nav-failure-handler.d.ts +8 -0
  10. package/dist/client/app-nav-failure-handler.js +44 -0
  11. package/dist/client/navigation-runtime.d.ts +3 -2
  12. package/dist/client/vinext-next-data.d.ts +18 -1
  13. package/dist/client/window-next.d.ts +8 -5
  14. package/dist/client/window-next.js +12 -1
  15. package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
  16. package/dist/config/config-matchers.d.ts +11 -4
  17. package/dist/config/config-matchers.js +88 -16
  18. package/dist/config/next-config.d.ts +59 -4
  19. package/dist/config/next-config.js +149 -48
  20. package/dist/deploy.d.ts +30 -11
  21. package/dist/deploy.js +189 -101
  22. package/dist/entries/app-browser-entry.d.ts +9 -3
  23. package/dist/entries/app-browser-entry.js +21 -3
  24. package/dist/entries/app-rsc-entry.d.ts +2 -0
  25. package/dist/entries/app-rsc-entry.js +71 -6
  26. package/dist/entries/app-rsc-manifest.js +2 -0
  27. package/dist/entries/app-ssr-entry.js +1 -1
  28. package/dist/entries/pages-client-entry.js +54 -9
  29. package/dist/entries/pages-server-entry.js +48 -11
  30. package/dist/index.d.ts +0 -2
  31. package/dist/index.js +285 -139
  32. package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
  33. package/dist/plugins/dynamic-preload-metadata.js +415 -0
  34. package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
  35. package/dist/plugins/extensionless-dynamic-import.js +152 -0
  36. package/dist/plugins/og-assets.js +2 -2
  37. package/dist/plugins/optimize-imports.d.ts +10 -5
  38. package/dist/plugins/optimize-imports.js +27 -21
  39. package/dist/plugins/postcss.js +7 -7
  40. package/dist/plugins/sass.d.ts +53 -24
  41. package/dist/plugins/sass.js +249 -1
  42. package/dist/plugins/typeof-window.d.ts +14 -0
  43. package/dist/plugins/typeof-window.js +150 -0
  44. package/dist/plugins/wasm-module-import.d.ts +15 -0
  45. package/dist/plugins/wasm-module-import.js +50 -0
  46. package/dist/routing/app-route-graph.d.ts +25 -2
  47. package/dist/routing/app-route-graph.js +91 -22
  48. package/dist/routing/file-matcher.d.ts +10 -1
  49. package/dist/routing/file-matcher.js +23 -2
  50. package/dist/routing/pages-router.js +3 -3
  51. package/dist/routing/utils.d.ts +35 -6
  52. package/dist/routing/utils.js +59 -7
  53. package/dist/server/api-handler.d.ts +6 -1
  54. package/dist/server/api-handler.js +21 -15
  55. package/dist/server/app-browser-action-result.d.ts +19 -6
  56. package/dist/server/app-browser-action-result.js +19 -10
  57. package/dist/server/app-browser-entry.js +269 -297
  58. package/dist/server/app-browser-error.d.ts +10 -3
  59. package/dist/server/app-browser-error.js +47 -6
  60. package/dist/server/app-browser-history-controller.d.ts +104 -0
  61. package/dist/server/app-browser-history-controller.js +210 -0
  62. package/dist/server/app-browser-hydration.d.ts +2 -0
  63. package/dist/server/app-browser-hydration.js +1 -0
  64. package/dist/server/app-browser-navigation-controller.d.ts +7 -4
  65. package/dist/server/app-browser-navigation-controller.js +33 -9
  66. package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
  67. package/dist/server/app-browser-rsc-redirect.js +30 -8
  68. package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
  69. package/dist/server/app-browser-server-action-navigation.js +9 -0
  70. package/dist/server/app-browser-state.js +4 -7
  71. package/dist/server/app-browser-stream.js +86 -43
  72. package/dist/server/app-browser-visible-commit.js +1 -1
  73. package/dist/server/app-elements-wire.d.ts +6 -1
  74. package/dist/server/app-elements-wire.js +14 -4
  75. package/dist/server/app-elements.d.ts +2 -2
  76. package/dist/server/app-elements.js +2 -2
  77. package/dist/server/app-fallback-renderer.d.ts +3 -1
  78. package/dist/server/app-fallback-renderer.js +6 -2
  79. package/dist/server/app-middleware.js +1 -0
  80. package/dist/server/app-optimistic-routing.js +24 -3
  81. package/dist/server/app-page-boundary-render.d.ts +3 -1
  82. package/dist/server/app-page-boundary-render.js +31 -16
  83. package/dist/server/app-page-cache-render.d.ts +53 -0
  84. package/dist/server/app-page-cache-render.js +91 -0
  85. package/dist/server/app-page-cache.d.ts +16 -2
  86. package/dist/server/app-page-cache.js +71 -8
  87. package/dist/server/app-page-dispatch.d.ts +34 -0
  88. package/dist/server/app-page-dispatch.js +167 -97
  89. package/dist/server/app-page-element-builder.d.ts +23 -2
  90. package/dist/server/app-page-element-builder.js +42 -10
  91. package/dist/server/app-page-execution.d.ts +7 -2
  92. package/dist/server/app-page-execution.js +53 -18
  93. package/dist/server/app-page-probe.d.ts +1 -0
  94. package/dist/server/app-page-probe.js +4 -0
  95. package/dist/server/app-page-render-observation.d.ts +3 -1
  96. package/dist/server/app-page-render-observation.js +17 -1
  97. package/dist/server/app-page-render.d.ts +13 -2
  98. package/dist/server/app-page-render.js +48 -17
  99. package/dist/server/app-page-request.d.ts +3 -0
  100. package/dist/server/app-page-request.js +5 -3
  101. package/dist/server/app-page-response.js +1 -1
  102. package/dist/server/app-page-route-wiring.d.ts +5 -1
  103. package/dist/server/app-page-route-wiring.js +21 -11
  104. package/dist/server/app-page-stream.d.ts +16 -9
  105. package/dist/server/app-page-stream.js +12 -9
  106. package/dist/server/app-pages-bridge.d.ts +18 -0
  107. package/dist/server/app-pages-bridge.js +22 -5
  108. package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
  109. package/dist/server/app-ppr-fallback-shell-render.js +26 -0
  110. package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
  111. package/dist/server/app-ppr-fallback-shell.js +8 -1
  112. package/dist/server/app-route-handler-dispatch.js +9 -2
  113. package/dist/server/app-route-handler-policy.d.ts +1 -0
  114. package/dist/server/app-route-handler-response.js +11 -10
  115. package/dist/server/app-route-handler-runtime.js +12 -1
  116. package/dist/server/app-router-entry.js +5 -0
  117. package/dist/server/app-rsc-cache-busting.js +2 -0
  118. package/dist/server/app-rsc-handler.d.ts +25 -0
  119. package/dist/server/app-rsc-handler.js +153 -53
  120. package/dist/server/app-rsc-response-finalizer.js +1 -1
  121. package/dist/server/app-rsc-route-matching.d.ts +3 -0
  122. package/dist/server/app-rsc-route-matching.js +2 -0
  123. package/dist/server/app-segment-config.d.ts +9 -1
  124. package/dist/server/app-segment-config.js +12 -3
  125. package/dist/server/app-server-action-execution.d.ts +12 -0
  126. package/dist/server/app-server-action-execution.js +47 -15
  127. package/dist/server/app-ssr-entry.d.ts +2 -0
  128. package/dist/server/app-ssr-entry.js +81 -8
  129. package/dist/server/app-ssr-stream.js +9 -1
  130. package/dist/server/cache-control.js +4 -0
  131. package/dist/server/dev-lockfile.js +2 -1
  132. package/dist/server/dev-server.d.ts +2 -2
  133. package/dist/server/dev-server.js +287 -63
  134. package/dist/server/headers.d.ts +8 -1
  135. package/dist/server/headers.js +8 -1
  136. package/dist/server/hybrid-route-priority.d.ts +22 -0
  137. package/dist/server/hybrid-route-priority.js +33 -0
  138. package/dist/server/image-optimization.d.ts +18 -9
  139. package/dist/server/image-optimization.js +37 -23
  140. package/dist/server/implicit-tags.d.ts +2 -1
  141. package/dist/server/implicit-tags.js +4 -1
  142. package/dist/server/instrumentation-runtime.d.ts +6 -0
  143. package/dist/server/instrumentation-runtime.js +8 -0
  144. package/dist/server/isr-decision.d.ts +79 -0
  145. package/dist/server/isr-decision.js +70 -0
  146. package/dist/server/metadata-route-response.js +5 -3
  147. package/dist/server/middleware-runtime.d.ts +13 -0
  148. package/dist/server/middleware-runtime.js +11 -7
  149. package/dist/server/middleware.js +1 -0
  150. package/dist/server/navigation-planner.d.ts +186 -22
  151. package/dist/server/navigation-planner.js +302 -0
  152. package/dist/server/navigation-trace.d.ts +18 -1
  153. package/dist/server/navigation-trace.js +18 -1
  154. package/dist/server/normalize-path.d.ts +0 -8
  155. package/dist/server/normalize-path.js +3 -1
  156. package/dist/server/otel-tracer-extension.d.ts +45 -0
  157. package/dist/server/otel-tracer-extension.js +89 -0
  158. package/dist/server/pages-api-route.d.ts +20 -3
  159. package/dist/server/pages-api-route.js +19 -3
  160. package/dist/server/pages-asset-tags.d.ts +16 -4
  161. package/dist/server/pages-asset-tags.js +22 -12
  162. package/dist/server/pages-data-route.d.ts +8 -1
  163. package/dist/server/pages-data-route.js +16 -3
  164. package/dist/server/pages-get-initial-props.d.ts +54 -4
  165. package/dist/server/pages-get-initial-props.js +43 -1
  166. package/dist/server/pages-node-compat.d.ts +3 -11
  167. package/dist/server/pages-node-compat.js +175 -122
  168. package/dist/server/pages-page-data.d.ts +39 -2
  169. package/dist/server/pages-page-data.js +261 -46
  170. package/dist/server/pages-page-handler.d.ts +5 -2
  171. package/dist/server/pages-page-handler.js +78 -25
  172. package/dist/server/pages-page-response.d.ts +47 -2
  173. package/dist/server/pages-page-response.js +73 -9
  174. package/dist/server/pages-readiness.d.ts +1 -1
  175. package/dist/server/pages-request-pipeline.d.ts +16 -1
  176. package/dist/server/pages-request-pipeline.js +96 -38
  177. package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
  178. package/dist/server/pregenerated-concrete-paths.js +2 -19
  179. package/dist/server/prerender-manifest.d.ts +33 -0
  180. package/dist/server/prerender-manifest.js +54 -0
  181. package/dist/server/prerender-route-params.d.ts +1 -2
  182. package/dist/server/prod-server.d.ts +39 -1
  183. package/dist/server/prod-server.js +107 -37
  184. package/dist/server/request-pipeline.d.ts +3 -15
  185. package/dist/server/request-pipeline.js +58 -47
  186. package/dist/server/rsc-stream-hints.d.ts +5 -1
  187. package/dist/server/rsc-stream-hints.js +6 -1
  188. package/dist/server/seed-cache.js +10 -18
  189. package/dist/shims/app-router-scroll-state.d.ts +3 -1
  190. package/dist/shims/app-router-scroll-state.js +14 -2
  191. package/dist/shims/app-router-scroll.d.ts +3 -0
  192. package/dist/shims/app-router-scroll.js +28 -18
  193. package/dist/shims/cache-runtime.js +12 -4
  194. package/dist/shims/cache.d.ts +1 -0
  195. package/dist/shims/cache.js +1 -1
  196. package/dist/shims/cdn-cache.d.ts +5 -5
  197. package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
  198. package/dist/shims/dynamic-preload-chunks.js +79 -0
  199. package/dist/shims/dynamic.d.ts +4 -0
  200. package/dist/shims/dynamic.js +4 -2
  201. package/dist/shims/error-boundary.d.ts +6 -4
  202. package/dist/shims/error-boundary.js +7 -0
  203. package/dist/shims/error.js +38 -11
  204. package/dist/shims/error.react-server.d.ts +9 -0
  205. package/dist/shims/error.react-server.js +6 -0
  206. package/dist/shims/fetch-cache.d.ts +11 -1
  207. package/dist/shims/fetch-cache.js +55 -20
  208. package/dist/shims/hash-scroll.js +6 -1
  209. package/dist/shims/head.js +6 -1
  210. package/dist/shims/headers.d.ts +16 -2
  211. package/dist/shims/headers.js +66 -5
  212. package/dist/shims/image-config.js +7 -1
  213. package/dist/shims/internal/als-registry.js +28 -1
  214. package/dist/shims/internal/app-route-detection.d.ts +6 -3
  215. package/dist/shims/internal/app-route-detection.js +18 -23
  216. package/dist/shims/internal/app-router-context.d.ts +5 -0
  217. package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
  218. package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
  219. package/dist/shims/internal/navigation-untracked.d.ts +35 -0
  220. package/dist/shims/internal/navigation-untracked.js +55 -0
  221. package/dist/shims/internal/pages-data-target.d.ts +7 -2
  222. package/dist/shims/internal/pages-data-target.js +17 -8
  223. package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
  224. package/dist/shims/internal/pages-router-accessor.js +13 -0
  225. package/dist/shims/internal/router-context.d.ts +2 -1
  226. package/dist/shims/internal/router-context.js +3 -1
  227. package/dist/shims/link.js +12 -5
  228. package/dist/shims/metadata.d.ts +6 -2
  229. package/dist/shims/metadata.js +32 -14
  230. package/dist/shims/navigation.d.ts +14 -17
  231. package/dist/shims/navigation.js +93 -46
  232. package/dist/shims/ppr-fallback-shell.d.ts +5 -1
  233. package/dist/shims/ppr-fallback-shell.js +28 -7
  234. package/dist/shims/router.d.ts +13 -2
  235. package/dist/shims/router.js +434 -116
  236. package/dist/shims/script-nonce-context.d.ts +1 -1
  237. package/dist/shims/script-nonce-context.js +11 -3
  238. package/dist/shims/server.d.ts +33 -2
  239. package/dist/shims/server.js +75 -18
  240. package/dist/shims/slot.js +1 -1
  241. package/dist/shims/unified-request-context.js +2 -0
  242. package/dist/typegen.js +1 -0
  243. package/dist/utils/built-asset-url.d.ts +4 -0
  244. package/dist/utils/built-asset-url.js +11 -0
  245. package/dist/utils/client-build-manifest.js +15 -5
  246. package/dist/utils/client-runtime-metadata.d.ts +45 -0
  247. package/dist/utils/client-runtime-metadata.js +63 -0
  248. package/dist/utils/commonjs-loader.d.ts +16 -0
  249. package/dist/utils/commonjs-loader.js +100 -0
  250. package/dist/utils/deployment-id.d.ts +8 -0
  251. package/dist/utils/deployment-id.js +22 -0
  252. package/dist/utils/hash.d.ts +17 -1
  253. package/dist/utils/hash.js +36 -1
  254. package/dist/utils/html-limited-bots.d.ts +18 -1
  255. package/dist/utils/html-limited-bots.js +23 -1
  256. package/dist/utils/lazy-chunks.d.ts +27 -1
  257. package/dist/utils/lazy-chunks.js +65 -1
  258. package/dist/utils/manifest-paths.d.ts +20 -2
  259. package/dist/utils/manifest-paths.js +38 -3
  260. package/dist/utils/parse-cookie.d.ts +13 -0
  261. package/dist/utils/parse-cookie.js +52 -0
  262. package/dist/utils/path.d.ts +8 -1
  263. package/dist/utils/path.js +13 -1
  264. package/package.json +2 -2
  265. package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
  266. package/dist/shims/internal/parse-cookie-header.js +0 -30
@@ -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 };
@@ -43,10 +43,15 @@ type PagesDataTarget = {
43
43
  */
44
44
  declare function resolvePagesDataNavigationTarget(browserUrl: string, basePath: string): PagesDataTarget | null;
45
45
  /**
46
- * Inject a `<link rel="prefetch">` for the data JSON and kick off the
47
- * code-split loader so the chunk is warm by the time the user clicks.
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 { dedupedPagesDataFetch } from "./pages-data-fetch-dedup.js";
5
+ import { NEXT_DEPLOYMENT_ID_HEADER, getDeploymentId } from "../../utils/deployment-id.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
- * Inject a `<link rel="prefetch">` for the data JSON and kick off the
70
- * code-split loader so the chunk is warm by the time the user clicks.
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 link = document.createElement("link");
81
- link.rel = "prefetch";
82
- link.as = "fetch";
83
- link.crossOrigin = "anonymous";
84
- link.href = target.dataHref;
85
- document.head.appendChild(link);
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: import("react").Context<NextRouter | null>;
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 RouterContext = createContext(null);
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 };
@@ -8,9 +8,10 @@ import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "../server/app-rsc-re
8
8
  import "../server/app-elements.js";
9
9
  import { addLocalePrefix, getDomainLocaleUrl } from "../utils/domain-locale.js";
10
10
  import { prefetchPagesData, resolvePagesDataNavigationTarget } from "./internal/pages-data-target.js";
11
- import { markAppRouteDetectedOnPrefetch } from "./internal/app-route-detection.js";
12
- import { isAbsoluteOrProtocolRelativeUrl, normalizePathTrailingSlash, resolveRelativeHref, toBrowserNavigationHref, toSameOriginAppPath, withBasePath } from "./url-utils.js";
13
11
  import { appendSearchParamsToUrl, urlQueryToSearchParams } from "../utils/query.js";
12
+ import { resolveHybridClientRouteOwner } from "./internal/hybrid-client-route-owner.js";
13
+ import { markAppRouteDetectedOnPrefetch } from "./internal/app-route-detection.js";
14
+ import { isAbsoluteOrProtocolRelativeUrl, normalizePathTrailingSlash, toBrowserNavigationHref, toSameOriginAppPath, withBasePath } from "./url-utils.js";
14
15
  import { getCurrentBrowserLocale } from "./client-locale.js";
15
16
  import { getCurrentRoutePathnameForWarning } from "./internal/route-pattern-for-warning.js";
16
17
  import { getNavigationRuntime, hasAppNavigationRuntime, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
@@ -122,7 +123,7 @@ function getLinkPrefetchRouterMode() {
122
123
  }
123
124
  function resolveMatchedAutoAppRoutePrefetch(route) {
124
125
  return {
125
- cacheForNavigation: !(route.isDynamic && route.canPrefetchLoadingShell),
126
+ cacheForNavigation: !route.canPrefetchLoadingShell,
126
127
  prefetchShellFirst: !route.isDynamic,
127
128
  shouldPrefetch: true
128
129
  };
@@ -189,6 +190,8 @@ function prefetchUrl(href, mode, priority = "low") {
189
190
  } : window.requestIdleCallback ?? ((fn) => setTimeout(fn, 100)))(() => {
190
191
  (async () => {
191
192
  if (hasAppNavigationRuntime()) {
193
+ const hybridOwner = resolveHybridClientRouteOwner(prefetchHref, __basePath);
194
+ if (hybridOwner === "pages" || hybridOwner === "document") return;
192
195
  const autoPrefetch = mode === "auto" ? resolveAutoAppRoutePrefetch(prefetchHref) : {
193
196
  cacheForNavigation: true,
194
197
  prefetchShellFirst: true,
@@ -490,7 +493,6 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
490
493
  navigateHref = localPath;
491
494
  }
492
495
  e.preventDefault();
493
- const absoluteHref = resolveRelativeHref(navigateHref, window.location.href, __basePath);
494
496
  const absoluteFullHref = toBrowserNavigationHref(navigateHref, window.location.href, __basePath);
495
497
  if (onNavigate) try {
496
498
  const navUrl = new URL(absoluteFullHref, window.location.origin);
@@ -507,6 +509,11 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
507
509
  onNavigate(navEvent);
508
510
  if (navEvent.defaultPrevented) return;
509
511
  } catch {}
512
+ if (getNavigationRuntime()?.functions.navigate && ["pages", "document"].includes(resolveHybridClientRouteOwner(navigateHref, __basePath) ?? "")) {
513
+ if (replace) window.location.replace(absoluteFullHref);
514
+ else window.location.assign(absoluteFullHref);
515
+ return;
516
+ }
510
517
  if (getNavigationRuntime()?.functions.navigate) {
511
518
  const setter = setPendingRef.current;
512
519
  if (setter) setLinkForCurrentNavigation(setter);
@@ -521,7 +528,7 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
521
528
  } else try {
522
529
  const Router = (await import("next/router.js")).default;
523
530
  await navigatePagesRouterLink(Router, {
524
- href: absoluteHref,
531
+ href: navigateHref,
525
532
  replace,
526
533
  scroll,
527
534
  shallow,
@@ -271,11 +271,15 @@ declare function resolveModuleMetadata(mod: Record<string, unknown>, params?: Re
271
271
  type MetadataHeadProps = {
272
272
  metadata: Metadata;
273
273
  pathname?: string;
274
+ trailingSlash?: boolean;
274
275
  };
275
- declare function renderMetadataToHtml(metadata: Metadata, pathname?: string): string;
276
+ declare function renderMetadataToHtml(metadata: Metadata, pathname?: string, options?: {
277
+ trailingSlash?: boolean;
278
+ }): string;
276
279
  declare function MetadataHead({
277
280
  metadata,
278
- pathname
281
+ pathname,
282
+ trailingSlash
279
283
  }: MetadataHeadProps): React.JSX.Element;
280
284
  //#endregion
281
285
  export { DEFAULT_VIEWPORT, Metadata, MetadataHead, MetadataMergeEntry, Viewport, ViewportHead, mergeMetadata, mergeMetadataEntries, mergeViewport, postProcessMetadata, renderMetadataToHtml, resolveModuleMetadata, resolveModuleViewport };
@@ -287,18 +287,35 @@ function formatResolvedMetadataUrl(url) {
287
287
  if (url.pathname === "/" && url.search === "" && url.hash === "") return url.origin;
288
288
  return url.href;
289
289
  }
290
- function resolveMetadataUrl(url, metadataBase) {
290
+ const TRAILING_SLASH_FILE_REGEX = /^(?:\/((?!\.well-known(?:\/.*)?)((?:[^/]+\/)*)([^/]+\.\w+)))(\/?|$)/i;
291
+ function resolveMetadataUrl(url, metadataBase, trailingSlash) {
291
292
  const value = stringifyUrl(url);
292
- if (isAbsoluteOrProtocolRelativeUrl(value) || !metadataBase) return value;
293
+ if (!metadataBase) return value;
293
294
  try {
294
- return formatResolvedMetadataUrl(new URL(joinMetadataPath(metadataBase.pathname, value), metadataBase));
295
+ const isAbsolute = isAbsoluteOrProtocolRelativeUrl(value);
296
+ const composed = isAbsolute ? new URL(value, metadataBase) : new URL(joinMetadataPath(metadataBase.pathname, value), metadataBase);
297
+ if (isAbsolute && composed.origin !== metadataBase.origin) return value;
298
+ if (trailingSlash === true && composed.search === "") {
299
+ if (composed.pathname !== "/" && !composed.pathname.endsWith("/") && !TRAILING_SLASH_FILE_REGEX.test(composed.pathname)) composed.pathname += "/";
300
+ }
301
+ const result = formatResolvedMetadataUrl(composed);
302
+ if (trailingSlash === true && result === metadataBase.origin) return `${metadataBase.origin}/`;
303
+ return result;
295
304
  } catch {
296
305
  return value;
297
306
  }
298
307
  }
299
- function resolveCanonicalUrl(url, metadataBase, pathname) {
300
- if (url instanceof URL) return resolveMetadataUrl(url, metadataBase);
301
- return resolveMetadataUrl(resolveRelativeMetadataUrl(url, pathname), metadataBase);
308
+ function resolveCanonicalUrl(url, metadataBase, pathname, trailingSlash) {
309
+ if (url instanceof URL) return resolveMetadataUrl(url, metadataBase, trailingSlash);
310
+ return resolveMetadataUrl(resolveRelativeMetadataUrl(url, pathname), metadataBase, trailingSlash);
311
+ }
312
+ function resolveAlternateUrl(url, metadataBase, pathname, trailingSlash) {
313
+ if (url instanceof URL) {
314
+ const resolvedUrl = new URL(pathname, url);
315
+ url.searchParams.forEach((value, key) => resolvedUrl.searchParams.set(key, value));
316
+ return resolveMetadataUrl(resolvedUrl, metadataBase, trailingSlash);
317
+ }
318
+ return resolveCanonicalUrl(url, metadataBase, pathname, trailingSlash);
302
319
  }
303
320
  function isSocialImageDescriptor(value) {
304
321
  return typeof value === "object" && !(value instanceof URL);
@@ -359,13 +376,14 @@ function renderMetadataElementToHtml(node) {
359
376
  default: return "";
360
377
  }
361
378
  }
362
- function renderMetadataToHtml(metadata, pathname = "/") {
379
+ function renderMetadataToHtml(metadata, pathname = "/", options) {
363
380
  return renderMetadataElementToHtml(MetadataHead({
364
381
  metadata,
365
- pathname
382
+ pathname,
383
+ trailingSlash: options?.trailingSlash
366
384
  }));
367
385
  }
368
- function MetadataHead({ metadata, pathname = "/" }) {
386
+ function MetadataHead({ metadata, pathname = "/", trailingSlash }) {
369
387
  const elements = [];
370
388
  let key = 0;
371
389
  const base = metadata.metadataBase;
@@ -474,7 +492,7 @@ function MetadataHead({ metadata, pathname = "/" }) {
474
492
  }, key++));
475
493
  if (og.url) elements.push(/* @__PURE__ */ jsx("meta", {
476
494
  property: "og:url",
477
- content: resolveUrl(og.url)
495
+ content: resolveCanonicalUrl(og.url, base, pathname, trailingSlash)
478
496
  }, key++));
479
497
  if (og.siteName) elements.push(/* @__PURE__ */ jsx("meta", {
480
498
  property: "og:site_name",
@@ -691,22 +709,22 @@ function MetadataHead({ metadata, pathname = "/" }) {
691
709
  const alt = metadata.alternates;
692
710
  if (alt.canonical) elements.push(/* @__PURE__ */ jsx("link", {
693
711
  rel: "canonical",
694
- href: resolveCanonicalUrl(alt.canonical, base, pathname)
712
+ href: resolveCanonicalUrl(alt.canonical, base, pathname, trailingSlash)
695
713
  }, key++));
696
714
  if (alt.languages) for (const [lang, href] of Object.entries(alt.languages)) elements.push(/* @__PURE__ */ jsx("link", {
697
715
  rel: "alternate",
698
716
  hrefLang: lang,
699
- href: resolveUrl(href)
717
+ href: resolveAlternateUrl(href, base, pathname, trailingSlash)
700
718
  }, key++));
701
719
  if (alt.media) for (const [media, href] of Object.entries(alt.media)) elements.push(/* @__PURE__ */ jsx("link", {
702
720
  rel: "alternate",
703
721
  media,
704
- href: resolveUrl(href)
722
+ href: resolveAlternateUrl(href, base, pathname, trailingSlash)
705
723
  }, key++));
706
724
  if (alt.types) for (const [type, href] of Object.entries(alt.types)) elements.push(/* @__PURE__ */ jsx("link", {
707
725
  rel: "alternate",
708
726
  type,
709
- href: resolveUrl(href)
727
+ href: resolveAlternateUrl(href, base, pathname, trailingSlash)
710
728
  }, key++));
711
729
  }
712
730
  if (metadata.verification) {
@@ -1,4 +1,6 @@
1
- import { NavigateOptions, PrefetchOptions as PrefetchOptions$1 } from "./internal/app-router-context.js";
1
+ import { AppRouterScrollIntent } from "./app-router-scroll-state.js";
2
+ import { NavigationRuntimeVisibleCommitMode } from "../client/navigation-runtime.js";
3
+ import { AppRouterInstance, NavigateOptions, PrefetchOptions as PrefetchOptions$1 } from "./internal/app-router-context.js";
2
4
  import { ReadonlyURLSearchParams } from "./readonly-url-search-params.js";
3
5
  import { UnrecognizedActionError, unstable_isUnrecognizedActionError } from "./unrecognized-action-error.js";
4
6
  import * as React$1 from "react";
@@ -96,7 +98,9 @@ declare function getPrefetchedUrls(): Set<string>;
96
98
  declare function resolveCachedRscResponseTtlMs(cached: Pick<CachedRscResponse, "dynamicStaleTimeSeconds">, fallbackTtlMs: number): number;
97
99
  declare function resolveCachedRscResponseExpiresAt(timestamp: number, cached: Pick<CachedRscResponse, "dynamicStaleTimeSeconds" | "expiresAt">, fallbackTtlMs: number): number;
98
100
  declare function resolvePrefetchCacheEntryMountedSlotsHeader(entry: PrefetchCacheEntry): string | null;
99
- declare function hasPrefetchCacheEntryForNavigation(rscUrl: string, interceptionContext?: string | null, mountedSlotsHeader?: string | null): boolean;
101
+ declare function hasPrefetchCacheEntryForNavigation(rscUrl: string, interceptionContext?: string | null, mountedSlotsHeader?: string | null, options?: {
102
+ notifyInvalidation?: boolean;
103
+ }): boolean;
100
104
  declare function invalidatePrefetchCache(): void;
101
105
  /**
102
106
  * Store a prefetched RSC response in the cache by snapshotting it to an
@@ -204,7 +208,10 @@ type ClientNavigationRenderSnapshot = {
204
208
  params: Record<string, string | string[]>;
205
209
  };
206
210
  declare function getClientNavigationRenderContext(): React$1.Context<ClientNavigationRenderSnapshot | null> | null;
211
+ /** @internal */
212
+ declare function useClientNavigationRenderSnapshot(): ClientNavigationRenderSnapshot | null;
207
213
  declare function createClientNavigationRenderSnapshot(href: string, params: Record<string, string | string[]>): ClientNavigationRenderSnapshot;
214
+ declare function createSnapshotPathAndSearch(snapshot: ClientNavigationRenderSnapshot): string;
208
215
  declare function setClientParams(params: Record<string, string | string[]>): void;
209
216
  declare function replaceClientParamsWithoutNotify(params: Record<string, string | string[]>): void;
210
217
  /** Get the current client params (for testing referential stability). */
@@ -253,10 +260,11 @@ declare function replaceHistoryStateWithoutNotify(data: unknown, unused: string,
253
260
  * history.replaceState interception (which would cause spurious re-renders).
254
261
  */
255
262
  declare function saveScrollPosition(): void;
263
+ declare function applyAppRouterScrollFallback(intent: AppRouterScrollIntent): void;
256
264
  /**
257
265
  * Navigate to a URL, handling external URLs, hash-only changes, and RSC navigation.
258
266
  */
259
- declare function navigateClientSide(href: string, mode: "push" | "replace", scroll: boolean, programmaticTransition?: boolean): Promise<void>;
267
+ declare function navigateClientSide(href: string, mode: "push" | "replace", scroll: boolean, programmaticTransition?: boolean, visibleCommitMode?: NavigationRuntimeVisibleCommitMode): Promise<void>;
260
268
  /**
261
269
  * Public App Router instance, exposed for the browser entry so it can wire
262
270
  * `window.next.router` to the same singleton returned from `useRouter()`.
@@ -264,19 +272,7 @@ declare function navigateClientSide(href: string, mode: "push" | "replace", scro
264
272
  * Mirrors `publicAppRouterInstance` from Next.js's
265
273
  * `packages/next/src/client/components/app-router-instance.ts` (line 392).
266
274
  */
267
- declare const appRouterInstance: {
268
- bfcacheId: string;
269
- push(href: string, options?: {
270
- scroll?: boolean;
271
- }): void;
272
- replace(href: string, options?: {
273
- scroll?: boolean;
274
- }): void;
275
- back(): void;
276
- forward(): void;
277
- refresh(): void;
278
- prefetch(href: string, options?: PrefetchOptions): void;
279
- };
275
+ declare const appRouterInstance: AppRouterInstance;
280
276
  /**
281
277
  * App Router's useRouter — returns push/replace/back/forward/refresh.
282
278
  * Different from Pages Router's useRouter (next/router).
@@ -292,6 +288,7 @@ declare function useRouter(): {
292
288
  push(href: string, options?: NavigateOptions): void;
293
289
  replace(href: string, options?: NavigateOptions): void;
294
290
  prefetch(href: string, options?: PrefetchOptions$1): void;
291
+ experimental_gesturePush?(href: string, options?: NavigateOptions): void;
295
292
  };
296
293
  /**
297
294
  * Returns the active child segment one level below the layout where it's called.
@@ -574,4 +571,4 @@ declare function isDynamicServerError(error: unknown): error is DynamicServerErr
574
571
  */
575
572
  declare function unstable_rethrow(error: unknown): void;
576
573
  //#endregion
577
- export { BailoutToCSRError, CachedRscResponse, ClientNavigationRenderSnapshot, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, NavigationContext, PREFETCH_CACHE_TTL, PrefetchCacheEntry, PrefetchOptions, ReadonlyURLSearchParams, RedirectType, SegmentMap, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, decodeRedirectError, flushServerInsertedHTML, forbidden, getAccessFallbackHTTPStatus, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getClientNavigationRenderContext, getClientNavigationState, getClientParams, getCurrentInterceptionContext, getCurrentNextUrl, getLayoutSegmentContext, getMountedSlotsHeader, getNavigationContext, getPrefetchCache, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, navigateClientSide, notFound, permanentRedirect, prefetchRscResponse, pushHistoryStateWithoutNotify, redirect, renderServerInsertedHTML, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveCachedRscResponseExpiresAt, resolveCachedRscResponseTtlMs, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
574
+ export { BailoutToCSRError, CachedRscResponse, ClientNavigationRenderSnapshot, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, NavigationContext, PREFETCH_CACHE_TTL, PrefetchCacheEntry, PrefetchOptions, ReadonlyURLSearchParams, RedirectType, SegmentMap, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, applyAppRouterScrollFallback, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, flushServerInsertedHTML, forbidden, getAccessFallbackHTTPStatus, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getClientNavigationRenderContext, getClientNavigationState, getClientParams, getCurrentInterceptionContext, getCurrentNextUrl, getLayoutSegmentContext, getMountedSlotsHeader, getNavigationContext, getPrefetchCache, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, navigateClientSide, notFound, permanentRedirect, prefetchRscResponse, pushHistoryStateWithoutNotify, redirect, renderServerInsertedHTML, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveCachedRscResponseExpiresAt, resolveCachedRscResponseTtlMs, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useClientNavigationRenderSnapshot, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };