vinext 0.1.0 → 0.1.2

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 (205) hide show
  1. package/README.md +2 -5
  2. package/dist/build/assets-ignore.d.ts +32 -0
  3. package/dist/build/assets-ignore.js +48 -0
  4. package/dist/build/client-build-config.d.ts +33 -1
  5. package/dist/build/client-build-config.js +66 -1
  6. package/dist/check.js +4 -3
  7. package/dist/cli.js +2 -0
  8. package/dist/client/navigation-runtime.d.ts +11 -2
  9. package/dist/client/navigation-runtime.js +1 -1
  10. package/dist/client/vinext-next-data.d.ts +2 -1
  11. package/dist/client/window-next.d.ts +6 -4
  12. package/dist/config/config-matchers.d.ts +31 -5
  13. package/dist/config/config-matchers.js +50 -3
  14. package/dist/config/next-config.d.ts +29 -3
  15. package/dist/config/next-config.js +32 -2
  16. package/dist/deploy.js +47 -304
  17. package/dist/entries/app-rsc-entry.d.ts +8 -2
  18. package/dist/entries/app-rsc-entry.js +61 -5
  19. package/dist/entries/app-rsc-manifest.js +20 -2
  20. package/dist/entries/pages-client-entry.js +1 -1
  21. package/dist/entries/pages-server-entry.js +16 -7
  22. package/dist/index.d.ts +0 -2
  23. package/dist/index.js +233 -280
  24. package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
  25. package/dist/plugins/dynamic-preload-metadata.js +415 -0
  26. package/dist/plugins/og-assets.js +2 -2
  27. package/dist/plugins/optimize-imports.d.ts +8 -4
  28. package/dist/plugins/optimize-imports.js +16 -12
  29. package/dist/plugins/postcss.js +18 -14
  30. package/dist/plugins/require-context.d.ts +6 -0
  31. package/dist/plugins/require-context.js +184 -0
  32. package/dist/plugins/sass.d.ts +53 -24
  33. package/dist/plugins/sass.js +249 -1
  34. package/dist/plugins/wasm-module-import.d.ts +15 -0
  35. package/dist/plugins/wasm-module-import.js +50 -0
  36. package/dist/routing/app-route-graph.d.ts +35 -2
  37. package/dist/routing/app-route-graph.js +179 -8
  38. package/dist/routing/file-matcher.js +1 -1
  39. package/dist/routing/route-pattern.d.ts +2 -1
  40. package/dist/routing/route-pattern.js +16 -1
  41. package/dist/server/api-handler.js +4 -0
  42. package/dist/server/app-browser-entry.js +155 -215
  43. package/dist/server/app-browser-error.d.ts +4 -1
  44. package/dist/server/app-browser-error.js +7 -1
  45. package/dist/server/app-browser-history-controller.d.ts +104 -0
  46. package/dist/server/app-browser-history-controller.js +210 -0
  47. package/dist/server/app-browser-interception-context.d.ts +2 -1
  48. package/dist/server/app-browser-interception-context.js +15 -2
  49. package/dist/server/app-browser-navigation-controller.d.ts +13 -2
  50. package/dist/server/app-browser-navigation-controller.js +83 -4
  51. package/dist/server/app-browser-popstate.d.ts +12 -3
  52. package/dist/server/app-browser-popstate.js +19 -4
  53. package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
  54. package/dist/server/app-browser-rsc-redirect.js +30 -8
  55. package/dist/server/app-browser-state.d.ts +3 -0
  56. package/dist/server/app-browser-state.js +10 -10
  57. package/dist/server/app-browser-visible-commit.js +10 -8
  58. package/dist/server/app-fallback-renderer.d.ts +2 -1
  59. package/dist/server/app-fallback-renderer.js +3 -1
  60. package/dist/server/app-history-state.d.ts +45 -1
  61. package/dist/server/app-history-state.js +109 -1
  62. package/dist/server/app-middleware.js +1 -0
  63. package/dist/server/app-optimistic-routing.js +22 -1
  64. package/dist/server/app-page-boundary-render.d.ts +2 -1
  65. package/dist/server/app-page-boundary-render.js +45 -21
  66. package/dist/server/app-page-cache.js +9 -7
  67. package/dist/server/app-page-dispatch.d.ts +14 -0
  68. package/dist/server/app-page-dispatch.js +21 -6
  69. package/dist/server/app-page-element-builder.d.ts +23 -2
  70. package/dist/server/app-page-element-builder.js +58 -17
  71. package/dist/server/app-page-execution.d.ts +1 -1
  72. package/dist/server/app-page-execution.js +32 -17
  73. package/dist/server/app-page-render.d.ts +7 -1
  74. package/dist/server/app-page-render.js +11 -16
  75. package/dist/server/app-page-request.d.ts +9 -6
  76. package/dist/server/app-page-request.js +14 -10
  77. package/dist/server/app-page-response.d.ts +2 -2
  78. package/dist/server/app-page-response.js +2 -2
  79. package/dist/server/app-page-route-wiring.d.ts +3 -1
  80. package/dist/server/app-page-route-wiring.js +10 -8
  81. package/dist/server/app-page-stream.d.ts +37 -7
  82. package/dist/server/app-page-stream.js +36 -6
  83. package/dist/server/app-pages-bridge.d.ts +16 -0
  84. package/dist/server/app-pages-bridge.js +23 -3
  85. package/dist/server/app-route-handler-cache.d.ts +1 -0
  86. package/dist/server/app-route-handler-cache.js +1 -0
  87. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  88. package/dist/server/app-route-handler-dispatch.js +2 -0
  89. package/dist/server/app-route-handler-execution.d.ts +1 -0
  90. package/dist/server/app-route-handler-execution.js +1 -0
  91. package/dist/server/app-route-handler-response.js +11 -10
  92. package/dist/server/app-route-handler-runtime.d.ts +1 -0
  93. package/dist/server/app-route-handler-runtime.js +15 -3
  94. package/dist/server/app-rsc-handler.d.ts +1 -0
  95. package/dist/server/app-rsc-handler.js +5 -4
  96. package/dist/server/app-rsc-response-finalizer.js +1 -1
  97. package/dist/server/app-rsc-route-matching.d.ts +20 -1
  98. package/dist/server/app-rsc-route-matching.js +29 -4
  99. package/dist/server/app-server-action-execution.d.ts +22 -1
  100. package/dist/server/app-server-action-execution.js +73 -12
  101. package/dist/server/app-ssr-entry.d.ts +6 -0
  102. package/dist/server/app-ssr-entry.js +19 -3
  103. package/dist/server/app-ssr-stream.js +9 -1
  104. package/dist/server/dev-lockfile.js +2 -1
  105. package/dist/server/dev-server.d.ts +1 -1
  106. package/dist/server/dev-server.js +97 -43
  107. package/dist/server/headers.d.ts +8 -1
  108. package/dist/server/headers.js +8 -1
  109. package/dist/server/instrumentation-runtime.d.ts +6 -0
  110. package/dist/server/instrumentation-runtime.js +8 -0
  111. package/dist/server/isr-cache.d.ts +37 -1
  112. package/dist/server/isr-cache.js +85 -1
  113. package/dist/server/isr-decision.d.ts +79 -0
  114. package/dist/server/isr-decision.js +70 -0
  115. package/dist/server/metadata-route-response.js +5 -3
  116. package/dist/server/middleware-runtime.d.ts +13 -0
  117. package/dist/server/middleware-runtime.js +11 -7
  118. package/dist/server/middleware.js +1 -0
  119. package/dist/server/navigation-planner.d.ts +62 -1
  120. package/dist/server/navigation-planner.js +193 -3
  121. package/dist/server/navigation-trace.d.ts +12 -2
  122. package/dist/server/navigation-trace.js +11 -1
  123. package/dist/server/normalize-path.d.ts +0 -8
  124. package/dist/server/normalize-path.js +3 -1
  125. package/dist/server/otel-tracer-extension.d.ts +45 -0
  126. package/dist/server/otel-tracer-extension.js +89 -0
  127. package/dist/server/pages-api-route.d.ts +14 -3
  128. package/dist/server/pages-api-route.js +6 -1
  129. package/dist/server/pages-asset-tags.d.ts +15 -4
  130. package/dist/server/pages-asset-tags.js +18 -12
  131. package/dist/server/pages-data-route.js +5 -1
  132. package/dist/server/pages-node-compat.d.ts +5 -11
  133. package/dist/server/pages-node-compat.js +175 -118
  134. package/dist/server/pages-page-data.d.ts +38 -7
  135. package/dist/server/pages-page-data.js +64 -18
  136. package/dist/server/pages-page-handler.d.ts +10 -2
  137. package/dist/server/pages-page-handler.js +49 -20
  138. package/dist/server/pages-page-response.d.ts +55 -2
  139. package/dist/server/pages-page-response.js +74 -6
  140. package/dist/server/pages-readiness.d.ts +36 -0
  141. package/dist/server/pages-readiness.js +21 -0
  142. package/dist/server/pages-request-pipeline.d.ts +113 -0
  143. package/dist/server/pages-request-pipeline.js +230 -0
  144. package/dist/server/pages-revalidate.d.ts +15 -0
  145. package/dist/server/pages-revalidate.js +19 -0
  146. package/dist/server/prod-server.d.ts +45 -3
  147. package/dist/server/prod-server.js +182 -234
  148. package/dist/server/socket-error-backstop.d.ts +19 -1
  149. package/dist/server/socket-error-backstop.js +77 -4
  150. package/dist/shims/app-router-scroll.js +22 -4
  151. package/dist/shims/cache-runtime.js +39 -2
  152. package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
  153. package/dist/shims/dynamic-preload-chunks.js +77 -0
  154. package/dist/shims/dynamic.d.ts +4 -0
  155. package/dist/shims/dynamic.js +4 -2
  156. package/dist/shims/error-boundary.d.ts +17 -7
  157. package/dist/shims/error-boundary.js +8 -1
  158. package/dist/shims/error.js +37 -11
  159. package/dist/shims/fetch-cache.d.ts +22 -1
  160. package/dist/shims/fetch-cache.js +28 -1
  161. package/dist/shims/hash-scroll.d.ts +1 -0
  162. package/dist/shims/hash-scroll.js +3 -1
  163. package/dist/shims/head.js +6 -1
  164. package/dist/shims/headers.d.ts +16 -2
  165. package/dist/shims/headers.js +37 -1
  166. package/dist/shims/image-config.js +7 -1
  167. package/dist/shims/internal/app-route-detection.d.ts +6 -3
  168. package/dist/shims/internal/app-route-detection.js +10 -6
  169. package/dist/shims/internal/app-router-context.d.ts +5 -0
  170. package/dist/shims/internal/link-status-registry.d.ts +43 -0
  171. package/dist/shims/internal/link-status-registry.js +42 -0
  172. package/dist/shims/internal/route-pattern-for-warning.d.ts +27 -0
  173. package/dist/shims/internal/route-pattern-for-warning.js +40 -0
  174. package/dist/shims/internal/utils.d.ts +1 -0
  175. package/dist/shims/link.js +20 -6
  176. package/dist/shims/metadata.d.ts +6 -2
  177. package/dist/shims/metadata.js +32 -14
  178. package/dist/shims/navigation.d.ts +9 -18
  179. package/dist/shims/navigation.js +96 -23
  180. package/dist/shims/router-state.d.ts +1 -0
  181. package/dist/shims/router-state.js +2 -0
  182. package/dist/shims/router.d.ts +6 -3
  183. package/dist/shims/router.js +156 -22
  184. package/dist/shims/script-nonce-context.d.ts +1 -1
  185. package/dist/shims/script-nonce-context.js +11 -3
  186. package/dist/shims/server.d.ts +17 -1
  187. package/dist/shims/server.js +31 -6
  188. package/dist/shims/slot.js +1 -1
  189. package/dist/shims/unified-request-context.js +1 -0
  190. package/dist/typegen.js +1 -0
  191. package/dist/utils/client-build-manifest.d.ts +8 -1
  192. package/dist/utils/client-build-manifest.js +41 -6
  193. package/dist/utils/client-entry-manifest.d.ts +11 -0
  194. package/dist/utils/client-entry-manifest.js +29 -0
  195. package/dist/utils/client-runtime-metadata.d.ts +45 -0
  196. package/dist/utils/client-runtime-metadata.js +63 -0
  197. package/dist/utils/hash.d.ts +17 -1
  198. package/dist/utils/hash.js +36 -1
  199. package/dist/utils/lazy-chunks.d.ts +27 -1
  200. package/dist/utils/lazy-chunks.js +65 -1
  201. package/dist/utils/manifest-paths.d.ts +20 -2
  202. package/dist/utils/manifest-paths.js +38 -3
  203. package/dist/utils/path.d.ts +2 -1
  204. package/dist/utils/path.js +5 -1
  205. package/package.json +6 -2
@@ -1,5 +1,5 @@
1
1
  import { splitPathSegments } from "../routing/utils.js";
2
- import { stripBasePath } from "../utils/base-path.js";
2
+ import { removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
3
3
  import { assertSafeNavigationUrl } from "./url-safety.js";
4
4
  import { matchRoutePattern, routePatternParts } from "../routing/route-pattern.js";
5
5
  import { isUnknownRecord } from "../utils/record.js";
@@ -247,15 +247,19 @@ function _registerRouterStateAccessors(accessors) {
247
247
  function setSSRContext(ctx) {
248
248
  _setSSRContextImpl(ctx);
249
249
  }
250
+ const PAGES_NAVIGATION_NOTIFY_KEY = Symbol.for("vinext.navigation.pagesNavigationNotify");
250
251
  let _cachedClientPagesNavCtx = null;
251
252
  let _cachedClientPagesNavCtxKey = null;
252
- function _buildClientPagesNavigationContext(routePattern, resolvedPath, searchString) {
253
- const cacheKey = `${routePattern}|${resolvedPath}|${searchString}`;
253
+ function _buildClientPagesNavigationContext(routePattern, resolvedPath, searchString, isReady, nextData) {
254
+ const cacheKey = `${isReady ? "1" : "0"}|${routePattern}|${resolvedPath}|${searchString}`;
254
255
  if (_cachedClientPagesNavCtxKey === cacheKey && _cachedClientPagesNavCtx) return _cachedClientPagesNavCtx;
256
+ const searchParams = isReady ? new URLSearchParams(searchString) : new URLSearchParams();
257
+ const params = isReady ? extractRouteParamsFromPath(routePattern, resolvedPath) ?? getRouteParamsFromQuery(routePattern, nextData?.query ?? {}) ?? {} : null;
258
+ const isAutoExportDynamic = nextData?.autoExport === true && extractRouteParamNames(routePattern).length > 0;
255
259
  const ctx = {
256
- pathname: resolvedPath,
257
- searchParams: new URLSearchParams(searchString),
258
- params: routePattern ? extractRouteParamsFromPath(routePattern, resolvedPath) ?? {} : {}
260
+ pathname: resolvePagesNavigationPathname(resolvedPath, nextData?.isFallback === true, isAutoExportDynamic, isReady),
261
+ searchParams,
262
+ params
259
263
  };
260
264
  _cachedClientPagesNavCtx = ctx;
261
265
  _cachedClientPagesNavCtxKey = cacheKey;
@@ -284,27 +288,33 @@ function getPagesNavigationContext() {
284
288
  if (!ssrCtx) return null;
285
289
  const cached = _ssrPagesNavCtxCache.get(ssrCtx);
286
290
  if (cached) return cached;
287
- let searchParams;
291
+ let searchString = "";
288
292
  let resolvedPath;
289
293
  try {
290
294
  const url = new URL(ssrCtx.asPath, "http://_");
291
- searchParams = url.searchParams;
295
+ searchString = url.search;
292
296
  resolvedPath = url.pathname;
293
297
  } catch {
294
- searchParams = new URLSearchParams();
295
298
  resolvedPath = ssrCtx.pathname;
296
299
  }
297
- const params = extractRouteParamsFromPath(ssrCtx.pathname, resolvedPath) ?? {};
300
+ const isReady = ssrCtx.navigationIsReady ?? true;
301
+ const searchParams = isReady ? new URLSearchParams(searchString) : new URLSearchParams();
302
+ const params = isReady ? extractRouteParamsFromPath(ssrCtx.pathname, resolvedPath) ?? getRouteParamsFromQuery(ssrCtx.pathname, ssrCtx.query) ?? {} : null;
303
+ const isAutoExportDynamic = ssrCtx.nextData?.autoExport === true && extractRouteParamNames(ssrCtx.pathname).length > 0;
298
304
  const ctx = {
299
- pathname: resolvedPath,
305
+ pathname: resolvePagesNavigationPathname(resolvedPath, ssrCtx.isFallback === true, isAutoExportDynamic, isReady),
300
306
  searchParams,
301
307
  params
302
308
  };
303
309
  _ssrPagesNavCtxCache.set(ssrCtx, ctx);
304
310
  return ctx;
305
311
  }
312
+ if (!isPagesRouterDocumentActive()) return null;
306
313
  const resolvedPath = stripBasePath(window.location.pathname, __basePath);
307
- return _buildClientPagesNavigationContext(window.__NEXT_DATA__?.page ?? "", resolvedPath, window.location.search);
314
+ const nextData = window.__NEXT_DATA__;
315
+ const pattern = resolvePagesRoutePatternForPath(nextData?.page, resolvedPath);
316
+ if (!pattern) return null;
317
+ return _buildClientPagesNavigationContext(pattern, resolvedPath, window.location.search, isPagesRouterReady(), nextData);
308
318
  }
309
319
  /**
310
320
  * Extract param names from a Next.js route pattern.
@@ -321,9 +331,52 @@ function extractRouteParamNames(pattern) {
321
331
  for (const m of colonMatches) names.push(m[1]);
322
332
  return names;
323
333
  }
334
+ /**
335
+ * Resolve the `pathname` snapshot for the Pages Router navigation context.
336
+ * Shared by the client and SSR branches of `getPagesNavigationContext` so both
337
+ * runtimes derive identical null-ness — diverging here would reintroduce a
338
+ * hydration mismatch. Returns `null` for a `getStaticPaths` fallback shell or a
339
+ * pre-ready auto-export dynamic route (the live path is published once the
340
+ * client router becomes ready).
341
+ */
342
+ function resolvePagesNavigationPathname(resolvedPath, isFallback, isAutoExportDynamic, isReady) {
343
+ return isFallback || isAutoExportDynamic && !isReady ? null : resolvedPath;
344
+ }
345
+ let _cachedPagesRoutePatternKey = null;
346
+ let _cachedPagesRoutePattern;
347
+ function resolvePagesRoutePatternForPath(nextDataPage, resolvedPath) {
348
+ if (nextDataPage && extractRouteParamNames(nextDataPage).length > 0) return nextDataPage;
349
+ const cacheKey = `${nextDataPage ?? ""}|${resolvedPath}`;
350
+ if (_cachedPagesRoutePatternKey === cacheKey) return _cachedPagesRoutePattern;
351
+ let resolved = nextDataPage;
352
+ for (const pattern of window.__VINEXT_PAGE_PATTERNS__ ?? []) if (matchRoutePattern(splitPathSegments(resolvedPath), routePatternParts(pattern))) {
353
+ resolved = pattern;
354
+ break;
355
+ }
356
+ _cachedPagesRoutePatternKey = cacheKey;
357
+ _cachedPagesRoutePattern = resolved;
358
+ return resolved;
359
+ }
324
360
  function extractRouteParamsFromPath(pattern, pathname) {
325
361
  return matchRoutePattern(splitPathSegments(pathname), routePatternParts(pattern));
326
362
  }
363
+ function getRouteParamsFromQuery(pattern, query) {
364
+ const names = extractRouteParamNames(pattern);
365
+ if (names.length === 0) return null;
366
+ const params = {};
367
+ let hasParam = false;
368
+ for (const name of names) {
369
+ const value = query[name];
370
+ if (typeof value === "string") {
371
+ params[name] = value;
372
+ hasParam = true;
373
+ } else if (Array.isArray(value)) {
374
+ params[name] = [...value];
375
+ hasParam = true;
376
+ }
377
+ }
378
+ return hasParam ? params : null;
379
+ }
327
380
  function getRouteQueryFromNextData(nextData, resolvedPath) {
328
381
  const routeQuery = {};
329
382
  if (!nextData?.query || !nextData.page) return routeQuery;
@@ -372,6 +425,47 @@ function getPathnameAndQuery() {
372
425
  asPath: resolvedPath + window.location.search + window.location.hash
373
426
  };
374
427
  }
428
+ function getPagesNavigationIsReadyFromSerializedState(routePattern, searchString, nextData) {
429
+ if (!routePattern) return true;
430
+ if (nextData?.gssp === true || nextData?.gip === true || nextData?.isExperimentalCompile === true || nextData?.appGip === true && nextData.gsp !== true) return true;
431
+ const autoExportDynamic = nextData?.autoExport === true && extractRouteParamNames(routePattern).length > 0;
432
+ const hasSearch = searchString.length > 0;
433
+ const hasRewrites = nextData?.__vinext?.hasRewrites === true;
434
+ return !autoExportDynamic && !hasSearch && !hasRewrites;
435
+ }
436
+ function shouldDeferInitialPagesRouterReady() {
437
+ if (typeof window === "undefined") return false;
438
+ const nextData = window.__NEXT_DATA__;
439
+ if (!nextData) return false;
440
+ return !getPagesNavigationIsReadyFromSerializedState(nextData.page, window.location.search, nextData);
441
+ }
442
+ let _pagesRouterReady = typeof window === "undefined" ? true : !shouldDeferInitialPagesRouterReady();
443
+ function isPagesRouterReady() {
444
+ return _pagesRouterReady;
445
+ }
446
+ function isPagesRouterDocumentActive() {
447
+ if (typeof window === "undefined") return true;
448
+ if (window.__VINEXT_PAGE_LOADERS__) return true;
449
+ if (window.next?.appDir === true) return false;
450
+ if (window.next?.router) return true;
451
+ return Boolean(window.__VINEXT_APP__ || window.__VINEXT_APP_LOADER__);
452
+ }
453
+ function markPagesRouterReady() {
454
+ if (typeof window === "undefined" || _pagesRouterReady) return false;
455
+ _pagesRouterReady = true;
456
+ return true;
457
+ }
458
+ function getRouterSnapshot() {
459
+ const isReady = typeof window === "undefined" ? _getSSRContext()?.navigationIsReady ?? true : isPagesRouterReady();
460
+ return {
461
+ ...getPathnameAndQuery(),
462
+ isReady
463
+ };
464
+ }
465
+ function notifyNextNavigationPagesContext() {
466
+ const notify = globalThis[PAGES_NAVIGATION_NOTIFY_KEY];
467
+ notify?.();
468
+ }
375
469
  /**
376
470
  * Error thrown when a navigation is superseded by a newer one.
377
471
  * Matches Next.js's convention of an Error with `.cancelled = true`.
@@ -779,7 +873,7 @@ async function runNavigateClient(fullUrl, resolvedUrl, fetchUrl = fullUrl, optio
779
873
  * and a set of navigation methods. Shared by the Pages Router context provider
780
874
  * and tests so the public router shape stays in sync.
781
875
  */
782
- function buildRouterValue(pathname, query, asPath, methods) {
876
+ function buildRouterValue(pathname, query, asPath, isReady, methods) {
783
877
  const _ssrState = _getSSRContext();
784
878
  const nextData = typeof window !== "undefined" ? window.__NEXT_DATA__ : void 0;
785
879
  const locale = typeof window === "undefined" ? _ssrState?.locale : window.__VINEXT_LOCALE__;
@@ -796,7 +890,7 @@ function buildRouterValue(pathname, query, asPath, methods) {
796
890
  locales,
797
891
  defaultLocale,
798
892
  domainLocales,
799
- isReady: true,
893
+ isReady,
800
894
  isPreview: false,
801
895
  isFallback: typeof window !== "undefined" ? nextData?.isFallback === true : _ssrState?.isFallback === true,
802
896
  ...methods,
@@ -815,6 +909,7 @@ function stripHash(url) {
815
909
  }
816
910
  /** Notify in-page listeners (e.g. useRouter hooks) that navigation occurred. */
817
911
  function dispatchNavigateEvent() {
912
+ notifyNextNavigationPagesContext();
818
913
  window.dispatchEvent(new CustomEvent("vinext:navigate"));
819
914
  }
820
915
  /**
@@ -922,6 +1017,14 @@ async function performNavigation(url, as, options, mode, onStateUpdate) {
922
1017
  dispatchNavigateEvent();
923
1018
  return true;
924
1019
  }
1020
+ const appPath = getLocalPathname(resolved);
1021
+ const appPathNorm = appPath !== null ? removeTrailingSlash(appPath) : null;
1022
+ const appPathEntry = appPathNorm !== null ? getPagesRouterComponentsMap()[appPathNorm] : void 0;
1023
+ if (appPathEntry !== void 0 && "__appRouter" in appPathEntry && appPathEntry.__appRouter) {
1024
+ if (mode === "push") window.location.assign(full);
1025
+ else window.location.replace(full);
1026
+ return new Promise(() => {});
1027
+ }
925
1028
  if (mode === "push") saveScrollPosition();
926
1029
  routerEvents.emit("routeChangeStart", resolved, { shallow });
927
1030
  routerEvents.emit("beforeHistoryChange", resolved, { shallow });
@@ -984,15 +1087,25 @@ function useRouter() {
984
1087
  return router;
985
1088
  }
986
1089
  function PagesRouterProvider({ children }) {
987
- const [{ pathname, query, asPath }, setState] = useState(getPathnameAndQuery);
1090
+ const [{ pathname, query, asPath, isReady }, setState] = useState(getRouterSnapshot);
988
1091
  useEffect(() => {
989
1092
  const onNavigate = ((_e) => {
990
- setState(getPathnameAndQuery());
1093
+ setState(getRouterSnapshot());
991
1094
  });
992
1095
  window.addEventListener("vinext:navigate", onNavigate);
993
- return () => window.removeEventListener("vinext:navigate", onNavigate);
1096
+ let cancelled = false;
1097
+ const readyTimer = window.setTimeout(() => {
1098
+ if (cancelled || !markPagesRouterReady()) return;
1099
+ setState(getRouterSnapshot());
1100
+ notifyNextNavigationPagesContext();
1101
+ }, 0);
1102
+ return () => {
1103
+ cancelled = true;
1104
+ window.clearTimeout(readyTimer);
1105
+ window.removeEventListener("vinext:navigate", onNavigate);
1106
+ };
994
1107
  }, []);
995
- const router = useMemo(() => buildRouterValue(pathname, query, asPath, {
1108
+ const router = useMemo(() => buildRouterValue(pathname, query, asPath, isReady, {
996
1109
  push: Router.push,
997
1110
  replace: Router.replace,
998
1111
  back: Router.back,
@@ -1002,7 +1115,8 @@ function PagesRouterProvider({ children }) {
1002
1115
  }), [
1003
1116
  pathname,
1004
1117
  query,
1005
- asPath
1118
+ asPath,
1119
+ isReady
1006
1120
  ]);
1007
1121
  const appRouter = useMemo(() => ({
1008
1122
  bfcacheId: "0",
@@ -1215,8 +1329,9 @@ const Router = Object.defineProperties(RouterMethods, {
1215
1329
  },
1216
1330
  isReady: {
1217
1331
  enumerable: true,
1218
- value: true,
1219
- writable: false
1332
+ get() {
1333
+ return isPagesRouterReady();
1334
+ }
1220
1335
  },
1221
1336
  isPreview: {
1222
1337
  enumerable: true,
@@ -1231,8 +1346,27 @@ const Router = Object.defineProperties(RouterMethods, {
1231
1346
  }
1232
1347
  }
1233
1348
  });
1349
+ for (const event of [
1350
+ "routeChangeStart",
1351
+ "beforeHistoryChange",
1352
+ "routeChangeComplete",
1353
+ "routeChangeError",
1354
+ "hashChangeStart",
1355
+ "hashChangeComplete"
1356
+ ]) {
1357
+ const eventField = `on${event.charAt(0).toUpperCase()}${event.substring(1)}`;
1358
+ routerEvents.on(event, (...args) => {
1359
+ const handler = Router[eventField];
1360
+ if (typeof handler === "function") try {
1361
+ handler(...args);
1362
+ } catch (err) {
1363
+ console.error(`Error when running the Router event: ${eventField}`);
1364
+ console.error(err instanceof Error ? `${err.message}\n${err.stack}` : String(err));
1365
+ }
1366
+ });
1367
+ }
1234
1368
  if (typeof window !== "undefined") installWindowNext({ router: Router });
1235
1369
  const _PAGES_NAVIGATION_ACCESSOR_KEY = Symbol.for("vinext.navigation.pagesNavigationContextAccessor");
1236
1370
  globalThis[_PAGES_NAVIGATION_ACCESSOR_KEY] = getPagesNavigationContext;
1237
1371
  //#endregion
1238
- export { _registerRouterStateAccessors, applyNavigationLocale, Router as default, getPagesNavigationContext, isExternalUrl, isHashOnlyChange, setSSRContext, useRouter, withRouter, wrapWithRouterContext };
1372
+ export { _registerRouterStateAccessors, applyNavigationLocale, Router as default, getPagesNavigationContext, getPagesNavigationIsReadyFromSerializedState, isExternalUrl, isHashOnlyChange, setSSRContext, useRouter, withRouter, wrapWithRouterContext };
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
 
3
3
  //#region src/shims/script-nonce-context.d.ts
4
- declare const ScriptNonceContext: React.Context<string | undefined>;
4
+ declare const ScriptNonceContext: React.Context<string | undefined> | null;
5
5
  declare function ScriptNonceProvider(props: React.PropsWithChildren<{
6
6
  nonce?: string;
7
7
  }>): React.ReactElement;
@@ -1,15 +1,23 @@
1
1
  import React from "react";
2
2
  //#region src/shims/script-nonce-context.tsx
3
- const ScriptNonceContext = React.createContext(void 0);
3
+ const ScriptNonceContext = typeof React.createContext === "function" ? React.createContext(void 0) : null;
4
4
  function ScriptNonceProvider(props) {
5
+ if (!ScriptNonceContext) return React.createElement(React.Fragment, null, props.children);
5
6
  return React.createElement(ScriptNonceContext.Provider, { value: props.nonce }, props.children);
6
7
  }
7
8
  function withScriptNonce(element, nonce) {
8
- if (!nonce) return element;
9
+ if (!nonce || !ScriptNonceContext) return element;
9
10
  return React.createElement(ScriptNonceProvider, { nonce }, element);
10
11
  }
12
+ function createScriptNonceHook(context) {
13
+ if (!context || typeof React.useContext !== "function") return function useScriptNonceFromContext() {};
14
+ return function useScriptNonceFromContext() {
15
+ return React.useContext(context);
16
+ };
17
+ }
18
+ const useScriptNonceFromContext = createScriptNonceHook(ScriptNonceContext);
11
19
  function useScriptNonce() {
12
- return React.useContext(ScriptNonceContext);
20
+ return useScriptNonceFromContext();
13
21
  }
14
22
  //#endregion
15
23
  export { ScriptNonceContext, ScriptNonceProvider, useScriptNonce, withScriptNonce };
@@ -91,13 +91,29 @@ type NextURLConfig = {
91
91
  declare class NextURL {
92
92
  /** Internal URL stores the pathname WITHOUT basePath or locale prefix. */
93
93
  private _url;
94
+ /**
95
+ * The configured basePath (from nextConfig). May differ from the active
96
+ * `_basePath`: parsing only activates basePath when the URL's pathname
97
+ * actually carries the configured prefix.
98
+ */
99
+ private _configBasePath;
94
100
  private _basePath;
95
101
  private _trailingSlash;
96
102
  private _locale;
97
103
  private _defaultLocale;
98
104
  private _locales;
99
105
  constructor(input: string | URL, base?: string | URL, config?: NextURLConfig);
100
- /** Strip basePath prefix from the internal pathname. */
106
+ /** Strip basePath prefix from the internal pathname.
107
+ * Mirrors Next.js's getNextPathnameInfo (re-run by NextURL.analyze() on
108
+ * every parse, including `href` reassignment): basePath is only considered
109
+ * active when the URL's pathname actually starts with the configured
110
+ * basePath prefix. If the pathname is outside the basePath, the active
111
+ * basePath is cleared to "" so that request.nextUrl.basePath reflects the
112
+ * actual URL rather than the config value; if a later `href` assignment
113
+ * moves the URL back inside the basePath, it is re-activated from the
114
+ * configured value. This matches the Next.js behavior tested by
115
+ * middleware-base-path's "should execute from absolute paths" case.
116
+ */
101
117
  private _stripBasePath;
102
118
  /** Extract locale from pathname, stripping it from the internal URL. */
103
119
  private _analyzeLocale;
@@ -1,4 +1,4 @@
1
- import { stripBasePath } from "../utils/base-path.js";
1
+ import { hasBasePath, stripBasePath } from "../utils/base-path.js";
2
2
  import { getRequestExecutionContext } from "./request-context.js";
3
3
  import { MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER } from "../server/headers.js";
4
4
  import { encodeMiddlewareRequestHeaders } from "../server/middleware-request-headers.js";
@@ -183,6 +183,12 @@ var NextResponse = class NextResponse extends Response {
183
183
  var NextURL = class NextURL {
184
184
  /** Internal URL stores the pathname WITHOUT basePath or locale prefix. */
185
185
  _url;
186
+ /**
187
+ * The configured basePath (from nextConfig). May differ from the active
188
+ * `_basePath`: parsing only activates basePath when the URL's pathname
189
+ * actually carries the configured prefix.
190
+ */
191
+ _configBasePath;
186
192
  _basePath;
187
193
  _trailingSlash;
188
194
  _locale;
@@ -190,7 +196,8 @@ var NextURL = class NextURL {
190
196
  _locales;
191
197
  constructor(input, base, config) {
192
198
  this._url = new URL(input.toString(), base);
193
- this._basePath = config?.basePath ?? "";
199
+ this._configBasePath = config?.basePath ?? "";
200
+ this._basePath = this._configBasePath;
194
201
  this._trailingSlash = config?.nextConfig?.trailingSlash ?? false;
195
202
  this._stripBasePath();
196
203
  const i18n = config?.nextConfig?.i18n;
@@ -200,10 +207,25 @@ var NextURL = class NextURL {
200
207
  this._analyzeLocale(this._locales);
201
208
  }
202
209
  }
203
- /** Strip basePath prefix from the internal pathname. */
210
+ /** Strip basePath prefix from the internal pathname.
211
+ * Mirrors Next.js's getNextPathnameInfo (re-run by NextURL.analyze() on
212
+ * every parse, including `href` reassignment): basePath is only considered
213
+ * active when the URL's pathname actually starts with the configured
214
+ * basePath prefix. If the pathname is outside the basePath, the active
215
+ * basePath is cleared to "" so that request.nextUrl.basePath reflects the
216
+ * actual URL rather than the config value; if a later `href` assignment
217
+ * moves the URL back inside the basePath, it is re-activated from the
218
+ * configured value. This matches the Next.js behavior tested by
219
+ * middleware-base-path's "should execute from absolute paths" case.
220
+ */
204
221
  _stripBasePath() {
205
- if (!this._basePath) return;
206
- this._url.pathname = stripBasePath(this._url.pathname, this._basePath);
222
+ if (!this._configBasePath) return;
223
+ if (!hasBasePath(this._url.pathname, this._configBasePath)) {
224
+ this._basePath = "";
225
+ return;
226
+ }
227
+ this._basePath = this._configBasePath;
228
+ this._url.pathname = stripBasePath(this._url.pathname, this._configBasePath);
207
229
  }
208
230
  /** Extract locale from pathname, stripping it from the internal URL. */
209
231
  _analyzeLocale(locales) {
@@ -655,10 +677,13 @@ function after(task) {
655
677
  * and sets Cache-Control: no-store on the response.
656
678
  */
657
679
  async function connection() {
658
- const { markDynamicUsage, markRenderRequestApiUsage, throwIfInsideCacheScope } = await import("./headers.js");
680
+ const { getHeadersContext, markDynamicUsage, markRenderRequestApiUsage, suspendConnectionProbe, throwIfInsideCacheScope } = await import("./headers.js");
681
+ if (getHeadersContext()?.forceStatic) return;
659
682
  markRenderRequestApiUsage("connection");
660
683
  throwIfInsideCacheScope("connection()");
661
684
  markDynamicUsage();
685
+ const pendingProbe = suspendConnectionProbe();
686
+ if (pendingProbe) await pendingProbe;
662
687
  }
663
688
  /**
664
689
  * URLPattern re-export — used in middleware for route matching.
@@ -23,7 +23,7 @@ const MAX_BFCACHE_SLOT_ENTRIES_WITH_CACHE_COMPONENTS = 3;
23
23
  const MAX_BFCACHE_SLOT_ENTRIES_WITHOUT_CACHE_COMPONENTS = 1;
24
24
  const BfcacheStateKeyMapContext = React$1.createContext(EMPTY_BFCACHE_STATE_KEYS);
25
25
  function isCacheComponentsEnabled() {
26
- return process.env.__NEXT_CACHE_COMPONENTS === "true";
26
+ return String(process.env.__NEXT_CACHE_COMPONENTS) === "true";
27
27
  }
28
28
  function getBfcacheSlotEntryLimit() {
29
29
  return isCacheComponentsEnabled() ? MAX_BFCACHE_SLOT_ENTRIES_WITH_CACHE_COMPONENTS : MAX_BFCACHE_SLOT_ENTRIES_WITHOUT_CACHE_COMPONENTS;
@@ -18,6 +18,7 @@ function createRequestContext(opts) {
18
18
  actionRevalidationKind: 0,
19
19
  dynamicUsageDetected: false,
20
20
  renderRequestApiUsage: /* @__PURE__ */ new Set(),
21
+ connectionProbe: null,
21
22
  invalidDynamicUsageError: null,
22
23
  pendingSetCookies: [],
23
24
  draftModeCookieHeader: null,
package/dist/typegen.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { decodeRouteSegment, isInvisibleSegment } from "./routing/utils.js";
2
2
  import { patternToNextFormat } from "./routing/route-validation.js";
3
3
  import { compareStrings } from "./utils/compare.js";
4
+ import "./routing/app-route-graph.js";
4
5
  import { appRouteGraph } from "./routing/app-router.js";
5
6
  import path from "node:path";
6
7
  import fs from "node:fs/promises";
@@ -4,11 +4,18 @@ import { BuildManifestChunk } from "./lazy-chunks.js";
4
4
  type ClientBuildManifest = Record<string, BuildManifestChunk>;
5
5
  declare function readClientBuildManifest(manifestPath: string): ClientBuildManifest | undefined;
6
6
  declare function findClientEntryFileFromManifest(buildManifest: ClientBuildManifest, assetBase: string): string | undefined;
7
+ declare function findPagesClientEntryFileFromManifest(buildManifest: ClientBuildManifest, assetBase: string): string | undefined;
7
8
  declare function findClientEntryFile(options: {
8
9
  buildManifest?: ClientBuildManifest;
9
10
  clientDir: string;
10
11
  assetsSubdir: string;
11
12
  assetBase: string;
12
13
  }): string | undefined;
14
+ declare function findPagesClientEntryFile(options: {
15
+ buildManifest?: ClientBuildManifest;
16
+ clientDir: string;
17
+ assetsSubdir: string;
18
+ assetBase: string;
19
+ }): string | undefined;
13
20
  //#endregion
14
- export { findClientEntryFile, findClientEntryFileFromManifest, readClientBuildManifest };
21
+ export { findClientEntryFile, findClientEntryFileFromManifest, findPagesClientEntryFile, findPagesClientEntryFileFromManifest, readClientBuildManifest };
@@ -3,7 +3,8 @@ import { manifestFileWithBase } from "./manifest-paths.js";
3
3
  import fs from "node:fs";
4
4
  import path from "node:path";
5
5
  //#region src/utils/client-build-manifest.ts
6
- const CLIENT_ENTRY_MARKERS = ["vinext-client-entry", "vinext-app-browser-entry"];
6
+ const PAGES_CLIENT_ENTRY_MARKERS = ["vinext-client-entry"];
7
+ const CLIENT_ENTRY_MARKERS = [...PAGES_CLIENT_ENTRY_MARKERS, "vinext-app-browser-entry"];
7
8
  function readClientBuildManifest(manifestPath) {
8
9
  if (!fs.existsSync(manifestPath)) return void 0;
9
10
  try {
@@ -32,21 +33,55 @@ function readClientBuildManifest(manifestPath) {
32
33
  }
33
34
  }
34
35
  function findClientEntryFileFromManifest(buildManifest, assetBase) {
36
+ return findEntryFileFromManifest(buildManifest, assetBase, CLIENT_ENTRY_MARKERS, true);
37
+ }
38
+ function findPagesClientEntryFileFromManifest(buildManifest, assetBase) {
39
+ return findEntryFileFromManifest(buildManifest, assetBase, PAGES_CLIENT_ENTRY_MARKERS, false);
40
+ }
41
+ function findEntryFileFromManifest(buildManifest, assetBase, markers, fallbackToFirstEntry) {
35
42
  const entries = Object.values(buildManifest).filter((entry) => entry.isEntry && entry.file);
36
- const chosen = entries.find((entry) => CLIENT_ENTRY_MARKERS.some((marker) => entry.file.includes(marker))) ?? entries[0];
43
+ for (const marker of markers) {
44
+ const markedEntry = entries.find((entry) => entry.file.includes(marker));
45
+ if (markedEntry) return manifestFileWithBase(markedEntry.file, assetBase);
46
+ }
47
+ const chosen = fallbackToFirstEntry ? entries[0] : void 0;
37
48
  return chosen ? manifestFileWithBase(chosen.file, assetBase) : void 0;
38
49
  }
50
+ function listFilesRecursive(dir) {
51
+ const out = [];
52
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
53
+ const full = path.join(dir, entry.name);
54
+ if (entry.isDirectory()) out.push(...listFilesRecursive(full));
55
+ else if (entry.isFile()) out.push(full);
56
+ }
57
+ return out;
58
+ }
39
59
  function findClientEntryFileInAssetsDir(options) {
40
60
  const assetsDir = path.join(options.clientDir, options.assetsSubdir);
41
61
  if (!fs.existsSync(assetsDir)) return void 0;
42
- const entry = fs.readdirSync(assetsDir).find((file) => CLIENT_ENTRY_MARKERS.some((marker) => file.includes(marker)) && file.endsWith(".js"));
43
- return entry ? manifestFileWithBase(`${options.assetsSubdir}/${entry}`, options.assetBase) : void 0;
62
+ const files = listFilesRecursive(assetsDir);
63
+ let entryFull;
64
+ for (const marker of options.markers) {
65
+ entryFull = files.find((file) => path.basename(file).includes(marker) && file.endsWith(".js"));
66
+ if (entryFull) break;
67
+ }
68
+ if (!entryFull) return void 0;
69
+ return manifestFileWithBase(path.relative(options.clientDir, entryFull).split(path.sep).join("/"), options.assetBase);
44
70
  }
45
71
  function findClientEntryFile(options) {
46
- return (options.buildManifest ? findClientEntryFileFromManifest(options.buildManifest, options.assetBase) : void 0) ?? findClientEntryFileInAssetsDir(options);
72
+ return (options.buildManifest ? findClientEntryFileFromManifest(options.buildManifest, options.assetBase) : void 0) ?? findClientEntryFileInAssetsDir({
73
+ ...options,
74
+ markers: CLIENT_ENTRY_MARKERS
75
+ });
76
+ }
77
+ function findPagesClientEntryFile(options) {
78
+ return (options.buildManifest ? findPagesClientEntryFileFromManifest(options.buildManifest, options.assetBase) : void 0) ?? findClientEntryFileInAssetsDir({
79
+ ...options,
80
+ markers: PAGES_CLIENT_ENTRY_MARKERS
81
+ });
47
82
  }
48
83
  function readStringArray(value) {
49
84
  return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : void 0;
50
85
  }
51
86
  //#endregion
52
- export { findClientEntryFile, findClientEntryFileFromManifest, readClientBuildManifest };
87
+ export { findClientEntryFile, findClientEntryFileFromManifest, findPagesClientEntryFile, findPagesClientEntryFileFromManifest, readClientBuildManifest };
@@ -0,0 +1,11 @@
1
+ //#region src/utils/client-entry-manifest.d.ts
2
+ declare const VINEXT_CLIENT_ENTRY_MANIFEST = "vinext-client-entry-manifest.json";
3
+ type ClientEntryManifest = {
4
+ pagesClientEntry?: string;
5
+ appBrowserEntry?: string;
6
+ };
7
+ declare function readClientEntryManifest(clientDir: string): ClientEntryManifest | undefined;
8
+ declare function findClientEntryFileFromVinextManifest(manifest: ClientEntryManifest | undefined, assetBase: string): string | undefined;
9
+ declare function findPagesClientEntryFileFromVinextManifest(manifest: ClientEntryManifest | undefined, assetBase: string): string | undefined;
10
+ //#endregion
11
+ export { ClientEntryManifest, VINEXT_CLIENT_ENTRY_MANIFEST, findClientEntryFileFromVinextManifest, findPagesClientEntryFileFromVinextManifest, readClientEntryManifest };
@@ -0,0 +1,29 @@
1
+ import { isUnknownRecord } from "./record.js";
2
+ import { manifestFileWithBase } from "./manifest-paths.js";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ //#region src/utils/client-entry-manifest.ts
6
+ const VINEXT_CLIENT_ENTRY_MANIFEST = "vinext-client-entry-manifest.json";
7
+ function readClientEntryManifest(clientDir) {
8
+ const manifestPath = path.join(clientDir, VINEXT_CLIENT_ENTRY_MANIFEST);
9
+ if (!fs.existsSync(manifestPath)) return void 0;
10
+ try {
11
+ const value = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
12
+ if (!isUnknownRecord(value)) return void 0;
13
+ const manifest = {};
14
+ if (typeof value.pagesClientEntry === "string") manifest.pagesClientEntry = value.pagesClientEntry;
15
+ if (typeof value.appBrowserEntry === "string") manifest.appBrowserEntry = value.appBrowserEntry;
16
+ return manifest.pagesClientEntry || manifest.appBrowserEntry ? manifest : void 0;
17
+ } catch {
18
+ return;
19
+ }
20
+ }
21
+ function findClientEntryFileFromVinextManifest(manifest, assetBase) {
22
+ const entry = manifest?.pagesClientEntry ?? manifest?.appBrowserEntry;
23
+ return entry ? manifestFileWithBase(entry, assetBase) : void 0;
24
+ }
25
+ function findPagesClientEntryFileFromVinextManifest(manifest, assetBase) {
26
+ return manifest?.pagesClientEntry ? manifestFileWithBase(manifest.pagesClientEntry, assetBase) : void 0;
27
+ }
28
+ //#endregion
29
+ export { VINEXT_CLIENT_ENTRY_MANIFEST, findClientEntryFileFromVinextManifest, findPagesClientEntryFileFromVinextManifest, readClientEntryManifest };
@@ -0,0 +1,45 @@
1
+ //#region src/utils/client-runtime-metadata.d.ts
2
+ type ClientRuntimeMetadata = {
3
+ clientEntryFile?: string;
4
+ lazyChunks?: string[];
5
+ dynamicPreloads?: Record<string, string[]>;
6
+ };
7
+ /**
8
+ * Read the client build manifest and compute runtime metadata used by
9
+ * Cloudflare worker entry injection and Node production server startup.
10
+ *
11
+ * - `lazyChunks` — chunks only reachable through dynamic `import()`, excluded
12
+ * from modulepreload hints.
13
+ * - `dynamicPreloads` — per-module JS/CSS files for rendered `next/dynamic()`
14
+ * boundaries, injected as preload links during SSR.
15
+ * - `clientEntryFile` — the client entry chunk filename (optional, only
16
+ * needed for Pages Router).
17
+ *
18
+ * All file paths are normalised with the configured `assetBase` (basePath)
19
+ * and `assetPrefix`.
20
+ */
21
+ declare function computeClientRuntimeMetadata(opts: {
22
+ clientDir: string;
23
+ assetBase: string;
24
+ assetPrefix: string;
25
+ includeClientEntry?: boolean | "pages-client-entry";
26
+ }): ClientRuntimeMetadata;
27
+ /**
28
+ * Serialize runtime metadata into the `globalThis.__VINEXT_*` assignment script
29
+ * that the Cloudflare `closeBundle` hook prepends to the worker entry. Returns
30
+ * `""` when there is nothing to inject.
31
+ *
32
+ * Both the App Router and Pages Router closeBundle paths call this (and the
33
+ * deploy tests mirror it), so the injection shape stays in one place. The caller
34
+ * decides which fields to pass — e.g. App Router only forwards `clientEntryFile`
35
+ * for mixed app+pages builds (where `computeClientRuntimeMetadata` was asked for
36
+ * the Pages client entry); pure App Router leaves it undefined.
37
+ */
38
+ declare function buildRuntimeGlobalsScript(input: {
39
+ clientEntryFile?: string | null;
40
+ ssrManifest?: Record<string, string[]> | null;
41
+ lazyChunks?: string[] | null;
42
+ dynamicPreloads?: Record<string, string[]> | null;
43
+ }): string;
44
+ //#endregion
45
+ export { buildRuntimeGlobalsScript, computeClientRuntimeMetadata };