vinext 0.1.7 → 0.1.8

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 (92) hide show
  1. package/dist/check.d.ts +18 -0
  2. package/dist/check.js +37 -17
  3. package/dist/cli.js +2 -2
  4. package/dist/config/next-config.d.ts +2 -1
  5. package/dist/config/next-config.js +3 -0
  6. package/dist/config/server-external-packages.d.ts +4 -0
  7. package/dist/config/server-external-packages.js +91 -0
  8. package/dist/deploy.d.ts +7 -0
  9. package/dist/deploy.js +25 -18
  10. package/dist/entries/app-rsc-entry.js +54 -10
  11. package/dist/entries/app-rsc-manifest.js +8 -0
  12. package/dist/entries/pages-client-entry.js +1 -0
  13. package/dist/entries/pages-server-entry.js +1 -0
  14. package/dist/index.js +46 -20
  15. package/dist/init.js +2 -1
  16. package/dist/plugins/middleware-server-only.d.ts +8 -6
  17. package/dist/plugins/middleware-server-only.js +8 -7
  18. package/dist/plugins/optimize-imports.js +1 -1
  19. package/dist/routing/app-route-graph.d.ts +6 -2
  20. package/dist/routing/app-route-graph.js +61 -13
  21. package/dist/routing/app-router.d.ts +5 -0
  22. package/dist/routing/app-router.js +5 -0
  23. package/dist/routing/file-matcher.d.ts +5 -0
  24. package/dist/routing/file-matcher.js +7 -1
  25. package/dist/server/app-browser-entry.js +42 -147
  26. package/dist/server/app-browser-history-controller.d.ts +2 -1
  27. package/dist/server/app-browser-history-controller.js +6 -2
  28. package/dist/server/app-browser-server-action-client.d.ts +32 -0
  29. package/dist/server/app-browser-server-action-client.js +128 -0
  30. package/dist/server/app-fallback-renderer.d.ts +3 -1
  31. package/dist/server/app-fallback-renderer.js +6 -2
  32. package/dist/server/app-page-boundary-render.d.ts +3 -0
  33. package/dist/server/app-page-boundary-render.js +14 -3
  34. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  35. package/dist/server/app-page-cache-finalizer.js +8 -2
  36. package/dist/server/app-page-dispatch.d.ts +33 -4
  37. package/dist/server/app-page-dispatch.js +62 -90
  38. package/dist/server/app-page-element-builder.d.ts +7 -1
  39. package/dist/server/app-page-element-builder.js +56 -19
  40. package/dist/server/app-page-head.d.ts +16 -1
  41. package/dist/server/app-page-head.js +44 -22
  42. package/dist/server/app-page-params.d.ts +2 -1
  43. package/dist/server/app-page-params.js +8 -1
  44. package/dist/server/app-page-ppr-runtime.d.ts +7 -0
  45. package/dist/server/app-page-ppr-runtime.js +70 -0
  46. package/dist/server/app-page-probe.d.ts +1 -0
  47. package/dist/server/app-page-probe.js +1 -1
  48. package/dist/server/app-page-render.d.ts +4 -1
  49. package/dist/server/app-page-render.js +8 -3
  50. package/dist/server/app-page-request.d.ts +8 -1
  51. package/dist/server/app-page-request.js +23 -11
  52. package/dist/server/app-page-route-wiring.d.ts +6 -1
  53. package/dist/server/app-page-route-wiring.js +30 -8
  54. package/dist/server/app-page-search-params-observation.d.ts +4 -2
  55. package/dist/server/app-page-search-params-observation.js +11 -7
  56. package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
  57. package/dist/server/app-route-handler-dispatch.js +1 -0
  58. package/dist/server/app-route-handler-execution.js +2 -1
  59. package/dist/server/app-route-module-loader.d.ts +2 -0
  60. package/dist/server/app-route-module-loader.js +1 -0
  61. package/dist/server/app-router-entry.js +7 -6
  62. package/dist/server/app-rsc-errors.js +7 -1
  63. package/dist/server/app-rsc-handler.d.ts +2 -1
  64. package/dist/server/app-rsc-handler.js +6 -9
  65. package/dist/server/app-rsc-route-matching.d.ts +7 -0
  66. package/dist/server/app-rsc-route-matching.js +36 -3
  67. package/dist/server/app-segment-config.d.ts +1 -0
  68. package/dist/server/app-segment-config.js +32 -2
  69. package/dist/server/app-server-action-execution.d.ts +4 -0
  70. package/dist/server/app-server-action-execution.js +41 -10
  71. package/dist/server/app-ssr-entry.js +4 -1
  72. package/dist/server/app-static-generation.d.ts +1 -0
  73. package/dist/server/app-static-generation.js +1 -0
  74. package/dist/server/headers.d.ts +3 -1
  75. package/dist/server/headers.js +3 -1
  76. package/dist/server/prod-server.js +15 -6
  77. package/dist/server/worker-utils.d.ts +2 -1
  78. package/dist/server/worker-utils.js +7 -1
  79. package/dist/shims/error-boundary.d.ts +19 -1
  80. package/dist/shims/error-boundary.js +11 -1
  81. package/dist/shims/headers.d.ts +3 -1
  82. package/dist/shims/headers.js +16 -5
  83. package/dist/shims/link.js +16 -12
  84. package/dist/shims/metadata.d.ts +3 -2
  85. package/dist/shims/metadata.js +8 -4
  86. package/dist/shims/router.js +13 -2
  87. package/dist/typegen.js +6 -5
  88. package/dist/utils/path.d.ts +2 -1
  89. package/dist/utils/path.js +1 -1
  90. package/dist/utils/project.d.ts +4 -0
  91. package/dist/utils/project.js +5 -1
  92. package/package.json +7 -3
@@ -9,6 +9,16 @@ import { isNavigationSignalError } from "../utils/navigation-signal.js";
9
9
  import React from "react";
10
10
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
11
  //#region src/shims/error-boundary.tsx
12
+ function SerializedErrorBoundary({ fallback: Fallback, error }) {
13
+ return /* @__PURE__ */ jsx(Fallback, {
14
+ error: Object.assign(new Error(error.message), {
15
+ digest: error.digest,
16
+ name: error.name ?? "Error",
17
+ stack: error.stack
18
+ }),
19
+ reset: () => globalThis.location?.reload()
20
+ });
21
+ }
12
22
  function normalizeBoundaryResetKey(resetKey) {
13
23
  return resetKey === void 0 || resetKey === null || resetKey === "" ? null : resetKey;
14
24
  }
@@ -339,4 +349,4 @@ var DevRecoveryBoundary = class extends React.Component {
339
349
  }
340
350
  };
341
351
  //#endregion
342
- export { DevRecoveryBoundary, ErrorBoundary, ErrorBoundaryInner, ForbiddenBoundary, ForbiddenBoundaryInner, GlobalErrorBoundary, NotFoundBoundary, RedirectBoundary, RedirectErrorBoundary, UnauthorizedBoundary, UnauthorizedBoundaryInner };
352
+ export { DevRecoveryBoundary, ErrorBoundary, ErrorBoundaryInner, ForbiddenBoundary, ForbiddenBoundaryInner, GlobalErrorBoundary, NotFoundBoundary, RedirectBoundary, RedirectErrorBoundary, SerializedErrorBoundary, UnauthorizedBoundary, UnauthorizedBoundaryInner };
@@ -5,6 +5,7 @@ type HeadersContext = {
5
5
  headers: Headers;
6
6
  cookies: Map<string, string>;
7
7
  accessError?: Error;
8
+ draftModeEnabled?: boolean;
8
9
  forceStatic?: boolean;
9
10
  mutableCookies?: RequestCookies;
10
11
  readonlyCookies?: RequestCookies;
@@ -47,6 +48,7 @@ type ConnectionProbeResult<T> = {
47
48
  */
48
49
  declare function markDynamicUsage(): void;
49
50
  declare function markRenderRequestApiUsage(kind: RenderRequestApiKind): void;
51
+ declare function throwIfStaticGenerationAccessError(): void;
50
52
  declare function runWithConnectionProbe<T>(fn: () => T | Promise<T>): Promise<ConnectionProbeResult<T>>;
51
53
  declare function suspendConnectionProbe(): Promise<never> | null;
52
54
  declare function peekRenderRequestApiUsage(): RenderRequestApiKind[];
@@ -250,4 +252,4 @@ declare class RequestCookies {
250
252
  toString(): string;
251
253
  }
252
254
  //#endregion
253
- export { HeadersAccessPhase, HeadersContext, type RequestCookies, VinextHeadersShimState, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithConnectionProbe, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope };
255
+ export { HeadersAccessPhase, HeadersContext, type RequestCookies, VinextHeadersShimState, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithConnectionProbe, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
@@ -1,6 +1,6 @@
1
1
  import { getOrCreateAls } from "./internal/als-registry.js";
2
2
  import { getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation } from "./unified-request-context.js";
3
- import { MIDDLEWARE_SET_COOKIE_HEADER } from "../server/headers.js";
3
+ import { FLIGHT_HEADERS, MIDDLEWARE_SET_COOKIE_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER } from "../server/headers.js";
4
4
  import { buildRequestHeadersFromMiddlewareResponse } from "../server/middleware-request-headers.js";
5
5
  import { serializeSetCookie, validateCookieAttributeValue, validateCookieName } from "./internal/cookie-serialize.js";
6
6
  import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
@@ -117,6 +117,10 @@ function markDynamicUsage() {
117
117
  function markRenderRequestApiUsage(kind) {
118
118
  _getState().renderRequestApiUsage.add(kind);
119
119
  }
120
+ function throwIfStaticGenerationAccessError() {
121
+ const accessError = _getState().headersContext?.accessError;
122
+ if (accessError) throw accessError;
123
+ }
120
124
  async function runWithConnectionProbe(fn) {
121
125
  const state = _getState();
122
126
  const previousProbe = state.connectionProbe;
@@ -468,7 +472,13 @@ function _getReadonlyCookies(ctx) {
468
472
  return ctx.readonlyCookies;
469
473
  }
470
474
  function _getReadonlyHeaders(ctx) {
471
- if (!ctx.readonlyHeaders) ctx.readonlyHeaders = _sealHeaders(ctx.headers);
475
+ if (!ctx.readonlyHeaders) {
476
+ const cleaned = new Headers(ctx.headers);
477
+ for (const header of FLIGHT_HEADERS) cleaned.delete(header);
478
+ cleaned.delete(NEXT_REQUEST_ID_HEADER);
479
+ cleaned.delete(NEXT_HTML_REQUEST_ID_HEADER);
480
+ ctx.readonlyHeaders = _sealHeaders(cleaned);
481
+ }
472
482
  return ctx.readonlyHeaders;
473
483
  }
474
484
  /**
@@ -631,16 +641,16 @@ async function draftMode() {
631
641
  const state = _getState();
632
642
  const context = state.headersContext;
633
643
  if (!context) throw createDraftModeScopeError("draftMode()");
634
- if (context.accessError) throw context.accessError;
635
644
  const secret = ensureContextDraftModeSecret(context);
636
645
  return {
637
646
  get isEnabled() {
638
- return context.cookies.get(DRAFT_MODE_COOKIE) === secret;
647
+ return context.draftModeEnabled ?? context.cookies.get(DRAFT_MODE_COOKIE) === secret;
639
648
  },
640
649
  enable() {
641
650
  throwIfInsideCacheScope("draftMode().enable()");
642
651
  const activeContext = requireActiveDraftModeContext(state, context, "draftMode().enable()");
643
652
  markDynamicUsage();
653
+ activeContext.draftModeEnabled = true;
644
654
  activeContext.cookies.set(DRAFT_MODE_COOKIE, secret);
645
655
  state.draftModeCookieHeader = `${DRAFT_MODE_COOKIE}=${secret}; ${draftModeCookieAttributes()}`;
646
656
  },
@@ -648,6 +658,7 @@ async function draftMode() {
648
658
  throwIfInsideCacheScope("draftMode().disable()");
649
659
  const activeContext = requireActiveDraftModeContext(state, context, "draftMode().disable()");
650
660
  markDynamicUsage();
661
+ activeContext.draftModeEnabled = false;
651
662
  activeContext.cookies.delete(DRAFT_MODE_COOKIE);
652
663
  state.draftModeCookieHeader = `${DRAFT_MODE_COOKIE}=; ${draftModeCookieAttributes()}; Expires=${DRAFT_MODE_EXPIRED_DATE}`;
653
664
  }
@@ -751,4 +762,4 @@ var RequestCookies = class {
751
762
  }
752
763
  };
753
764
  //#endregion
754
- export { applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithConnectionProbe, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope };
765
+ export { applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithConnectionProbe, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
@@ -32,6 +32,7 @@ import { jsx } from "react/jsx-runtime";
32
32
  * On click, prevents full page reload and triggers client-side
33
33
  * page swap via the router's navigation system.
34
34
  */
35
+ const HAS_PAGES_ROUTER = process.env.__VINEXT_HAS_PAGES_ROUTER !== "false";
35
36
  const LinkStatusContext = createContext({ pending: false });
36
37
  /**
37
38
  * useLinkStatus returns the pending state of the enclosing <Link>.
@@ -58,6 +59,7 @@ function resolveHref(href) {
58
59
  return url;
59
60
  }
60
61
  function resolvePagesQueryOnlyHref(href) {
62
+ if (!HAS_PAGES_ROUTER) return href;
61
63
  if (!href.startsWith("?") || typeof window === "undefined") return href;
62
64
  const pagesRouter = window.next?.appDir === true ? void 0 : window.next?.router;
63
65
  return resolvePagesRouterQueryOnlyHref(href, {
@@ -70,6 +72,11 @@ function resolvePagesQueryOnlyHref(href) {
70
72
  function resolvePagesLinkNavigationHref(href, locale) {
71
73
  return normalizePathTrailingSlash(applyLocaleToHref(resolvePagesQueryOnlyHref(href), locale), __trailingSlash);
72
74
  }
75
+ function applyPagesNavigationFallback(href, replace) {
76
+ if (replace) window.history.replaceState({}, "", href);
77
+ else window.history.pushState({}, "", href);
78
+ window.dispatchEvent(new PopStateEvent("popstate"));
79
+ }
73
80
  /**
74
81
  * Collapse repeated forward-slashes (and convert backslashes to forward-slashes)
75
82
  * in the path portion of a URL, preserving any query string.
@@ -261,7 +268,7 @@ function prefetchUrl(href, mode, priority = "low") {
261
268
  cacheForNavigation: autoPrefetch.cacheForNavigation,
262
269
  optimisticRouteShell: isOptimisticRouteShellPrefetch
263
270
  });
264
- } else if (window.__NEXT_DATA__) {
271
+ } else if (HAS_PAGES_ROUTER && window.__NEXT_DATA__) {
265
272
  const dataTarget = resolvePagesDataNavigationTarget(fullHref, __basePath);
266
273
  if (dataTarget) prefetchPagesData(dataTarget);
267
274
  else {
@@ -415,7 +422,7 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
415
422
  let children = childrenProp;
416
423
  if (legacyBehavior && (typeof childrenProp === "string" || typeof childrenProp === "number")) children = React.createElement("a", null, childrenProp);
417
424
  const rawResolvedHref = as ?? resolveHref(href);
418
- const routeHrefRaw = resolveConcreteRouteHref(href, as) ?? (typeof href === "string" ? href : resolveHref(href));
425
+ const routeHrefRaw = (HAS_PAGES_ROUTER ? resolveConcreteRouteHref(href, as) : null) ?? (typeof href === "string" ? href : resolveHref(href));
419
426
  const resolvedHref = typeof rawResolvedHref === "string" ? warnAndNormalizeRepeatedSlashesInHref(rawResolvedHref) : rawResolvedHref;
420
427
  const isDangerous = typeof resolvedHref === "string" && isDangerousScheme(resolvedHref);
421
428
  const normalizedHref = normalizePathTrailingSlash(applyLocaleToHref(isDangerous ? "/" : resolvedHref, locale), __trailingSlash);
@@ -527,8 +534,8 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
527
534
  }
528
535
  e.preventDefault();
529
536
  const hasAppNavigationRuntime = Boolean(getNavigationRuntime()?.functions.navigate);
530
- const pagesNavigateHref = resolvedHref.startsWith("?") ? resolvePagesLinkNavigationHref(resolvedHref, locale) : navigateHref;
531
- const pagesAsForLink = typeof as === "string" && typeof routeHrefRaw === "string" && as !== routeHrefRaw ? pagesNavigateHref : void 0;
537
+ const pagesNavigateHref = HAS_PAGES_ROUTER && resolvedHref.startsWith("?") ? resolvePagesLinkNavigationHref(resolvedHref, locale) : navigateHref;
538
+ const pagesAsForLink = HAS_PAGES_ROUTER && typeof as === "string" && typeof routeHrefRaw === "string" && as !== routeHrefRaw ? pagesNavigateHref : void 0;
532
539
  const pagesHrefForLink = pagesAsForLink === void 0 ? pagesNavigateHref : routeHrefRaw;
533
540
  const absoluteFullHref = toBrowserNavigationHref(hasAppNavigationRuntime ? navigateHref : pagesNavigateHref, window.location.href, __basePath);
534
541
  if (onNavigate) try {
@@ -546,7 +553,7 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
546
553
  onNavigate(navEvent);
547
554
  if (navEvent.defaultPrevented) return;
548
555
  } catch {}
549
- if (hasAppNavigationRuntime && ["pages", "document"].includes(resolveHybridClientRouteOwner(navigateHref, __basePath) ?? "")) {
556
+ if (HAS_PAGES_ROUTER && hasAppNavigationRuntime && ["pages", "document"].includes(resolveHybridClientRouteOwner(navigateHref, __basePath) ?? "")) {
550
557
  if (replace) window.location.replace(absoluteFullHref);
551
558
  else window.location.assign(absoluteFullHref);
552
559
  return;
@@ -562,7 +569,7 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
562
569
  });
563
570
  });
564
571
  return;
565
- } else {
572
+ } else if (HAS_PAGES_ROUTER) {
566
573
  const Router = window.next?.appDir === true ? void 0 : window.next?.router;
567
574
  await navigatePagesRouterLinkWithFallback({
568
575
  router: Router && "reload" in Router ? Router : void 0,
@@ -576,13 +583,10 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
576
583
  locale,
577
584
  interpolateDynamicRoute: resolvedHref.startsWith("?")
578
585
  },
579
- fallback: () => {
580
- if (replace) window.history.replaceState({}, "", absoluteFullHref);
581
- else window.history.pushState({}, "", absoluteFullHref);
582
- window.dispatchEvent(new PopStateEvent("popstate"));
583
- }
586
+ fallback: () => applyPagesNavigationFallback(absoluteFullHref, replace)
584
587
  });
585
- }
588
+ } else if (replace) window.location.replace(absoluteFullHref);
589
+ else window.location.assign(absoluteFullHref);
586
590
  };
587
591
  const anchorProps = restWithoutLocale;
588
592
  const linkStatusValue = React.useMemo(() => ({ pending }), [pending]);
@@ -1,3 +1,4 @@
1
+ import { ThenableParamsObserver } from "./thenable-params.js";
1
2
  import React from "react";
2
3
 
3
4
  //#region src/shims/metadata.d.ts
@@ -18,7 +19,7 @@ type Viewport = {
18
19
  * Resolve viewport config from a module. Handles both static `viewport` export
19
20
  * and async `generateViewport()` function.
20
21
  */
21
- declare function resolveModuleViewport(mod: Record<string, unknown>, params: Record<string, string | string[]>): Promise<Viewport | null>;
22
+ declare function resolveModuleViewport(mod: Record<string, unknown>, params: Record<string, string | string[]>, searchParams?: Record<string, string | string[]>, searchParamsObserver?: ThenableParamsObserver): Promise<Viewport | null>;
22
23
  /**
23
24
  * Merge viewport configs from multiple sources (layouts + page).
24
25
  * Later entries override earlier ones.
@@ -267,7 +268,7 @@ declare function mergeMetadataEntries(entries: readonly MetadataMergeEntry[]): M
267
268
  * resolution approach. If not provided, defaults to a promise that resolves
268
269
  * to an empty object (so `await parent` never throws).
269
270
  */
270
- declare function resolveModuleMetadata(mod: Record<string, unknown>, params?: Record<string, string | string[]>, searchParams?: Record<string, string | string[]>, parent?: Promise<Metadata>): Promise<Metadata | null>;
271
+ declare function resolveModuleMetadata(mod: Record<string, unknown>, params?: Record<string, string | string[]>, searchParams?: Record<string, string | string[]>, parent?: Promise<Metadata>, searchParamsObserver?: ThenableParamsObserver): Promise<Metadata | null>;
271
272
  type MetadataHeadProps = {
272
273
  metadata: Metadata;
273
274
  pathname?: string;
@@ -13,10 +13,14 @@ import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
13
13
  * Resolve viewport config from a module. Handles both static `viewport` export
14
14
  * and async `generateViewport()` function.
15
15
  */
16
- async function resolveModuleViewport(mod, params) {
16
+ async function resolveModuleViewport(mod, params, searchParams, searchParamsObserver) {
17
17
  if (typeof mod.generateViewport === "function") {
18
18
  const asyncParams = makeThenableParams(params);
19
- return await mod.generateViewport({ params: asyncParams });
19
+ const props = searchParams === void 0 ? { params: asyncParams } : {
20
+ params: asyncParams,
21
+ searchParams: makeThenableParams(searchParams, searchParamsObserver)
22
+ };
23
+ return await mod.generateViewport(props);
20
24
  }
21
25
  if (mod.viewport && typeof mod.viewport === "object") return mod.viewport;
22
26
  return null;
@@ -213,12 +217,12 @@ function mergeMetadataEntries(entries) {
213
217
  * resolution approach. If not provided, defaults to a promise that resolves
214
218
  * to an empty object (so `await parent` never throws).
215
219
  */
216
- async function resolveModuleMetadata(mod, params = {}, searchParams, parent = Promise.resolve({})) {
220
+ async function resolveModuleMetadata(mod, params = {}, searchParams, parent = Promise.resolve({}), searchParamsObserver) {
217
221
  if (typeof mod.generateMetadata === "function") {
218
222
  const asyncParams = makeThenableParams(params);
219
223
  const props = searchParams === void 0 ? { params: asyncParams } : {
220
224
  params: asyncParams,
221
- searchParams: makeThenableParams(searchParams)
225
+ searchParams: makeThenableParams(searchParams, searchParamsObserver)
222
226
  };
223
227
  return await (mod.generateMetadata.length >= 2 ? mod.generateMetadata(props, parent) : mod.generateMetadata(props));
224
228
  }
@@ -186,6 +186,7 @@ function createPagesRouterRuntimeState() {
186
186
  activeAbortController: null,
187
187
  cancelPendingRenderCommit: null,
188
188
  lastPathnameAndSearch: typeof window !== "undefined" ? window.location.pathname + window.location.search : "",
189
+ lastHash: typeof window !== "undefined" ? window.location.hash : "",
189
190
  isFirstPopStateEvent: true,
190
191
  routerDidNavigate: false,
191
192
  deprecatedEventBridgeInstalled: false,
@@ -941,6 +942,7 @@ async function navigateClientData(url, initialTarget, controller, navId, assertS
941
942
  if (!redirectedUrl) scheduleHardNavigationAndThrow(softRedirect, "Navigation redirected externally");
942
943
  window.history.replaceState(window.history.state ?? {}, "", redirectedUrl);
943
944
  routerRuntimeState.lastPathnameAndSearch = window.location.pathname + window.location.search;
945
+ routerRuntimeState.lastHash = window.location.hash;
944
946
  await navigateClientHtml(redirectedUrl, redirectedUrl, controller, navId, assertStillCurrent);
945
947
  return;
946
948
  }
@@ -1099,6 +1101,7 @@ async function navigateClientHtml(url, fetchUrl, controller, navId, assertStillC
1099
1101
  if (pendingRedirectHistoryUrl) {
1100
1102
  window.history.replaceState(window.history.state ?? {}, "", pendingRedirectHistoryUrl);
1101
1103
  routerRuntimeState.lastPathnameAndSearch = window.location.pathname + window.location.search;
1104
+ routerRuntimeState.lastHash = window.location.hash;
1102
1105
  }
1103
1106
  window.__NEXT_DATA__ = nextData;
1104
1107
  applyVinextLocaleGlobals(window, nextData);
@@ -1153,6 +1156,7 @@ async function navigateClient(url, fetchUrl = url, options = {}, routeUrl = url)
1153
1156
  if (!redirectedUrl) scheduleHardNavigationAndThrow(redirectLocation, "Navigation redirected externally");
1154
1157
  window.history.replaceState(window.history.state ?? {}, "", redirectedUrl);
1155
1158
  routerRuntimeState.lastPathnameAndSearch = window.location.pathname + window.location.search;
1159
+ routerRuntimeState.lastHash = window.location.hash;
1156
1160
  browserUrl = redirectedUrl;
1157
1161
  htmlFetchUrl = redirectedUrl;
1158
1162
  } else if (middlewareEffect?.rewriteTarget) {
@@ -1263,6 +1267,7 @@ function updateHistory(mode, fullUrl, navState) {
1263
1267
  else window.history.replaceState(state, "", fullUrl);
1264
1268
  routerRuntimeState.currentHistoryKey = key;
1265
1269
  routerRuntimeState.lastPathnameAndSearch = window.location.pathname + window.location.search;
1270
+ routerRuntimeState.lastHash = window.location.hash;
1266
1271
  routerRuntimeState.routerDidNavigate = true;
1267
1272
  }
1268
1273
  function createHistoryKey() {
@@ -1519,6 +1524,10 @@ function getRouterStateKey(state) {
1519
1524
  if (!isNextRouterState(state)) return void 0;
1520
1525
  return typeof state.key === "string" ? state.key : void 0;
1521
1526
  }
1527
+ function getTrackedPagesRouterAsPath() {
1528
+ const trackedUrl = new URL(routerRuntimeState.lastPathnameAndSearch, window.location.href);
1529
+ return removeNavigationLocalePrefix(stripBasePath(trackedUrl.pathname, __basePath) + trackedUrl.search);
1530
+ }
1522
1531
  function handlePagesRouterPopState(e) {
1523
1532
  const browserUrl = window.location.pathname + window.location.search;
1524
1533
  const appUrl = stripBasePath(window.location.pathname, __basePath) + window.location.search;
@@ -1528,9 +1537,10 @@ function handlePagesRouterPopState(e) {
1528
1537
  if (state !== null && state !== void 0 && !isNextRouterState(state)) return;
1529
1538
  if (wasFirst && !routerRuntimeState.routerDidNavigate && isNextRouterState(state)) {
1530
1539
  const currentLocale = window.__VINEXT_LOCALE__;
1531
- if (state.options?.locale === currentLocale && typeof state.as === "string" && withBasePath(state.as, __basePath) === routerRuntimeState.lastPathnameAndSearch) return;
1540
+ if (state.options?.locale === currentLocale && typeof state.as === "string" && state.as === getTrackedPagesRouterAsPath()) return;
1532
1541
  }
1533
- const isHashOnly = browserUrl === routerRuntimeState.lastPathnameAndSearch;
1542
+ const currentHash = window.location.hash;
1543
+ const isHashOnly = browserUrl === routerRuntimeState.lastPathnameAndSearch && (currentHash !== routerRuntimeState.lastHash || currentHash !== "");
1534
1544
  const targetKey = getRouterStateKey(state);
1535
1545
  let forcedScroll;
1536
1546
  if (manualScrollRestoration) {
@@ -1555,6 +1565,7 @@ function handlePagesRouterPopState(e) {
1555
1565
  }
1556
1566
  if (targetKey !== void 0) routerRuntimeState.currentHistoryKey = targetKey;
1557
1567
  routerRuntimeState.lastPathnameAndSearch = browserUrl;
1568
+ routerRuntimeState.lastHash = currentHash;
1558
1569
  if (isHashOnly) {
1559
1570
  const hashUrl = appUrl + window.location.hash;
1560
1571
  routerEvents.emit("hashChangeStart", hashUrl, { shallow: false });
package/dist/typegen.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { findDir } from "./utils/project.js";
2
2
  import { decodeRouteSegment, isInvisibleSegment } from "./routing/utils.js";
3
+ import { normalizePathSeparators } from "./utils/path.js";
3
4
  import { patternToNextFormat } from "./routing/route-validation.js";
4
5
  import { compareStrings } from "./utils/compare.js";
5
6
  import "./routing/app-route-graph.js";
@@ -15,17 +16,17 @@ import "./.next/types/routes.d.ts";
15
16
  // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
16
17
  `;
17
18
  async function generateRouteTypes(options) {
18
- const root = path.resolve(options.root);
19
- const appDir = options.appDir ? path.resolve(options.appDir) : findDir(root, "app", path.join("src", "app"));
20
- const outPath = path.join(root, ".next", "types", "routes.d.ts");
19
+ const root = normalizePathSeparators(path.resolve(options.root));
20
+ const appDir = options.appDir ? normalizePathSeparators(path.resolve(options.appDir)) : findDir(root, "app", "src/app");
21
+ const outPath = path.posix.join(root, ".next", "types", "routes.d.ts");
21
22
  const content = appDir ? renderRouteTypes(await collectRouteTypeModel(appDir, options.pageExtensions)) : renderRouteTypes(emptyRouteTypeModel());
22
- await fs.mkdir(path.dirname(outPath), { recursive: true });
23
+ await fs.mkdir(path.posix.dirname(outPath), { recursive: true });
23
24
  await fs.writeFile(outPath, content, "utf-8");
24
25
  await ensureNextEnvFile(root);
25
26
  return outPath;
26
27
  }
27
28
  async function ensureNextEnvFile(root) {
28
- const envPath = path.join(root, "next-env.d.ts");
29
+ const envPath = path.posix.join(root, "next-env.d.ts");
29
30
  try {
30
31
  await fs.writeFile(envPath, NEXT_ENV_FILE_CONTENT, {
31
32
  encoding: "utf-8",
@@ -1,4 +1,5 @@
1
1
  //#region src/utils/path.d.ts
2
+ declare const isWindows: boolean;
2
3
  /**
3
4
  * Convert Windows-style backslash path separators to forward slashes.
4
5
  *
@@ -19,4 +20,4 @@ declare function stripViteModuleQuery(id: string): string;
19
20
  * files like `headers.js.ts`. */
20
21
  declare function stripJsExtension(name: string): string;
21
22
  //#endregion
22
- export { normalizePathSeparators, stripJsExtension, stripViteModuleQuery };
23
+ export { isWindows, normalizePathSeparators, stripJsExtension, stripViteModuleQuery };
@@ -27,4 +27,4 @@ function stripJsExtension(name) {
27
27
  return name.endsWith(".js") ? name.slice(0, -3) : name;
28
28
  }
29
29
  //#endregion
30
- export { normalizePathSeparators, stripJsExtension, stripViteModuleQuery };
30
+ export { isWindows, normalizePathSeparators, stripJsExtension, stripViteModuleQuery };
@@ -66,6 +66,10 @@ declare function hasViteConfig(root: string): boolean;
66
66
  * Return the first candidate directory (resolved against `root`) that exists,
67
67
  * or null. Used to locate conventional `app`/`pages` directories that may live
68
68
  * at the root or under `src/`.
69
+ *
70
+ * `root` and `candidates` must be forward-slash, and the returned path is
71
+ * forward-slash too: the candidate is joined with `path.posix.join`, which only
72
+ * stays canonical when its inputs already are.
69
73
  */
70
74
  declare function findDir(root: string, ...candidates: string[]): string | null;
71
75
  /**
@@ -193,10 +193,14 @@ function hasViteConfig(root) {
193
193
  * Return the first candidate directory (resolved against `root`) that exists,
194
194
  * or null. Used to locate conventional `app`/`pages` directories that may live
195
195
  * at the root or under `src/`.
196
+ *
197
+ * `root` and `candidates` must be forward-slash, and the returned path is
198
+ * forward-slash too: the candidate is joined with `path.posix.join`, which only
199
+ * stays canonical when its inputs already are.
196
200
  */
197
201
  function findDir(root, ...candidates) {
198
202
  for (const candidate of candidates) {
199
- const full = path.join(root, candidate);
203
+ const full = path.posix.join(root, candidate);
200
204
  try {
201
205
  if (fs.statSync(full).isDirectory()) return full;
202
206
  } catch {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinext",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Run Next.js apps on Vite. Drop-in replacement for the next CLI.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -93,7 +93,6 @@
93
93
  "ipaddr.js": "^2.1.0",
94
94
  "magic-string": "^0.30.21",
95
95
  "vite-plugin-commonjs": "^0.10.4",
96
- "vite-tsconfig-paths": "^6.1.1",
97
96
  "web-vitals": "^4.2.4"
98
97
  },
99
98
  "devDependencies": {
@@ -105,6 +104,7 @@
105
104
  "react-server-dom-webpack": "^19.2.7",
106
105
  "vite": "npm:@voidzero-dev/vite-plus-core@0.2.1",
107
106
  "vite-plus": "0.2.1",
107
+ "vite-tsconfig-paths": "^6.1.1",
108
108
  "@vinext/cloudflare": "0.1.2"
109
109
  },
110
110
  "peerDependencies": {
@@ -114,7 +114,8 @@
114
114
  "react": "^19.2.6",
115
115
  "react-dom": "^19.2.6",
116
116
  "react-server-dom-webpack": "^19.2.6",
117
- "vite": "^7.0.0 || ^8.0.0"
117
+ "vite": "^7.0.0 || ^8.0.0",
118
+ "vite-tsconfig-paths": "^6.1.1"
118
119
  },
119
120
  "peerDependenciesMeta": {
120
121
  "@mdx-js/rollup": {
@@ -125,6 +126,9 @@
125
126
  },
126
127
  "react-server-dom-webpack": {
127
128
  "optional": true
129
+ },
130
+ "vite-tsconfig-paths": {
131
+ "optional": true
128
132
  }
129
133
  },
130
134
  "engines": {