vinext 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/README.md +72 -1
  2. package/THIRD_PARTY_LICENSES.md +26 -0
  3. package/dist/build/app-page-static-eligibility.d.ts +15 -0
  4. package/dist/build/app-page-static-eligibility.js +82 -0
  5. package/dist/build/lifecycle.js +10 -10
  6. package/dist/build/pages-client-assets-module.js +6 -1
  7. package/dist/build/precompress.js +1 -1
  8. package/dist/build/prerender-paths.js +6 -85
  9. package/dist/build/prerender.d.ts +8 -1
  10. package/dist/build/prerender.js +167 -46
  11. package/dist/build/run-prerender.js +4 -3
  12. package/dist/build/server-entry.d.ts +2 -0
  13. package/dist/build/server-entry.js +7 -1
  14. package/dist/build/server-manifest.d.ts +7 -0
  15. package/dist/build/server-manifest.js +11 -1
  16. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  17. package/dist/cache/cache-adapters-virtual.js +3 -3
  18. package/dist/client/browser-globals.d.ts +4 -0
  19. package/dist/client/browser-globals.js +5 -0
  20. package/dist/client/navigation-runtime.d.ts +11 -1
  21. package/dist/client/navigation-runtime.js +3 -3
  22. package/dist/config/config-matchers.js +3 -1
  23. package/dist/config/dotenv.js +14 -3
  24. package/dist/config/next-config.d.ts +7 -0
  25. package/dist/config/next-config.js +18 -3
  26. package/dist/entries/app-rsc-entry.d.ts +2 -0
  27. package/dist/entries/app-rsc-entry.js +67 -45
  28. package/dist/index.d.ts +4 -1
  29. package/dist/index.js +200 -100
  30. package/dist/init-cloudflare.d.ts +1 -1
  31. package/dist/init-cloudflare.js +6 -6
  32. package/dist/init-platform.js +1 -1
  33. package/dist/init.js +4 -2
  34. package/dist/plugins/cache-flight-codec.d.ts +19 -0
  35. package/dist/plugins/cache-flight-codec.js +68 -0
  36. package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
  37. package/dist/plugins/commonjs-esm-facade.js +80 -0
  38. package/dist/plugins/commonjs-syntax.d.ts +16 -0
  39. package/dist/plugins/commonjs-syntax.js +22 -0
  40. package/dist/plugins/fonts.d.ts +8 -11
  41. package/dist/plugins/fonts.js +71 -34
  42. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  43. package/dist/plugins/ignore-dynamic-requests.js +54 -3
  44. package/dist/plugins/import-meta-url.js +6 -6
  45. package/dist/plugins/og-asset-ownership.d.ts +2 -0
  46. package/dist/plugins/og-asset-ownership.js +24 -13
  47. package/dist/plugins/og-assets.d.ts +18 -0
  48. package/dist/plugins/og-assets.js +50 -8
  49. package/dist/plugins/og-harfbuzz.js +38 -27
  50. package/dist/plugins/optimize-imports.js +2 -1
  51. package/dist/plugins/require-context.d.ts +1 -0
  52. package/dist/plugins/require-context.js +28 -1
  53. package/dist/plugins/scan-build-css.d.ts +12 -0
  54. package/dist/plugins/scan-build-css.js +39 -0
  55. package/dist/plugins/strip-server-exports.d.ts +2 -0
  56. package/dist/plugins/strip-server-exports.js +3 -1
  57. package/dist/plugins/transform-result.d.ts +18 -0
  58. package/dist/plugins/transform-result.js +23 -2
  59. package/dist/plugins/typeof-window.d.ts +10 -0
  60. package/dist/plugins/typeof-window.js +33 -9
  61. package/dist/routing/app-route-graph.d.ts +0 -1
  62. package/dist/routing/app-route-graph.js +2 -4
  63. package/dist/routing/app-route-ids.d.ts +3 -0
  64. package/dist/routing/app-route-ids.js +6 -0
  65. package/dist/routing/file-matcher.d.ts +1 -0
  66. package/dist/routing/file-matcher.js +1 -1
  67. package/dist/server/api-handler.js +17 -7
  68. package/dist/server/app-bfcache-id.d.ts +1 -0
  69. package/dist/server/app-bfcache-id.js +7 -1
  70. package/dist/server/app-bfcache-identity.js +1 -2
  71. package/dist/server/app-browser-entry.js +15 -9
  72. package/dist/server/app-browser-history-controller.d.ts +2 -0
  73. package/dist/server/app-browser-history-controller.js +8 -0
  74. package/dist/server/app-browser-hydration.d.ts +1 -1
  75. package/dist/server/app-browser-hydration.js +2 -2
  76. package/dist/server/app-browser-interception-context.js +26 -2
  77. package/dist/server/app-browser-navigation-controller.d.ts +7 -1
  78. package/dist/server/app-browser-navigation-controller.js +94 -11
  79. package/dist/server/app-browser-state.js +1 -1
  80. package/dist/server/app-browser-stream.d.ts +1 -1
  81. package/dist/server/app-fallback-renderer.d.ts +2 -0
  82. package/dist/server/app-fallback-renderer.js +1 -0
  83. package/dist/server/app-history-state.d.ts +3 -1
  84. package/dist/server/app-history-state.js +9 -5
  85. package/dist/server/app-middleware.js +2 -1
  86. package/dist/server/app-optimistic-routing.js +1 -1
  87. package/dist/server/app-page-boundary-render.d.ts +5 -0
  88. package/dist/server/app-page-boundary-render.js +6 -4
  89. package/dist/server/app-page-cache-finalizer.d.ts +11 -0
  90. package/dist/server/app-page-cache-finalizer.js +41 -7
  91. package/dist/server/app-page-cache-render.d.ts +18 -0
  92. package/dist/server/app-page-cache-render.js +65 -44
  93. package/dist/server/app-page-cache.d.ts +5 -0
  94. package/dist/server/app-page-cache.js +27 -7
  95. package/dist/server/app-page-dispatch.d.ts +9 -1
  96. package/dist/server/app-page-dispatch.js +47 -30
  97. package/dist/server/app-page-element-builder.d.ts +7 -0
  98. package/dist/server/app-page-element-builder.js +27 -42
  99. package/dist/server/app-page-execution.d.ts +15 -12
  100. package/dist/server/app-page-execution.js +30 -40
  101. package/dist/server/app-page-head.d.ts +5 -0
  102. package/dist/server/app-page-head.js +9 -3
  103. package/dist/server/app-page-probe.d.ts +0 -109
  104. package/dist/server/app-page-probe.js +3 -136
  105. package/dist/server/app-page-render-identity.d.ts +0 -1
  106. package/dist/server/app-page-render-identity.js +1 -1
  107. package/dist/server/app-page-render-observation.js +2 -2
  108. package/dist/server/app-page-render.d.ts +13 -5
  109. package/dist/server/app-page-render.js +219 -118
  110. package/dist/server/app-page-request.d.ts +0 -1
  111. package/dist/server/app-page-request.js +1 -2
  112. package/dist/server/app-page-response.d.ts +4 -3
  113. package/dist/server/app-page-response.js +4 -3
  114. package/dist/server/app-page-route-wiring.d.ts +17 -5
  115. package/dist/server/app-page-route-wiring.js +55 -33
  116. package/dist/server/app-page-rsc-render-status.d.ts +48 -0
  117. package/dist/server/app-page-rsc-render-status.js +54 -0
  118. package/dist/server/app-page-search-params-observation.js +1 -1
  119. package/dist/server/app-page-stream.d.ts +15 -8
  120. package/dist/server/app-page-stream.js +7 -1
  121. package/dist/server/app-page-tracing.js +2 -1
  122. package/dist/server/app-pages-bridge.js +3 -2
  123. package/dist/server/app-render-abort-error.d.ts +3 -0
  124. package/dist/server/app-render-abort-error.js +8 -0
  125. package/dist/server/app-request-stage-dispatch.js +1 -1
  126. package/dist/server/app-request-stage-independent-entry.js +8 -11
  127. package/dist/server/app-response-header-provenance.d.ts +2 -0
  128. package/dist/server/app-response-header-provenance.js +10 -4
  129. package/dist/server/app-route-handler-cache.d.ts +2 -1
  130. package/dist/server/app-route-handler-cache.js +11 -7
  131. package/dist/server/app-route-handler-dispatch.js +11 -4
  132. package/dist/server/app-route-handler-execution.d.ts +9 -1
  133. package/dist/server/app-route-handler-execution.js +28 -13
  134. package/dist/server/app-route-handler-policy.js +2 -2
  135. package/dist/server/app-route-handler-response.d.ts +1 -1
  136. package/dist/server/app-route-handler-response.js +14 -5
  137. package/dist/server/app-router-entry.d.ts +2 -1
  138. package/dist/server/app-router-entry.js +8 -12
  139. package/dist/server/app-rsc-errors.d.ts +0 -1
  140. package/dist/server/app-rsc-errors.js +2 -6
  141. package/dist/server/app-rsc-handler.d.ts +5 -0
  142. package/dist/server/app-rsc-handler.js +229 -102
  143. package/dist/server/app-rsc-request-normalization.d.ts +4 -2
  144. package/dist/server/app-rsc-request-normalization.js +7 -4
  145. package/dist/server/app-rsc-response-finalizer.js +4 -1
  146. package/dist/server/app-rsc-response-stage.d.ts +1 -1
  147. package/dist/server/app-rsc-response-stage.js +6 -4
  148. package/dist/server/app-rsc-route-matching.d.ts +9 -1
  149. package/dist/server/app-rsc-route-matching.js +37 -20
  150. package/dist/server/app-server-action-execution.d.ts +2 -1
  151. package/dist/server/app-server-action-execution.js +1 -1
  152. package/dist/server/app-ssr-entry.d.ts +3 -2
  153. package/dist/server/app-ssr-entry.js +9 -7
  154. package/dist/server/app-ssr-search-params-gate.js +1 -1
  155. package/dist/server/app-ssr-stream.d.ts +6 -1
  156. package/dist/server/app-ssr-stream.js +35 -16
  157. package/dist/server/app-worker-stages.d.ts +2 -2
  158. package/dist/server/app-worker-stages.js +3 -3
  159. package/dist/server/cache-control.js +3 -11
  160. package/dist/server/cacheability-request.js +56 -52
  161. package/dist/server/config-headers.js +3 -1
  162. package/dist/server/dev-server.js +23 -5
  163. package/dist/server/headers.d.ts +16 -0
  164. package/dist/server/headers.js +19 -1
  165. package/dist/server/http-error-responses.js +1 -0
  166. package/dist/server/image-optimization.d.ts +16 -0
  167. package/dist/server/image-optimization.js +26 -6
  168. package/dist/server/isr-cache.d.ts +2 -0
  169. package/dist/server/isr-cache.js +8 -3
  170. package/dist/server/metadata-route-response.js +94 -37
  171. package/dist/server/middleware-matcher-pattern.js +8 -4
  172. package/dist/server/middleware-response-headers.js +2 -0
  173. package/dist/server/multi-stage.d.ts +8 -0
  174. package/dist/server/navigation-planner.js +1 -1
  175. package/dist/server/node-response-signal.d.ts +16 -0
  176. package/dist/server/node-response-signal.js +26 -0
  177. package/dist/server/open-redirect.d.ts +47 -0
  178. package/dist/server/open-redirect.js +74 -1
  179. package/dist/server/pages-api-route.js +8 -2
  180. package/dist/server/pages-asset-tags.d.ts +1 -0
  181. package/dist/server/pages-asset-tags.js +73 -22
  182. package/dist/server/pages-client-assets.d.ts +2 -0
  183. package/dist/server/pages-page-data.d.ts +6 -1
  184. package/dist/server/pages-page-data.js +71 -65
  185. package/dist/server/pages-page-handler.js +50 -15
  186. package/dist/server/pages-page-response.js +3 -1
  187. package/dist/server/pages-request-pipeline.d.ts +2 -1
  188. package/dist/server/pages-request-pipeline.js +20 -5
  189. package/dist/server/pages-request-stage-entry.js +14 -8
  190. package/dist/server/prerender-manifest.d.ts +6 -0
  191. package/dist/server/prerender-manifest.js +1 -1
  192. package/dist/server/prod-server.d.ts +8 -7
  193. package/dist/server/prod-server.js +152 -78
  194. package/dist/server/request-pipeline.d.ts +20 -8
  195. package/dist/server/request-pipeline.js +21 -7
  196. package/dist/server/response-compression.d.ts +43 -0
  197. package/dist/server/response-compression.js +111 -0
  198. package/dist/server/response-stage-cacheability.js +1 -1
  199. package/dist/server/seed-cache.js +10 -7
  200. package/dist/server/socket-error-backstop.d.ts +14 -0
  201. package/dist/server/socket-error-backstop.js +27 -4
  202. package/dist/server/worker-revalidation-context.d.ts +2 -1
  203. package/dist/server/worker-revalidation-context.js +1 -0
  204. package/dist/server/workers-tracing.d.ts +17 -0
  205. package/dist/server/workers-tracing.js +48 -8
  206. package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
  207. package/dist/shims/cache-adapter-instantiate.js +118 -0
  208. package/dist/shims/cache-callable-runtime.d.ts +2 -40
  209. package/dist/shims/cache-callable-runtime.js +50 -168
  210. package/dist/shims/cache-flight-arguments.d.ts +22 -0
  211. package/dist/shims/cache-flight-arguments.js +56 -0
  212. package/dist/shims/cache-request-state.d.ts +18 -14
  213. package/dist/shims/cache-request-state.js +33 -21
  214. package/dist/shims/cache-runtime.d.ts +6 -19
  215. package/dist/shims/cache-runtime.js +168 -226
  216. package/dist/shims/cache.d.ts +3 -2
  217. package/dist/shims/cache.js +8 -5
  218. package/dist/shims/cacheability-classification.d.ts +8 -1
  219. package/dist/shims/cacheability-classification.js +2 -2
  220. package/dist/shims/cdn-cache.d.ts +10 -1
  221. package/dist/shims/cdn-cache.js +16 -9
  222. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  223. package/dist/shims/error-boundary-navigation.js +19 -1
  224. package/dist/shims/error-boundary.d.ts +10 -10
  225. package/dist/shims/error-boundary.js +26 -7
  226. package/dist/shims/error.d.ts +4 -18
  227. package/dist/shims/error.js +17 -10
  228. package/dist/shims/error.react-server.d.ts +4 -6
  229. package/dist/shims/error.react-server.js +4 -1
  230. package/dist/shims/fetch-cache.d.ts +6 -0
  231. package/dist/shims/fetch-cache.js +23 -4
  232. package/dist/shims/form.js +1 -1
  233. package/dist/shims/headers.d.ts +19 -69
  234. package/dist/shims/headers.js +82 -183
  235. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
  236. package/dist/shims/internal/app-page-props-cache-key.js +24 -15
  237. package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
  238. package/dist/shims/internal/cache-context-accessor.js +15 -0
  239. package/dist/shims/internal/headers-state.d.ts +73 -0
  240. package/dist/shims/internal/headers-state.js +157 -0
  241. package/dist/shims/metadata.js +3 -3
  242. package/dist/shims/navigation-errors.d.ts +6 -0
  243. package/dist/shims/navigation-errors.js +11 -1
  244. package/dist/shims/navigation.d.ts +7 -0
  245. package/dist/shims/navigation.js +16 -6
  246. package/dist/shims/request-context.d.ts +9 -0
  247. package/dist/shims/request-state-types.d.ts +2 -1
  248. package/dist/shims/root-params.js +1 -1
  249. package/dist/shims/server.js +52 -2
  250. package/dist/shims/thenable-params.d.ts +4 -0
  251. package/dist/shims/thenable-params.js +25 -3
  252. package/dist/shims/unified-request-context.d.ts +1 -1
  253. package/dist/shims/unified-request-context.js +1 -0
  254. package/dist/utils/encode-cache-tag.d.ts +1 -0
  255. package/dist/utils/encode-cache-tag.js +11 -1
  256. package/dist/utils/mdx-scan.d.ts +5 -0
  257. package/dist/utils/mdx-scan.js +8 -1
  258. package/dist/utils/regex-safety.d.ts +10 -0
  259. package/dist/utils/regex-safety.js +70 -18
  260. package/dist/utils/vite-cli-invocation.js +8 -1
  261. package/package.json +8 -4
  262. package/dist/server/metadata-route-cache-policy.d.ts +0 -5
  263. package/dist/server/metadata-route-cache-policy.js +0 -6
@@ -1,3 +1,4 @@
1
+ import { VinextAssetFetcher } from "../server/multi-stage.js";
1
2
  import { CacheHandlerValue, IncrementalCacheValue } from "./cache-handler.js";
2
3
  import { setCdnCacheAdapter } from "./cdn-cache-state.js";
3
4
  //#region src/shims/cdn-cache.d.ts
@@ -10,6 +11,8 @@ export type CdnCacheableHeaderInput = {
10
11
  * when no cacheable policy applies.
11
12
  */
12
13
  cacheControl: string;
14
+ /** Explicit endpoint policy returned to clients, independent of shared admission. */
15
+ browserCacheControl?: string;
13
16
  /**
14
17
  * True when this is a freshly-rendered **streaming** response whose
15
18
  * dynamic-ness is not yet proven (late Server Component request-API usage can
@@ -47,8 +50,10 @@ export type CdnResponsePolicy = {
47
50
  /** Whether provider policy explicitly opts out of storage. */
48
51
  hasExplicitNonCacheablePolicy(headers: Headers, baseline?: Headers): boolean;
49
52
  };
53
+ /** Split Cache-Control directives without treating quoted commas as separators. */
54
+ export declare function splitCacheControlDirectives(cacheControl: string): string[];
50
55
  /** Whether a Cache-Control value contains an exact non-cacheable directive. */
51
- export declare function isNonCacheableCacheControl(cacheControl: string): boolean;
56
+ export declare function isNonCacheableCacheControl(cacheControl: string, scope?: "shared" | "browser"): boolean;
52
57
  /**
53
58
  * The serving strategy for page-level ISR. Implement this to delegate
54
59
  * page/route/image caching to a CDN edge instead of the origin store.
@@ -100,6 +105,10 @@ export type CdnCacheAdapter = {
100
105
  * edge owns serving.
101
106
  */
102
107
  get(key: string, ctx?: Record<string, unknown>): Promise<CacheHandlerValue | null>;
108
+ /** Also supplies build-time PAGES entries for pages without getStaticProps. */
109
+ readonly hasPrerenderedPages?: boolean;
110
+ /** Optional host asset fetcher resolved by the adapter's platform bindings. */
111
+ readonly assets?: VinextAssetFetcher;
103
112
  /**
104
113
  * Persist a freshly-rendered page-level artifact.
105
114
  *
@@ -1,17 +1,16 @@
1
1
  import { getExplicitCdnCacheAdapter, setCdnCacheAdapter } from "./cdn-cache-state.js";
2
2
  //#region src/shims/cdn-cache.ts
3
- /** Whether a Cache-Control value contains an exact non-cacheable directive. */
4
- function isNonCacheableCacheControl(cacheControl) {
3
+ /** Split Cache-Control directives without treating quoted commas as separators. */
4
+ function splitCacheControlDirectives(cacheControl) {
5
+ const directives = [];
5
6
  let start = 0;
6
7
  let quoted = false;
7
8
  let escaped = false;
8
9
  for (let index = 0; index <= cacheControl.length; index++) {
9
10
  const char = cacheControl[index];
10
11
  if (index === cacheControl.length || char === "," && !quoted) {
11
- const directive = cacheControl.slice(start, index);
12
- const equals = directive.indexOf("=");
13
- const name = (equals === -1 ? directive : directive.slice(0, equals)).trim().toLowerCase();
14
- if (name === "no-store" || equals === -1 && (name === "private" || name === "no-cache")) return true;
12
+ const directive = cacheControl.slice(start, index).trim();
13
+ if (directive) directives.push(directive);
15
14
  start = index + 1;
16
15
  continue;
17
16
  }
@@ -22,7 +21,15 @@ function isNonCacheableCacheControl(cacheControl) {
22
21
  if (char === "\"" && !escaped) quoted = !quoted;
23
22
  escaped = false;
24
23
  }
25
- return false;
24
+ return directives;
25
+ }
26
+ /** Whether a Cache-Control value contains an exact non-cacheable directive. */
27
+ function isNonCacheableCacheControl(cacheControl, scope = "shared") {
28
+ return splitCacheControlDirectives(cacheControl).some((directive) => {
29
+ const equals = directive.indexOf("=");
30
+ const name = (equals === -1 ? directive : directive.slice(0, equals)).trim().toLowerCase();
31
+ return name === "no-store" || equals === -1 && (name === "no-cache" || scope === "shared" && name === "private");
32
+ });
26
33
  }
27
34
  const PENDING_DYNAMIC_CACHE_CONTROL = "no-store, must-revalidate";
28
35
  /**
@@ -48,7 +55,7 @@ var DefaultCdnCacheAdapter = class {
48
55
  }
49
56
  buildResponseHeaders(input) {
50
57
  if (input.pendingDynamicCheck) return { "Cache-Control": PENDING_DYNAMIC_CACHE_CONTROL };
51
- return { "Cache-Control": input.cacheControl };
58
+ return { "Cache-Control": input.browserCacheControl ?? input.cacheControl };
52
59
  }
53
60
  buildResponseIdentityHeaders() {
54
61
  return this.buildIdentity ? { "X-Vinext-Build-Id": this.buildIdentity } : {};
@@ -88,4 +95,4 @@ function getCdnCacheAdapter() {
88
95
  return _defaultAdapter ??= new DefaultCdnCacheAdapter();
89
96
  }
90
97
  //#endregion
91
- export { DefaultCdnCacheAdapter, getCdnCacheAdapter, isNonCacheableCacheControl, setCdnCacheAdapter };
98
+ export { DefaultCdnCacheAdapter, getCdnCacheAdapter, isNonCacheableCacheControl, setCdnCacheAdapter, splitCacheControlDirectives };
@@ -2,4 +2,11 @@ import { AppRouterInstance } from "./internal/app-router-context.js";
2
2
  //#region src/shims/error-boundary-navigation.d.ts
3
3
  export declare function useErrorBoundaryPathname(): string;
4
4
  export declare function useErrorBoundaryRouter(): AppRouterInstance;
5
+ /**
6
+ * Whether following a redirect() would refetch the URL the browser is at,
7
+ * which renders the same redirect again. As in the navigation planner, only the
8
+ * exact URL refreshes the page; any hash change, including removing the
9
+ * current hash, only scrolls.
10
+ */
11
+ export declare function isRedirectToCurrentUrl(redirect: string): boolean;
5
12
  //#endregion
@@ -1,6 +1,7 @@
1
1
  import { stripBasePath } from "../utils/base-path.js";
2
2
  import { markPprFallbackShellDynamicBoundary } from "./ppr-fallback-shell.js";
3
3
  import { AppRouterContext } from "./internal/app-router-context.js";
4
+ import { toCanonicalBrowserNavigationHref, toSameOriginAppPath } from "./url-utils.js";
4
5
  import { getNavigationContext } from "./navigation-context-state.js";
5
6
  import "./navigation-server.js";
6
7
  import * as React$1 from "react";
@@ -8,6 +9,7 @@ import * as React$1 from "react";
8
9
  const CLIENT_NAVIGATION_STATE_KEY = Symbol.for("vinext.clientNavigationState");
9
10
  const CLIENT_NAVIGATION_RENDER_CONTEXT_KEY = Symbol.for("vinext.clientNavigationRenderContext");
10
11
  const BASE_PATH = process.env.__NEXT_ROUTER_BASEPATH ?? "";
12
+ const TRAILING_SLASH = process.env.__VINEXT_TRAILING_SLASH === "true";
11
13
  function getClientNavigationState() {
12
14
  return globalThis[CLIENT_NAVIGATION_STATE_KEY];
13
15
  }
@@ -40,5 +42,21 @@ function useErrorBoundaryRouter() {
40
42
  if (router === null) throw new Error("invariant expected app router to be mounted");
41
43
  return router;
42
44
  }
45
+ /**
46
+ * Whether following a redirect() would refetch the URL the browser is at,
47
+ * which renders the same redirect again. As in the navigation planner, only the
48
+ * exact URL refreshes the page; any hash change, including removing the
49
+ * current hash, only scrolls.
50
+ */
51
+ function isRedirectToCurrentUrl(redirect) {
52
+ if (typeof window === "undefined") return false;
53
+ try {
54
+ const current = new URL(window.location.href);
55
+ const target = new URL(toCanonicalBrowserNavigationHref(toSameOriginAppPath(redirect, BASE_PATH) ?? redirect, current.href, BASE_PATH, TRAILING_SLASH), current.href);
56
+ return target.hash === current.hash && target.origin === current.origin && target.pathname === current.pathname && target.search === current.search;
57
+ } catch {
58
+ return false;
59
+ }
60
+ }
43
61
  //#endregion
44
- export { useErrorBoundaryPathname, useErrorBoundaryRouter };
62
+ export { isRedirectToCurrentUrl, useErrorBoundaryPathname, useErrorBoundaryRouter };
@@ -29,6 +29,11 @@ type CapturedError = {
29
29
  type RedirectBoundaryState = {
30
30
  redirect: string | null;
31
31
  redirectType: "push" | "replace" | null;
32
+ previousResetKey: string | null;
33
+ };
34
+ type RedirectBoundaryProps = {
35
+ children?: React.ReactNode;
36
+ resetKey?: string | null;
32
37
  };
33
38
  type ErrorBoundaryInnerProps = {
34
39
  isImplicitRootErrorBoundary?: boolean;
@@ -39,18 +44,13 @@ export type ErrorBoundaryState = {
39
44
  previousPathname: string | null;
40
45
  previousResetKey: string | null;
41
46
  };
42
- export declare class RedirectErrorBoundary extends React.Component<{
43
- children?: React.ReactNode;
44
- }, RedirectBoundaryState> {
45
- constructor(props: {
46
- children?: React.ReactNode;
47
- });
48
- static getDerivedStateFromError(error: unknown): RedirectBoundaryState;
47
+ export declare class RedirectErrorBoundary extends React.Component<RedirectBoundaryProps, RedirectBoundaryState> {
48
+ constructor(props: RedirectBoundaryProps);
49
+ static getDerivedStateFromProps(props: RedirectBoundaryProps, state: RedirectBoundaryState): RedirectBoundaryState | null;
50
+ static getDerivedStateFromError(error: unknown): Omit<RedirectBoundaryState, "previousResetKey">;
49
51
  render(): string | number | bigint | boolean | React.JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | Iterable<React.ReactNode> | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | React.ReactPortal | null | undefined> | null | undefined;
50
52
  }
51
- export declare function RedirectBoundary({ children }: {
52
- children?: React.ReactNode;
53
- }): React.JSX.Element;
53
+ export declare function RedirectBoundary({ children, resetKey }: RedirectBoundaryProps): React.JSX.Element;
54
54
  /**
55
55
  * Generic ErrorBoundary used to wrap route segments with error.tsx.
56
56
  * This must be a client component since error boundaries use
@@ -2,7 +2,7 @@
2
2
  import { isNavigationSignalError } from "../utils/navigation-signal.js";
3
3
  import { decodeRedirectError, isRedirectError } from "./navigation-errors.js";
4
4
  import "./navigation-server.js";
5
- import { useErrorBoundaryPathname, useErrorBoundaryRouter } from "./error-boundary-navigation.js";
5
+ import { isRedirectToCurrentUrl, useErrorBoundaryPathname, useErrorBoundaryRouter } from "./error-boundary-navigation.js";
6
6
  import DefaultGlobalError from "./default-global-error.js";
7
7
  import { handleAppNavigationFailure } from "../client/app-nav-failure-handler.js";
8
8
  import { VINEXT_DEV_ERROR_RECOVERY_EVENT } from "../utils/dev-error-recovery-event.js";
@@ -43,9 +43,13 @@ function removeDevErrorRecoveryListener(listener) {
43
43
  if (typeof window === "undefined") return;
44
44
  window.removeEventListener(VINEXT_DEV_ERROR_RECOVERY_EVENT, listener);
45
45
  }
46
- function HandleRedirect({ redirect, redirectType, reset }) {
46
+ function HandleRedirect({ redirect, redirectType, reset, stopsSelfRedirect }) {
47
47
  const router = useErrorBoundaryRouter();
48
48
  React.useEffect(() => {
49
+ if (stopsSelfRedirect && isRedirectToCurrentUrl(redirect)) {
50
+ console.error("[vinext] redirect() resolved to the current URL — not following it, to prevent an infinite loop.");
51
+ return;
52
+ }
49
53
  React.startTransition(() => {
50
54
  if (redirectType === "push") router.push(redirect);
51
55
  else router.replace(redirect);
@@ -55,7 +59,8 @@ function HandleRedirect({ redirect, redirectType, reset }) {
55
59
  redirect,
56
60
  redirectType,
57
61
  reset,
58
- router
62
+ router,
63
+ stopsSelfRedirect
59
64
  ]);
60
65
  return null;
61
66
  }
@@ -64,7 +69,17 @@ var RedirectErrorBoundary = class extends React.Component {
64
69
  super(props);
65
70
  this.state = {
66
71
  redirect: null,
67
- redirectType: null
72
+ redirectType: null,
73
+ previousResetKey: normalizeBoundaryResetKey(props.resetKey)
74
+ };
75
+ }
76
+ static getDerivedStateFromProps(props, state) {
77
+ const resetKey = normalizeBoundaryResetKey(props.resetKey);
78
+ if (resetKey === state.previousResetKey) return null;
79
+ return {
80
+ redirect: null,
81
+ redirectType: null,
82
+ previousResetKey: resetKey
68
83
  };
69
84
  }
70
85
  static getDerivedStateFromError(error) {
@@ -90,13 +105,17 @@ var RedirectErrorBoundary = class extends React.Component {
90
105
  reset: () => this.setState({
91
106
  redirect: null,
92
107
  redirectType: null
93
- })
108
+ }),
109
+ stopsSelfRedirect: this.props.resetKey !== void 0
94
110
  });
95
111
  return this.props.children;
96
112
  }
97
113
  };
98
- function RedirectBoundary({ children }) {
99
- return /* @__PURE__ */ jsx(RedirectErrorBoundary, { children });
114
+ function RedirectBoundary({ children, resetKey }) {
115
+ return /* @__PURE__ */ jsx(RedirectErrorBoundary, {
116
+ resetKey,
117
+ children
118
+ });
100
119
  }
101
120
  /**
102
121
  * Generic ErrorBoundary used to wrap route segments with error.tsx.
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import { IncomingMessage, ServerResponse } from "node:http";
3
+ import { ErrorInfo, catchError as catchError$1, unstable_catchError as unstable_catchError$1 } from "@vinext/types/next/vinext/error";
3
4
  //#region src/shims/error.d.ts
4
5
  export type ErrorProps = {
5
6
  statusCode: number;
@@ -21,22 +22,7 @@ declare class ErrorComponent<P = {}> extends React.Component<P & ErrorProps> {
21
22
  static origGetInitialProps: typeof getErrorInitialProps;
22
23
  render(): React.ReactElement;
23
24
  }
24
- export type ErrorInfo = {
25
- error: Error;
26
- reset: () => void;
27
- unstable_retry: () => void;
28
- };
29
- type _UserProps = Record<string, unknown>;
30
- /**
31
- * Wrap a fallback render function in a Component-level error boundary.
32
- * Returns a Component that renders `children` and, on error, renders the
33
- * supplied fallback with an `ErrorInfo` value.
34
- *
35
- * Ported from Next.js:
36
- * https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/catch-error.tsx
37
- */
38
- export declare function unstable_catchError<P extends _UserProps>(fallback: (props: P, errorInfo: ErrorInfo) => React.ReactNode): React.ComponentType<P & {
39
- children?: React.ReactNode;
40
- }>;
25
+ export declare const catchError: typeof catchError$1;
26
+ export declare const unstable_catchError: typeof unstable_catchError$1;
41
27
  //#endregion
42
- export { ErrorComponent as default };
28
+ export { type ErrorInfo, ErrorComponent as default };
@@ -13,9 +13,9 @@ import React from "react";
13
13
  * Used by apps that import `import Error from 'next/error'` for
14
14
  * custom error handling in getServerSideProps or API routes.
15
15
  *
16
- * Also re-exports the unstable App Router error-boundary HOC
17
- * (`unstable_catchError`) and its `ErrorInfo` type, mirroring
18
- * `next/error`'s public surface.
16
+ * Also exports the App Router error-boundary HOC (`catchError`, plus its
17
+ * former unstable name) and its `ErrorInfo` type, mirroring `next/error`'s
18
+ * public surface.
19
19
  */
20
20
  const statusCodes = {
21
21
  400: "Bad Request",
@@ -83,7 +83,7 @@ var ErrorComponent = class extends React.Component {
83
83
  const _CatchErrorAppRouterContext = AppRouterContext ?? React.createContext(null);
84
84
  var _CatchError = class extends React.Component {
85
85
  static contextType = _CatchErrorAppRouterContext;
86
- static displayName = "unstable_catchError(Next.CatchError)";
86
+ static displayName = "catchError(Next.CatchError)";
87
87
  constructor(props) {
88
88
  super(props);
89
89
  this.state = {
@@ -108,19 +108,24 @@ var _CatchError = class extends React.Component {
108
108
  reset = () => {
109
109
  this.setState({ error: null });
110
110
  };
111
- unstable_retry = () => {
112
- if (this.props.isPagesRouter) throw new Error("`unstable_retry()` can only be used in the App Router. Use `reset()` in the Pages Router.");
111
+ retry = () => {
112
+ if (this.props.isPagesRouter) throw new Error("`retry()` can only be used in the App Router. Use `reset()` in the Pages Router.");
113
113
  React.startTransition(() => {
114
114
  this.context?.refresh();
115
115
  this.reset();
116
116
  });
117
117
  };
118
+ unstable_retry = () => {
119
+ if (this.props.isPagesRouter) throw new Error("`unstable_retry()` can only be used in the App Router. Use `reset()` in the Pages Router.");
120
+ this.retry();
121
+ };
118
122
  render() {
119
123
  if (this.state.error) {
120
124
  const Fallback = this.props.fallback;
121
125
  const errorInfo = {
122
- error: this.state.error.thrownValue instanceof Error ? this.state.error.thrownValue : new Error(String(this.state.error.thrownValue)),
126
+ error: this.state.error.thrownValue,
123
127
  reset: this.reset,
128
+ retry: this.retry,
124
129
  unstable_retry: this.unstable_retry
125
130
  };
126
131
  return React.createElement(Fallback, {
@@ -139,7 +144,7 @@ var _CatchError = class extends React.Component {
139
144
  * Ported from Next.js:
140
145
  * https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/catch-error.tsx
141
146
  */
142
- function unstable_catchError(fallback) {
147
+ function createCatchError(fallback) {
143
148
  const Fallback = ({ props, errorInfo }) => fallback(props, errorInfo);
144
149
  Fallback.displayName = fallback.name || "CatchErrorFallback";
145
150
  function CatchErrorBoundary(allProps) {
@@ -154,8 +159,10 @@ function unstable_catchError(fallback) {
154
159
  props: forwardedProps
155
160
  }, children);
156
161
  }
157
- CatchErrorBoundary.displayName = `unstable_catchError(${fallback.name || "CatchErrorFallback"})`;
162
+ CatchErrorBoundary.displayName = `catchError(${fallback.name || "CatchErrorFallback"})`;
158
163
  return CatchErrorBoundary;
159
164
  }
165
+ const catchError = createCatchError;
166
+ const unstable_catchError = createCatchError;
160
167
  //#endregion
161
- export { ErrorComponent as default, unstable_catchError };
168
+ export { catchError, ErrorComponent as default, unstable_catchError };
@@ -1,8 +1,6 @@
1
+ import { ErrorInfo } from "./error.js";
1
2
  //#region src/shims/error.react-server.d.ts
2
- export type ErrorInfo = {
3
- error: unknown;
4
- reset: () => void;
5
- unstable_retry: () => void;
6
- };
7
3
  export declare function unstable_catchError(): never;
8
- //#endregion
4
+ export declare function catchError(): never;
5
+ //#endregion
6
+ export type { ErrorInfo };
@@ -2,5 +2,8 @@
2
2
  function unstable_catchError() {
3
3
  throw new Error("`unstable_catchError` can only be used in Client Components.");
4
4
  }
5
+ function catchError() {
6
+ throw new Error("`catchError` can only be used in Client Components.");
7
+ }
5
8
  //#endregion
6
- export { unstable_catchError };
9
+ export { catchError, unstable_catchError };
@@ -103,6 +103,12 @@ export declare function setRefreshStaleFetchesInForeground(enabled: boolean): vo
103
103
  * try { await render(); } finally { cleanup(); }
104
104
  */
105
105
  export declare function withFetchCache(): () => void;
106
+ /**
107
+ * Run `fn` with the request's fetch settings but its own record of the tags and
108
+ * URLs its fetches touch, so work done on the request's behalf after the fact
109
+ * (a background regeneration) leaves the request's response untouched.
110
+ */
111
+ export declare function runWithDetachedFetchObservations<T>(fn: () => Promise<T>): Promise<T>;
106
112
  /**
107
113
  * Run an async function with patched fetch caching enabled.
108
114
  * Uses `AsyncLocalStorage.run()` for proper per-request isolation
@@ -4,7 +4,8 @@ import { getRequestExecutionContext } from "./request-context.js";
4
4
  import { getDataCacheHandler } from "./cache-handler.js";
5
5
  import { encodeCacheTags } from "../utils/encode-cache-tag.js";
6
6
  import { traceAppFetch } from "../server/app-fetch-tracing.js";
7
- import { getHeadersContext, isInsideAnyCacheScope, markDynamicUsage } from "./headers.js";
7
+ import { isInsideAnyCacheScope, markDynamicUsage } from "./internal/headers-state.js";
8
+ import { getHeadersContext } from "./headers.js";
8
9
  import { _hasPendingRevalidatedTag, _setRequestScopedCacheLife } from "./cache-request-state.js";
9
10
  import { Buffer } from "node:buffer";
10
11
  //#region src/shims/fetch-cache.ts
@@ -688,11 +689,12 @@ function createPatchedFetch() {
688
689
  recordDynamicFetchObservation(input);
689
690
  return recordFetchOutcome(await dedupeFetch(input, cleanInit), "skip", "auto no cache");
690
691
  }
692
+ const tags = encodeCacheTags(nextOpts?.tags ?? []);
691
693
  let revalidateSeconds;
692
694
  if (cacheDirective === "force-cache") revalidateSeconds = nextOpts?.revalidate && typeof nextOpts.revalidate === "number" ? nextOpts.revalidate : ONE_YEAR_SECONDS;
693
695
  else if (nextOpts?.revalidate === false) revalidateSeconds = ONE_YEAR_SECONDS;
694
696
  else if (typeof nextOpts?.revalidate === "number" && nextOpts.revalidate > 0) revalidateSeconds = nextOpts.revalidate;
695
- else if (nextOpts?.tags && nextOpts.tags.length > 0) {
697
+ else if (tags.length > 0) {
696
698
  const routeRevalidate = _getState().currentFetchRevalidate;
697
699
  if (routeRevalidate === 0) {
698
700
  const cleanInit = stripNextFromInit(init, cacheDirective);
@@ -712,7 +714,6 @@ function createPatchedFetch() {
712
714
  recordFiniteFetchRevalidate(nextOpts.revalidate);
713
715
  }
714
716
  const reqTags = _getState().currentRequestTags;
715
- const tags = encodeCacheTags(nextOpts?.tags ?? []);
716
717
  if (tags.length > 0) {
717
718
  for (const tag of tags) if (!reqTags.includes(tag)) reqTags.push(tag);
718
719
  }
@@ -833,6 +834,24 @@ function withFetchCache() {
833
834
  };
834
835
  }
835
836
  /**
837
+ * Run `fn` with the request's fetch settings but its own record of the tags and
838
+ * URLs its fetches touch, so work done on the request's behalf after the fact
839
+ * (a background regeneration) leaves the request's response untouched.
840
+ */
841
+ function runWithDetachedFetchObservations(fn) {
842
+ if (isInsideUnifiedScope()) return runWithUnifiedStateMutation((uCtx) => {
843
+ uCtx.cacheableFetchUrls = /* @__PURE__ */ new Set();
844
+ uCtx.currentRequestTags = [];
845
+ uCtx.dynamicFetchUrls = /* @__PURE__ */ new Set();
846
+ }, fn);
847
+ return _als.run({
848
+ ..._getState(),
849
+ cacheableFetchUrls: /* @__PURE__ */ new Set(),
850
+ currentRequestTags: [],
851
+ dynamicFetchUrls: /* @__PURE__ */ new Set()
852
+ }, fn);
853
+ }
854
+ /**
836
855
  * Run an async function with patched fetch caching enabled.
837
856
  * Uses `AsyncLocalStorage.run()` for proper per-request isolation
838
857
  * of collected fetch tags in concurrent server environments.
@@ -896,4 +915,4 @@ function getOriginalFetch() {
896
915
  return originalFetch;
897
916
  }
898
917
  //#endregion
899
- export { _resetPendingRefetches, addCollectedRequestTags, consumeDynamicFetchObservations, ensureFetchPatch, getCollectedFetchTags, getCurrentFetchSoftTags, getOriginalFetch, peekCacheableFetchObservations, peekDynamicFetchObservations, runWithFetchCache, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, setRefreshStaleFetchesInForeground, withFetchCache };
918
+ export { _resetPendingRefetches, addCollectedRequestTags, consumeDynamicFetchObservations, ensureFetchPatch, getCollectedFetchTags, getCurrentFetchSoftTags, getOriginalFetch, peekCacheableFetchObservations, peekDynamicFetchObservations, runWithDetachedFetchObservations, runWithFetchCache, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, setRefreshStaleFetchesInForeground, withFetchCache };
@@ -4,9 +4,9 @@ import { VINEXT_MOUNTED_SLOTS_HEADER } from "../server/app-rsc-vary.js";
4
4
  import "../server/headers.js";
5
5
  import { assertSafeNavigationUrl } from "./url-safety.js";
6
6
  import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "../server/app-rsc-render-mode.js";
7
+ import { withBasePath } from "./url-utils.js";
7
8
  import { AppElementsWire } from "../server/app-elements-wire.js";
8
9
  import "../server/app-elements.js";
9
- import { withBasePath } from "./url-utils.js";
10
10
  import { createRscRequestHeaders, createRscRequestUrl } from "../server/app-rsc-cache-busting.js";
11
11
  import { hasAppNavigationRuntime } from "../client/navigation-runtime.js";
12
12
  import { getMountedSlotsHeader, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, navigateClientSide, prefetchRscResponse } from "./navigation.js";
@@ -1,4 +1,6 @@
1
1
  import { RenderRequestApiKind } from "../server/cache-proof.js";
2
+ import { CacheLifeConfig } from "./cache-request-state.js";
3
+ import { ConnectionProbeResult, HeadersAccessPhase, RenderDynamicLatch, VinextHeadersShimState, createRenderDynamicLatch, getHeadersAccessPhase, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, throwIfInsideCacheScope, throwIfStaticGenerationAccessError } from "./internal/headers-state.js";
2
4
  import { ReadonlyRequestCookies } from "@vinext/types/next/upstream/dist/server/web/spec-extension/adapters/request-cookies";
3
5
  import { ResponseCookie } from "@vinext/types/next/upstream/dist/compiled/@edge-runtime/cookies/index";
4
6
  //#region src/shims/headers.d.ts
@@ -16,61 +18,6 @@ export type HeadersContext = {
16
18
  type HeadersContextFromRequestOptions = {
17
19
  draftModeSecret?: string;
18
20
  };
19
- export type HeadersAccessPhase = "render" | "action" | "route-handler";
20
- /**
21
- * Whether the current render has used a dynamic API. Unlike
22
- * `dynamicUsageDetected`, nothing clears it, and one object is shared by every
23
- * child scope of the request, so usage inside isolated scopes (such as the
24
- * layout probe) stays visible to later readers.
25
- */
26
- export type RenderDynamicLatch = {
27
- dynamic: boolean;
28
- listeners: Set<() => void>;
29
- };
30
- export declare function createRenderDynamicLatch(): RenderDynamicLatch;
31
- export type VinextHeadersShimState = {
32
- headersContext: HeadersContext | null;
33
- dynamicUsageDetected: boolean;
34
- renderDynamicLatch: RenderDynamicLatch;
35
- renderRequestApiUsage: Set<RenderRequestApiKind>;
36
- connectionProbe: ConnectionProbeState | null;
37
- /** Error recorded by throwIfInsideCacheScope for dev diagnostics, persists even if caught by user code. */
38
- invalidDynamicUsageError: unknown;
39
- pendingSetCookies: string[];
40
- draftModeCookieHeader: string | null;
41
- phase: HeadersAccessPhase;
42
- };
43
- type ConnectionProbeState = {
44
- active: boolean;
45
- dynamicUsageTarget: VinextHeadersShimState;
46
- interrupted: boolean;
47
- interrupt: () => void;
48
- pending: Promise<never>;
49
- };
50
- type ConnectionProbeResult<T> = {
51
- completed: true;
52
- result: T;
53
- } | {
54
- completed: false;
55
- };
56
- /**
57
- * Dynamic usage flag — set when a component calls connection(), cookies(),
58
- * headers(), or noStore() during rendering. When true, ISR caching is
59
- * bypassed and the response gets Cache-Control: no-store.
60
- */
61
- /**
62
- * Mark the current render as requiring dynamic (uncached) rendering.
63
- * Called by connection(), cookies(), headers(), and noStore().
64
- */
65
- export declare function markDynamicUsage(): void;
66
- /** Whether the current render has used a dynamic API at any point so far. */
67
- export declare function isRenderDynamicLatched(): boolean;
68
- /**
69
- * Call `listener` once when the current render first uses a dynamic API.
70
- * Returns an unsubscribe function. The listener never runs if the render is
71
- * already latched; check `isRenderDynamicLatched()` first.
72
- */
73
- export declare function onRenderDynamicLatched(listener: () => void): () => void;
74
21
  /**
75
22
  * Measure dynamic usage in a child async scope without clearing the parent.
76
23
  * Concurrent work that already belongs to the request (such as deferred
@@ -81,22 +28,22 @@ export declare function runWithIsolatedDynamicUsage<T>(fn: () => T | Promise<T>)
81
28
  result: T;
82
29
  dynamicDetected: boolean;
83
30
  }>;
84
- export declare function markRenderRequestApiUsage(kind: RenderRequestApiKind): void;
85
- export declare function throwIfStaticGenerationAccessError(): void;
31
+ /**
32
+ * Run a pre-render probe without letting its dynamic API usage classify the
33
+ * request. Next.js has no probe: only the render decides whether a page is
34
+ * dynamic, and the render runs the probed layouts and page again. Returns the
35
+ * probe's own usage and cacheLife for a caller whose probe response replaces
36
+ * the render.
37
+ */
38
+ export declare function runWithDetachedDynamicUsage<T>(fn: () => T | Promise<T>): Promise<{
39
+ result: T;
40
+ dynamicDetected: boolean;
41
+ cacheLife: CacheLifeConfig | null;
42
+ }>;
86
43
  export declare function runWithConnectionProbe<T>(fn: () => T | Promise<T>): Promise<ConnectionProbeResult<T>>;
87
44
  export declare function suspendConnectionProbe(): Promise<never> | null;
88
45
  export declare function peekRenderRequestApiUsage(): RenderRequestApiKind[];
89
46
  export declare function consumeRenderRequestApiUsage(): RenderRequestApiKind[];
90
- /** Whether work is executing inside a cache boundary that owns its reuse. */
91
- export declare function isInsideAnyCacheScope(): boolean;
92
- /**
93
- * Throw if the current execution is inside a "use cache" or unstable_cache()
94
- * scope. Called by dynamic request APIs (headers, cookies, connection) to
95
- * prevent request-specific data from being frozen into cached results.
96
- *
97
- * @param apiName - The name of the API being called (e.g. "connection()")
98
- */
99
- export declare function throwIfInsideCacheScope(apiName: string): void;
100
47
  /**
101
48
  * Check, consume, and return any invalid dynamic usage error recorded during
102
49
  * the render (e.g. cookies() called inside "use cache"). This error persists
@@ -121,7 +68,6 @@ export declare function consumeDynamicUsage(): boolean;
121
68
  */
122
69
  export declare function peekDynamicUsage(): boolean;
123
70
  export declare function setHeadersAccessPhase(phase: HeadersAccessPhase): HeadersAccessPhase;
124
- export declare function getHeadersAccessPhase(): HeadersAccessPhase;
125
71
  /**
126
72
  * Set the headers/cookies context for the current RSC render.
127
73
  * Called by the framework's RSC entry before rendering each request.
@@ -151,6 +97,8 @@ export declare function hasEffectiveRequestCookieChanges(cookieHeader: string |
151
97
  export declare function applyEffectiveRequestCookieHeader(cookieHeader: string): void;
152
98
  /** Restore a middleware draft-mode transition inside a staged render scope. */
153
99
  export declare function restoreDraftModeTransition(cookieHeader: string): void;
100
+ /** Replace request API inputs while retaining dynamic usage and pending mutations. */
101
+ export declare function replaceHeadersContext(ctx: HeadersContext): void;
154
102
  export declare function setHeadersContext(ctx: HeadersContext | null): void;
155
103
  /**
156
104
  * Run a function with headers context, ensuring the context propagates
@@ -224,6 +172,8 @@ export declare function getAndClearPendingCookies(): string[];
224
172
  * Get any Set-Cookie header generated by draftMode().enable()/disable().
225
173
  * Called by the framework after rendering to attach the header to the response.
226
174
  */
175
+ /** Check a pending draft transition without consuming its outgoing cookie. */
176
+ export declare function hasDraftModeCookieHeader(): boolean;
227
177
  export declare function getDraftModeCookieHeader(): string | null;
228
178
  export declare function isDraftModeRequest(request: Request, draftModeSecret: string): boolean;
229
179
  /**
@@ -288,4 +238,4 @@ declare class RequestCookies {
288
238
  [SYNCHRONIZE_REQUEST_COOKIES](): void;
289
239
  }
290
240
  //#endregion
291
- export type { RequestCookies };
241
+ export { type HeadersAccessPhase, type RenderDynamicLatch, type RequestCookies, type VinextHeadersShimState, createRenderDynamicLatch, getHeadersAccessPhase, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };