vinext 1.0.0-beta.1 → 1.0.0-beta.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 (175) hide show
  1. package/README.md +4 -1
  2. package/dist/build/client-build-config.js +1 -0
  3. package/dist/build/report.d.ts +8 -1
  4. package/dist/build/report.js +12 -2
  5. package/dist/check.js +15 -2
  6. package/dist/cli.js +3 -2
  7. package/dist/config/config-matchers.d.ts +13 -37
  8. package/dist/config/config-matchers.js +31 -121
  9. package/dist/config/next-config.d.ts +3 -2
  10. package/dist/config/next-config.js +3 -1
  11. package/dist/config/request-context.d.ts +14 -0
  12. package/dist/config/request-context.js +26 -0
  13. package/dist/entries/app-rsc-entry.js +27 -9
  14. package/dist/entries/app-rsc-manifest.js +17 -0
  15. package/dist/entries/pages-server-entry.js +3 -2
  16. package/dist/index.js +82 -58
  17. package/dist/init.d.ts +6 -4
  18. package/dist/init.js +20 -22
  19. package/dist/plugins/og-assets.js +1 -1
  20. package/dist/routing/app-route-graph.d.ts +13 -5
  21. package/dist/routing/app-route-graph.js +59 -13
  22. package/dist/routing/app-router.js +12 -6
  23. package/dist/routing/file-matcher.d.ts +11 -22
  24. package/dist/routing/file-matcher.js +21 -33
  25. package/dist/routing/pages-router.js +23 -29
  26. package/dist/routing/route-matching.d.ts +14 -1
  27. package/dist/routing/route-matching.js +13 -1
  28. package/dist/routing/route-pattern.d.ts +2 -1
  29. package/dist/routing/route-pattern.js +7 -4
  30. package/dist/routing/route-trie.d.ts +5 -1
  31. package/dist/routing/route-trie.js +5 -2
  32. package/dist/server/app-browser-entry.js +7 -6
  33. package/dist/server/app-browser-history-controller.d.ts +1 -1
  34. package/dist/server/app-browser-history-controller.js +3 -3
  35. package/dist/server/app-browser-navigation-controller.js +1 -1
  36. package/dist/server/app-browser-state.js +1 -1
  37. package/dist/server/app-browser-visible-commit.js +1 -1
  38. package/dist/server/app-fallback-renderer.d.ts +3 -0
  39. package/dist/server/app-fallback-renderer.js +4 -2
  40. package/dist/server/app-middleware.js +2 -1
  41. package/dist/server/app-page-boundary-render.d.ts +12 -1
  42. package/dist/server/app-page-boundary-render.js +84 -2
  43. package/dist/server/app-page-cache-finalizer.d.ts +1 -1
  44. package/dist/server/app-page-cache.d.ts +1 -1
  45. package/dist/server/app-page-dispatch.d.ts +11 -2
  46. package/dist/server/app-page-dispatch.js +14 -17
  47. package/dist/server/app-page-element-builder.d.ts +7 -2
  48. package/dist/server/app-page-element-builder.js +112 -27
  49. package/dist/server/app-page-head.d.ts +54 -2
  50. package/dist/server/app-page-head.js +164 -78
  51. package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
  52. package/dist/server/app-page-http-access-fallback-metadata.js +106 -0
  53. package/dist/server/app-page-render.d.ts +2 -2
  54. package/dist/server/app-page-render.js +1 -1
  55. package/dist/server/app-page-request.d.ts +12 -0
  56. package/dist/server/app-page-request.js +133 -13
  57. package/dist/server/app-page-route-wiring.d.ts +9 -0
  58. package/dist/server/app-page-route-wiring.js +43 -3
  59. package/dist/server/app-post-middleware-context.d.ts +1 -1
  60. package/dist/server/app-post-middleware-context.js +1 -1
  61. package/dist/server/app-route-handler-dispatch.js +31 -17
  62. package/dist/server/app-route-handler-execution.d.ts +6 -1
  63. package/dist/server/app-route-handler-execution.js +42 -16
  64. package/dist/server/app-route-handler-policy.d.ts +2 -0
  65. package/dist/server/app-route-handler-policy.js +3 -3
  66. package/dist/server/app-route-module-loader.d.ts +3 -1
  67. package/dist/server/app-route-module-loader.js +1 -0
  68. package/dist/server/app-rsc-cache-busting.d.ts +1 -1
  69. package/dist/server/app-rsc-errors.d.ts +1 -1
  70. package/dist/server/app-rsc-errors.js +12 -2
  71. package/dist/server/app-rsc-handler.d.ts +10 -5
  72. package/dist/server/app-rsc-handler.js +52 -24
  73. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  74. package/dist/server/app-rsc-request-normalization.js +8 -2
  75. package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
  76. package/dist/server/app-rsc-response-finalizer.js +5 -11
  77. package/dist/server/app-rsc-route-matching.d.ts +20 -0
  78. package/dist/server/app-rsc-route-matching.js +87 -11
  79. package/dist/server/app-segment-config.js +13 -3
  80. package/dist/server/app-server-action-execution.d.ts +3 -1
  81. package/dist/server/app-server-action-execution.js +9 -7
  82. package/dist/server/app-ssr-entry.js +2 -2
  83. package/dist/server/app-ssr-stream.d.ts +1 -7
  84. package/dist/server/app-ssr-stream.js +2 -10
  85. package/dist/server/config-headers.d.ts +24 -0
  86. package/dist/server/config-headers.js +52 -0
  87. package/dist/server/dev-initial-server-error.d.ts +1 -1
  88. package/dist/server/dev-server.js +29 -13
  89. package/dist/server/isr-cache.d.ts +1 -1
  90. package/dist/server/middleware-matcher-pattern.d.ts +22 -0
  91. package/dist/server/middleware-matcher-pattern.js +219 -0
  92. package/dist/server/middleware-matcher.d.ts +2 -7
  93. package/dist/server/middleware-matcher.js +13 -60
  94. package/dist/server/middleware-path-to-regexp.d.ts +14 -0
  95. package/dist/server/middleware-path-to-regexp.js +228 -0
  96. package/dist/server/middleware-runtime.js +4 -3
  97. package/dist/server/middleware.d.ts +1 -1
  98. package/dist/server/middleware.js +2 -1
  99. package/dist/server/pages-data-route.d.ts +11 -1
  100. package/dist/server/pages-data-route.js +16 -1
  101. package/dist/server/pages-get-initial-props.d.ts +15 -2
  102. package/dist/server/pages-get-initial-props.js +16 -6
  103. package/dist/server/pages-page-data.d.ts +3 -1
  104. package/dist/server/pages-page-data.js +16 -7
  105. package/dist/server/pages-page-handler.d.ts +4 -2
  106. package/dist/server/pages-page-handler.js +16 -17
  107. package/dist/server/pages-page-response.js +1 -1
  108. package/dist/server/pages-readiness.d.ts +3 -3
  109. package/dist/server/pages-request-pipeline.d.ts +1 -0
  110. package/dist/server/pages-request-pipeline.js +25 -11
  111. package/dist/server/pages-router-entry.js +6 -0
  112. package/dist/server/prerender-route-params.js +2 -2
  113. package/dist/server/prod-server.d.ts +1 -4
  114. package/dist/server/prod-server.js +36 -23
  115. package/dist/server/request-pipeline.d.ts +15 -29
  116. package/dist/server/request-pipeline.js +24 -59
  117. package/dist/server/rsc-stream-hints.js +122 -18
  118. package/dist/shims/app.d.ts +1 -1
  119. package/dist/shims/cache-request-state.d.ts +27 -1
  120. package/dist/shims/cache-request-state.js +60 -1
  121. package/dist/shims/cache-runtime.d.ts +12 -1
  122. package/dist/shims/cache-runtime.js +22 -7
  123. package/dist/shims/cache.d.ts +5 -5
  124. package/dist/shims/cache.js +26 -10
  125. package/dist/shims/document.d.ts +42 -83
  126. package/dist/shims/document.js +62 -53
  127. package/dist/shims/dynamic.d.ts +5 -25
  128. package/dist/shims/dynamic.js +29 -8
  129. package/dist/shims/error.d.ts +1 -1
  130. package/dist/shims/error.js +1 -1
  131. package/dist/shims/fetch-cache.js +12 -3
  132. package/dist/shims/font-google-base.d.ts +11 -4
  133. package/dist/shims/font-local.d.ts +10 -3
  134. package/dist/shims/head.d.ts +13 -2
  135. package/dist/shims/head.js +3 -3
  136. package/dist/shims/headers.d.ts +28 -31
  137. package/dist/shims/headers.js +109 -49
  138. package/dist/shims/image.d.ts +27 -37
  139. package/dist/shims/image.js +21 -14
  140. package/dist/shims/internal/cookie-serialize.d.ts +3 -1
  141. package/dist/shims/internal/cookie-serialize.js +3 -1
  142. package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
  143. package/dist/shims/internal/utils.d.ts +3 -3
  144. package/dist/shims/legacy-image.d.ts +3 -37
  145. package/dist/shims/legacy-image.js +6 -16
  146. package/dist/shims/link.d.ts +15 -22
  147. package/dist/shims/link.js +20 -11
  148. package/dist/shims/navigation-context-state.d.ts +1 -1
  149. package/dist/shims/navigation.d.ts +7 -3
  150. package/dist/shims/navigation.js +24 -13
  151. package/dist/shims/navigation.react-server.js +1 -1
  152. package/dist/shims/next-shims-augmentations.d.ts +1 -0
  153. package/dist/shims/next-shims-public.d.ts +1 -0
  154. package/dist/shims/public-shim-map.json.js +103 -0
  155. package/dist/shims/readonly-url-search-params.d.ts +3 -3
  156. package/dist/shims/readonly-url-search-params.js +3 -3
  157. package/dist/shims/request-state-types.d.ts +1 -1
  158. package/dist/shims/router.d.ts +55 -21
  159. package/dist/shims/router.js +162 -37
  160. package/dist/shims/script.d.ts +6 -10
  161. package/dist/shims/script.js +6 -3
  162. package/dist/shims/server.d.ts +45 -22
  163. package/dist/shims/server.js +44 -5
  164. package/dist/shims/unified-request-context.d.ts +1 -1
  165. package/dist/shims/unified-request-context.js +2 -0
  166. package/dist/shims/url-safety.d.ts +1 -1
  167. package/dist/shims/url-safety.js +2 -2
  168. package/dist/typegen.d.ts +8 -2
  169. package/dist/typegen.js +76 -15
  170. package/dist/utils/domain-locale.d.ts +2 -2
  171. package/dist/utils/external-url.d.ts +5 -0
  172. package/dist/utils/external-url.js +7 -0
  173. package/dist/utils/regex-safety.d.ts +8 -0
  174. package/dist/utils/regex-safety.js +737 -0
  175. package/package.json +13 -2
@@ -401,6 +401,10 @@ function matchRoute(url) {
401
401
  return __routeMatcher.matchRoute(url);
402
402
  }
403
403
 
404
+ function matchRequestRoute(url) {
405
+ return __routeMatcher.matchRequestRoute(url);
406
+ }
407
+
404
408
  /**
405
409
  * Check if a pathname matches any intercepting route.
406
410
  * Returns the match info or null.
@@ -523,6 +527,7 @@ export default createAppRscHandler({
523
527
  actionFailed,
524
528
  handlerStart,
525
529
  interceptionContext,
530
+ interceptionPathname,
526
531
  isProgressiveActionRender,
527
532
  isRscRequest,
528
533
  middlewareContext,
@@ -589,6 +594,7 @@ export default createAppRscHandler({
589
594
  observeMetadataSearchParamsAccess: buildOptions?.observeMetadataSearchParamsAccess === true,
590
595
  observePageSearchParamsAccess: buildOptions?.observePageSearchParamsAccess === true,
591
596
  serveStreamingMetadata: buildOptions?.serveStreamingMetadata,
597
+ isProduction: process.env.NODE_ENV === "production",
592
598
  }, layoutParamAccess, displayPathname);
593
599
  },
594
600
  clientReuseManifest,
@@ -608,7 +614,10 @@ export default createAppRscHandler({
608
614
  fetchCache: __segmentConfig.fetchCache ?? null,
609
615
  isEdgeRuntime: __isEdgeRuntime(__segmentConfig.runtime),
610
616
  findIntercept(pathname) {
611
- return findIntercept(pathname, interceptionContext);
617
+ return findIntercept(
618
+ pathname === cleanPathname ? interceptionPathname : pathname,
619
+ interceptionContext,
620
+ );
612
621
  },
613
622
  generateStaticParams: __generateStaticParams,
614
623
  getFontLinks: _getSSRFontLinks,
@@ -660,7 +669,7 @@ export default createAppRscHandler({
660
669
  });
661
670
  },
662
671
  async probePage(probeSearchParams = searchParams) {
663
- const __probeIntercept = findIntercept(cleanPathname, interceptionContext);
672
+ const __probeIntercept = findIntercept(interceptionPathname, interceptionContext);
664
673
  // The intercepting-route page module is lazy (page: null + __pageLoader).
665
674
  // Resolve it before probing so buildAppPageProbes inspects the real page
666
675
  // component for dynamic bailout — matching the render path, which also
@@ -682,7 +691,7 @@ export default createAppRscHandler({
682
691
  }));
683
692
  },
684
693
  renderErrorBoundaryPage(renderErr, errorOrigin) {
685
- const __activeIntercept = findIntercept(cleanPathname, interceptionContext);
694
+ const __activeIntercept = findIntercept(interceptionPathname, interceptionContext);
686
695
  return __fallbackRenderer.renderErrorBoundary(route, renderErr, isRscRequest, request, params, scriptNonce, middlewareContext, {
687
696
  isEdgeRuntime: __isEdgeRuntime(__segmentConfig.runtime),
688
697
  sourcePageSegments: __activeIntercept?.slotKey === __SIBLING_PAGE_INTERCEPT_SLOT_KEY
@@ -691,9 +700,10 @@ export default createAppRscHandler({
691
700
  }, errorOrigin);
692
701
  },
693
702
  renderHttpAccessFallbackPage(statusCode, opts, currentMiddlewareContext) {
694
- const __activeIntercept = findIntercept(cleanPathname, interceptionContext);
703
+ const __activeIntercept = findIntercept(interceptionPathname, interceptionContext);
695
704
  return __fallbackRenderer.renderHttpAccessFallback(route, statusCode, isRscRequest, request, opts, scriptNonce, currentMiddlewareContext, {
696
705
  isEdgeRuntime: __isEdgeRuntime(__segmentConfig.runtime),
706
+ routePathname: cleanPathname,
697
707
  sourcePageSegments: __activeIntercept?.slotKey === __SIBLING_PAGE_INTERCEPT_SLOT_KEY
698
708
  ? __activeIntercept.sourcePageSegments
699
709
  : null,
@@ -772,6 +782,7 @@ export default createAppRscHandler({
772
782
  contentType,
773
783
  middlewareContext,
774
784
  request,
785
+ routeMatch,
775
786
  }) {
776
787
  const {
777
788
  handleProgressiveServerActionRequest: __handleProgressiveServerActionRequest,
@@ -792,11 +803,10 @@ export default createAppRscHandler({
792
803
  contentType,
793
804
  actionId,
794
805
  );
795
- const __progressiveActionMatch = __isProgressiveAction ? matchRoute(cleanPathname) : null;
796
806
  const __hasPageRoute = Boolean(
797
- __progressiveActionMatch &&
798
- __progressiveActionMatch.route.__loadPage &&
799
- !__progressiveActionMatch.route.__loadRouteHandler,
807
+ __isProgressiveAction &&
808
+ routeMatch?.route.__loadPage &&
809
+ !routeMatch.route.__loadRouteHandler,
800
810
  );
801
811
  return __handleProgressiveServerActionRequest({
802
812
  actionId,
@@ -829,6 +839,8 @@ export default createAppRscHandler({
829
839
  middlewareContext,
830
840
  mountedSlotsHeader,
831
841
  request,
842
+ routeMatch,
843
+ routePathname,
832
844
  searchParams,
833
845
  }) {
834
846
  const {
@@ -836,7 +848,7 @@ export default createAppRscHandler({
836
848
  readActionBodyWithLimit: __readBodyWithLimit,
837
849
  readActionFormDataWithLimit: __readFormDataWithLimit,
838
850
  } = await __loadAppServerActionExecution();
839
- const __actionMatch = matchRoute(cleanPathname);
851
+ const __actionMatch = routeMatch;
840
852
  if (__actionMatch) await __ensureRouteLoaded(__actionMatch.route);
841
853
  const __actionIsEdgeRuntime = __actionMatch
842
854
  ? __isEdgeRuntime(__resolveRouteRuntime(__actionMatch.route))
@@ -876,6 +888,8 @@ export default createAppRscHandler({
876
888
  __clearRequestContext();
877
889
  },
878
890
  contentType,
891
+ currentRouteMatch: __actionMatch,
892
+ currentRoutePathname: routePathname,
879
893
  createNotFoundElement(actionRouteId) {
880
894
  return {
881
895
  ...__AppElementsWire.createMetadataEntries({
@@ -940,6 +954,9 @@ export default createAppRscHandler({
940
954
  interceptLayouts: intercept.interceptLayouts,
941
955
  interceptLayoutSegments: intercept.interceptLayoutSegments,
942
956
  interceptBranchSegments: intercept.interceptBranchSegments,
957
+ interceptNotFoundBranchSegments: intercept.interceptNotFoundBranchSegments,
958
+ interceptNotFound: intercept.notFound,
959
+ interceptNotFoundTreePosition: intercept.notFoundTreePosition,
943
960
  interceptSlotId: intercept.slotId,
944
961
  interceptSlotKey: intercept.slotKey,
945
962
  interceptSourceMatchedUrl: interceptionContext,
@@ -963,6 +980,7 @@ export default createAppRscHandler({
963
980
  });
964
981
  },` : ""}
965
982
  matchRoute,
983
+ matchRequestRoute,
966
984
  ${middlewarePath ? `runMiddleware({ cleanPathname, context, hadBasePath, isDataRequest, request }) {
967
985
  return __applyAppMiddleware({
968
986
  basePath: __basePath,
@@ -77,13 +77,16 @@ function registerRouteModules(routes, imports) {
77
77
  for (const layoutPath of slot.configLayoutPaths ?? []) imports.getLazyLoaderVar(layoutPath);
78
78
  if (slot.loadingPath) imports.getLazyLoaderVar(slot.loadingPath);
79
79
  if (slot.errorPath) imports.getLazyLoaderVar(slot.errorPath);
80
+ if (slot.notFoundPath) imports.getLazyLoaderVar(slot.notFoundPath);
80
81
  for (const ir of slot.interceptingRoutes) {
81
82
  imports.getLazyLoaderVar(ir.pagePath);
83
+ if (ir.notFoundPath) imports.getLazyLoaderVar(ir.notFoundPath);
82
84
  for (const layoutPath of ir.layoutPaths) imports.getLazyLoaderVar(layoutPath);
83
85
  }
84
86
  }
85
87
  for (const ir of route.siblingIntercepts ?? []) {
86
88
  imports.getLazyLoaderVar(ir.pagePath);
89
+ if (ir.notFoundPath) imports.getLazyLoaderVar(ir.notFoundPath);
87
90
  for (const layoutPath of ir.layoutPaths) imports.getLazyLoaderVar(layoutPath);
88
91
  }
89
92
  }
@@ -115,8 +118,12 @@ function buildRouteEntries(routes, imports) {
115
118
  __loadInterceptLayouts: ${lazyLoaderArray(ir.layoutPaths, imports)},
116
119
  interceptLayoutSegments: ${JSON.stringify(ir.layoutSegments ?? [])},
117
120
  interceptBranchSegments: ${JSON.stringify(ir.branchSegments ?? [])},
121
+ interceptNotFoundBranchSegments: ${JSON.stringify(ir.notFoundBranchSegments ?? ir.branchSegments ?? [])},
118
122
  page: null,
119
123
  __pageLoader: ${imports.getLazyLoaderVar(ir.pagePath)},
124
+ notFound: null,
125
+ __loadNotFound: ${ir.notFoundPath ? imports.getLazyLoaderVar(ir.notFoundPath) : "null"},
126
+ notFoundTreePosition: ${ir.notFoundTreePosition ?? "null"},
120
127
  params: ${JSON.stringify(ir.params)},
121
128
  }`);
122
129
  const slotEntries = route.parallelSlots.map((slot) => {
@@ -129,8 +136,12 @@ function buildRouteEntries(routes, imports) {
129
136
  __loadInterceptLayouts: ${lazyLoaderArray(ir.layoutPaths, imports)},
130
137
  interceptLayoutSegments: ${JSON.stringify(ir.layoutSegments ?? [])},
131
138
  interceptBranchSegments: ${JSON.stringify(ir.branchSegments ?? [])},
139
+ interceptNotFoundBranchSegments: ${JSON.stringify(ir.notFoundBranchSegments ?? ir.branchSegments ?? [])},
132
140
  page: null,
133
141
  __pageLoader: ${imports.getLazyLoaderVar(ir.pagePath)},
142
+ notFound: null,
143
+ __loadNotFound: ${ir.notFoundPath ? imports.getLazyLoaderVar(ir.notFoundPath) : "null"},
144
+ notFoundTreePosition: ${ir.notFoundTreePosition ?? "null"},
134
145
  params: ${JSON.stringify(ir.params)},
135
146
  }`);
136
147
  return ` ${JSON.stringify(slot.key)}: {
@@ -149,6 +160,9 @@ function buildRouteEntries(routes, imports) {
149
160
  __loadLoading: ${slot.loadingPath ? imports.getLazyLoaderVar(slot.loadingPath) : "null"},
150
161
  error: null,
151
162
  __loadError: ${slot.errorPath ? imports.getLazyLoaderVar(slot.errorPath) : "null"},
163
+ notFound: null,
164
+ __loadNotFound: ${slot.notFoundPath ? imports.getLazyLoaderVar(slot.notFoundPath) : "null"},
165
+ notFoundTreePosition: ${slot.notFoundTreePosition ?? "null"},
152
166
  layoutIndex: ${slot.layoutIndex},
153
167
  routeSegments: ${JSON.stringify(slot.routeSegments)},
154
168
  slotPatternParts: ${slot.slotPatternParts ? JSON.stringify(slot.slotPatternParts) : "null"},
@@ -204,14 +218,17 @@ ${siblingInterceptEntries.join(",\n")}
204
218
  __loadError: ${route.errorPath ? imports.getLazyLoaderVar(route.errorPath) : "null"},
205
219
  notFound: null,
206
220
  __loadNotFound: ${route.notFoundPath ? imports.getLazyLoaderVar(route.notFoundPath) : "null"},
221
+ notFoundTreePosition: ${route.notFoundTreePosition ?? "null"},
207
222
  notFounds: ${moduleArray(notFoundPaths.length)},
208
223
  __loadNotFounds: ${notFoundLoaders},
209
224
  forbidden: null,
210
225
  __loadForbidden: ${route.forbiddenPath ? imports.getLazyLoaderVar(route.forbiddenPath) : "null"},
226
+ forbiddenTreePosition: ${route.forbiddenTreePosition ?? "null"},
211
227
  forbiddens: ${moduleArray(forbiddenPaths.length)},
212
228
  __loadForbiddens: ${forbiddenLoaders},
213
229
  unauthorized: null,
214
230
  __loadUnauthorized: ${route.unauthorizedPath ? imports.getLazyLoaderVar(route.unauthorizedPath) : "null"},
231
+ unauthorizedTreePosition: ${route.unauthorizedTreePosition ?? "null"},
215
232
  unauthorizeds: ${moduleArray(unauthorizedPaths.length)},
216
233
  __loadUnauthorizeds: ${unauthorizedLoaders},
217
234
  }`;
@@ -236,8 +236,8 @@ const _apiRouteTrie = _buildRouteTrie(apiRoutes);
236
236
  function matchRoute(url, routes) {
237
237
  const pathname = url.split("?")[0];
238
238
  let normalizedUrl = pathname === "/" ? "/" : pathname.replace(/\\/$/, "");
239
- // NOTE: Do NOT decodeURIComponent here. The pathname is already decoded at
240
- // the entry point. Decoding again would create a double-decode vector.
239
+ // Static route selection uses raw encoded identity (/%61bout must not
240
+ // select /about). _trieMatch decodes dynamic captures exactly once.
241
241
  const urlParts = normalizedUrl.split("/").filter(Boolean);
242
242
  const trie = routes === pageRoutes ? _pageRouteTrie : _apiRouteTrie;
243
243
  return _trieMatch(trie, urlParts);
@@ -307,6 +307,7 @@ const _renderPage = __createPagesPageHandler({
307
307
  : null,
308
308
  setI18nContext: typeof setI18nContext === "function" ? setI18nContext : null,
309
309
  wrapWithRouterContext: typeof wrapWithRouterContext === "function" ? wrapWithRouterContext : null,
310
+ router: Router,
310
311
  resetSSRHead: typeof resetSSRHead === "function" ? resetSSRHead : undefined,
311
312
  getSSRHeadHTML: typeof getSSRHeadHTML === "function" ? getSSRHeadHTML : undefined,
312
313
  setDocumentInitialHead: typeof setDocumentInitialHead === "function" ? setDocumentInitialHead : undefined,
package/dist/index.js CHANGED
@@ -2,15 +2,17 @@ import path, { toSlash } from "./deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/
2
2
  import { detectPackageManager, formatMissingCloudflarePluginError, hasWranglerConfig } from "./utils/project.js";
3
3
  import { normalizePathnameForRouteMatchStrict } from "./routing/utils.js";
4
4
  import { buildViteResolveExtensions, createValidFileMatcher, findFileWithExts, normalizeViteResolveExtensions } from "./routing/file-matcher.js";
5
+ import { hasBasePath, stripBasePath } from "./utils/base-path.js";
5
6
  import { apiRouter, invalidateRouteCache, matchRoute, pagesRouter } from "./routing/pages-router.js";
6
7
  import { VINEXT_MW_CTX_HEADER } from "./utils/protocol-headers.js";
7
8
  import { INTERNAL_HEADERS, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_TIMING_HEADER } from "./server/headers.js";
8
9
  import { normalizePath as normalizePath$1 } from "./server/normalize-path.js";
9
10
  import { matchesRewriteSource, proxyExternalRequest } from "./config/config-matchers.js";
11
+ import { validateMiddlewareMatcherPatterns } from "./server/middleware-matcher-pattern.js";
10
12
  import { isOpenRedirectShaped } from "./server/open-redirect.js";
11
- import { filterInternalHeaders, normalizeTrailingSlash } from "./server/request-pipeline.js";
13
+ import { canonicalizeRequestUrlPathname, filterInternalHeaders, normalizeTrailingSlash } from "./server/request-pipeline.js";
12
14
  import { findMiddlewareFile, isProxyFile, runMiddleware } from "./server/middleware.js";
13
- import { extractMiddlewareMatcherConfig, hasExportedName } from "./build/report.js";
15
+ import { extractMiddlewareMatcherConfig, extractMiddlewareMatcherConfigValue, hasExportedName } from "./build/report.js";
14
16
  import { generateServerEntry } from "./entries/pages-server-entry.js";
15
17
  import { generateClientEntry } from "./entries/pages-client-entry.js";
16
18
  import { appRouteGraph, appRouter, invalidateAppRouteCache, matchAppRoute } from "./routing/app-router.js";
@@ -18,7 +20,7 @@ import { findInstrumentationClientFile, findInstrumentationFile, runInstrumentat
18
20
  import { isUnknownRecord } from "./utils/record.js";
19
21
  import { logRequest, now } from "./server/request-log.js";
20
22
  import { resolvePagesI18nRequest, stripI18nLocaleForApiRoute } from "./server/pages-i18n.js";
21
- import { isNextDataPathname, normalizeNextDataPagePathname, parseNextDataPathname } from "./server/pages-data-route.js";
23
+ import { encodeUrlParserIgnoredCharacters, isNextDataPathname, normalizeNextDataPagePathname, parseNextDataPathname, urlParserCreatesPagesDataPath } from "./server/pages-data-route.js";
22
24
  import { resolveAssetsDir } from "./utils/asset-prefix.js";
23
25
  import { getPagesPreviewModeId } from "./server/pages-preview.js";
24
26
  import { createSSRHandler } from "./server/dev-server.js";
@@ -68,6 +70,7 @@ import { createOgAssetsPlugin, createOgInlineFetchAssetsPlugin } from "./plugins
68
70
  import { generateRouteTypes } from "./typegen.js";
69
71
  import { SSR_EXTERNAL_REACT_ENTRIES, VINEXT_OPTIMIZE_DEPS_EXCLUDE, mergeOptimizeDepsExclude } from "./plugins/rsc-client-shim-excludes.js";
70
72
  import { createServerExternalsManifestPlugin } from "./plugins/server-externals-manifest.js";
73
+ import public_shim_map_default from "./shims/public-shim-map.json.js";
71
74
  import { VINEXT_CLIENT_ENTRY_MANIFEST } from "./utils/client-entry-manifest.js";
72
75
  import { computeClientRuntimeMetadata } from "./utils/client-runtime-metadata.js";
73
76
  import { PAGES_CLIENT_ASSETS_MODULE, buildPagesClientAssetsModule, setPagesClientAssetsBuildMetadata, takePagesClientAssetsBuildMetadata, writePagesClientAssetsModuleIfMissing } from "./build/pages-client-assets-module.js";
@@ -667,27 +670,14 @@ function generateRootParamsModule(rootParamNames) {
667
670
  const exports = names.map((name) => `export function ${name}() { return getRootParam(${JSON.stringify(name)}); }`).join("\n");
668
671
  return `import { getRootParam } from ${JSON.stringify(rootParamsShimPath)};\n${exports}\n`;
669
672
  }
670
- /**
671
- * Shims with a `.react-server.ts` variant for the RSC environment.
672
- * Maps import specifier base shim name. In the RSC env, resolveId
673
- * appends `.react-server`; in other envs it resolves to the base.
674
- *
675
- * These MUST NOT appear in `nextShimMap` (resolve.alias) because Vite's
676
- * alias plugin runs before user `enforce:"pre"` plugins — aliases are
677
- * unoverridable. Keeping them out of the alias lets the resolveId hook
678
- * control resolution per-environment.
679
- *
680
- * To add a new react-server shim:
681
- * 1. Create `<name>.react-server.ts` in src/shims/
682
- * 2. Add entries here for each import specifier.
683
- */
684
- const _reactServerShims = /* @__PURE__ */ new Map([
685
- ["next/navigation", "navigation"],
686
- ["next/navigation.js", "navigation"],
687
- ["next/dist/client/components/navigation", "navigation"],
688
- ["next/error", "error"],
689
- ["next/error.js", "error"]
690
- ]);
673
+ const _publicNextShimMap = public_shim_map_default;
674
+ const _reactServerShims = /* @__PURE__ */ new Map();
675
+ for (const [specifier, definition] of Object.entries(_publicNextShimMap)) {
676
+ if (!definition.reactServer) continue;
677
+ _reactServerShims.set(specifier, definition.shim);
678
+ _reactServerShims.set(`${specifier}.js`, definition.shim);
679
+ }
680
+ _reactServerShims.set("next/dist/client/components/navigation", "navigation");
691
681
  const clientCodeSplittingConfig = createClientCodeSplittingConfig(createClientManualChunks(_shimsDir));
692
682
  const appClientCodeSplittingConfig = createClientCodeSplittingConfig(createClientManualChunks(_shimsDir, true));
693
683
  function getClientOutputConfig(assetsDir, preserveAppRouteBoundaries = false) {
@@ -774,10 +764,9 @@ function vinext(options = {}) {
774
764
  });
775
765
  }
776
766
  async function writeRouteTypes() {
777
- if (!hasAppDir) return;
778
767
  await generateRouteTypes({
779
768
  root,
780
- appDir,
769
+ appDir: hasAppDir ? appDir : null,
781
770
  pageExtensions: nextConfig.pageExtensions
782
771
  });
783
772
  }
@@ -989,7 +978,7 @@ function vinext(options = {}) {
989
978
  if (mode === "test") resolvedNodeEnv = "test";
990
979
  else if (env?.command === "build" || env?.isPreview === true) resolvedNodeEnv = "production";
991
980
  else resolvedNodeEnv = "development";
992
- if (process.env.NODE_ENV !== resolvedNodeEnv) process.env.NODE_ENV = resolvedNodeEnv;
981
+ if (process.env.NODE_ENV !== resolvedNodeEnv) Reflect.set(process.env, "NODE_ENV", resolvedNodeEnv);
993
982
  if (env?.command === "build") previewBuildCredentials = getPreviewBuildCredentials() ?? createPreviewBuildCredentials();
994
983
  draftModeSecret = previewBuildCredentials?.id ?? getPagesPreviewModeId();
995
984
  let baseDir;
@@ -1008,6 +997,8 @@ function vinext(options = {}) {
1008
997
  appDir = path.join(baseDir, "app");
1009
998
  hasPagesDir = fs.existsSync(pagesDir);
1010
999
  hasAppDir = !options.disableAppRouter && fs.existsSync(appDir);
1000
+ invalidateRouteCache(pagesDir);
1001
+ invalidateAppRouteCache();
1011
1002
  if (!nextConfig) {
1012
1003
  const phase = env?.command === "build" ? PHASE_PRODUCTION_BUILD : PHASE_DEVELOPMENT_SERVER;
1013
1004
  let rawConfig;
@@ -1036,6 +1027,10 @@ function vinext(options = {}) {
1036
1027
  instrumentationClientPath = findInstrumentationClientFile(root, fileMatcher);
1037
1028
  const middlewareConventionDir = canonicalize(baseDir) === canonicalize(path.join(root, "src")) ? path.join(root, "src") : root;
1038
1029
  middlewarePath = findMiddlewareFile(root, fileMatcher, middlewareConventionDir);
1030
+ if (middlewarePath) {
1031
+ const staticMatcher = extractMiddlewareMatcherConfigValue(middlewarePath);
1032
+ if (staticMatcher !== void 0) validateMiddlewareMatcherPatterns(staticMatcher);
1033
+ }
1039
1034
  const instrumentationClientInjects = nextConfig.instrumentationClientInject.map((spec) => spec.startsWith("./") || spec.startsWith("../") ? path.resolve(root, spec) : spec);
1040
1035
  clientInjectModule = instrumentationClientInjects.length ? generateInstrumentationClientInjectModule(instrumentationClientInjects, instrumentationClientPath, INSTRUMENTATION_CLIENT_EMPTY_MODULE) : null;
1041
1036
  if (env?.command === "build") await writeRouteTypes();
@@ -1050,6 +1045,10 @@ function vinext(options = {}) {
1050
1045
  }
1051
1046
  defines["process.env.__NEXT_ROUTER_BASEPATH"] = JSON.stringify(nextConfig.basePath);
1052
1047
  defines["process.env.__VINEXT_HAS_PAGES_ROUTER"] = JSON.stringify(String(hasPagesDir));
1048
+ defines["process.env.__VINEXT_HAS_CLIENT_REWRITES"] = JSON.stringify(String(nextConfig.rewrites.beforeFiles.length > 0 || nextConfig.rewrites.afterFiles.length > 0 || nextConfig.rewrites.fallback.length > 0));
1049
+ defines["process.env.__VINEXT_HAS_CONFIG_HEADERS"] = JSON.stringify(String(nextConfig.headers.length > 0));
1050
+ defines["process.env.__VINEXT_HAS_CONFIG_REDIRECTS"] = JSON.stringify(String(nextConfig.redirects.length > 0));
1051
+ defines["process.env.__VINEXT_HAS_CONFIG_REWRITES"] = JSON.stringify(String(nextConfig.rewrites.beforeFiles.length > 0 || nextConfig.rewrites.afterFiles.length > 0 || nextConfig.rewrites.fallback.length > 0));
1053
1052
  defines["process.env.__NEXT_CLIENT_ROUTER_DYNAMIC_STALETIME"] = JSON.stringify(String(nextConfig.staleTimes.dynamic));
1054
1053
  defines["process.env.__NEXT_CLIENT_ROUTER_STATIC_STALETIME"] = JSON.stringify(String(nextConfig.staleTimes.static));
1055
1054
  defines["process.env.__VINEXT_PREFETCH_INLINING"] = JSON.stringify(nextConfig.prefetchInlining ? "true" : "false");
@@ -1101,28 +1100,7 @@ function vinext(options = {}) {
1101
1100
  }
1102
1101
  for (const key of Object.keys(nextConfig.compilerDefineServer)) if (key in defines) throw new Error(`The \`compiler.defineServer\` option is configured to replace the \`${key}\` variable. This variable is either part of a built-in or is already configured.`);
1103
1102
  nextShimMap = Object.fromEntries(Object.entries({
1104
- "next/link": path.join(shimsDir, "link"),
1105
- "next/head": path.join(shimsDir, "head"),
1106
- "next/router": path.join(shimsDir, "router"),
1107
- "next/compat/router": path.join(shimsDir, "compat-router"),
1108
- "next/image": path.join(shimsDir, "image"),
1109
- "next/legacy/image": path.join(shimsDir, "legacy-image"),
1110
- "next/dynamic": path.join(shimsDir, "dynamic"),
1111
- "next/app": path.join(shimsDir, "app"),
1112
- "next/document": path.join(shimsDir, "document"),
1113
- "next/config": path.join(shimsDir, "config"),
1114
- "next/script": path.join(shimsDir, "script"),
1115
- "next/server": path.join(shimsDir, "server"),
1116
- "next/headers": path.join(shimsDir, "headers"),
1117
- "next/font/google": path.join(shimsDir, "font-google"),
1118
- "next/font/local": path.join(shimsDir, "font-local"),
1119
- "next/cache": path.join(shimsDir, "cache"),
1120
- "next/form": path.join(shimsDir, "form"),
1121
- "next/og": path.join(shimsDir, "og"),
1122
- "next/web-vitals": path.join(shimsDir, "web-vitals"),
1123
- "next/amp": path.join(shimsDir, "amp"),
1124
- "next/offline": path.join(shimsDir, "offline"),
1125
- "next/constants": path.join(shimsDir, "constants"),
1103
+ ...Object.fromEntries(Object.entries(_publicNextShimMap).filter(([, definition]) => !definition.reactServer).map(([specifier, definition]) => [specifier, path.join(shimsDir, definition.shim)])),
1126
1104
  "next/dist/shared/lib/app-router-context.shared-runtime": path.join(shimsDir, "internal", "app-router-context"),
1127
1105
  "next/dist/shared/lib/app-router-context": path.join(shimsDir, "internal", "app-router-context"),
1128
1106
  "next/dist/shared/lib/router-context.shared-runtime": path.join(shimsDir, "internal", "router-context"),
@@ -1460,7 +1438,7 @@ function vinext(options = {}) {
1460
1438
  config.optimizeDeps.exclude = mergeOptimizeDepsExclude(config.optimizeDeps.exclude ?? [], VINEXT_OPTIMIZE_DEPS_EXCLUDE, PAGES_CLOUDFLARE_WORKER_OPTIMIZE_DEPS_EXCLUDE);
1461
1439
  }
1462
1440
  const configuredExtensions = name === "client" ? nextConfig.resolveExtensions : nextConfig.serverResolveExtensions;
1463
- const extensions = configuredExtensions === null ? buildViteResolveExtensions(nextConfig.pageExtensions, config.resolve?.extensions) : normalizeViteResolveExtensions(configuredExtensions);
1441
+ const extensions = configuredExtensions === null ? buildViteResolveExtensions(config.resolve?.extensions) : normalizeViteResolveExtensions(configuredExtensions);
1464
1442
  config.resolve ??= {};
1465
1443
  config.resolve.extensions = extensions;
1466
1444
  return null;
@@ -1856,6 +1834,10 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
1856
1834
  }
1857
1835
  },
1858
1836
  configureServer(server) {
1837
+ server.middlewares.use((req, _res, next) => {
1838
+ req.__vinextOriginalEncodedUrl ??= req.url;
1839
+ next();
1840
+ });
1859
1841
  const pageExtensions = fileMatcher.extensionRegex;
1860
1842
  let pagesRunner = null;
1861
1843
  let cachedSSRHandler = null;
@@ -2193,9 +2175,25 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
2193
2175
  res.end();
2194
2176
  return;
2195
2177
  }
2178
+ const originalEncodedUrl = req.__vinextOriginalEncodedUrl ?? url;
2179
+ const originalEncodedPathname = originalEncodedUrl.split("?")[0];
2180
+ if (isOpenRedirectShaped(originalEncodedPathname)) {
2181
+ res.writeHead(404);
2182
+ res.end("This page could not be found");
2183
+ return;
2184
+ }
2185
+ const canonicalOriginalUrl = canonicalizeRequestUrlPathname(originalEncodedUrl);
2186
+ url = canonicalizeRequestUrlPathname(url);
2196
2187
  const rawPathname = url.split("?")[0];
2197
2188
  if (rawPathname.endsWith("/index.html")) url = url.replace("/index.html", "/");
2198
2189
  else if (rawPathname.endsWith(".html")) url = url.replace(/\.html(?=\?|$)/, "");
2190
+ let middlewareUrl = canonicalOriginalUrl;
2191
+ let routeUrl = middlewareUrl;
2192
+ {
2193
+ const routePathname = routeUrl.split("?")[0];
2194
+ if (routePathname.endsWith("/index.html")) routeUrl = routeUrl.replace("/index.html", "/");
2195
+ else if (routePathname.endsWith(".html")) routeUrl = routeUrl.replace(/\.html(?=\?|$)/, "");
2196
+ }
2199
2197
  let pathname = url.split("?")[0];
2200
2198
  if (isOpenRedirectShaped(pathname)) {
2201
2199
  res.writeHead(404);
@@ -2210,20 +2208,42 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
2210
2208
  res.end("Bad Request");
2211
2209
  return;
2212
2210
  }
2211
+ if (urlParserCreatesPagesDataPath(pathname)) {
2212
+ res.writeHead(404);
2213
+ res.end("This page could not be found");
2214
+ return;
2215
+ }
2216
+ pathname = encodeUrlParserIgnoredCharacters(pathname);
2213
2217
  {
2214
2218
  const qs = url.includes("?") ? url.slice(url.indexOf("?")) : "";
2215
2219
  url = pathname + qs;
2216
2220
  }
2217
2221
  const capturedMiddlewarePath = middlewarePath;
2218
2222
  const bp = nextConfig?.basePath ?? "";
2219
- if (bp && pathname.startsWith(bp)) {
2220
- const stripped = pathname.slice(bp.length) || "/";
2221
- url = stripped + (url.includes("?") ? url.slice(url.indexOf("?")) : "");
2222
- pathname = stripped;
2223
+ const viteBase = server.config.base;
2224
+ const viteBasePath = viteBase.startsWith("/") && viteBase !== "/" ? viteBase.replace(/\/+$/, "") : "";
2225
+ const routingBasePath = bp || viteBasePath;
2226
+ if (routingBasePath) {
2227
+ if (hasBasePath(pathname, routingBasePath)) {
2228
+ const stripped = stripBasePath(pathname, routingBasePath);
2229
+ url = stripped + (url.includes("?") ? url.slice(url.indexOf("?")) : "");
2230
+ pathname = stripped;
2231
+ }
2232
+ const middlewarePathname = middlewareUrl.split("?")[0];
2233
+ if (hasBasePath(middlewarePathname, routingBasePath)) {
2234
+ const middlewareQs = middlewareUrl.includes("?") ? middlewareUrl.slice(middlewareUrl.indexOf("?")) : "";
2235
+ middlewareUrl = stripBasePath(middlewarePathname, routingBasePath) + middlewareQs;
2236
+ }
2237
+ const routePathname = routeUrl.split("?")[0];
2238
+ if (hasBasePath(routePathname, routingBasePath)) {
2239
+ const routeQs = routeUrl.includes("?") ? routeUrl.slice(routeUrl.indexOf("?")) : "";
2240
+ routeUrl = stripBasePath(routePathname, routingBasePath) + routeQs;
2241
+ }
2223
2242
  }
2243
+ let configMatchPathname = stripBasePath(middlewareUrl.split("?")[0], routingBasePath);
2224
2244
  if (nextConfig) {
2225
2245
  const qs = url.includes("?") ? url.slice(url.indexOf("?")) : "";
2226
- const trailingSlashRedirect = normalizeTrailingSlash(pathname, bp, nextConfig.trailingSlash, qs);
2246
+ const trailingSlashRedirect = normalizeTrailingSlash(routeUrl.split("?")[0], bp, nextConfig.trailingSlash, qs);
2227
2247
  if (trailingSlashRedirect) {
2228
2248
  const location = trailingSlashRedirect.headers.get("Location");
2229
2249
  res.writeHead(trailingSlashRedirect.status, location ? { Location: location } : void 0);
@@ -2241,7 +2261,10 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
2241
2261
  const qs = url.includes("?") ? url.slice(url.indexOf("?")) : "";
2242
2262
  const pagePathname = normalizeNextDataPagePathname(dataMatch.pagePathname, capturedMiddlewarePath !== null && nextConfig?.trailingSlash === true);
2243
2263
  url = pagePathname + qs;
2264
+ middlewareUrl = url;
2265
+ routeUrl = url;
2244
2266
  pathname = pagePathname;
2267
+ configMatchPathname = pagePathname;
2245
2268
  req.url = url;
2246
2269
  } else {
2247
2270
  const deploymentId = process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID;
@@ -2276,7 +2299,7 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
2276
2299
  for (const header of INTERNAL_HEADERS) delete req.headers[header];
2277
2300
  for (const header of VINEXT_INTERNAL_HEADERS) delete req.headers[header];
2278
2301
  const method = req.method ?? "GET";
2279
- const webRequest = new Request(new URL(url, requestOrigin), {
2302
+ const webRequest = new Request(new URL(routeUrl, requestOrigin), {
2280
2303
  method,
2281
2304
  headers: nodeRequestHeaders
2282
2305
  });
@@ -2287,11 +2310,11 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
2287
2310
  const devRunMiddlewareAdapter = capturedMiddlewarePath ? async (_request, _ctx, opts) => {
2288
2311
  const rawProto = process.env.VINEXT_TRUST_PROXY === "1" || (process.env.VINEXT_TRUSTED_HOSTS ?? "").split(",").some((h) => h.trim()) ? String(req.headers["x-forwarded-proto"] || "").split(",")[0].trim() : "";
2289
2312
  const mwOrigin = `${rawProto === "https" || rawProto === "http" ? rawProto : "http"}://${requestHost}`;
2290
- const middlewareRequest = new Request(new URL(url, mwOrigin), {
2313
+ const middlewareRequest = new Request(new URL(middlewareUrl, mwOrigin), {
2291
2314
  method: req.method,
2292
2315
  headers: nodeRequestHeaders
2293
2316
  });
2294
- const result = await runMiddleware(getPagesRunner(), capturedMiddlewarePath, middlewareRequest, nextConfig?.i18n, nextConfig?.basePath, nextConfig?.trailingSlash, opts.isDataRequest);
2317
+ const result = await runMiddleware(getPagesRunner(), capturedMiddlewarePath, middlewareRequest, nextConfig?.i18n, nextConfig?.basePath, nextConfig?.trailingSlash, opts.isDataRequest, pathname);
2295
2318
  if (hasAppDir && result.continue) {
2296
2319
  const mwCtxEntries = [];
2297
2320
  if (result.responseHeaders) {
@@ -2335,6 +2358,7 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
2335
2358
  isDataRequest,
2336
2359
  hasMiddleware: capturedMiddlewarePath !== null,
2337
2360
  rawSearch: url.includes("?") ? url.slice(url.indexOf("?")) : "",
2361
+ configMatchPathname,
2338
2362
  runMiddleware: devRunMiddlewareAdapter,
2339
2363
  matchPageRoute: (resolvedPathname, request) => {
2340
2364
  const m = matchRoute(nextConfig?.i18n ? resolvePagesI18nRequest(resolvedPathname, nextConfig.i18n, request.headers, getUrlHostname(request.url), bp, nextConfig.trailingSlash ?? false).url : resolvedPathname, devPageRoutes);
package/dist/init.d.ts CHANGED
@@ -3,14 +3,15 @@ import { getReactUpgradeDeps } from "./utils/react-version.js";
3
3
 
4
4
  //#region src/init.d.ts
5
5
  type InitOptions = {
6
- /** Project root directory */root: string; /** Dev server port (default: 3001) */
7
- port?: number; /** Skip the compatibility check step */
6
+ /** Project root directory */root: string; /** Dev server port (default: 3001), or false to omit the port flag. */
7
+ port?: number | false; /** Skip the compatibility check step */
8
8
  skipCheck?: boolean; /** Force overwrite even if vite.config.ts exists */
9
9
  force?: boolean; /** Deployment target selected by the user */
10
10
  platform?: InitPlatform; /** Configure build-time pre-rendering for all discovered static routes */
11
11
  prerender?: boolean; /** Cloudflare cache and image choices. */
12
12
  cloudflare?: CloudflareInitOptions; /** Install missing dependencies with the detected package manager (default: true). */
13
- install?: boolean; /** @internal override exec for testing (avoids ESM spy issues) */
13
+ install?: boolean; /** Script naming style (default: namespaced, e.g. dev:vinext). */
14
+ scriptNames?: "namespaced" | "standard"; /** @internal — override exec for testing (avoids ESM spy issues) */
14
15
  _exec?: (cmd: string, opts: {
15
16
  cwd: string;
16
17
  stdio: string;
@@ -34,8 +35,9 @@ declare function generateViteConfig(_isAppRouter: boolean, prerender?: boolean):
34
35
  * Add vinext scripts to package.json without overwriting existing scripts.
35
36
  * Returns the list of script names that were added.
36
37
  */
37
- declare function addScripts(root: string, port: number, platform?: InitPlatform, options?: {
38
+ declare function addScripts(root: string, port: number | false, platform?: InitPlatform, options?: {
38
39
  warmCdnCache?: boolean;
40
+ scriptNames?: "namespaced" | "standard";
39
41
  }): string[];
40
42
  type InitDependencyGroups = {
41
43
  dependencies: string[];
package/dist/init.js CHANGED
@@ -78,22 +78,16 @@ function addScripts(root, port, platform = "node", options = {}) {
78
78
  const pkg = JSON.parse(raw);
79
79
  if (!pkg.scripts) pkg.scripts = {};
80
80
  const added = [];
81
- if (!pkg.scripts["dev:vinext"]) {
82
- pkg.scripts["dev:vinext"] = `vinext dev --port ${port}`;
83
- added.push("dev:vinext");
84
- }
85
- if (!pkg.scripts["build:vinext"]) {
86
- pkg.scripts["build:vinext"] = "vinext build";
87
- added.push("build:vinext");
88
- }
89
- if (!pkg.scripts["start:vinext"]) {
90
- pkg.scripts["start:vinext"] = platform === "cloudflare" ? "wrangler dev --config dist/server/wrangler.json" : "vinext start";
91
- added.push("start:vinext");
92
- }
93
- if (platform === "cloudflare" && !pkg.scripts["deploy:vinext"]) {
94
- pkg.scripts["deploy:vinext"] = options.warmCdnCache ? "vinext-cloudflare deploy --config dist/server/wrangler.json --experimental-warm-cdn-cache" : "vinext-cloudflare deploy --config dist/server/wrangler.json";
95
- added.push("deploy:vinext");
96
- }
81
+ const addScript = (name, command) => {
82
+ const scriptName = options.scriptNames === "standard" ? name : `${name}:vinext`;
83
+ if (pkg.scripts[scriptName]) return;
84
+ pkg.scripts[scriptName] = command;
85
+ added.push(scriptName);
86
+ };
87
+ addScript("dev", port === false ? "vinext dev" : `vinext dev --port ${port}`);
88
+ addScript("build", "vinext build");
89
+ addScript("start", platform === "cloudflare" ? "wrangler dev --config dist/server/wrangler.json" : "vinext start");
90
+ if (platform === "cloudflare") addScript("deploy", options.warmCdnCache ? "vinext-cloudflare deploy --config dist/server/wrangler.json --experimental-warm-cdn-cache" : "vinext-cloudflare deploy --config dist/server/wrangler.json");
97
91
  if (added.length > 0) fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
98
92
  return added;
99
93
  } catch {
@@ -342,7 +336,10 @@ async function init(options) {
342
336
  existingViteConfigPath = renamedPath;
343
337
  }
344
338
  const addedTypeModule = ensureESModule(root);
345
- const addedScripts = addScripts(root, port, platform, { warmCdnCache: options.cloudflare?.warmCdnCache ?? false });
339
+ const addedScripts = addScripts(root, port, platform, {
340
+ warmCdnCache: options.cloudflare?.warmCdnCache ?? false,
341
+ scriptNames: options.scriptNames
342
+ });
346
343
  const setupContext = {
347
344
  root,
348
345
  isAppRouter: isApp,
@@ -436,15 +433,16 @@ async function init(options) {
436
433
  if (updatedGitignore) console.log(` ${terminalStyle.green("✓")} Added vinext output directories to .gitignore`);
437
434
  const nextSteps = [...platformSetup.nextSteps];
438
435
  if (dependencyInstallNeedsApproval) nextSteps.push("Dependency installation is incomplete because pnpm blocked dependency build scripts:", "1. Review and approve the required build scripts:", " pnpm approve-builds", "2. Finish installing dependencies:", " pnpm install");
439
- const deployCommandStep = platform === "cloudflare" ? ` ${pmName} run deploy:vinext Deploy to Cloudflare Workers\n` : "";
436
+ const scriptName = (name) => options.scriptNames === "standard" ? name : `${name}:vinext`;
437
+ const deployCommandStep = platform === "cloudflare" ? ` ${pmName} run ${scriptName("deploy")} Deploy to Cloudflare Workers\n` : "";
440
438
  const startCommandDescription = platform === "cloudflare" ? "Start the built Worker locally with Wrangler" : "Start vinext production server";
441
439
  console.log(`
442
440
  ${terminalStyle.cyan(terminalStyle.bold("Next steps:"))}
443
441
  ${nextSteps.map((step) => ` ${step}`).join("\n")}${nextSteps.length > 0 ? "\n" : ""}
444
- ${pmName} run dev:vinext Start the vinext dev server
445
- ${pmName} run build:vinext Build production output
446
- ${pmName} run start:vinext ${startCommandDescription}
447
- ${deployCommandStep} ${pmName} run dev Start Next.js (still works as before)
442
+ ${pmName} run ${scriptName("dev")} Start the vinext dev server
443
+ ${pmName} run ${scriptName("build")} Build production output
444
+ ${pmName} run ${scriptName("start")} ${startCommandDescription}
445
+ ${deployCommandStep}${options.scriptNames === "standard" ? "" : ` ${pmName} run dev Start Next.js (still works as before)\n`}
448
446
  `);
449
447
  return {
450
448
  installedDeps: [.../* @__PURE__ */ new Set([...dependencyEntriesAdded, ...devDependencyEntriesAdded])],
@@ -109,7 +109,7 @@ const OG_WASM_ASSETS = ["resvg.wasm", "yoga.wasm"];
109
109
  */
110
110
  function findEmittedWasmAsset(bundle, baseName) {
111
111
  const stem = baseName.replace(/\.wasm$/, "");
112
- const re = new RegExp(`^${stem}(?:-[\\w-]+)?\\.wasm$`);
112
+ const re = new RegExp(`^${stem}(?:[-.][\\w-]+)?\\.wasm$`);
113
113
  for (const output of Object.values(bundle)) {
114
114
  if (output.type !== "asset") continue;
115
115
  if (re.test(path.basename(output.fileName))) return output.fileName;