vinext 0.1.3 → 0.1.5

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 (185) hide show
  1. package/dist/build/client-build-config.d.ts +11 -2
  2. package/dist/build/client-build-config.js +17 -6
  3. package/dist/build/css-url-assets.d.ts +1 -1
  4. package/dist/build/css-url-assets.js +9 -7
  5. package/dist/build/prerender.js +3 -1
  6. package/dist/cache/cache-adapters-virtual.js +1 -1
  7. package/dist/client/pages-router-link-navigation.d.ts +33 -7
  8. package/dist/client/pages-router-link-navigation.js +32 -2
  9. package/dist/client/vinext-next-data.js +2 -0
  10. package/dist/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +1 -1
  11. package/dist/config/config-matchers.d.ts +11 -1
  12. package/dist/config/config-matchers.js +14 -2
  13. package/dist/config/tsconfig-paths.js +14 -1
  14. package/dist/deploy.js +20 -13
  15. package/dist/entries/app-rsc-entry.js +27 -22
  16. package/dist/entries/pages-client-entry.js +14 -13
  17. package/dist/entries/pages-server-entry.js +8 -27
  18. package/dist/index.js +365 -147
  19. package/dist/plugins/css-data-url.js +30 -26
  20. package/dist/plugins/dynamic-preload-metadata.js +2 -4
  21. package/dist/plugins/extensionless-dynamic-import.js +27 -24
  22. package/dist/plugins/fonts.js +5 -4
  23. package/dist/plugins/import-meta-url.js +21 -15
  24. package/dist/plugins/instrumentation-client.js +1 -1
  25. package/dist/plugins/middleware-server-only.js +7 -6
  26. package/dist/plugins/og-assets.js +48 -46
  27. package/dist/plugins/optimize-imports.js +9 -3
  28. package/dist/plugins/remove-console.d.ts +7 -1
  29. package/dist/plugins/remove-console.js +4 -1
  30. package/dist/plugins/require-context.js +21 -20
  31. package/dist/plugins/strip-server-exports.d.ts +16 -8
  32. package/dist/plugins/strip-server-exports.js +496 -46
  33. package/dist/routing/app-route-graph.js +2 -2
  34. package/dist/server/app-bfcache-identity.d.ts +26 -0
  35. package/dist/server/app-bfcache-identity.js +127 -0
  36. package/dist/server/app-browser-action-result.js +1 -1
  37. package/dist/server/app-browser-entry.js +22 -12
  38. package/dist/server/app-browser-navigation-controller.d.ts +1 -1
  39. package/dist/server/app-browser-navigation-controller.js +1 -1
  40. package/dist/server/app-browser-state.d.ts +3 -22
  41. package/dist/server/app-browser-state.js +23 -139
  42. package/dist/server/app-browser-stream.js +1 -1
  43. package/dist/server/app-browser-visible-commit.d.ts +1 -1
  44. package/dist/server/app-browser-visible-commit.js +3 -2
  45. package/dist/server/app-fallback-renderer.d.ts +1 -1
  46. package/dist/server/app-layout-param-observation.d.ts +1 -1
  47. package/dist/server/app-layout-param-observation.js +1 -1
  48. package/dist/server/app-middleware.js +2 -1
  49. package/dist/server/app-page-boundary-render.d.ts +1 -1
  50. package/dist/server/app-page-boundary.js +1 -1
  51. package/dist/server/app-page-cache-finalizer.d.ts +62 -0
  52. package/dist/server/app-page-cache-finalizer.js +122 -0
  53. package/dist/server/app-page-cache-render.d.ts +2 -2
  54. package/dist/server/app-page-cache-render.js +1 -1
  55. package/dist/server/app-page-cache.d.ts +2 -53
  56. package/dist/server/app-page-cache.js +5 -131
  57. package/dist/server/app-page-dispatch.d.ts +2 -2
  58. package/dist/server/app-page-dispatch.js +10 -8
  59. package/dist/server/app-page-probe.js +3 -2
  60. package/dist/server/app-page-render-observation.js +2 -2
  61. package/dist/server/app-page-render.d.ts +3 -3
  62. package/dist/server/app-page-render.js +3 -2
  63. package/dist/server/app-page-stream.d.ts +2 -9
  64. package/dist/server/app-page-stream.js +1 -35
  65. package/dist/server/app-pages-bridge.d.ts +5 -1
  66. package/dist/server/app-pages-bridge.js +5 -13
  67. package/dist/server/app-request-context.d.ts +1 -2
  68. package/dist/server/app-request-context.js +2 -1
  69. package/dist/server/app-route-handler-dispatch.js +3 -2
  70. package/dist/server/app-route-handler-execution.d.ts +1 -1
  71. package/dist/server/app-route-handler-execution.js +1 -1
  72. package/dist/server/app-route-handler-response.d.ts +1 -1
  73. package/dist/server/app-router-entry.js +2 -1
  74. package/dist/server/app-rsc-handler.d.ts +3 -0
  75. package/dist/server/app-rsc-handler.js +73 -31
  76. package/dist/server/app-rsc-response-finalizer.js +1 -1
  77. package/dist/server/app-rsc-route-matching.js +6 -2
  78. package/dist/server/app-server-action-execution.d.ts +1 -1
  79. package/dist/server/app-server-action-execution.js +10 -6
  80. package/dist/server/app-ssr-entry.d.ts +1 -1
  81. package/dist/server/app-ssr-entry.js +12 -38
  82. package/dist/server/app-ssr-router-instance.d.ts +6 -0
  83. package/dist/server/app-ssr-router-instance.js +24 -0
  84. package/dist/server/app-ssr-stream.js +1 -1
  85. package/dist/server/artifact-compatibility.js +1 -1
  86. package/dist/server/before-interactive-head.d.ts +17 -0
  87. package/dist/server/before-interactive-head.js +35 -0
  88. package/dist/server/client-reuse-manifest.js +1 -1
  89. package/dist/server/csp.js +1 -4
  90. package/dist/server/defer-until-stream-consumed.d.ts +7 -0
  91. package/dist/server/defer-until-stream-consumed.js +34 -0
  92. package/dist/server/dev-server.js +82 -37
  93. package/dist/server/instrumentation.js +1 -1
  94. package/dist/server/isr-cache.d.ts +1 -1
  95. package/dist/server/isr-cache.js +1 -1
  96. package/dist/server/isr-decision.d.ts +1 -1
  97. package/dist/server/middleware-matcher.js +20 -9
  98. package/dist/server/middleware-runtime.d.ts +3 -4
  99. package/dist/server/middleware-runtime.js +4 -2
  100. package/dist/server/navigation-planner.d.ts +3 -12
  101. package/dist/server/navigation-planner.js +24 -0
  102. package/dist/server/navigation-trace.d.ts +2 -1
  103. package/dist/server/navigation-trace.js +1 -0
  104. package/dist/server/open-redirect.d.ts +12 -0
  105. package/dist/server/open-redirect.js +21 -0
  106. package/dist/server/operation-token.d.ts +40 -0
  107. package/dist/server/operation-token.js +85 -0
  108. package/dist/server/pages-data-route.d.ts +1 -1
  109. package/dist/server/pages-data-route.js +7 -4
  110. package/dist/server/pages-dev-module-url.d.ts +4 -0
  111. package/dist/server/pages-dev-module-url.js +15 -0
  112. package/dist/server/pages-document-initial-props.d.ts +4 -15
  113. package/dist/server/pages-document-initial-props.js +27 -56
  114. package/dist/server/pages-i18n.js +2 -2
  115. package/dist/server/pages-page-data.d.ts +1 -1
  116. package/dist/server/pages-page-data.js +3 -1
  117. package/dist/server/pages-page-handler.js +3 -1
  118. package/dist/server/pages-page-response.d.ts +3 -1
  119. package/dist/server/pages-page-response.js +6 -6
  120. package/dist/server/pages-readiness.js +1 -1
  121. package/dist/server/pages-request-pipeline.d.ts +7 -7
  122. package/dist/server/pages-request-pipeline.js +63 -21
  123. package/dist/server/prod-server.d.ts +3 -1
  124. package/dist/server/prod-server.js +43 -11
  125. package/dist/server/request-pipeline.d.ts +1 -24
  126. package/dist/server/request-pipeline.js +1 -33
  127. package/dist/server/seed-cache.d.ts +1 -1
  128. package/dist/server/static-file-cache.js +16 -4
  129. package/dist/shims/before-interactive-context.d.ts +14 -3
  130. package/dist/shims/cache-handler.d.ts +106 -0
  131. package/dist/shims/cache-handler.js +176 -0
  132. package/dist/shims/cache-request-state.d.ts +47 -0
  133. package/dist/shims/cache-request-state.js +126 -0
  134. package/dist/shims/cache-runtime.d.ts +2 -2
  135. package/dist/shims/cache-runtime.js +3 -14
  136. package/dist/shims/cache.d.ts +3 -231
  137. package/dist/shims/cache.js +17 -383
  138. package/dist/shims/cdn-cache.d.ts +1 -1
  139. package/dist/shims/cdn-cache.js +1 -1
  140. package/dist/shims/document.d.ts +15 -20
  141. package/dist/shims/document.js +5 -8
  142. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  143. package/dist/shims/error-boundary-navigation.js +44 -0
  144. package/dist/shims/error-boundary.js +10 -8
  145. package/dist/shims/error.js +2 -1
  146. package/dist/shims/fetch-cache.js +1 -1
  147. package/dist/shims/form.js +1 -1
  148. package/dist/shims/image.js +74 -9
  149. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -0
  150. package/dist/shims/internal/app-page-props-cache-key.js +16 -0
  151. package/dist/shims/internal/navigation-untracked.js +2 -1
  152. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +6 -7
  153. package/dist/shims/internal/pages-data-fetch-dedup.js +67 -14
  154. package/dist/shims/internal/pages-data-target.js +1 -1
  155. package/dist/shims/layout-segment-context.d.ts +1 -1
  156. package/dist/shims/layout-segment-context.js +2 -1
  157. package/dist/shims/link.js +38 -17
  158. package/dist/shims/metadata.js +4 -4
  159. package/dist/shims/navigation-context-state.d.ts +40 -0
  160. package/dist/shims/navigation-context-state.js +116 -0
  161. package/dist/shims/navigation-errors.d.ts +55 -0
  162. package/dist/shims/navigation-errors.js +110 -0
  163. package/dist/shims/navigation-server.d.ts +3 -0
  164. package/dist/shims/navigation-server.js +3 -0
  165. package/dist/shims/navigation-state.d.ts +1 -2
  166. package/dist/shims/navigation-state.js +2 -1
  167. package/dist/shims/navigation.d.ts +3 -291
  168. package/dist/shims/navigation.js +16 -445
  169. package/dist/shims/navigation.react-server.d.ts +2 -2
  170. package/dist/shims/navigation.react-server.js +3 -1
  171. package/dist/shims/request-state-types.d.ts +3 -3
  172. package/dist/shims/router.d.ts +6 -2
  173. package/dist/shims/router.js +99 -20
  174. package/dist/shims/script.js +9 -5
  175. package/dist/shims/slot.js +3 -1
  176. package/dist/shims/unified-request-context.d.ts +2 -2
  177. package/dist/utils/has-trailing-comma.d.ts +24 -0
  178. package/dist/utils/has-trailing-comma.js +62 -0
  179. package/dist/utils/text-stream.d.ts +1 -1
  180. package/dist/utils/text-stream.js +2 -2
  181. package/dist/utils/virtual-module.d.ts +5 -0
  182. package/dist/utils/virtual-module.js +0 -0
  183. package/dist/utils/vite-version.d.ts +12 -1
  184. package/dist/utils/vite-version.js +9 -1
  185. package/package.json +5 -1
@@ -1,7 +1,7 @@
1
1
  import { splitPathSegments } from "../routing/utils.js";
2
2
  import { removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
3
3
  import { assertSafeNavigationUrl } from "./url-safety.js";
4
- import { matchRoutePattern, routePatternParts } from "../routing/route-pattern.js";
4
+ import { fillRoutePatternSegments, matchRoutePattern, routePatternParts } from "../routing/route-pattern.js";
5
5
  import { isUnknownRecord } from "../utils/record.js";
6
6
  import { AppRouterContext } from "./internal/app-router-context.js";
7
7
  import { RouterContext } from "./internal/router-context.js";
@@ -9,8 +9,8 @@ import { applyVinextLocaleGlobals, extractVinextNextDataJson, parseVinextNextDat
9
9
  import { isValidModulePath } from "../client/validate-module-path.js";
10
10
  import { addLocalePrefix, getDomainLocaleUrl, getLocalePathPrefix } from "../utils/domain-locale.js";
11
11
  import { buildPagesDataHref } from "./internal/pages-data-url.js";
12
- import { dedupedPagesDataFetch } from "./internal/pages-data-fetch-dedup.js";
13
12
  import { NEXT_DEPLOYMENT_ID_HEADER, getDeploymentId } from "../utils/deployment-id.js";
13
+ import { dedupedPagesDataFetch } from "./internal/pages-data-fetch-dedup.js";
14
14
  import { prefetchPagesData, resolvePagesDataNavigationTarget } from "./internal/pages-data-target.js";
15
15
  import { addQueryParam, appendSearchParamsToUrl, mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
16
16
  import { resolveHybridClientRouteOwner } from "./internal/hybrid-client-route-owner.js";
@@ -214,11 +214,20 @@ function getPagesRouterRuntimeComponents() {
214
214
  }
215
215
  function resolveUrl(url) {
216
216
  if (typeof url === "string") return url;
217
- let result = url.pathname ?? "/";
218
- if (url.query) {
217
+ const hasQuery = url.query !== void 0 && Object.keys(url.query).length > 0;
218
+ const hasSearch = typeof url.search === "string" && url.search.length > 0;
219
+ const hasHash = typeof url.hash === "string" && url.hash.length > 0;
220
+ const inheritsVisiblePath = url.pathname === void 0 && (hasQuery || hasSearch || hasHash);
221
+ let result = url.pathname ?? (typeof window !== "undefined" ? inheritsVisiblePath ? stripBasePath(window.location.pathname, __basePath) : window.__NEXT_DATA__?.page ?? stripBasePath(window.location.pathname, __basePath) : "/");
222
+ if (hasSearch) {
223
+ const search = url.search.startsWith("?") ? url.search : `?${url.search}`;
224
+ const hashIndex = search.indexOf("#");
225
+ result += hashIndex === -1 ? search : `${search.slice(0, hashIndex)}%23${search.slice(hashIndex + 1)}`;
226
+ } else if (hasQuery) {
219
227
  const params = urlQueryToSearchParams(url.query);
220
228
  result = appendSearchParamsToUrl(result, params);
221
- }
229
+ } else if (hasHash && typeof window !== "undefined") result += window.location.search;
230
+ if (hasHash) result += url.hash.startsWith("#") ? url.hash : `#${url.hash}`;
222
231
  return result;
223
232
  }
224
233
  /**
@@ -230,8 +239,39 @@ function resolveUrl(url) {
230
239
  * Pages error routes are handled as a narrow exception below because Next.js
231
240
  * treats their href as the component route while preserving `as` in history.
232
241
  */
233
- function resolveNavigationTarget(url, as, locale) {
234
- return applyNavigationLocale(as ?? resolveUrl(url), locale);
242
+ function resolveNavigationTarget(url, as, locale, replaceExistingLocale = false) {
243
+ return applyNavigationLocale(as ?? resolveUrl(url), locale, replaceExistingLocale);
244
+ }
245
+ var HrefInterpolationError = class extends Error {};
246
+ function interpolateCurrentDynamicRoute(resolved) {
247
+ if (typeof window === "undefined") return resolved;
248
+ const routePattern = window.__NEXT_DATA__?.page;
249
+ if (!routePattern || extractRouteParamNames(routePattern).length === 0) return resolved;
250
+ try {
251
+ const target = new URL(resolved, "http://vinext.local");
252
+ const currentOrigin = getWindowOrigin();
253
+ if (currentOrigin && target.origin !== "http://vinext.local" && target.origin !== currentOrigin) return resolved;
254
+ const visiblePath = stripBasePath(window.location.pathname, __basePath);
255
+ const visibleLocale = getLocalePathPrefix(visiblePath, window.__VINEXT_LOCALES__);
256
+ if (extractRouteParamsFromPath(routePattern, visibleLocale ? visiblePath.slice(visibleLocale.length + 1) || "/" : visiblePath) === null) return resolved;
257
+ const query = parseQueryString(target.search);
258
+ const missingParams = routePatternParts(routePattern).filter((part) => part.startsWith(":") && !part.endsWith("*")).map((part) => part.slice(1, part.endsWith("+") ? -1 : void 0)).filter((paramName) => {
259
+ const value = query[paramName];
260
+ return value === void 0 || value === "" || Array.isArray(value) && value.length === 0;
261
+ });
262
+ if (missingParams.length > 0) throw new HrefInterpolationError(`The provided \`href\` (${`${routePattern}${target.search}${target.hash}`}) value is missing query values (${missingParams.join(", ")}) to be interpolated properly. Read more: https://nextjs.org/docs/messages/href-interpolation-failed`);
263
+ const routeParams = getRouteParamsFromQuery(routePattern, query);
264
+ if (!routeParams) return resolved;
265
+ const pathname = fillRoutePatternSegments(routePattern, Object.fromEntries(Object.entries(routeParams).map(([key, value]) => [key, Array.isArray(value) ? value.map(encodeURIComponent) : encodeURIComponent(value)])));
266
+ if (!pathname) return resolved;
267
+ const targetLocale = getLocalePathPrefix(target.pathname, window.__VINEXT_LOCALES__);
268
+ target.pathname = targetLocale ? `/${targetLocale}${pathname}` : pathname;
269
+ for (const paramName of extractRouteParamNames(routePattern)) target.searchParams.delete(paramName);
270
+ return target.href.slice(target.origin.length);
271
+ } catch (error) {
272
+ if (error instanceof HrefInterpolationError) throw error;
273
+ return resolved;
274
+ }
235
275
  }
236
276
  function getCurrentUrlLocale() {
237
277
  return getCurrentBrowserLocale({
@@ -296,13 +336,26 @@ function getDomainLocalePath(url, locale) {
296
336
  * Apply locale prefix to a URL for client-side navigation.
297
337
  * Same logic as Link's applyLocaleToHref but reads from window globals.
298
338
  */
299
- function applyNavigationLocale(url, locale) {
339
+ function applyNavigationLocale(url, locale, replaceExistingLocale = false) {
300
340
  if (!locale || typeof window === "undefined") return url;
301
341
  if (isAbsoluteOrProtocolRelativeUrl(url)) return url;
302
- if (getLocalePathPrefix(url, window.__VINEXT_LOCALES__)) return url;
303
- const domainLocalePath = getDomainLocalePath(url, locale);
342
+ if (!replaceExistingLocale && getLocalePathPrefix(url, window.__VINEXT_LOCALES__)) return url;
343
+ const normalizedUrl = replaceExistingLocale ? removeNavigationLocalePrefix(url) : url;
344
+ const domainLocalePath = getDomainLocalePath(normalizedUrl, locale);
304
345
  if (domainLocalePath) return domainLocalePath;
305
- return addLocalePrefix(url, locale, window.__VINEXT_DEFAULT_LOCALE__ ?? "");
346
+ return addLocalePrefix(normalizedUrl, locale, window.__VINEXT_DEFAULT_LOCALE__ ?? "");
347
+ }
348
+ function removeNavigationLocalePrefix(url) {
349
+ const locales = window.__VINEXT_LOCALES__;
350
+ if (!locales?.length) return url;
351
+ try {
352
+ const parsed = new URL(url, "http://vinext.local");
353
+ const locale = getLocalePathPrefix(parsed.pathname, locales);
354
+ if (!locale) return url;
355
+ return `${parsed.pathname.slice(locale.length + 1) || "/"}${parsed.search}${parsed.hash}`;
356
+ } catch {
357
+ return url;
358
+ }
306
359
  }
307
360
  function isDefaultLocaleRootNavigation(url, locale) {
308
361
  if (typeof window === "undefined") return false;
@@ -640,9 +693,23 @@ function getPathnameAndQuery() {
640
693
  ...searchQuery,
641
694
  ...routeQuery
642
695
  },
643
- asPath: resolvedPath + window.location.search + window.location.hash
696
+ asPath: getCurrentHistoryAsPath() ?? resolvedPath + window.location.search + window.location.hash
644
697
  };
645
698
  }
699
+ function getCurrentHistoryAsPath() {
700
+ const state = window.history?.state;
701
+ if (!isNextRouterState(state) || typeof state.as !== "string") return null;
702
+ try {
703
+ const browserUrl = new URL(window.location.href);
704
+ const stateUrl = new URL(toBrowserNavigationHref(state.as, window.location.href, __basePath), window.location.href);
705
+ if (stateUrl.pathname !== browserUrl.pathname || stateUrl.search !== browserUrl.search) return null;
706
+ const stateAs = stripHash(state.as);
707
+ const visibleAs = `${stripBasePath(window.location.pathname, __basePath)}${window.location.search}`;
708
+ return `${stateAs || visibleAs}${window.location.hash}`;
709
+ } catch {
710
+ return null;
711
+ }
712
+ }
646
713
  function getPagesNavigationIsReadyFromSerializedState(routePattern, searchString, nextData) {
647
714
  if (!routePattern) return true;
648
715
  if (nextData?.gssp === true || nextData?.gip === true || nextData?.isExperimentalCompile === true || nextData?.appGip === true && nextData.gsp !== true) return true;
@@ -672,6 +739,10 @@ function markPagesRouterReady() {
672
739
  routerRuntimeState.pagesRouterReady = true;
673
740
  return true;
674
741
  }
742
+ function initializePagesRouterReadyFromNextData(nextData) {
743
+ if (typeof window === "undefined") return;
744
+ routerRuntimeState.pagesRouterReady = getPagesNavigationIsReadyFromSerializedState(nextData.page, window.location.search, nextData);
745
+ }
675
746
  function markPagesRouterHydrated() {
676
747
  if (typeof window === "undefined" || window.__NEXT_HYDRATED === true) return;
677
748
  const hydratedAt = performance.now();
@@ -792,10 +863,13 @@ async function resolveMiddlewareDataEffect(browserUrl, signal) {
792
863
  if (!dataUrl) return null;
793
864
  if (signal.aborted) throw new DOMException("Aborted", "AbortError");
794
865
  try {
795
- const res = await dedupedPagesDataFetch(dataUrl, { headers: {
796
- Accept: "application/json",
797
- "x-nextjs-data": "1"
798
- } });
866
+ const res = await dedupedPagesDataFetch(dataUrl, {
867
+ headers: {
868
+ Accept: "application/json",
869
+ "x-nextjs-data": "1"
870
+ },
871
+ signal
872
+ });
799
873
  return {
800
874
  redirectLocation: res.headers.get("x-nextjs-redirect"),
801
875
  rewriteTarget: res.headers.get("x-nextjs-rewrite"),
@@ -851,7 +925,10 @@ async function navigateClientData(url, initialTarget, controller, navId, assertS
851
925
  };
852
926
  const deploymentId = getDeploymentId();
853
927
  if (deploymentId) headers[NEXT_DEPLOYMENT_ID_HEADER] = deploymentId;
854
- res = await dedupedPagesDataFetch(initialTarget.dataHref, { headers });
928
+ res = await dedupedPagesDataFetch(initialTarget.dataHref, {
929
+ headers,
930
+ signal: controller.signal
931
+ });
855
932
  } catch (err) {
856
933
  if (err instanceof DOMException && err.name === "AbortError") throw new NavigationCancelledError(url);
857
934
  throw err;
@@ -1043,7 +1120,8 @@ async function navigateClientHtml(url, fetchUrl, controller, navId, assertStillC
1043
1120
  */
1044
1121
  async function navigateClient(url, fetchUrl = url, options = {}) {
1045
1122
  if (typeof window === "undefined") return;
1046
- routerRuntimeState.activeAbortController?.abort();
1123
+ const previousAbortController = routerRuntimeState.activeAbortController;
1124
+ if (previousAbortController) queueMicrotask(() => previousAbortController.abort());
1047
1125
  cancelPreviousRenderCommit();
1048
1126
  const controller = new AbortController();
1049
1127
  routerRuntimeState.activeAbortController = controller;
@@ -1222,7 +1300,8 @@ async function performNavigation(url, as, options, mode, onStateUpdate) {
1222
1300
  assertSafeNavigationUrl(resolveUrl(url));
1223
1301
  if (as !== void 0) assertSafeNavigationUrl(String(as));
1224
1302
  const navigationLocale = resolveTransitionLocale(options?.locale);
1225
- let resolved = resolveNavigationTarget(url, as, navigationLocale);
1303
+ let resolved = resolveNavigationTarget(url, as, navigationLocale, as === void 0 && options?.locale !== void 0 && typeof url !== "string" && url.pathname === void 0 && (url.query !== void 0 && Object.keys(url.query).length > 0 || typeof url.search === "string" && url.search.length > 0 || typeof url.hash === "string" && url.hash.length > 0));
1304
+ if (as === void 0 && (typeof url === "string" && options?._vinextInterpolateDynamicRoute === true || typeof url !== "string" && url.pathname === void 0 && (url.query !== void 0 && Object.keys(url.query).length > 0 || typeof url.search === "string" && url.search.length > 0))) resolved = interpolateCurrentDynamicRoute(resolved);
1226
1305
  if (isExternalUrl(resolved)) {
1227
1306
  const localPath = toSameOriginAppPath(resolved, __basePath);
1228
1307
  if (localPath == null) {
@@ -1660,4 +1739,4 @@ if (typeof window !== "undefined") {
1660
1739
  const _PAGES_NAVIGATION_ACCESSOR_KEY = Symbol.for("vinext.navigation.pagesNavigationContextAccessor");
1661
1740
  globalThis[_PAGES_NAVIGATION_ACCESSOR_KEY] = getPagesNavigationContext;
1662
1741
  //#endregion
1663
- export { markPagesRouterReady as _markPagesRouterReady, _registerRouterStateAccessors, applyNavigationLocale, Router as default, getPagesNavigationContext, getPagesNavigationIsReadyFromSerializedState, isExternalUrl, isHashOnlyChange, setSSRContext, useRouter, withRouter, wrapWithRouterContext };
1742
+ export { initializePagesRouterReadyFromNextData as _initializePagesRouterReadyFromNextData, markPagesRouterReady as _markPagesRouterReady, _registerRouterStateAccessors, applyNavigationLocale, Router as default, getPagesNavigationContext, getPagesNavigationIsReadyFromSerializedState, isExternalUrl, isHashOnlyChange, setSSRContext, useRouter, withRouter, wrapWithRouterContext };
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { escapeInlineContent } from "./head.js";
3
- import { hasAppNavigationRuntimeBootstrap } from "../client/navigation-runtime.js";
4
3
  import { useScriptNonce } from "./script-nonce-context.js";
4
+ import { hasAppNavigationRuntimeBootstrap } from "../client/navigation-runtime.js";
5
5
  import { useBeforeInteractiveRegister } from "./before-interactive-context.js";
6
6
  import React, { useEffect, useRef } from "react";
7
7
  import * as ReactDOM from "react-dom";
@@ -113,8 +113,10 @@ function extractBeforeInteractiveInlineContent(children, dangerouslySetInnerHTML
113
113
  const REACT_TO_HTML_ATTR = {
114
114
  acceptCharset: "accept-charset",
115
115
  className: "class",
116
+ crossOrigin: "crossorigin",
116
117
  htmlFor: "for",
117
- httpEquiv: "http-equiv"
118
+ httpEquiv: "http-equiv",
119
+ referrerPolicy: "referrerpolicy"
118
120
  };
119
121
  /**
120
122
  * Convert the residual `<Script>` props into a plain string-attributes record
@@ -331,10 +333,11 @@ function Script(props) {
331
333
  }
332
334
  if (strategy === "beforeInteractive") {
333
335
  const inlineContent = src ? null : extractBeforeInteractiveInlineContent(children, dangerouslySetInnerHTML);
334
- if (inlineContent !== null && registerBeforeInteractive) {
336
+ if ((src || inlineContent !== null) && registerBeforeInteractive) {
335
337
  registerBeforeInteractive({
336
338
  id,
337
- innerHTML: escapeInlineContent(inlineContent, "script"),
339
+ src: src ?? void 0,
340
+ innerHTML: inlineContent !== null ? escapeInlineContent(inlineContent, "script") : void 0,
338
341
  nonce: resolvedNonce,
339
342
  attributes: collectBeforeInteractiveAttributes(rest)
340
343
  });
@@ -351,7 +354,8 @@ function Script(props) {
351
354
  return null;
352
355
  }
353
356
  if (strategy === "beforeInteractive") {
354
- if ((src ? null : extractBeforeInteractiveInlineContent(children, dangerouslySetInnerHTML)) !== null && hasAppNavigationRuntimeBootstrap()) return null;
357
+ const inlineContent = src ? null : extractBeforeInteractiveInlineContent(children, dangerouslySetInnerHTML);
358
+ if ((src || inlineContent !== null) && hasAppNavigationRuntimeBootstrap()) return null;
355
359
  return React.createElement("script", buildBeforeInteractiveScriptProps({
356
360
  src,
357
361
  id,
@@ -1,7 +1,9 @@
1
1
  "use client";
2
2
  import { AppElementsWire, UNMATCHED_SLOT } from "../server/app-elements-wire.js";
3
3
  import "../server/app-elements.js";
4
- import { getBfcacheIdMapContext, getBfcacheSegmentIdContext, notFound } from "./navigation.js";
4
+ import { getBfcacheIdMapContext, getBfcacheSegmentIdContext } from "./navigation-context-state.js";
5
+ import { notFound } from "./navigation-errors.js";
6
+ import "./navigation-server.js";
5
7
  import * as React$1 from "react";
6
8
  import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
7
9
  //#region src/shims/slot.tsx
@@ -1,10 +1,10 @@
1
- import { PrivateCacheState } from "./cache-runtime.js";
1
+ import { CacheState } from "./cache-request-state.js";
2
2
  import { ExecutionContextLike } from "./request-context.js";
3
- import { CacheState } from "./cache.js";
4
3
  import { RootParamsState } from "./root-params.js";
5
4
  import { FetchCacheState } from "./fetch-cache.js";
6
5
  import { VinextHeadersShimState } from "./headers.js";
7
6
  import { RouterState } from "./router-state.js";
7
+ import { PrivateCacheState } from "./cache-runtime.js";
8
8
  import { HeadState } from "./head-state.js";
9
9
  import { I18nState } from "./i18n-state.js";
10
10
  import { NavigationState } from "./navigation-state.js";
@@ -0,0 +1,24 @@
1
+ //#region src/utils/has-trailing-comma.d.ts
2
+ /**
3
+ * Return the last syntactically significant character of a JS source fragment,
4
+ * skipping whitespace and comments. A forward scan tracks string and comment
5
+ * state so that `//` or `/*` sequences appearing INSIDE a string literal (e.g. a
6
+ * URL such as `"https://example.com"` or a path with a double slash) are NOT
7
+ * mistaken for comments.
8
+ *
9
+ * This is deliberately stricter than a whole-string comment strip: stripping
10
+ * every `//...`/`/* ... *\/` would also delete those sequences from inside
11
+ * string literals, which can swallow the real trailing comma that follows them
12
+ * and corrupt the trailing-comma / empty-object detection this feeds.
13
+ *
14
+ * Returns "" for an empty / whitespace-only / comment-only fragment.
15
+ */
16
+ declare function lastSignificantChar(source: string): string;
17
+ /**
18
+ * True when `source` ends — ignoring trailing whitespace and comments — with a
19
+ * real trailing comma. Used to avoid splicing a second comma (`,,` is a syntax
20
+ * error) when injecting a property or argument into existing source.
21
+ */
22
+ declare function hasTrailingComma(source: string): boolean;
23
+ //#endregion
24
+ export { hasTrailingComma, lastSignificantChar };
@@ -0,0 +1,62 @@
1
+ //#region src/utils/has-trailing-comma.ts
2
+ /**
3
+ * Return the last syntactically significant character of a JS source fragment,
4
+ * skipping whitespace and comments. A forward scan tracks string and comment
5
+ * state so that `//` or `/*` sequences appearing INSIDE a string literal (e.g. a
6
+ * URL such as `"https://example.com"` or a path with a double slash) are NOT
7
+ * mistaken for comments.
8
+ *
9
+ * This is deliberately stricter than a whole-string comment strip: stripping
10
+ * every `//...`/`/* ... *\/` would also delete those sequences from inside
11
+ * string literals, which can swallow the real trailing comma that follows them
12
+ * and corrupt the trailing-comma / empty-object detection this feeds.
13
+ *
14
+ * Returns "" for an empty / whitespace-only / comment-only fragment.
15
+ */
16
+ function lastSignificantChar(source) {
17
+ let last = "";
18
+ let i = 0;
19
+ const n = source.length;
20
+ while (i < n) {
21
+ const c = source[i];
22
+ const next = source[i + 1];
23
+ if (c === "/" && next === "/") {
24
+ i += 2;
25
+ while (i < n && source[i] !== "\n") i += 1;
26
+ continue;
27
+ }
28
+ if (c === "/" && next === "*") {
29
+ i += 2;
30
+ while (i < n && !(source[i] === "*" && source[i + 1] === "/")) i += 1;
31
+ i += 2;
32
+ continue;
33
+ }
34
+ if (c === "\"" || c === "'" || c === "`") {
35
+ i += 1;
36
+ while (i < n && source[i] !== c) {
37
+ if (source[i] === "\\") i += 1;
38
+ i += 1;
39
+ }
40
+ last = c;
41
+ i += 1;
42
+ continue;
43
+ }
44
+ if (/\s/.test(c)) {
45
+ i += 1;
46
+ continue;
47
+ }
48
+ last = c;
49
+ i += 1;
50
+ }
51
+ return last;
52
+ }
53
+ /**
54
+ * True when `source` ends — ignoring trailing whitespace and comments — with a
55
+ * real trailing comma. Used to avoid splicing a second comma (`,,` is a syntax
56
+ * error) when injecting a property or argument into existing source.
57
+ */
58
+ function hasTrailingComma(source) {
59
+ return lastSignificantChar(source) === ",";
60
+ }
61
+ //#endregion
62
+ export { hasTrailingComma, lastSignificantChar };
@@ -16,7 +16,7 @@
16
16
  declare function readStreamAsText(stream: ReadableStream<Uint8Array>): Promise<string>;
17
17
  /**
18
18
  * Drain a UTF-8 byte stream up to `maxBytes` of *raw* input, returning the
19
- * decoded text. If the raw size limit is exceeded, the reader is cancelled
19
+ * decoded text. If the raw size limit is exceeded, cancellation is signalled
20
20
  * and `onLimitExceeded` is invoked; it MUST throw — its return type is
21
21
  * `never` to enforce that. Each caller passes its own error type.
22
22
  *
@@ -31,7 +31,7 @@ async function readStreamAsText(stream) {
31
31
  }
32
32
  /**
33
33
  * Drain a UTF-8 byte stream up to `maxBytes` of *raw* input, returning the
34
- * decoded text. If the raw size limit is exceeded, the reader is cancelled
34
+ * decoded text. If the raw size limit is exceeded, cancellation is signalled
35
35
  * and `onLimitExceeded` is invoked; it MUST throw — its return type is
36
36
  * `never` to enforce that. Each caller passes its own error type.
37
37
  *
@@ -49,7 +49,7 @@ async function readStreamAsTextWithLimit(stream, maxBytes, onLimitExceeded) {
49
49
  if (result.done) break;
50
50
  totalSize += result.value.byteLength;
51
51
  if (totalSize > maxBytes) {
52
- await reader.cancel();
52
+ reader.cancel();
53
53
  onLimitExceeded();
54
54
  }
55
55
  chunks.push(decoder.decode(result.value, { stream: true }));
@@ -0,0 +1,5 @@
1
+ //#region src/utils/virtual-module.d.ts
2
+ declare const VIRTUAL_PREFIX = "\0";
3
+ declare const VIRTUAL_MODULE_ID_RE: RegExp;
4
+ //#endregion
5
+ export { VIRTUAL_MODULE_ID_RE, VIRTUAL_PREFIX };
Binary file
@@ -1,4 +1,15 @@
1
1
  //#region src/utils/vite-version.d.ts
2
+ declare function serializeViteDefine(value: unknown): string;
3
+ declare function getDepOptimizeNodeEnvOptions(viteMajorVersion: number, nodeEnvDefine: string): {
4
+ rolldownOptions?: {
5
+ transform: {
6
+ define: Record<string, string>;
7
+ };
8
+ };
9
+ esbuildOptions?: {
10
+ define: Record<string, string>;
11
+ };
12
+ };
2
13
  /**
3
14
  * Detect Vite major version at runtime by resolving from cwd.
4
15
  * The plugin may be installed in a workspace root with Vite 7 but used
@@ -7,4 +18,4 @@
7
18
  */
8
19
  declare function getViteMajorVersion(): number;
9
20
  //#endregion
10
- export { getViteMajorVersion };
21
+ export { getDepOptimizeNodeEnvOptions, getViteMajorVersion, serializeViteDefine };
@@ -9,6 +9,14 @@ import path from "node:path";
9
9
  * `rolldownOptions`) or Vite 7 (Rollup/esbuild). This helper centralizes the
10
10
  * detection so the Vite-major gate is computed the same way everywhere.
11
11
  */
12
+ function serializeViteDefine(value) {
13
+ if (typeof value === "string") return value;
14
+ return JSON.stringify(value) ?? "undefined";
15
+ }
16
+ function getDepOptimizeNodeEnvOptions(viteMajorVersion, nodeEnvDefine) {
17
+ const define = { "process.env.NODE_ENV": nodeEnvDefine };
18
+ return viteMajorVersion >= 8 ? { rolldownOptions: { transform: { define } } } : { esbuildOptions: { define } };
19
+ }
12
20
  /**
13
21
  * Detect Vite major version at runtime by resolving from cwd.
14
22
  * The plugin may be installed in a workspace root with Vite 7 but used
@@ -31,4 +39,4 @@ function getViteMajorVersion() {
31
39
  }
32
40
  }
33
41
  //#endregion
34
- export { getViteMajorVersion };
42
+ export { getDepOptimizeNodeEnvOptions, getViteMajorVersion, serializeViteDefine };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinext",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Run Next.js apps on Vite. Drop-in replacement for the next CLI.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -57,6 +57,10 @@
57
57
  "types": "./dist/server/app-router-entry.d.ts",
58
58
  "import": "./dist/server/app-router-entry.js"
59
59
  },
60
+ "./server/app-rsc-handler": {
61
+ "types": "./dist/server/app-rsc-handler.d.ts",
62
+ "import": "./dist/server/app-rsc-handler.js"
63
+ },
60
64
  "./config/config-matchers": {
61
65
  "types": "./dist/config/config-matchers.d.ts",
62
66
  "import": "./dist/config/config-matchers.js"