vinext 1.1.0 → 1.2.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 (234) hide show
  1. package/README.md +21 -9
  2. package/dist/build/client-build-config.d.ts +10 -0
  3. package/dist/build/client-build-config.js +18 -2
  4. package/dist/build/pages-client-assets-module.d.ts +8 -0
  5. package/dist/build/pages-client-assets-module.js +21 -1
  6. package/dist/build/prerender-paths.js +5 -3
  7. package/dist/build/run-prerender.js +1 -1
  8. package/dist/build/ssr-manifest.d.ts +2 -0
  9. package/dist/build/ssr-manifest.js +6 -2
  10. package/dist/check.js +7 -6
  11. package/dist/cli.js +2 -1
  12. package/dist/client/client-redirect-matcher.d.ts +14 -0
  13. package/dist/client/client-redirect-matcher.js +37 -0
  14. package/dist/client/client-redirects.d.ts +27 -0
  15. package/dist/client/client-redirects.js +28 -0
  16. package/dist/client/client-rewrites.d.ts +2 -1
  17. package/dist/client/client-rewrites.js +1 -1
  18. package/dist/config/config-matchers.d.ts +26 -11
  19. package/dist/config/config-matchers.js +78 -81
  20. package/dist/config/destination-params.d.ts +47 -0
  21. package/dist/config/destination-params.js +116 -0
  22. package/dist/config/next-config.d.ts +7 -0
  23. package/dist/config/next-config.js +3 -0
  24. package/dist/entries/app-rsc-entry.d.ts +4 -0
  25. package/dist/entries/app-rsc-entry.js +20 -6
  26. package/dist/entries/pages-client-entry.js +3 -1
  27. package/dist/entries/pages-server-entry.js +13 -37
  28. package/dist/index.d.ts +3 -1
  29. package/dist/index.js +134 -43
  30. package/dist/init-cloudflare.d.ts +9 -0
  31. package/dist/init-cloudflare.js +107 -31
  32. package/dist/init-platform.d.ts +4 -0
  33. package/dist/init-platform.js +27 -2
  34. package/dist/init.d.ts +1 -0
  35. package/dist/init.js +67 -3
  36. package/dist/plugins/ast-scope.d.ts +7 -0
  37. package/dist/plugins/ast-scope.js +59 -3
  38. package/dist/plugins/cache-flight-codec.d.ts +1 -1
  39. package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
  40. package/dist/plugins/dynamic-preload-metadata.js +9 -8
  41. package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
  42. package/dist/plugins/ignore-dynamic-requests.js +3 -4
  43. package/dist/plugins/middleware-server-only.d.ts +5 -4
  44. package/dist/plugins/middleware-server-only.js +8 -5
  45. package/dist/plugins/pages-node-externals.js +1 -1
  46. package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
  47. package/dist/plugins/rsc-scan-glob-imports.js +50 -0
  48. package/dist/plugins/strip-server-exports.js +262 -98
  49. package/dist/plugins/transform-result.d.ts +9 -5
  50. package/dist/plugins/transitive-externals.js +1 -1
  51. package/dist/plugins/typeof-window.d.ts +2 -2
  52. package/dist/plugins/use-cache-callable.js +8 -2
  53. package/dist/plugins/worker-server-only-imports.d.ts +20 -0
  54. package/dist/plugins/worker-server-only-imports.js +31 -0
  55. package/dist/plugins/worker-use-server.d.ts +25 -0
  56. package/dist/plugins/worker-use-server.js +129 -0
  57. package/dist/server/api-handler.d.ts +1 -0
  58. package/dist/server/api-handler.js +2 -1
  59. package/dist/server/app-browser-action-result.d.ts +1 -1
  60. package/dist/server/app-browser-action-result.js +9 -2
  61. package/dist/server/app-browser-navigation-controller.js +1 -1
  62. package/dist/server/app-browser-server-action-client.js +1 -1
  63. package/dist/server/app-middleware.d.ts +11 -0
  64. package/dist/server/app-middleware.js +17 -2
  65. package/dist/server/app-page-cache.d.ts +1 -1
  66. package/dist/server/app-page-cache.js +1 -1
  67. package/dist/server/app-page-dispatch.d.ts +3 -1
  68. package/dist/server/app-page-dispatch.js +4 -3
  69. package/dist/server/app-page-ppr-runtime.js +1 -1
  70. package/dist/server/app-page-render-observation.js +1 -1
  71. package/dist/server/app-page-request.js +53 -15
  72. package/dist/server/app-page-route-wiring.js +2 -2
  73. package/dist/server/app-pages-bridge.d.ts +1 -1
  74. package/dist/server/app-pages-bridge.js +2 -3
  75. package/dist/server/app-prerender-endpoints.js +9 -6
  76. package/dist/server/app-request-stage-dispatch.js +6 -2
  77. package/dist/server/app-request-stage-independent-entry.js +25 -5
  78. package/dist/server/app-response-stage-entry.js +10 -2
  79. package/dist/server/app-route-handler-cache.d.ts +1 -0
  80. package/dist/server/app-route-handler-cache.js +1 -0
  81. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  82. package/dist/server/app-route-handler-dispatch.js +5 -2
  83. package/dist/server/app-route-handler-execution.d.ts +1 -0
  84. package/dist/server/app-route-handler-execution.js +1 -0
  85. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  86. package/dist/server/app-route-handler-runtime.js +45 -24
  87. package/dist/server/app-router-entry.js +24 -5
  88. package/dist/server/app-rsc-cache-busting.js +1 -1
  89. package/dist/server/app-rsc-errors.js +20 -16
  90. package/dist/server/app-rsc-handler.d.ts +7 -0
  91. package/dist/server/app-rsc-handler.js +85 -35
  92. package/dist/server/app-rsc-response-stage.js +4 -2
  93. package/dist/server/app-segment-config.d.ts +2 -1
  94. package/dist/server/app-server-action-execution.d.ts +2 -1
  95. package/dist/server/app-server-action-execution.js +61 -22
  96. package/dist/server/app-ssr-entry.js +2 -1
  97. package/dist/server/app-worker-stages.d.ts +5 -0
  98. package/dist/server/app-worker-stages.js +1 -1
  99. package/dist/server/cacheability-request.js +2 -2
  100. package/dist/server/client-build-files.d.ts +16 -0
  101. package/dist/server/client-build-files.js +36 -0
  102. package/dist/server/client-reuse-manifest.js +1 -1
  103. package/dist/server/dev-server.js +38 -27
  104. package/dist/server/dev-stack-sourcemap.js +18 -23
  105. package/dist/server/document-initial-head.d.ts +0 -11
  106. package/dist/server/document-initial-head.js +1 -1
  107. package/dist/server/forwarded-middleware-context.d.ts +5 -0
  108. package/dist/server/forwarded-middleware-context.js +22 -0
  109. package/dist/server/headers.d.ts +4 -1
  110. package/dist/server/headers.js +4 -1
  111. package/dist/server/http-conditional.d.ts +11 -0
  112. package/dist/server/http-conditional.js +10 -1
  113. package/dist/server/http-error-responses.d.ts +1 -1
  114. package/dist/server/image-optimization.d.ts +38 -0
  115. package/dist/server/image-optimization.js +93 -4
  116. package/dist/server/isr-cache.d.ts +10 -0
  117. package/dist/server/isr-cache.js +41 -6
  118. package/dist/server/metadata-route-response.js +9 -8
  119. package/dist/server/middleware-matcher.d.ts +2 -0
  120. package/dist/server/middleware-matcher.js +23 -2
  121. package/dist/server/middleware-runtime.d.ts +13 -0
  122. package/dist/server/middleware-runtime.js +33 -20
  123. package/dist/server/middleware.d.ts +1 -1
  124. package/dist/server/middleware.js +3 -1
  125. package/dist/server/multi-stage.d.ts +11 -0
  126. package/dist/server/normalize-path.d.ts +0 -13
  127. package/dist/server/normalize-path.js +1 -34
  128. package/dist/server/pages-api-route.d.ts +3 -2
  129. package/dist/server/pages-api-route.js +4 -3
  130. package/dist/server/pages-cache-tag.d.ts +12 -0
  131. package/dist/server/pages-cache-tag.js +19 -0
  132. package/dist/server/pages-client-assets.d.ts +2 -0
  133. package/dist/server/pages-data-route.d.ts +10 -0
  134. package/dist/server/pages-data-route.js +19 -2
  135. package/dist/server/pages-document-asset-props.d.ts +5 -1
  136. package/dist/server/pages-document-asset-props.js +13 -5
  137. package/dist/server/pages-document-splice.d.ts +19 -0
  138. package/dist/server/pages-document-splice.js +55 -0
  139. package/dist/server/pages-i18n.d.ts +12 -1
  140. package/dist/server/pages-i18n.js +18 -4
  141. package/dist/server/pages-node-compat.d.ts +16 -5
  142. package/dist/server/pages-node-compat.js +20 -12
  143. package/dist/server/pages-page-data.d.ts +32 -24
  144. package/dist/server/pages-page-data.js +50 -120
  145. package/dist/server/pages-page-handler.d.ts +0 -6
  146. package/dist/server/pages-page-handler.js +188 -126
  147. package/dist/server/pages-page-response.d.ts +12 -6
  148. package/dist/server/pages-page-response.js +41 -34
  149. package/dist/server/pages-request-pipeline.d.ts +10 -2
  150. package/dist/server/pages-request-pipeline.js +37 -18
  151. package/dist/server/pages-request-stage-entry.d.ts +6 -0
  152. package/dist/server/pages-request-stage-entry.js +71 -12
  153. package/dist/server/pages-response-stage-entry.js +4 -0
  154. package/dist/server/pages-revalidate.js +1 -1
  155. package/dist/server/pages-router-entry.js +4 -3
  156. package/dist/server/prerender-manifest.d.ts +3 -3
  157. package/dist/server/prerender-manifest.js +4 -3
  158. package/dist/server/prerender-work-unit-setup.js +4 -0
  159. package/dist/server/prod-server.d.ts +12 -0
  160. package/dist/server/prod-server.js +199 -69
  161. package/dist/server/proper-error.d.ts +4 -0
  162. package/dist/server/proper-error.js +31 -0
  163. package/dist/server/request-pipeline.d.ts +4 -1
  164. package/dist/server/request-pipeline.js +3 -2
  165. package/dist/server/revalidation-request.d.ts +1 -0
  166. package/dist/server/revalidation-request.js +1 -1
  167. package/dist/server/rsc-stream-hints.js +31 -2
  168. package/dist/server/seed-cache.d.ts +1 -0
  169. package/dist/server/seed-cache.js +5 -4
  170. package/dist/server/server-reference-loader.d.ts +4 -0
  171. package/dist/server/server-reference-loader.js +29 -0
  172. package/dist/server/socket-error-backstop.d.ts +9 -1
  173. package/dist/server/socket-error-backstop.js +46 -17
  174. package/dist/server/static-file-signal.d.ts +15 -4
  175. package/dist/server/static-file-signal.js +46 -12
  176. package/dist/server/worker-image-optimization.d.ts +34 -0
  177. package/dist/server/worker-image-optimization.js +86 -0
  178. package/dist/server/worker-stages.d.ts +1 -1
  179. package/dist/server/worker-stages.js +2 -2
  180. package/dist/server/worker-utils.d.ts +8 -3
  181. package/dist/server/worker-utils.js +12 -7
  182. package/dist/shims/app-router-scroll.js +4 -1
  183. package/dist/shims/app-router-tree-context.d.ts +5 -0
  184. package/dist/shims/app-router-tree-context.js +27 -0
  185. package/dist/shims/cache-callable-runtime.d.ts +4 -2
  186. package/dist/shims/cache-callable-runtime.js +21 -12
  187. package/dist/shims/cache-handler.js +1 -9
  188. package/dist/shims/cache-runtime.d.ts +6 -1
  189. package/dist/shims/cache-runtime.js +2 -1
  190. package/dist/shims/cache.d.ts +2 -2
  191. package/dist/shims/cache.js +40 -13
  192. package/dist/shims/cdn-cache.d.ts +8 -0
  193. package/dist/shims/cdn-cache.js +17 -1
  194. package/dist/shims/disable-smooth-scroll.d.ts +3 -0
  195. package/dist/shims/disable-smooth-scroll.js +36 -0
  196. package/dist/shims/document-placeholders.d.ts +19 -0
  197. package/dist/shims/document-placeholders.js +45 -0
  198. package/dist/shims/document.js +21 -5
  199. package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
  200. package/dist/shims/dynamic-preload-chunks.js +13 -9
  201. package/dist/shims/dynamic.d.ts +1 -1
  202. package/dist/shims/dynamic.js +60 -8
  203. package/dist/shims/fetch-cache-state.d.ts +66 -0
  204. package/dist/shims/fetch-cache-state.js +92 -0
  205. package/dist/shims/fetch-cache.d.ts +3 -67
  206. package/dist/shims/fetch-cache.js +160 -125
  207. package/dist/shims/head.d.ts +10 -6
  208. package/dist/shims/head.js +15 -13
  209. package/dist/shims/image.js +2 -1
  210. package/dist/shims/internal/work-store-scope.d.ts +5 -0
  211. package/dist/shims/internal/work-store-scope.js +24 -0
  212. package/dist/shims/navigation.js +31 -5
  213. package/dist/shims/request-context.d.ts +2 -0
  214. package/dist/shims/request-state-types.d.ts +2 -1
  215. package/dist/shims/router.js +12 -20
  216. package/dist/shims/server.d.ts +16 -0
  217. package/dist/shims/server.js +24 -4
  218. package/dist/shims/unified-request-context.d.ts +1 -1
  219. package/dist/shims/url-utils.d.ts +2 -0
  220. package/dist/shims/url-utils.js +3 -1
  221. package/dist/utils/client-runtime-metadata.js +1 -1
  222. package/dist/utils/hash.d.ts +7 -0
  223. package/dist/utils/hash.js +11 -1
  224. package/dist/utils/package-name.d.ts +6 -0
  225. package/dist/utils/package-name.js +12 -1
  226. package/dist/utils/plugin-rsc-version.d.ts +4 -0
  227. package/dist/utils/plugin-rsc-version.js +15 -0
  228. package/dist/utils/prerender-output-paths.js +15 -4
  229. package/dist/utils/public-file-path.d.ts +10 -2
  230. package/dist/utils/public-file-path.js +13 -9
  231. package/dist/utils/public-routes.js +2 -2
  232. package/dist/utils/react-version.d.ts +3 -0
  233. package/dist/utils/react-version.js +1 -1
  234. package/package.json +7 -3
@@ -9,14 +9,15 @@ import { getPprFallbackShellState, markPprFallbackShellDynamicBoundary } from ".
9
9
  import { AppRouterContext } from "./internal/app-router-context.js";
10
10
  import { resolveDirectHybridClientRouteOwner } from "./internal/hybrid-client-route-owner-direct.js";
11
11
  import { isHashOnlyBrowserUrlChange, toCanonicalBrowserNavigationHref, toSameOriginAppPath, withBasePath } from "./url-utils.js";
12
- import { retryScrollTo, scrollToHashTarget, scrollToHashTargetOnNextFrame } from "./hash-scroll.js";
12
+ import { disableSmoothScrollDuringRouteTransition } from "./disable-smooth-scroll.js";
13
+ import { retryScrollTo, scrollToHashTarget } from "./hash-scroll.js";
13
14
  import { AppElementsWire } from "../server/app-elements-wire.js";
14
15
  import "../server/app-elements.js";
15
16
  import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessors, clearClientHydrationContext, clearServerInsertedHTML, flushServerInsertedHTML, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getLayoutSegmentContext, getNavigationContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "./navigation-context-state.js";
16
17
  import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow } from "./navigation-errors.js";
17
18
  import { clearAppNavigationFailureTarget, stageAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
18
19
  import { beginAppRouterScrollIntent, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, isLatestAppRouterScrollIntent } from "./app-router-scroll-state.js";
19
- import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam, stripRscSuffix } from "../server/app-rsc-cache-busting.js";
20
+ import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam, stripRscSuffix } from "../server/app-rsc-cache-busting.js";
20
21
  import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
21
22
  import { getNavigationRuntime, hasAppNavigationRuntime } from "../client/navigation-runtime.js";
22
23
  import { UnrecognizedActionError, unstable_isUnrecognizedActionError } from "./unrecognized-action-error.js";
@@ -797,6 +798,22 @@ async function fetchRouteTreeGatedPrefetch(options) {
797
798
  return fetchFullRscPayload();
798
799
  }
799
800
  /**
801
+ * Whether a prefetch response may be decoded as Flight. A successful response
802
+ * that is not Flight (e.g. a Route Handler's text download) is a miss: decoding
803
+ * its bytes would let text shaped like Flight resource hints insert scripts.
804
+ * Navigation then fetches it and falls back to a document navigation.
805
+ *
806
+ * Ported from Next.js: fetchPrefetchResponse in
807
+ * packages/next/src/client/components/segment-cache/cache.ts, which skips the
808
+ * check in `output: "export"` because a static host, not Next.js, chooses the
809
+ * MIME type of the exported `.txt` payloads.
810
+ */
811
+ function isFlightPrefetchResponse(response) {
812
+ if (!response.ok) return false;
813
+ if (process.env.NODE_ENV === "production" && process.env.__NEXT_CONFIG_OUTPUT === "export") return true;
814
+ return response.headers.get("content-type")?.toLowerCase().startsWith(VINEXT_RSC_CONTENT_TYPE) === true;
815
+ }
816
+ /**
800
817
  * Prefetch an RSC response and snapshot it for later consumption.
801
818
  * Stores the in-flight promise so immediate clicks can await it instead
802
819
  * of firing a duplicate fetch.
@@ -824,7 +841,7 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
824
841
  addPrefetchInvalidationCallback(entry, options?.onInvalidate);
825
842
  entry.fetchPromise = fetchPromise;
826
843
  entry.pending = fetchPromise.then(async (response) => {
827
- if (response.ok) {
844
+ if (isFlightPrefetchResponse(response)) {
828
845
  const snapshot = await snapshotRscResponse(response);
829
846
  if (cache.get(cacheKey) !== entry) return;
830
847
  const previousSize = getPrefetchCacheEntrySize(entry);
@@ -841,6 +858,7 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
841
858
  evictPrefetchCacheIfNeeded();
842
859
  } else {
843
860
  releaseAppPrefetchFetchSlot(response);
861
+ response.body?.cancel().catch(() => {});
844
862
  deletePrefetchCacheEntry(cache, prefetched, cacheKey, entry, false);
845
863
  }
846
864
  }).catch(() => {
@@ -1333,11 +1351,19 @@ function commitHashOnlyHistoryState(href, mode, scroll) {
1333
1351
  function applyAppRouterScrollFallback(intent) {
1334
1352
  if (typeof document === "undefined" || typeof window === "undefined") return;
1335
1353
  if (intent.hash !== null) {
1336
- scrollToHashTargetOnNextFrame(intent.hash, () => isLatestAppRouterScrollIntent(intent));
1354
+ const hash = intent.hash;
1355
+ requestAnimationFrame(() => {
1356
+ if (!isLatestAppRouterScrollIntent(intent)) return;
1357
+ disableSmoothScrollDuringRouteTransition(() => {
1358
+ scrollToHashTarget(hash);
1359
+ });
1360
+ });
1337
1361
  return;
1338
1362
  }
1339
1363
  if (intent.targetHoistedInHead) return;
1340
- document.documentElement.scrollTop = 0;
1364
+ disableSmoothScrollDuringRouteTransition(() => {
1365
+ document.documentElement.scrollTop = 0;
1366
+ });
1341
1367
  }
1342
1368
  function scheduleAppRouterScrollFallback(intent) {
1343
1369
  queueMicrotask(() => {
@@ -44,6 +44,8 @@ export type ExecutionContextLike = {
44
44
  isInternalPagesRevalidation?: boolean;
45
45
  /** Marks a build-secret-authorized Worker request that may run prerender discovery hooks. */
46
46
  isPrerenderPathDiscovery?: boolean;
47
+ /** Marks an adapter-invoked regeneration of an entry stored for this build. */
48
+ isStoredEntryRegeneration?: boolean;
47
49
  /**
48
50
  * Installed only by the prerender server: records the page's special error
49
51
  * that escaped the shell, with the headers to store, for the build.
@@ -3,7 +3,8 @@ import { NavigationContext } from "./navigation-context-state.js";
3
3
  import "./navigation.js";
4
4
  import { CacheLifeConfig, CacheState } from "./cache-request-state.js";
5
5
  import { RootParamsState } from "./root-params.js";
6
- import { FetchCacheState } from "./fetch-cache.js";
6
+ import { FetchCacheState } from "./fetch-cache-state.js";
7
+ import "./fetch-cache.js";
7
8
  import { HeadersAccessPhase, VinextHeadersShimState } from "./internal/headers-state.js";
8
9
  import { HeadersContext } from "./headers.js";
9
10
  import { RouterState, SSRContext } from "./router-state.js";
@@ -1,6 +1,7 @@
1
1
  import { isUnknownRecord } from "../utils/record.js";
2
2
  import { parseCookieHeader } from "../utils/parse-cookie.js";
3
3
  import { isExternalUrl } from "../utils/external-url.js";
4
+ import { substituteDestinationParams } from "../config/destination-params.js";
4
5
  import { sortRoutes, splitPathSegments } from "../routing/utils.js";
5
6
  import { hasBasePath, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
6
7
  import { assertSafeNavigationUrl } from "./url-safety.js";
@@ -19,6 +20,7 @@ import { resolveDirectHybridClientRouteOwner } from "./internal/hybrid-client-ro
19
20
  import { installWindowNext } from "../client/window-next.js";
20
21
  import { getWindowOrigin, isAbsoluteOrProtocolRelativeUrl, isAbsoluteUrl, isHashOnlyBrowserUrlChange, normalizePathTrailingSlash, toBrowserNavigationHref, toSameOriginAppPath, toSameOriginPath, withBasePath } from "./url-utils.js";
21
22
  import { addQueryParam, mergeRewriteQuery, mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
23
+ import { disableSmoothScrollDuringRouteTransition } from "./disable-smooth-scroll.js";
22
24
  import { scrollToHashTarget } from "./hash-scroll.js";
23
25
  import { installPagesRouterRuntime, setPagesRouterPopStateHandler, setStampInitialHistoryState } from "./pages-router-runtime.js";
24
26
  import { interpolateDynamicRouteHref, resolveDynamicRouteHref } from "./internal/interpolate-as.js";
@@ -129,16 +131,9 @@ function scrollToPagesRouterPosition({ x, y }) {
129
131
  window.scrollTo(x, y);
130
132
  return;
131
133
  }
132
- const htmlElement = document.documentElement;
133
- if (!(htmlElement.dataset.scrollBehavior === "smooth")) {
134
+ disableSmoothScrollDuringRouteTransition(() => {
134
135
  window.scrollTo(x, y);
135
- return;
136
- }
137
- const previousScrollBehavior = htmlElement.style.scrollBehavior;
138
- htmlElement.style.scrollBehavior = "auto";
139
- htmlElement.getClientRects();
140
- window.scrollTo(x, y);
141
- htmlElement.style.scrollBehavior = previousScrollBehavior;
136
+ });
142
137
  }
143
138
  function isAtScrollPosition({ x, y }) {
144
139
  return Math.abs(window.scrollX - x) <= SCROLL_RESTORE_TOLERANCE_PX && Math.abs(window.scrollY - y) <= SCROLL_RESTORE_TOLERANCE_PX;
@@ -1020,10 +1015,10 @@ async function resolveClientConfigRedirect(href) {
1020
1015
  if (!redirects || redirects.length === 0) return null;
1021
1016
  const routeContext = getClientConfigRouteContext(href);
1022
1017
  if (!routeContext) return null;
1023
- const { matchRedirect, preserveRedirectDestinationQuery } = await import("../config/config-matchers.js");
1024
- const redirect = matchRedirect(routeContext.pathname, redirects, routeContext.context, routeContext.basePathState);
1018
+ const [{ matchClientRedirect }, { preserveRedirectDestinationQuery }] = await Promise.all([import("../client/client-redirect-matcher.js"), import("../config/config-matchers.js")]);
1019
+ const redirect = matchClientRedirect(routeContext.pathname, redirects, routeContext.context, routeContext.basePathState);
1025
1020
  if (!redirect) return null;
1026
- return preserveRedirectDestinationQuery(__basePath && routeContext.basePathState.hadBasePath && !isExternalUrl(redirect.destination) && !hasBasePath(redirect.destination, __basePath) ? __basePath + redirect.destination : redirect.destination, routeContext.search);
1021
+ return preserveRedirectDestinationQuery(__basePath && routeContext.basePathState.hadBasePath && !isExternalUrl(redirect.destination) && !hasBasePath(redirect.destination, __basePath) ? __basePath + redirect.destination : redirect.destination, routeContext.search, redirect.destinationQuery);
1027
1022
  }
1028
1023
  async function applyClientConfigRewrite(href, rewrite) {
1029
1024
  const routeContext = getClientConfigRouteContext(href);
@@ -1076,12 +1071,6 @@ function simpleClientConfigSourceCouldMatch(pathname, source) {
1076
1071
  const normalizedPathname = removeTrailingSlash(pathname);
1077
1072
  return normalizedPathname === normalizedPrefix || normalizedPathname.startsWith(`${normalizedPrefix}/`);
1078
1073
  }
1079
- function substituteSimpleClientConfigDestination(destination, params) {
1080
- const keys = Object.keys(params);
1081
- if (keys.length === 0) return destination;
1082
- const alternation = keys.sort((a, b) => b.length - a.length).map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
1083
- return destination.replace(new RegExp(`:(${alternation})([+*])?(?![A-Za-z0-9_])`, "g"), (_token, key) => params[key] ?? _token);
1084
- }
1085
1074
  function isExternalClientConfigUrl(url) {
1086
1075
  return /^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith("//");
1087
1076
  }
@@ -1111,7 +1100,7 @@ function resolveClientConfigRewriteSync(href) {
1111
1100
  const params = matchSimpleClientConfigPattern(routeContext.pathname, rewrite.source);
1112
1101
  if (params === void 0) return void 0;
1113
1102
  if (params === null) continue;
1114
- const rewritten = substituteSimpleClientConfigDestination(rewrite.destination, params);
1103
+ const rewritten = substituteDestinationParams(rewrite.destination, params, "rewrite");
1115
1104
  if (isExternalClientConfigUrl(rewritten)) return { kind: "document" };
1116
1105
  currentHref = mergeRewriteQuery(currentHref, rewritten);
1117
1106
  matched = true;
@@ -2018,7 +2007,10 @@ See more info: https://nextjs.org/docs/messages/invalid-relative-url-external-as
2018
2007
  emitBeforeHistoryChange();
2019
2008
  if (doScroll) {
2020
2009
  if (hash) scrollToHashTarget(hash);
2021
- else window.scrollTo(0, 0);
2010
+ else scrollToPagesRouterPosition({
2011
+ x: 0,
2012
+ y: 0
2013
+ });
2022
2014
  }
2023
2015
  }
2024
2016
  onStateUpdate?.();
@@ -26,6 +26,7 @@ export type RequestInit = globalThis.RequestInit & {
26
26
  }>;
27
27
  } | null;
28
28
  trailingSlash?: boolean;
29
+ skipTrailingSlashRedirect?: boolean;
29
30
  };
30
31
  signal?: AbortSignal;
31
32
  duplex?: "half";
@@ -109,6 +110,14 @@ export type NextURLConfig = {
109
110
  * honour the user's `trailingSlash` config.
110
111
  */
111
112
  trailingSlash?: boolean;
113
+ /**
114
+ * When true, the trailing slash follows the parsed URL instead, and
115
+ * `trailingSlash` only decides the root, like Next.js's
116
+ * getNextPathnameInfo. Without the trailing-slash redirect, requests
117
+ * arrive in either form, so the config can no longer be applied as a
118
+ * policy.
119
+ */
120
+ skipTrailingSlashRedirect?: boolean;
112
121
  };
113
122
  };
114
123
  export declare class NextURL {
@@ -121,6 +130,8 @@ export declare class NextURL {
121
130
  */
122
131
  private _configBasePath;
123
132
  private _basePath;
133
+ private _configTrailingSlash;
134
+ private _manualTrailingSlash;
124
135
  private _trailingSlash;
125
136
  private _locale;
126
137
  private _configDefaultLocale;
@@ -129,6 +140,11 @@ export declare class NextURL {
129
140
  private _domains;
130
141
  private _domainLocale;
131
142
  constructor(input: string | URL, base?: string | URL, config?: NextURLConfig);
143
+ /**
144
+ * With `skipTrailingSlashRedirect`, take the slash from the parsed pathname
145
+ * (before basePath and locale are stripped), as getNextPathnameInfo does.
146
+ */
147
+ private _analyzeTrailingSlash;
132
148
  /** Strip basePath prefix from the internal pathname.
133
149
  * Mirrors Next.js's getNextPathnameInfo (re-run by NextURL.analyze() on
134
150
  * every parse, including `href` reassignment): basePath is only considered
@@ -131,7 +131,8 @@ var NextRequest = class extends Request {
131
131
  basePath: _nextConfig.basePath,
132
132
  nextConfig: {
133
133
  i18n,
134
- trailingSlash: _nextConfig.trailingSlash
134
+ trailingSlash: _nextConfig.trailingSlash,
135
+ skipTrailingSlashRedirect: _nextConfig.skipTrailingSlashRedirect
135
136
  }
136
137
  } : void 0;
137
138
  this._nextUrl = new NextURL(url, void 0, urlConfig);
@@ -266,6 +267,8 @@ var NextURL = class NextURL {
266
267
  */
267
268
  _configBasePath;
268
269
  _basePath;
270
+ _configTrailingSlash;
271
+ _manualTrailingSlash;
269
272
  _trailingSlash;
270
273
  _locale;
271
274
  _configDefaultLocale;
@@ -277,7 +280,10 @@ var NextURL = class NextURL {
277
280
  this._url = new URL(input.toString(), base);
278
281
  this._configBasePath = config?.basePath ?? "";
279
282
  this._basePath = this._configBasePath;
280
- this._trailingSlash = config?.nextConfig?.trailingSlash ?? false;
283
+ this._configTrailingSlash = config?.nextConfig?.trailingSlash ?? false;
284
+ this._manualTrailingSlash = config?.nextConfig?.skipTrailingSlashRedirect === true;
285
+ this._trailingSlash = this._configTrailingSlash;
286
+ this._analyzeTrailingSlash();
281
287
  this._stripBasePath();
282
288
  const i18n = config?.nextConfig?.i18n;
283
289
  if (i18n) {
@@ -290,6 +296,15 @@ var NextURL = class NextURL {
290
296
  this._analyzeI18n();
291
297
  }
292
298
  }
299
+ /**
300
+ * With `skipTrailingSlashRedirect`, take the slash from the parsed pathname
301
+ * (before basePath and locale are stripped), as getNextPathnameInfo does.
302
+ */
303
+ _analyzeTrailingSlash() {
304
+ if (!this._manualTrailingSlash) return;
305
+ const { pathname } = this._url;
306
+ this._trailingSlash = pathname !== "/" ? pathname.endsWith("/") : this._configTrailingSlash;
307
+ }
293
308
  /** Strip basePath prefix from the internal pathname.
294
309
  * Mirrors Next.js's getNextPathnameInfo (re-run by NextURL.analyze() on
295
310
  * every parse, including `href` reassignment): basePath is only considered
@@ -348,7 +363,8 @@ var NextURL = class NextURL {
348
363
  */
349
364
  _applyTrailingSlash(pathname) {
350
365
  if (pathname === "" || pathname === "/") return pathname;
351
- if ((this._basePath ? stripBasePath(pathname, this._basePath) : pathname).startsWith("/_next/")) return removeTrailingSlash(pathname);
366
+ const pathnameWithoutBasePath = this._basePath ? stripBasePath(pathname, this._basePath) : pathname;
367
+ if (!this._manualTrailingSlash && pathnameWithoutBasePath.startsWith("/_next/")) return removeTrailingSlash(pathname);
352
368
  if (this._trailingSlash) return pathname.endsWith("/") ? pathname : pathname + "/";
353
369
  return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
354
370
  }
@@ -361,6 +377,7 @@ var NextURL = class NextURL {
361
377
  }
362
378
  set href(value) {
363
379
  this._url.href = value;
380
+ this._analyzeTrailingSlash();
364
381
  this._stripBasePath();
365
382
  this._analyzeI18n();
366
383
  }
@@ -467,7 +484,10 @@ var NextURL = class NextURL {
467
484
  locales: domain.locales ? [...domain.locales] : void 0
468
485
  }))
469
486
  };
470
- if (this._trailingSlash) nextConfig.trailingSlash = true;
487
+ if (this._manualTrailingSlash) {
488
+ nextConfig.skipTrailingSlashRedirect = true;
489
+ if (this._configTrailingSlash) nextConfig.trailingSlash = true;
490
+ } else if (this._trailingSlash) nextConfig.trailingSlash = true;
471
491
  const config = {
472
492
  basePath: this._configBasePath,
473
493
  nextConfig: Object.keys(nextConfig).length > 0 ? nextConfig : void 0
@@ -1,7 +1,7 @@
1
1
  import { ExecutionContextLike } from "./request-context.js";
2
2
  import { CacheState } from "./cache-request-state.js";
3
3
  import { RootParamsState } from "./root-params.js";
4
- import { FetchCacheState } from "./fetch-cache.js";
4
+ import { FetchCacheState } from "./fetch-cache-state.js";
5
5
  import { VinextHeadersShimState } from "./internal/headers-state.js";
6
6
  import { RouterState } from "./router-state.js";
7
7
  import { markFullyBufferedBody, preserveFullyBufferedBodyMetadata } from "../server/fully-buffered-response.js";
@@ -30,6 +30,8 @@ export declare function toSameOriginAppPath(url: string, basePath: string): stri
30
30
  * `.well-known`-aware redirect rule shipped in `routes-manifest.json`.
31
31
  * - Query strings and hash fragments are preserved verbatim.
32
32
  * - Idempotent: already-canonical paths round-trip unchanged.
33
+ * - With `skipTrailingSlashRedirect`, every path is returned as written, like
34
+ * Next.js's `__NEXT_MANUAL_TRAILING_SLASH` short-circuit.
33
35
  */
34
36
  export declare function normalizePathTrailingSlash(path: string, trailingSlash: boolean): string;
35
37
  /**
@@ -99,9 +99,11 @@ function removeRouteTrailingSlash(route) {
99
99
  * `.well-known`-aware redirect rule shipped in `routes-manifest.json`.
100
100
  * - Query strings and hash fragments are preserved verbatim.
101
101
  * - Idempotent: already-canonical paths round-trip unchanged.
102
+ * - With `skipTrailingSlashRedirect`, every path is returned as written, like
103
+ * Next.js's `__NEXT_MANUAL_TRAILING_SLASH` short-circuit.
102
104
  */
103
105
  function normalizePathTrailingSlash(path, trailingSlash) {
104
- if (!path.startsWith("/") || path.startsWith("//")) return path;
106
+ if (!path.startsWith("/") || path.startsWith("//") || process.env.__VINEXT_MANUAL_TRAILING_SLASH === "true") return path;
105
107
  const { pathname, query, hash } = parsePath(path);
106
108
  if (trailingSlash) {
107
109
  if (/\.[^/]+\/?$/.test(pathname)) return `${removeRouteTrailingSlash(pathname)}${query}${hash}`;
@@ -1,8 +1,8 @@
1
1
  import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import { isAbsoluteAssetPrefix, resolveAssetsDir } from "./asset-prefix.js";
3
3
  import { manifestFileWithAssetPrefix, manifestFileWithBase } from "./manifest-paths.js";
4
- import { findClientEntryFile, findPagesClientEntryFile, readClientBuildManifest } from "./client-build-manifest.js";
5
4
  import { findClientEntryFileFromVinextManifest, findPagesClientEntryFileFromVinextManifest, readClientEntryManifest } from "./client-entry-manifest.js";
5
+ import { findClientEntryFile, findPagesClientEntryFile, readClientBuildManifest } from "./client-build-manifest.js";
6
6
  import { computeDynamicImportPreloads, computeLazyChunks, dynamicImportPreloadsWithBase } from "./lazy-chunks.js";
7
7
  //#region src/utils/client-runtime-metadata.ts
8
8
  function collectCssGraph(buildManifest, applyBase) {
@@ -20,4 +20,11 @@ export declare function fnv1a64(input: string): string;
20
20
  * key format and produces different values. Do not swap one for the other.
21
21
  */
22
22
  export declare function fnv1a52(str: string): number;
23
+ /**
24
+ * Hex-encoded SHA-256 digest of a string's UTF-8 bytes, via Web Crypto so it
25
+ * runs unchanged in Node.js, Workers and browsers. Used for cache keys built
26
+ * from inputs a request can influence, where crafted inputs could collide
27
+ * under a non-cryptographic hash like `fnv1a64`.
28
+ */
29
+ export declare function sha256Hex(input: string): Promise<string>;
23
30
  //#endregion
@@ -51,5 +51,15 @@ function fnv1a52(str) {
51
51
  }
52
52
  return (v3 & 15) * 281474976710656 + v2 * 4294967296 + v1 * 65536 + (v0 ^ v3 >> 4);
53
53
  }
54
+ /**
55
+ * Hex-encoded SHA-256 digest of a string's UTF-8 bytes, via Web Crypto so it
56
+ * runs unchanged in Node.js, Workers and browsers. Used for cache keys built
57
+ * from inputs a request can influence, where crafted inputs could collide
58
+ * under a non-cryptographic hash like `fnv1a64`.
59
+ */
60
+ async function sha256Hex(input) {
61
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
62
+ return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, "0")).join("");
63
+ }
54
64
  //#endregion
55
- export { fnv1a52, fnv1a64 };
65
+ export { fnv1a52, fnv1a64, sha256Hex };
@@ -7,4 +7,10 @@ export declare const BARE_PACKAGE_SPECIFIER_RE: RegExp;
7
7
  * scoped names, and Node builtins are not npm package references.
8
8
  */
9
9
  export declare function packageNameFromSpecifier(specifier: string): string | null;
10
+ /**
11
+ * Turbopack's "foreign code" condition: a module under node_modules whose
12
+ * package is not in the (Turbopack) transpile list. Next.js skips its
13
+ * app-code transforms, such as next/dynamic, for foreign code.
14
+ */
15
+ export declare function isForeignNodeModule(id: string, transpiledPackages: readonly string[]): boolean;
10
16
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
1
2
  import { builtinModules } from "node:module";
2
3
  //#region src/utils/package-name.ts
3
4
  const BUILTIN_MODULES = new Set(builtinModules.flatMap((name) => name.startsWith("node:") ? [name, name.slice(5)] : [name, `node:${name}`]));
@@ -14,5 +15,15 @@ function packageNameFromSpecifier(specifier) {
14
15
  if (!packageName || BUILTIN_MODULES.has(packageName)) return null;
15
16
  return packageName;
16
17
  }
18
+ /**
19
+ * Turbopack's "foreign code" condition: a module under node_modules whose
20
+ * package is not in the (Turbopack) transpile list. Next.js skips its
21
+ * app-code transforms, such as next/dynamic, for foreign code.
22
+ */
23
+ function isForeignNodeModule(id, transpiledPackages) {
24
+ const normalizedId = toSlash(id);
25
+ if (!normalizedId.includes("/node_modules/")) return false;
26
+ return !transpiledPackages.some((packageName) => normalizedId.includes(`/node_modules/${packageName}/`));
27
+ }
17
28
  //#endregion
18
- export { BARE_PACKAGE_SPECIFIER_RE, packageNameFromSpecifier };
29
+ export { BARE_PACKAGE_SPECIFIER_RE, isForeignNodeModule, packageNameFromSpecifier };
@@ -0,0 +1,4 @@
1
+ //#region src/utils/plugin-rsc-version.d.ts
2
+ /** Return the installed @vitejs/plugin-rsc version, or throw if it is unsupported. */
3
+ export declare function assertPluginRscVersion(resolvedRscPath: string): string;
4
+ //#endregion
@@ -0,0 +1,15 @@
1
+ import { findPackageVersion, isVersionBelow } from "./react-version.js";
2
+ //#region src/utils/plugin-rsc-version.ts
3
+ const MINIMUM_PLUGIN_RSC_VERSION = [
4
+ 0,
5
+ 5,
6
+ 37
7
+ ];
8
+ /** Return the installed @vitejs/plugin-rsc version, or throw if it is unsupported. */
9
+ function assertPluginRscVersion(resolvedRscPath) {
10
+ const version = findPackageVersion(resolvedRscPath, "@vitejs/plugin-rsc");
11
+ if (!version || isVersionBelow(version, MINIMUM_PLUGIN_RSC_VERSION)) throw new Error(`vinext: App Router requires @vitejs/plugin-rsc ${MINIMUM_PLUGIN_RSC_VERSION.join(".")} or newer (found ${version ?? "an unknown version"}). Upgrade @vitejs/plugin-rsc.`);
12
+ return version;
13
+ }
14
+ //#endregion
15
+ export { assertPluginRscVersion };
@@ -1,11 +1,22 @@
1
1
  //#region src/utils/prerender-output-paths.ts
2
2
  /**
3
+ * Map a prerendered URL to the file path its artifacts are written under, as
4
+ * Next.js's `normalizePagePath` does. `/index` becomes `/index/index` (and
5
+ * `/index/foo` becomes `/index/index/foo`) so it never shares `/`'s files.
6
+ * Unlike Next.js, dynamic fallback-shell paths such as `/index/[slug]` are
7
+ * also prefixed; build and seed both use this mapping, so they stay in step.
8
+ * Source: https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/page-path/normalize-page-path.ts
9
+ */
10
+ function toOutputUrlPath(urlPath) {
11
+ return /^\/index(?:\/|$)/.test(urlPath) ? `/index${urlPath}` : urlPath;
12
+ }
13
+ /**
3
14
  * Determine the HTML output file path for a prerendered URL.
4
15
  * Respects trailingSlash config.
5
16
  */
6
17
  function getOutputPath(urlPath, trailingSlash, basePath = "") {
7
18
  if (urlPath === "/" && basePath === "") return "index.html";
8
- const clean = (basePath === "" ? urlPath : urlPath === "/" ? trailingSlash ? `${basePath}/` : basePath : `${basePath}${urlPath}`).replace(/^\//, "").replace(/\/$/, "");
19
+ const clean = (basePath === "" ? toOutputUrlPath(urlPath) : urlPath === "/" ? trailingSlash ? `${basePath}/` : basePath : `${basePath}${toOutputUrlPath(urlPath)}`).replace(/^\//, "").replace(/\/$/, "");
9
20
  if (trailingSlash) return `${clean}/index.html`;
10
21
  return `${clean}.html`;
11
22
  }
@@ -19,16 +30,16 @@ function getRscOutputPath(urlPath, options = {
19
30
  const cleanBasePath = options.basePath?.replace(/^\//, "");
20
31
  return cleanBasePath ? `${cleanBasePath}/index.txt` : "index.txt";
21
32
  }
22
- const clean = (options.basePath ? `${options.basePath}${urlPath}` : urlPath).replace(/^\//, "").replace(/\/$/, "");
33
+ const clean = `${options.basePath ?? ""}${toOutputUrlPath(urlPath)}`.replace(/^\//, "").replace(/\/$/, "");
23
34
  return options.trailingSlash ? `${clean}/index.txt` : `${clean}.txt`;
24
35
  }
25
36
  if (urlPath === "/") return "index.rsc";
26
- return urlPath.replace(/^\//, "") + ".rsc";
37
+ return toOutputUrlPath(urlPath).replace(/^\//, "") + ".rsc";
27
38
  }
28
39
  /** Determine the binary artifact path for a prerendered App Route response. */
29
40
  function getAppRouteOutputPath(urlPath) {
30
41
  if (urlPath === "/") return "index.route";
31
- return urlPath.replace(/^\//, "") + ".route";
42
+ return toOutputUrlPath(urlPath).replace(/^\//, "") + ".route";
32
43
  }
33
44
  //#endregion
34
45
  export { getAppRouteOutputPath, getOutputPath, getRscOutputPath };
@@ -1,4 +1,12 @@
1
1
  //#region src/utils/public-file-path.d.ts
2
- /** Precompute keys for both encoded requests and decoded proxy/dev variants. */
3
- export declare function publicFilePathVariants(pathname: string): string[];
2
+ /**
3
+ * Key a public file by the normalized pathname a request for it matches with.
4
+ *
5
+ * Request pathnames are decoded once per segment with path delimiters kept
6
+ * encoded, so `public/a b.txt` is `/a b.txt` and `public/C#.txt` is
7
+ * `/C%23.txt`. Keying only this form keeps a double-encoded alias such as
8
+ * `/a%2520b.txt`, which middleware matchers see as `/a%20b.txt`, from
9
+ * reaching `public/a b.txt`.
10
+ */
11
+ export declare function publicFileRouteKey(pathname: string): string;
4
12
  //#endregion
@@ -1,12 +1,16 @@
1
+ import { normalizePathnameForRouteMatch } from "../routing/utils.js";
1
2
  //#region src/utils/public-file-path.ts
2
- /** Encode each pathname segment without encoding `/` separators. */
3
- function encodePublicFilePath(pathname) {
4
- return pathname.split("/").map((segment) => encodeURIComponent(segment)).join("/");
5
- }
6
- /** Precompute keys for both encoded requests and decoded proxy/dev variants. */
7
- function publicFilePathVariants(pathname) {
8
- const encoded = encodePublicFilePath(pathname);
9
- return encoded === pathname ? [pathname] : [pathname, encoded];
3
+ /**
4
+ * Key a public file by the normalized pathname a request for it matches with.
5
+ *
6
+ * Request pathnames are decoded once per segment with path delimiters kept
7
+ * encoded, so `public/a b.txt` is `/a b.txt` and `public/C#.txt` is
8
+ * `/C%23.txt`. Keying only this form keeps a double-encoded alias such as
9
+ * `/a%2520b.txt`, which middleware matchers see as `/a%20b.txt`, from
10
+ * reaching `public/a b.txt`.
11
+ */
12
+ function publicFileRouteKey(pathname) {
13
+ return normalizePathnameForRouteMatch(pathname.split("/").map((segment) => encodeURIComponent(segment)).join("/"));
10
14
  }
11
15
  //#endregion
12
- export { publicFilePathVariants };
16
+ export { publicFileRouteKey };
@@ -1,5 +1,5 @@
1
1
  import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
- import { publicFilePathVariants } from "./public-file-path.js";
2
+ import { publicFileRouteKey } from "./public-file-path.js";
3
3
  import fs from "node:fs";
4
4
  //#region src/utils/public-routes.ts
5
5
  function scanPublicFileRoutes(root, configuredPublicDir = "public") {
@@ -37,7 +37,7 @@ function scanPublicFileRoutes(root, configuredPublicDir = "public") {
37
37
  if (!stat.isFile()) continue;
38
38
  } else if (!entry.isFile()) continue;
39
39
  const relativePath = path.relative(publicDir, fullPath);
40
- routes.push(...publicFilePathVariants("/" + relativePath));
40
+ routes.push(publicFileRouteKey("/" + relativePath));
41
41
  }
42
42
  }
43
43
  if (fs.existsSync(publicDir)) try {
@@ -2,4 +2,7 @@
2
2
  export declare function getReactUpgradeDeps(root: string, options?: {
3
3
  fromManifest?: boolean;
4
4
  }): string[];
5
+ export declare function isVersionBelow(version: string, minimum: [number, number, number]): boolean;
6
+ /** Walk up from a resolved module entry to find its package version. */
7
+ export declare function findPackageVersion(resolvedEntry: string, packageName: string): string | null;
5
8
  //#endregion
@@ -59,4 +59,4 @@ function findPackageVersion(resolvedEntry, packageName) {
59
59
  return null;
60
60
  }
61
61
  //#endregion
62
- export { getReactUpgradeDeps };
62
+ export { findPackageVersion, getReactUpgradeDeps, isVersionBelow };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinext",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Run Next.js apps on Vite. Drop-in replacement for the next CLI.",
5
5
  "homepage": "https://vinext.dev/",
6
6
  "license": "MIT",
@@ -98,6 +98,10 @@
98
98
  "types": "./dist/server/headers.d.ts",
99
99
  "import": "./dist/server/headers.js"
100
100
  },
101
+ "./internal/server/http-conditional": {
102
+ "types": "./dist/server/http-conditional.d.ts",
103
+ "import": "./dist/server/http-conditional.js"
104
+ },
101
105
  "./internal/server/isr-cache": {
102
106
  "types": "./dist/server/isr-cache.d.ts",
103
107
  "import": "./dist/server/isr-cache.js"
@@ -234,7 +238,7 @@
234
238
  "@types/react-dom": "^19.2.3",
235
239
  "@types/ua-parser-js": "0.7.36",
236
240
  "@vitejs/plugin-react": "^6.1.0",
237
- "@vitejs/plugin-rsc": "^0.5.34",
241
+ "@vitejs/plugin-rsc": "^0.5.37",
238
242
  "am-i-vibing": "^0.5.0",
239
243
  "ignore": "5.3.2",
240
244
  "image-size": "2.0.2",
@@ -247,7 +251,7 @@
247
251
  "peerDependencies": {
248
252
  "@mdx-js/rollup": "^3.0.0",
249
253
  "@vitejs/plugin-react": "^5.1.4 || ^6.0.0",
250
- "@vitejs/plugin-rsc": "^0.5.34",
254
+ "@vitejs/plugin-rsc": "^0.5.37",
251
255
  "react": "^19.2.6",
252
256
  "react-dom": "^19.2.6",
253
257
  "react-server-dom-webpack": "^19.2.6",