vinext 0.0.28 → 0.0.29

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 (89) hide show
  1. package/dist/build/report.d.ts +117 -0
  2. package/dist/build/report.d.ts.map +1 -0
  3. package/dist/build/report.js +303 -0
  4. package/dist/build/report.js.map +1 -0
  5. package/dist/cli.js +106 -9
  6. package/dist/cli.js.map +1 -1
  7. package/dist/cloudflare/kv-cache-handler.d.ts.map +1 -1
  8. package/dist/cloudflare/kv-cache-handler.js +14 -12
  9. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  10. package/dist/cloudflare/tpr.d.ts +10 -0
  11. package/dist/cloudflare/tpr.d.ts.map +1 -1
  12. package/dist/cloudflare/tpr.js +36 -41
  13. package/dist/cloudflare/tpr.js.map +1 -1
  14. package/dist/config/next-config.d.ts.map +1 -1
  15. package/dist/config/next-config.js +16 -0
  16. package/dist/config/next-config.js.map +1 -1
  17. package/dist/entries/app-rsc-entry.d.ts.map +1 -1
  18. package/dist/entries/app-rsc-entry.js +19 -24
  19. package/dist/entries/app-rsc-entry.js.map +1 -1
  20. package/dist/entries/pages-server-entry.d.ts.map +1 -1
  21. package/dist/entries/pages-server-entry.js +94 -44
  22. package/dist/entries/pages-server-entry.js.map +1 -1
  23. package/dist/index.d.ts +17 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +111 -38
  26. package/dist/index.js.map +1 -1
  27. package/dist/routing/app-router.d.ts +2 -0
  28. package/dist/routing/app-router.d.ts.map +1 -1
  29. package/dist/routing/app-router.js +92 -79
  30. package/dist/routing/app-router.js.map +1 -1
  31. package/dist/routing/pages-router.d.ts.map +1 -1
  32. package/dist/routing/pages-router.js +17 -57
  33. package/dist/routing/pages-router.js.map +1 -1
  34. package/dist/routing/route-trie.d.ts +57 -0
  35. package/dist/routing/route-trie.d.ts.map +1 -0
  36. package/dist/routing/route-trie.js +160 -0
  37. package/dist/routing/route-trie.js.map +1 -0
  38. package/dist/routing/route-validation.d.ts.map +1 -1
  39. package/dist/routing/route-validation.js +13 -1
  40. package/dist/routing/route-validation.js.map +1 -1
  41. package/dist/routing/utils.d.ts +19 -0
  42. package/dist/routing/utils.d.ts.map +1 -1
  43. package/dist/routing/utils.js +47 -0
  44. package/dist/routing/utils.js.map +1 -1
  45. package/dist/server/api-handler.d.ts.map +1 -1
  46. package/dist/server/api-handler.js +28 -13
  47. package/dist/server/api-handler.js.map +1 -1
  48. package/dist/server/dev-server.d.ts.map +1 -1
  49. package/dist/server/dev-server.js +58 -6
  50. package/dist/server/dev-server.js.map +1 -1
  51. package/dist/server/image-optimization.d.ts.map +1 -1
  52. package/dist/server/image-optimization.js +1 -1
  53. package/dist/server/image-optimization.js.map +1 -1
  54. package/dist/server/instrumentation.d.ts.map +1 -1
  55. package/dist/server/instrumentation.js +17 -8
  56. package/dist/server/instrumentation.js.map +1 -1
  57. package/dist/server/middleware-codegen.d.ts +10 -0
  58. package/dist/server/middleware-codegen.d.ts.map +1 -1
  59. package/dist/server/middleware-codegen.js +39 -0
  60. package/dist/server/middleware-codegen.js.map +1 -1
  61. package/dist/server/middleware.d.ts.map +1 -1
  62. package/dist/server/middleware.js +2 -1
  63. package/dist/server/middleware.js.map +1 -1
  64. package/dist/server/prod-server.d.ts +8 -2
  65. package/dist/server/prod-server.d.ts.map +1 -1
  66. package/dist/server/prod-server.js +60 -20
  67. package/dist/server/prod-server.js.map +1 -1
  68. package/dist/shims/headers.d.ts.map +1 -1
  69. package/dist/shims/headers.js +2 -5
  70. package/dist/shims/headers.js.map +1 -1
  71. package/dist/shims/link.d.ts.map +1 -1
  72. package/dist/shims/link.js +11 -43
  73. package/dist/shims/link.js.map +1 -1
  74. package/dist/shims/metadata.d.ts +56 -0
  75. package/dist/shims/metadata.d.ts.map +1 -1
  76. package/dist/shims/metadata.js +66 -0
  77. package/dist/shims/metadata.js.map +1 -1
  78. package/dist/shims/navigation.d.ts +2 -0
  79. package/dist/shims/navigation.d.ts.map +1 -1
  80. package/dist/shims/navigation.js +41 -29
  81. package/dist/shims/navigation.js.map +1 -1
  82. package/dist/shims/router.d.ts.map +1 -1
  83. package/dist/shims/router.js +13 -19
  84. package/dist/shims/router.js.map +1 -1
  85. package/dist/shims/url-utils.d.ts +20 -6
  86. package/dist/shims/url-utils.d.ts.map +1 -1
  87. package/dist/shims/url-utils.js +79 -0
  88. package/dist/shims/url-utils.js.map +1 -1
  89. package/package.json +2 -2
@@ -10,7 +10,7 @@
10
10
  import fs from "node:fs";
11
11
  import { fileURLToPath } from "node:url";
12
12
  import { generateDevOriginCheckCode } from "../server/dev-origin-check.js";
13
- import { generateSafeRegExpCode, generateMiddlewareMatcherCode, generateNormalizePathCode, } from "../server/middleware-codegen.js";
13
+ import { generateSafeRegExpCode, generateMiddlewareMatcherCode, generateNormalizePathCode, generateRouteMatchNormalizationCode, } from "../server/middleware-codegen.js";
14
14
  import { isProxyFile } from "../server/middleware.js";
15
15
  // Pre-computed absolute paths for generated-code imports. The virtual RSC
16
16
  // entry can't use relative imports (it has no real file location), so we
@@ -18,6 +18,7 @@ import { isProxyFile } from "../server/middleware.js";
18
18
  const configMatchersPath = fileURLToPath(new URL("../config/config-matchers.js", import.meta.url)).replace(/\\/g, "/");
19
19
  const requestPipelinePath = fileURLToPath(new URL("../server/request-pipeline.js", import.meta.url)).replace(/\\/g, "/");
20
20
  const requestContextShimPath = fileURLToPath(new URL("../shims/request-context.js", import.meta.url)).replace(/\\/g, "/");
21
+ const routeTriePath = fileURLToPath(new URL("../routing/route-trie.js", import.meta.url)).replace(/\\/g, "/");
21
22
  /**
22
23
  * Generate the virtual RSC entry module.
23
24
  *
@@ -215,6 +216,7 @@ import { validateCsrfOrigin, validateImageUrl, guardProtocolRelativeUrl, hasBase
215
216
  import { _consumeRequestScopedCacheLife, _runWithCacheState, getCacheHandler } from "next/cache";
216
217
  import { runWithExecutionContext as _runWithExecutionContext, getRequestExecutionContext as _getRequestExecutionContext } from ${JSON.stringify(requestContextShimPath)};
217
218
  import { getCollectedFetchTags, runWithFetchCache } from "vinext/fetch-cache";
219
+ import { buildRouteTrie as _buildRouteTrie, trieMatch as _trieMatch } from ${JSON.stringify(routeTriePath)};
218
220
  import { runWithPrivateCache as _runWithPrivateCache } from "vinext/cache-runtime";
219
221
  // Import server-only state module to register ALS-backed accessors.
220
222
  import { runWithNavigationContext as _runWithNavigationContext } from "vinext/navigation-state";
@@ -484,9 +486,7 @@ function rscOnError(error, requestInfo, errorContext) {
484
486
  error instanceof Error ? error : new Error(String(error)),
485
487
  requestInfo,
486
488
  errorContext,
487
- ).catch((reportErr) => {
488
- console.error("[vinext] Failed to report render error:", reportErr);
489
- });
489
+ );
490
490
  }
491
491
 
492
492
  // In production, generate a digest hash for non-navigation errors
@@ -552,6 +552,7 @@ async function __ensureInstrumentation() {
552
552
  const routes = [
553
553
  ${routeEntries.join(",\n")}
554
554
  ];
555
+ const _routeTrie = _buildRouteTrie(routes);
555
556
 
556
557
  const metadataRoutes = [
557
558
  ${metaRouteEntries.join(",\n")}
@@ -844,20 +845,17 @@ async function renderErrorBoundaryPage(route, error, isRscRequest, request, matc
844
845
  });
845
846
  }
846
847
 
847
- function matchRoute(url, routes) {
848
+ function matchRoute(url) {
848
849
  const pathname = url.split("?")[0];
849
850
  let normalizedUrl = pathname === "/" ? "/" : pathname.replace(/\\/$/, "");
850
851
  // NOTE: Do NOT decodeURIComponent here. The caller is responsible for decoding
851
852
  // the pathname exactly once at the request entry point. Decoding again here
852
853
  // would cause inconsistent path matching between middleware and routing.
853
854
  const urlParts = normalizedUrl.split("/").filter(Boolean);
854
- for (const route of routes) {
855
- const params = matchPattern(urlParts, route.patternParts);
856
- if (params !== null) return { route, params };
857
- }
858
- return null;
855
+ return _trieMatch(_routeTrie, urlParts);
859
856
  }
860
857
 
858
+ // matchPattern is kept for findIntercept (linear scan over small interceptLookup array).
861
859
  function matchPattern(urlParts, patternParts) {
862
860
  const params = Object.create(null);
863
861
  for (let i = 0; i < patternParts.length; i++) {
@@ -1233,6 +1231,7 @@ ${generateSafeRegExpCode("modern")}
1233
1231
 
1234
1232
  // ── Path normalization ──────────────────────────────────────────────────
1235
1233
  ${generateNormalizePathCode("modern")}
1234
+ ${generateRouteMatchNormalizationCode("modern")}
1236
1235
 
1237
1236
  // ── Config pattern matching, redirects, rewrites, headers, CSRF validation,
1238
1237
  // external URL proxy, cookie parsing, and request context are imported from
@@ -1364,7 +1363,7 @@ export default async function handler(request, ctx) {
1364
1363
  if (__configHeaders.length) {
1365
1364
  const url = new URL(request.url);
1366
1365
  let pathname;
1367
- try { pathname = __normalizePath(decodeURIComponent(url.pathname)); } catch { pathname = url.pathname; }
1366
+ try { pathname = __normalizePath(__normalizePathnameForRouteMatch(url.pathname)); } catch { pathname = url.pathname; }
1368
1367
  ${bp ? `if (pathname.startsWith(${JSON.stringify(bp)})) pathname = pathname.slice(${JSON.stringify(bp)}.length) || "/";` : ""}
1369
1368
  const extraHeaders = matchHeaders(pathname, __configHeaders, __reqCtx);
1370
1369
  for (const h of extraHeaders) {
@@ -1413,11 +1412,11 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
1413
1412
  const __protoGuard = guardProtocolRelativeUrl(url.pathname);
1414
1413
  if (__protoGuard) return __protoGuard;
1415
1414
 
1416
- // Decode percent-encoding and normalize pathname to canonical form.
1417
- // decodeURIComponent prevents /%61dmin from bypassing /admin matchers.
1415
+ // Decode percent-encoding segment-wise and normalize pathname to canonical form.
1416
+ // This preserves encoded path delimiters like %2F within a single segment.
1418
1417
  // __normalizePath collapses //foo///bar → /foo/bar, resolves . and .. segments.
1419
1418
  let decodedUrlPathname;
1420
- try { decodedUrlPathname = decodeURIComponent(url.pathname); } catch (e) {
1419
+ try { decodedUrlPathname = __normalizePathnameForRouteMatchStrict(url.pathname); } catch (e) {
1421
1420
  return new Response("Bad Request", { status: 400 });
1422
1421
  }
1423
1422
  let pathname = __normalizePath(decodedUrlPathname);
@@ -1758,7 +1757,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
1758
1757
 
1759
1758
  // After the action, re-render the current page so the client
1760
1759
  // gets an updated React tree reflecting any mutations.
1761
- const match = matchRoute(cleanPathname, routes);
1760
+ const match = matchRoute(cleanPathname);
1762
1761
  let element;
1763
1762
  if (match) {
1764
1763
  const { route: actionRoute, params: actionParams } = match;
@@ -1806,9 +1805,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
1806
1805
  err instanceof Error ? err : new Error(String(err)),
1807
1806
  { path: cleanPathname, method: request.method, headers: Object.fromEntries(request.headers.entries()) },
1808
1807
  { routerKind: "App Router", routePath: cleanPathname, routeType: "action" },
1809
- ).catch((reportErr) => {
1810
- console.error("[vinext] Failed to report server action error:", reportErr);
1811
- });
1808
+ );
1812
1809
  setHeadersContext(null);
1813
1810
  setNavigationContext(null);
1814
1811
  return new Response(
@@ -1833,7 +1830,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
1833
1830
  }
1834
1831
  }
1835
1832
 
1836
- let match = matchRoute(cleanPathname, routes);
1833
+ let match = matchRoute(cleanPathname);
1837
1834
 
1838
1835
  // ── Fallback rewrites from next.config.js (if no route matched) ───────
1839
1836
  if (!match && __configRewrites.fallback && __configRewrites.fallback.length) {
@@ -1845,7 +1842,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
1845
1842
  return proxyExternalRequest(request, __fallbackRewritten);
1846
1843
  }
1847
1844
  cleanPathname = __fallbackRewritten;
1848
- match = matchRoute(cleanPathname, routes);
1845
+ match = matchRoute(cleanPathname);
1849
1846
  }
1850
1847
  }
1851
1848
 
@@ -2010,9 +2007,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
2010
2007
  err instanceof Error ? err : new Error(String(err)),
2011
2008
  { path: cleanPathname, method: request.method, headers: Object.fromEntries(request.headers.entries()) },
2012
2009
  { routerKind: "App Router", routePath: route.pattern, routeType: "route" },
2013
- ).catch((reportErr) => {
2014
- console.error("[vinext] Failed to report route handler error:", reportErr);
2015
- });
2010
+ );
2016
2011
  return attachRouteHandlerMiddlewareContext(new Response(null, { status: 500 }));
2017
2012
  } finally {
2018
2013
  setHeadersAccessPhase(previousHeadersPhase);
@@ -2281,7 +2276,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
2281
2276
  const sourceRoute = routes[intercept.sourceRouteIndex];
2282
2277
  if (sourceRoute && sourceRoute !== route) {
2283
2278
  // Render the source route (e.g. /feed) with the intercepting page in the slot
2284
- const sourceMatch = matchRoute(sourceRoute.pattern, routes);
2279
+ const sourceMatch = matchRoute(sourceRoute.pattern);
2285
2280
  const sourceParams = sourceMatch ? sourceMatch.params : {};
2286
2281
  setNavigationContext({
2287
2282
  pathname: cleanPathname,